diff options
Diffstat (limited to 'sound/timestamp.cpp')
-rw-r--r-- | sound/timestamp.cpp | 130 |
1 files changed, 95 insertions, 35 deletions
diff --git a/sound/timestamp.cpp b/sound/timestamp.cpp index 6157d87d32..f705ff4521 100644 --- a/sound/timestamp.cpp +++ b/sound/timestamp.cpp @@ -36,7 +36,7 @@ static uint gcd(uint a, uint b) { return b; } -Timestamp::Timestamp(uint32 ms, int fr) { +Timestamp::Timestamp(uint ms, uint fr) { assert(fr > 0); _secs = ms / 1000; @@ -44,20 +44,21 @@ Timestamp::Timestamp(uint32 ms, int fr) { _framerate = fr * _framerateFactor; // Note that _framerate is always divisible by 1000. - _numberOfFrames = (ms % 1000) * (_framerate / 1000); + _numFrames = (ms % 1000) * (_framerate / 1000); } -Timestamp::Timestamp(uint s, int frames, int fr) { +Timestamp::Timestamp(uint s, uint frames, uint fr) { assert(fr > 0); _secs = s; _framerateFactor = 1000 / gcd(1000, fr); _framerate = fr * _framerateFactor; - _numberOfFrames = 0; - addFramesIntern(frames * _framerateFactor); + _numFrames = frames * _framerateFactor; + + normalize(); } -Timestamp Timestamp::convertToFramerate(int newFramerate) const { +Timestamp Timestamp::convertToFramerate(uint newFramerate) const { Timestamp ts(*this); if (ts.framerate() != newFramerate) { @@ -72,15 +73,28 @@ Timestamp Timestamp::convertToFramerate(int newFramerate) const { // 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._numFrames = (ts._numFrames * q + p/2) / p; - ts._secs += (ts._numberOfFrames / ts._framerate); - ts._numberOfFrames %= ts._framerate; + ts.normalize(); } return ts; } +void Timestamp::normalize() { + // Convert negative _numFrames values to positive ones by adjusting _secs + if (_numFrames < 0) { + int secsub = 1 + (-_numFrames / _framerate); + + _numFrames += _framerate * secsub; + _secs -= secsub; + } + + // Wrap around if necessary + _secs += (_numFrames / _framerate); + _numFrames %= _framerate; +} + bool Timestamp::operator==(const Timestamp &ts) const { return cmp(ts) == 0; } @@ -112,7 +126,7 @@ int Timestamp::cmp(const Timestamp &ts) const { const uint p = _framerate / g; const uint q = ts._framerate / g; - delta = (_numberOfFrames * q - ts._numberOfFrames * p); + delta = (_numFrames * q - ts._numFrames * p); } return delta; @@ -124,45 +138,91 @@ Timestamp Timestamp::addFrames(int frames) const { // The frames are given in the original framerate, so we have to // adjust by _framerateFactor accordingly. - ts.addFramesIntern(frames * _framerateFactor); + ts._numFrames += frames * _framerateFactor; + ts.normalize(); return ts; } -void Timestamp::addFramesIntern(int frames) { - _numberOfFrames += frames; +Timestamp Timestamp::addMsecs(int ms) const { + Timestamp ts(*this); + ts._secs += ms / 1000; + // Add the remaining frames. Note that _framerate is always divisible by 1000. + ts._numFrames += (ms % 1000) * (ts._framerate / 1000); + + ts.normalize(); + + return ts; +} - if (_numberOfFrames < 0) { - int secsub = 1 + (-_numberOfFrames / _framerate); +void Timestamp::addIntern(const Timestamp &ts) { + _secs += ts._secs; - _numberOfFrames += _framerate * secsub; - _secs -= secsub; + if (_framerate == ts._framerate) { + _numFrames += ts._numFrames; + } 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; + + _framerate *= q; + _numFrames = _numFrames * q + ts._numFrames * p; } - // Wrap around if necessary - _secs += (_numberOfFrames / _framerate); - _numberOfFrames %= _framerate; + normalize(); } -Timestamp Timestamp::addMsecs(int ms) const { - assert(ms >= 0); - Timestamp ts(*this); - ts._secs += ms / 1000; - // Add the remaining frames. Note that _framerate is always divisible by 1000. - ts.addFramesIntern((ms % 1000) * (ts._framerate / 1000)); - return ts; +Timestamp Timestamp::operator-() const { + Timestamp result(*this); + result._secs = -_secs; + result._numFrames = -_numFrames; + result.normalize(); + return result; +} + +Timestamp Timestamp::operator+(const Timestamp &ts) const { + Timestamp result(*this); + result.addIntern(ts); + return result; +} + +Timestamp Timestamp::operator-(const Timestamp &ts) const { + Timestamp result(*this); + result.addIntern(-ts); + return result; +} + +/* +Timestamp &Timestamp::operator+=(const Timestamp &ts) { + addIntern(ts); + return *this; +} + +Timestamp &Timestamp::operator-=(const Timestamp &ts) { + addIntern(-ts); + return *this; +} +*/ + +/* +int Timestamp::frameDiff(const Timestamp &ts) const { + return (*this - ts).totalNumberOfFrames(); } +*/ int Timestamp::frameDiff(const Timestamp &ts) const { int delta = 0; if (_secs != ts._secs) - delta = (long(_secs) - long(ts._secs)) * _framerate; + delta = (_secs - ts._secs) * _framerate; - delta += _numberOfFrames; + delta += _numFrames; if (_framerate == ts._framerate) { - delta -= ts._numberOfFrames; + delta -= ts._numFrames; } else { // We need to multiply by the quotient of the two framerates. // We cancel the GCD in this fraction to reduce the risk of @@ -171,19 +231,19 @@ int Timestamp::frameDiff(const Timestamp &ts) const { const uint p = _framerate / g; const uint q = ts._framerate / g; - delta -= (ts._numberOfFrames * p + q/2) / q; + delta -= ((long)ts._numFrames * p + q/2) / (long)q; } - return delta / _framerateFactor; + return delta / (int)_framerateFactor; } int Timestamp::msecsDiff(const Timestamp &ts) const { - return long(msecs()) - long(ts.msecs()); + return msecs() - ts.msecs(); } -uint32 Timestamp::msecs() const { +int Timestamp::msecs() const { // Note that _framerate is always divisible by 1000. - return _secs * 1000 + _numberOfFrames / (_framerate / 1000); + return _secs * 1000 + _numFrames / (_framerate / 1000); } |