[Scummvm-devel] Recent Audio API changes

Max Horn max at quendi.de
Mon Jan 11 10:12:49 CET 2010


Johannes asked me to write a bit about Audio::Timestamp, so here I go:


Audio::Timestamp is a light class from sound/timestamp.h. Its purpose  
is to unify and simplify measuring points in time and time intervals  
in a precise fashion. In particular, it easily allows combining  
measurements in milliseconds with measurements in frame / sample  
numbers (together with a frame/sample rate) while retaining full  
precision.


This is important when synchronizing audio and video (but also for  
some other applications). For audio and video, frames are used to  
measure progress (in audio terms, a frame is either a single sample in  
mono mode, or a pair of samples in stereo mode). So you have  
information like "for this audio stream, 5000 samples already played  
at a sample rate of 44100 Hz"). On the other hand, our only time  
source, OSystem::getMillis(), measures time in milliseconds. If you  
have another audio or video stream, it may use a different frame rate,  
say 22050 Hz. Finally, your game engine might run at 60 Hz.

Now, combining all this data accurately to sync audio, video and  
scripts, can pose a challenge. The math are not really hard, but doing  
it right is tricky, esp. if you want to avoid over- and underflows,  
accumulating rounding errors (which may seem harmless at first but can  
lead to serious delays over time), and other hassles. Multiply this by  
a number of engines and audiostream implementations, and you also get  
a fair bit of code duplication.

Enter Audio::Timestamp. You can use it to measure simultaneously with  
milliseconds and frames, and retain full accuracy. No intermediate  
rounding errors, internal calculations are always with full precision.  
Rounding only takes place when you convert a timestamp to a  
millisecond or frame value, for example if you need to compare or  
print it. However, you can also compare Timestamps with each other  
precisely, add them, etc. (Technically detail: This is achieved by  
computing with fractions a/b, where b is the least common multiple of  
1000 and the original framerate).

We already converted lots of the audio code to use Timestamps. I think  
that it would be very good to convert the code in graphics/video to  
use it, too.


The class is documented with Doxygen comments (see also <http://doxygen.scummvm.org/d2/deb/classAudio_1_1Timestamp.html 
 >). If something is unclear there, please ping me about it and I'll  
try to clarify.

Finally, here's a brief fake example:

   // start point at 0, frame rate is 22050;
   const Audio::Timestamp start(0, 22050);
   // end after 100 frames (samples)
   const  Audio::Timestamp end = start.addFrames(100);
   Audio::Timestamp pos = start;

   // loop until the end
   while (pos < end) {
     // go to next frame
     pos = pos.addFrames(1);
     // ... do something ...
     if (pos.msecs() > g_system->getMillis())
        printf("we went beyond the current time, woo-hoo\n");
   }



Cheers,
Max




More information about the Scummvm-devel mailing list