Hello! I am making a program which is used to play music accross different hosts on a network. I am currently working on synchronizing the playing music.
All the clients measure their clock difference from the server. This is accurate to +1/-1 µs after running a few seconds. To synchronize the music i get the starting time of the track from the server and then calculate how much time has passed using the system clock. Then I check the position of the sound (Channel::getPosition) in ms. To adjust the sound to the correct position i use Channel::setFrequency.
In some computers this works quite well but in some computers it doesn’t. So I thought it was the fault of setFrequency but it wasn’t.
I found that while playing a mp3 stream the time difference between getPosition and (systemclock – startingtime) starts to grow as fast as 0.5 seconds in just 2 minutes when i don’t adjust the frequency. And it’s not the fault of the synchronized clock since on 3 machines the clock runs at the same speed (the clock difference between the host doesn’t change even a microsecond).
I tried this with different MP3 files and different open flags (opening it as a basic sound helped just a little bit, ACCURATETIME didn’t change a thing). I also tried to read the position in PCM samples.
How can I accurately find out what part of the sound/stream is playing?
I am currently using FMOD_VERSION 0x00040439 and coding in C++/C#.
- Squider asked 10 years ago
I think the problem is most likely that sound card clicks are not always exactly 48000hz. This is what fmod calculates its time from. It is sample accurate time, not ‘real time’ accurate, as fmod feeds x samples to the output, then says, positionpcm += x, then ms = positionpcm * 1000 / samplerate. So this logic is the same on all machines and the only difference is, did 48000 samples actually pass in 1 second?
Yeah but that’s the weird part… if I start the songs simultaneously on all the computers they play the songs very much at the same time all the way through… but the getPosition reports very different values. As you can see from the graph all the songs ended at the same time according to the system clocks.
Edit: And ofcourse if I try to sync them even with setPosition, they’ll come out out-of-sync (after the first 5 minutes this is over 1 second). And the audio frequency that comes out of the soundcards is very much right on (compared this with a 440 Hz sine-wave, no beating whatsoever). If I try to sync the position with the real-time clock with setFrequency it will result in a major drift…
Just to see if the drifting only happened with FMOD I created a Windows Media Player control on the test application form… made it play the same song starting at the same time with FMOD plotting the position of the song. And what do you know, this resulted in a graph that was very similiar to the FMOD’s… So now I know it’s not FMOD’s fault. =)
The graph from the AMD Turion 64 machine: http://users.tkk.fi/~jthelle/graph_fazeriina.png
Red = FMOD
Blue = WMP
I’m also curious to know whether this is an issue only on AMD CPUs (that they feed less data to the soundcard than they should) since on the P4 machine the getPosition was quite accurate to real time (checked it also with the P4 laptop’s integrated Conexant AMC Audio chip).
But then again… how would I archieve the synchronization between the hosts as synchronizing the clocks isn’t enough…
[quote="Squider":1ndk0ypw]how would I archieve the synchronization between the hosts as synchronizing the clocks isn’t enough…[/quote:1ndk0ypw]
I would not expect that you would be able to achieve perfect sync between dissimilar systems, and not even on identical systems without some form of calibration and possibly even running in kernel space as opposed to user space due to slight variations in the manufacturing process of the system’s components.
OK so I just created a test application that just draws a graph of the difference between the system clock and the channel position (getPosition).
In the test I open a MP3 file as a stream and with FMOD.MODE.ACCURATETIME | FMOD.MODE.SOFTWARE. Then each 500ms I calculate the difference between the position (milliseconds) returned by getPosition and the time (DateTime.Now) since the sound started playing and plot it.
In the graph one horizontal pixel is 500ms and one vertical pixel is 10ms.
Red = AMD Athlon XP with Creative SoundBlaster Audigy 4 Pro
Green = AMD Turion 64 with Realtek AC’97 Audio
Blue = Intel Pentium 4 with Creative SoundBlaster Audigy 2 NX
Gah just an accurate way to measure time like FMOD does would be enough ^^
Oh… and the clocks on the computers don’t drift significantly.
[b:373n3nr8]This is strictly theory so feel free to disregard it[/b:373n3nr8]
I am wondering if the difference would be caused by drift in the CPU’s clock generator. Instead of generating a stable lets say, 200MHz for a P4 3GHz FSB, the room & system temperatures are causing a little drift say towards 205MHz.
This would cause the CPU’s execution speed after the multiplier to drift upwards towards say 3.1GHz, now since the system doesn’t account for this thermal overclock unlike a normal overclock where the system accounts for a 205MHz FSB, it will cause a long-term trend towards running processes faster.
There would also be no reason why the clock cant drift in reverse either.
(3.0GHz = 100.0% Execution Speed : 44100Hz plays at 44100Hz, 10min mp3 takes 10min to play)
(3.1GHz = 103.3% Execution Speed : 44100Hz plays at 45555.3Hz, 10min mp3 takes 9.68min to play)
Now I may be off mark with this since any good clock generator manufacturer would compensate for thermal drift, but even then it’s not 100% perfect
Please login first to submit.