[Scummvm-cvs-logs] SF.net SVN: scummvm:[46994] scummvm/trunk
fingolfin at users.sourceforge.net
fingolfin at users.sourceforge.net
Mon Jan 4 23:48:28 CET 2010
Revision: 46994
http://scummvm.svn.sourceforge.net/scummvm/?rev=46994&view=rev
Author: fingolfin
Date: 2010-01-04 22:48:28 +0000 (Mon, 04 Jan 2010)
Log Message:
-----------
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
Modified Paths:
--------------
scummvm/trunk/sound/timestamp.cpp
scummvm/trunk/sound/timestamp.h
scummvm/trunk/test/sound/timestamp.h
Modified: scummvm/trunk/sound/timestamp.cpp
===================================================================
--- scummvm/trunk/sound/timestamp.cpp 2010-01-04 22:23:45 UTC (rev 46993)
+++ scummvm/trunk/sound/timestamp.cpp 2010-01-04 22:48:28 UTC (rev 46994)
@@ -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 msecdelta = 0;
- if (_msecs != b._msecs)
- msecdelta = (long(_msecs) - long(b._msecs)) * _frameRate / 1000;
+ int delta = 0;
+ if (_msecs != ts._msecs)
+ delta = (long(_msecs) - long(ts._msecs)) * _framerate / 1000;
- return msecdelta + _frameOffset - b._frameOffset;
+ delta += _numberOfFrames;
+
+ 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 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;
}
Modified: scummvm/trunk/sound/timestamp.h
===================================================================
--- scummvm/trunk/sound/timestamp.h 2010-01-04 22:23:45 UTC (rev 46993)
+++ scummvm/trunk/sound/timestamp.h 2010-01-04 22:48:28 UTC (rev 46994)
@@ -38,33 +38,77 @@
*/
class Timestamp {
protected:
- uint32 _msecs;
- int _frameRate;
- int _frameOffset;
- /* Total time: msecs + frame_offset/frame_rate */
+ /**
+ * The millisecond part of this timestamp.
+ * The total time represented by this timestamp is
+ * computed as follows:
+ * _msecs + 1000 * _numberOfFrames / _framerate
+ */
+ uint _msecs;
+ /**
+ * The number of frames which together with _msecs encodes
+ * the timestamp. The total number of frames represented
+ * by this timestamp is computed as follows:
+ * _numberOfFrames + _msecs * _framerate / 1000
+ */
+ int _numberOfFrames;
+
+ /** The framerate, i.e. the number of frames per second. */
+ int _framerate;
+
public:
/**
* Set up a timestamp with a given time and framerate.
- * @param msecs staring time in milliseconds
- * @param frameRate number of frames per second (must be > 0)
+ * @param msecs starting time in milliseconds
+ * @param framerate number of frames per second (must be > 0)
*/
- Timestamp(uint32 msecs, int frameRate);
+ Timestamp(uint32 msecs, int framerate);
- /** Adds a number of frames to a timestamp. */
+ /**
+ * Return a timestamp which represents as closely as possible
+ * the point in time describes by this timestamp, but with
+ * a different framerate.
+ */
+ Timestamp convertToFramerate(int newFramerate) const;
+
+ bool operator==(const Timestamp &ts) const;
+ bool operator!=(const Timestamp &ts) const;
+// bool operator<(const Timestamp &ts) const;
+// bool operator<=(const Timestamp &ts) const;
+// bool operator>(const Timestamp &ts) const;
+// bool operator>=(const Timestamp &ts) const;
+
+ /**
+ * Returns a new timestamp, which corresponds to the time encoded
+ * by this timestamp with the given number of frames added.
+ */
Timestamp addFrames(int frames) const;
- /** Adds a number of milliseconds to a timestamp. */
+ /**
+ * Returns a new timestamp, which corresponds to the time encoded
+ * by this timestamp with the given number of milliseconds added.
+ */
Timestamp addMsecs(int ms) const;
- /** Computes the difference (# of frames) between this timestamp and b. */
- int frameDiff(const Timestamp &b) const;
+ /**
+ * Computes the number of frames between this timestamp and ts.
+ * The frames are with respect to the framerate used by this
+ * Timestamp (which may differ from the framerate used by ts).
+ */
+ int frameDiff(const Timestamp &ts) const;
- /** Computes the difference (# of milliseconds) between this timestamp and b. */
- int msecsDiff(const Timestamp &b) const;
+ /** Computes the number off milliseconds between this timestamp and ts. */
+ int msecsDiff(const Timestamp &ts) const;
- /** Determines the time in milliseconds described by this timestamp. */
+ /**
+ * Determines the time in milliseconds described by this timestamp,
+ * rounded down.
+ */
uint32 msecs() const;
+
+ /** Return the framerate used by this timestamp. */
+ int getFramerate() const { return _framerate; }
};
Modified: scummvm/trunk/test/sound/timestamp.h
===================================================================
--- scummvm/trunk/test/sound/timestamp.h 2010-01-04 22:23:45 UTC (rev 46993)
+++ scummvm/trunk/test/sound/timestamp.h 2010-01-04 22:48:28 UTC (rev 46994)
@@ -47,7 +47,6 @@
TS_ASSERT_EQUALS(a.addFrames(-60).msecs(), (uint32)(1234 - 1000 * 60/60));
}
-
void test_more_add_diff() {
const Audio::Timestamp c(10002, 1000);
@@ -56,4 +55,33 @@
TS_ASSERT_EQUALS(v, i);
}
}
+
+
+ void test_diff_with_conversion() {
+ const Audio::Timestamp a = Audio::Timestamp(10, 1000).addFrames(20);
+ const Audio::Timestamp b = Audio::Timestamp(10, 1000/5).addFrames(20/5);
+ const Audio::Timestamp c = Audio::Timestamp(10, 1000*2).addFrames(20*2);
+
+ TS_ASSERT_EQUALS(a.frameDiff(a), 0);
+ TS_ASSERT_EQUALS(a.frameDiff(b), 0);
+ TS_ASSERT_EQUALS(a.frameDiff(c), 0);
+
+ TS_ASSERT_EQUALS(b.frameDiff(a), 0);
+ TS_ASSERT_EQUALS(b.frameDiff(b), 0);
+ TS_ASSERT_EQUALS(b.frameDiff(c), 0);
+
+ TS_ASSERT_EQUALS(c.frameDiff(a), 0);
+ TS_ASSERT_EQUALS(c.frameDiff(b), 0);
+ TS_ASSERT_EQUALS(c.frameDiff(c), 0);
+ }
+
+
+ void test_convert() {
+ const Audio::Timestamp a = Audio::Timestamp(10, 1000).addFrames(20);
+ const Audio::Timestamp b = Audio::Timestamp(10, 1000/5).addFrames(20/5);
+ const Audio::Timestamp c = Audio::Timestamp(10, 1000*2).addFrames(20*2);
+
+ TS_ASSERT_EQUALS(a.convertToFramerate(1000/5), b);
+ TS_ASSERT_EQUALS(a.convertToFramerate(1000*2), c);
+ }
};
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list