1

I have a bit of a unique issue. I'm collaborating with several other Computer Science Majors at my university on an Android Metronome app that allows two users with the app to sync metronomes. Right now, I can send the desired beats per minute of the metronome from one phone to the other and both phones will start to play their respective metronomes. Due to the latency of Bluetooth, the metronomes are only in sync about 20% of the time.

So, here's where the problem is. We're trying to make it so both of the metronomes will start at the exact same time. One way I've thought of doing this is once the first user presses the send button on their phone, a time stamp will be created. This time stamp will be exactly two seconds after the user presses the send button. The time stamp will then be sent to the second phone and the phone will utilize this time stamp to start it's metronome at the same exact time as the first phone. I've tried accomplishing this by putting UTC time in a while loop and then constantly checking the time, to no avail. Does anyone have any ideas as to how we can go about implementing this? I couldn't find any similar problem on StackOverflow, or any other website for that matter.

Will
  • 71
  • 8
  • Possible duplicate of [Sync Android devices via GPS time?](http://stackoverflow.com/questions/8210264/sync-android-devices-via-gps-time) – 323go Dec 23 '15 at 21:09
  • The duplicate question addresses the same basic problem in a different application. Your best bet is to implement an NTC client and determine NIST offset to system time, and then use that to address any jitter. I've used the same method to get two devices to synchronize video/audio playback, and you can get accurate within 5-10ms, which seems enough for audio. Forget GPS time, for me, it's always returned system time. – 323go Dec 23 '15 at 21:13

2 Answers2

4

It's a bit late probably for your project, but if interested. This is a bit long, it's more like a case study. If your project was about syncing two device clocks remotely, then this won't help you, but if it was about syncing the metronomes, then this may be a start.

First, getting millisecond accurate timings and callbacks in android using java is next to impossible, since android is not a real time system ( All sleep methods and timer might not execute on the exact millisecond you're expecting ). You may want to go with NDK for triggering your beat events, because native threads in android can achieve that, but if you're happy with your single metronome implementation, then that's good enough to read the rest of this .

Full disclosure : I am the author of JAM the app referenced in the answer I just published a few days ago.

I ran into the same problem when developing the app. And whether this answer will help you or not, depending on your situation. and if you're going down the "clock sync" route ( Which I do plan on exploring to improve my app down the road with more features ) but the solution that I found did not involves time sync.

I will mention my approach and then state what I found as advantages/disadvantages for each of the methods .

Instead of syncing clocks ( A very difficult problem, especially for what the app was supposed to do , and that is trigger ticks on multiple devices at the "same" time ) I opted for a subscribe/publish model, where multiple devices can "subscribe" to a host device via bluetooth, and the host device controls and "publishes" the metronome beats.

most times sending a few hundred bytes ( Enough information about each beat ) via bluetooth takes less than 2ms , it could spike up to 10 and sometimes even 30, but that rarely seems to happen . That approach took care of the syncing problem, now I can send beat events from one device to another in 2ms , and if some sort of delay happened, it will self correct once the interference is gone, because the other event comes in time.

However that approach does require constant connection, you can't start and separate the devices later on, but it's much easier to implement.

Now the interesting part, the problem I never thought of when starting this, and that was the Android 10 millisecond audio path latency problem. I'm not affiliated with superpowered, but I did use their engine in my app to deal with that problem .

To summarize : Metronome sync over bluetooth in Android has two issues :
1 - triggering beat events simultaneously ( or within acceptable latency )
2 - The beat event should trigger sound events with minimal delay after the beat event is received

#1 is related to the original question, #2 I thought was an important addition to the original problem this question is asking.

Terry Jan Reedy
  • 18,414
  • 3
  • 40
  • 52
jay
  • 507
  • 4
  • 16
0

I would use (S)NTP to check the clock drift to a public time server. After that I would just send the interval and a start time and let the devices calculate the interval individually. So you just need to sync changes and relay on the clocks of the individual devices. Together with the now known clock drift you can fix this error.

rekire
  • 47,260
  • 30
  • 167
  • 264