ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

timestamp.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "audio/timestamp.h"
00024 #include "common/algorithm.h"
00025 
00026 namespace Audio {
00027 
00028 Timestamp::Timestamp(uint ms, uint fr) {
00029     assert(fr > 0);
00030 
00031     _secs = ms / 1000;
00032     _framerateFactor = 1000 / Common::gcd<uint>(1000, fr);
00033     _framerate = fr * _framerateFactor;
00034 
00035     // Note that _framerate is always divisible by 1000.
00036     _numFrames = (ms % 1000) * (_framerate / 1000);
00037 }
00038 
00039 Timestamp::Timestamp(uint s, uint frames, uint fr) {
00040     assert(fr > 0);
00041 
00042     _secs = s + (frames / fr);
00043     _framerateFactor = 1000 / Common::gcd<uint>(1000, fr);
00044     _framerate = fr * _framerateFactor;
00045     _numFrames = (frames % fr) * _framerateFactor;
00046 }
00047 
00048 Timestamp Timestamp::convertToFramerate(uint newFramerate) const {
00049     Timestamp ts(*this);
00050 
00051     if (ts.framerate() != newFramerate) {
00052         ts._framerateFactor = 1000 / Common::gcd<uint>(1000, newFramerate);
00053         ts._framerate = newFramerate * ts._framerateFactor;
00054 
00055         const uint g = Common::gcd(_framerate, ts._framerate);
00056         const uint p = _framerate / g;
00057         const uint q = ts._framerate / g;
00058 
00059         // Convert the frame offset to the new framerate.
00060         // We round to the nearest (as opposed to always
00061         // rounding down), to minimize rounding errors during
00062         // round trip conversions.
00063         ts._numFrames = (ts._numFrames * q + p/2) / p;
00064 
00065         ts.normalize();
00066     }
00067 
00068     return ts;
00069 }
00070 
00071 void Timestamp::normalize() {
00072     // Convert negative _numFrames values to positive ones by adjusting _secs
00073     if (_numFrames < 0) {
00074         int secsub = 1 + (-_numFrames / _framerate);
00075 
00076         _numFrames += _framerate * secsub;
00077         _secs -= secsub;
00078     }
00079 
00080     // Wrap around if necessary
00081     _secs += (_numFrames / _framerate);
00082     _numFrames %= _framerate;
00083 }
00084 
00085 bool Timestamp::operator==(const Timestamp &ts) const {
00086     return cmp(ts) == 0;
00087 }
00088 
00089 bool Timestamp::operator!=(const Timestamp &ts) const {
00090     return cmp(ts) != 0;
00091 }
00092 
00093 bool Timestamp::operator<(const Timestamp &ts) const {
00094     return cmp(ts) < 0;
00095 }
00096 
00097 bool Timestamp::operator<=(const Timestamp &ts) const {
00098     return cmp(ts) <= 0;
00099 }
00100 
00101 bool Timestamp::operator>(const Timestamp &ts) const {
00102     return cmp(ts) > 0;
00103 }
00104 
00105 bool Timestamp::operator>=(const Timestamp &ts) const {
00106     return cmp(ts) >= 0;
00107 }
00108 
00109 int Timestamp::cmp(const Timestamp &ts) const {
00110     int delta = _secs - ts._secs;
00111     if (!delta) {
00112         const uint g = Common::gcd(_framerate, ts._framerate);
00113         const uint p = _framerate / g;
00114         const uint q = ts._framerate / g;
00115 
00116         delta = (_numFrames * q - ts._numFrames * p);
00117     }
00118 
00119     return delta;
00120 }
00121 
00122 
00123 Timestamp Timestamp::addFrames(int frames) const {
00124     Timestamp ts(*this);
00125 
00126     // The frames are given in the original framerate, so we have to
00127     // adjust by _framerateFactor accordingly.
00128     ts._numFrames += frames * _framerateFactor;
00129     ts.normalize();
00130 
00131     return ts;
00132 }
00133 
00134 Timestamp Timestamp::addMsecs(int ms) const {
00135     Timestamp ts(*this);
00136     ts._secs += ms / 1000;
00137     // Add the remaining frames. Note that _framerate is always divisible by 1000.
00138     ts._numFrames += (ms % 1000) * (ts._framerate / 1000);
00139 
00140     ts.normalize();
00141 
00142     return ts;
00143 }
00144 
00145 void Timestamp::addIntern(const Timestamp &ts) {
00146     assert(_framerate == ts._framerate);
00147     _secs += ts._secs;
00148     _numFrames += ts._numFrames;
00149 
00150     normalize();
00151 }
00152 
00153 Timestamp Timestamp::operator-() const {
00154     Timestamp result(*this);
00155     result._secs = -_secs;
00156     result._numFrames = -_numFrames;
00157     result.normalize();
00158     return result;
00159 }
00160 
00161 Timestamp Timestamp::operator+(const Timestamp &ts) const {
00162     Timestamp result(*this);
00163     result.addIntern(ts);
00164     return result;
00165 }
00166 
00167 Timestamp Timestamp::operator-(const Timestamp &ts) const {
00168     Timestamp result(*this);
00169     result.addIntern(-ts);
00170     return result;
00171 }
00172 
00173 int Timestamp::frameDiff(const Timestamp &ts) const {
00174 
00175     int delta = 0;
00176     if (_secs != ts._secs)
00177         delta = (_secs - ts._secs) * _framerate;
00178 
00179     delta += _numFrames;
00180 
00181     if (_framerate == ts._framerate) {
00182         delta -= ts._numFrames;
00183     } else {
00184         // We need to multiply by the quotient of the two framerates.
00185         // We cancel the GCD in this fraction to reduce the risk of
00186         // overflows.
00187         const uint g = Common::gcd(_framerate, ts._framerate);
00188         const uint p = _framerate / g;
00189         const uint q = ts._framerate / g;
00190 
00191         delta -= ((long)ts._numFrames * p + q/2) / (long)q;
00192     }
00193 
00194     return delta / (int)_framerateFactor;
00195 }
00196 
00197 int Timestamp::msecsDiff(const Timestamp &ts) const {
00198     return msecs() - ts.msecs();
00199 }
00200 
00201 int Timestamp::msecs() const {
00202     // Note that _framerate is always divisible by 1000.
00203     return _secs * 1000 + _numFrames / (_framerate / 1000);
00204 }
00205 
00206 
00207 } // End of namespace Audio


Generated on Sat May 25 2019 05:00:55 for ResidualVM by doxygen 1.7.1
curved edge   curved edge