diff options
author | Max Horn | 2010-01-04 22:48:28 +0000 |
---|---|---|
committer | Max Horn | 2010-01-04 22:48:28 +0000 |
commit | 4ae9412a3aea75990008c3a32080c54533fdb389 (patch) | |
tree | 5f7910434efd0e25c9278fa75cc86628dab7a4ce /sound/timestamp.cpp | |
parent | a6aaeb70e6dfb3a9727e8861041601cf658aa5cd (diff) | |
download | scummvm-rg350-4ae9412a3aea75990008c3a32080c54533fdb389.tar.gz scummvm-rg350-4ae9412a3aea75990008c3a32080c54533fdb389.tar.bz2 scummvm-rg350-4ae9412a3aea75990008c3a32080c54533fdb389.zip |
Make some improvements for Audio::Timestamp.
* Add convertToFramerate() method
* Add framerate() method
* Add operator == and !=
* Improve frameDiff() to work for two timestamps with distinct framerates
* Improve Doxygen comments
svn-id: r46994
Diffstat (limited to 'sound/timestamp.cpp')
-rw-r--r-- | sound/timestamp.cpp | 107 |
1 files changed, 83 insertions, 24 deletions
diff --git a/sound/timestamp.cpp b/sound/timestamp.cpp index c85ec47ae8..a517462bb4 100644 --- a/sound/timestamp.cpp +++ b/sound/timestamp.cpp @@ -27,51 +27,110 @@ namespace Audio { -Timestamp::Timestamp(uint32 m, int frameRate) : - _msecs(m), _frameRate(frameRate), _frameOffset(0) { - assert(_frameRate > 0); +static uint gcd(uint a, uint b) { + while (a > 0) { + int tmp = a; + a = b % a; + b = tmp; + } + return b; +} + +Timestamp::Timestamp(uint32 m, int framerate) : + _msecs(m), _framerate(framerate), _numberOfFrames(0) { + assert(_framerate > 0); +} + + +Timestamp Timestamp::convertToFramerate(int newFramerate) const { + Timestamp ts(*this); + + if (ts._framerate != newFramerate) { + ts._framerate = newFramerate; + + const uint g = gcd(_framerate, ts._framerate); + const uint p = _framerate / g; + const uint q = ts._framerate / g; + + // Convert the frame offset to the new framerate. + // We round to the nearest (as opposed to always + // rounding down), to minimize rounding errors during + // round trip conversions. + ts._numberOfFrames = (ts._numberOfFrames * q + p/2) / p; + + ts._msecs += (ts._numberOfFrames / ts._framerate) * 1000; + ts._numberOfFrames %= ts._framerate; + } + + return ts; +} + +bool Timestamp::operator==(const Timestamp &ts) const { + // TODO: Alternatively, we could define equality to mean that + // two timestamps describe the exacts same moment in time. + return (_msecs == ts._msecs) && + (_numberOfFrames == ts._numberOfFrames) && + (_framerate == ts._framerate); +} + +bool Timestamp::operator!=(const Timestamp &ts) const { + return !(*this == ts); } Timestamp Timestamp::addFrames(int frames) const { - Timestamp timestamp(*this); - timestamp._frameOffset += frames; + Timestamp ts(*this); + ts._numberOfFrames += frames; - if (timestamp._frameOffset < 0) { - int secsub = 1 + (-timestamp._frameOffset / timestamp._frameRate); + if (ts._numberOfFrames < 0) { + int secsub = 1 + (-ts._numberOfFrames / ts._framerate); - timestamp._frameOffset += timestamp._frameRate * secsub; - timestamp._msecs -= secsub * 1000; + ts._numberOfFrames += ts._framerate * secsub; + ts._msecs -= secsub * 1000; } - timestamp._msecs += (timestamp._frameOffset / timestamp._frameRate) * 1000; - timestamp._frameOffset %= timestamp._frameRate; + ts._msecs += (ts._numberOfFrames / ts._framerate) * 1000; + ts._numberOfFrames %= ts._framerate; - return timestamp; + return ts; } Timestamp Timestamp::addMsecs(int ms) const { - Timestamp timestamp(*this); - timestamp._msecs += ms; - return timestamp; + Timestamp ts(*this); + ts._msecs += ms; + return ts; } -int Timestamp::frameDiff(const Timestamp &b) const { - assert(_frameRate == b._frameRate); +int Timestamp::frameDiff(const Timestamp &ts) const { + + int delta = 0; + if (_msecs != ts._msecs) + delta = (long(_msecs) - long(ts._msecs)) * _framerate / 1000; + + delta += _numberOfFrames; - int msecdelta = 0; - if (_msecs != b._msecs) - msecdelta = (long(_msecs) - long(b._msecs)) * _frameRate / 1000; + if (_framerate == ts._framerate) { + delta -= ts._numberOfFrames; + } else { + // We need to multiply by the quotient of the two framerates. + // We cancel the GCD in this fraction to reduce the risk of + // overflows. + const uint g = gcd(_framerate, ts._framerate); + const uint p = _framerate / g; + const uint q = ts._framerate / g; + + delta -= (ts._numberOfFrames * p + q/2) / q; + } - return msecdelta + _frameOffset - b._frameOffset; + return delta; } -int Timestamp::msecsDiff(const Timestamp &b) const { - return long(msecs()) - long(b.msecs()); +int Timestamp::msecsDiff(const Timestamp &ts) const { + return long(msecs()) - long(ts.msecs()); } uint32 Timestamp::msecs() const { - return _msecs + _frameOffset * 1000L / _frameRate; + return _msecs + _numberOfFrames * 1000L / _framerate; } |