[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