[Scummvm-cvs-logs] SF.net SVN: scummvm:[47244] scummvm/trunk

fingolfin at users.sourceforge.net fingolfin at users.sourceforge.net
Mon Jan 11 11:17:55 CET 2010


Revision: 47244
          http://scummvm.svn.sourceforge.net/scummvm/?rev=47244&view=rev
Author:   fingolfin
Date:     2010-01-11 10:17:55 +0000 (Mon, 11 Jan 2010)

Log Message:
-----------
Improve support for negative Timestamps, and add + and - operators

Modified Paths:
--------------
    scummvm/trunk/engines/made/scriptfuncs.cpp
    scummvm/trunk/sound/audiostream.cpp
    scummvm/trunk/sound/audiostream.h
    scummvm/trunk/sound/timestamp.cpp
    scummvm/trunk/sound/timestamp.h
    scummvm/trunk/test/sound/timestamp.h

Modified: scummvm/trunk/engines/made/scriptfuncs.cpp
===================================================================
--- scummvm/trunk/engines/made/scriptfuncs.cpp	2010-01-11 10:17:23 UTC (rev 47243)
+++ scummvm/trunk/engines/made/scriptfuncs.cpp	2010-01-11 10:17:55 UTC (rev 47244)
@@ -653,7 +653,7 @@
 		while (_vm->_soundEnergyIndex < _vm->_soundEnergyArray->size()) {
 			SoundEnergyItem *soundEnergyItem = &(*_vm->_soundEnergyArray)[_vm->_soundEnergyIndex];
 			const Audio::Timestamp ts = _vm->_mixer->getElapsedTime(_audioStreamHandle);
-			if (ts.convertToFramerate(_vm->_soundRate).totalNumberOfFrames() < soundEnergyItem->position) {
+			if (ts.convertToFramerate(_vm->_soundRate).totalNumberOfFrames() < (int)soundEnergyItem->position) {
 				result = soundEnergyItem->energy;
 				break;
 			}

Modified: scummvm/trunk/sound/audiostream.cpp
===================================================================
--- scummvm/trunk/sound/audiostream.cpp	2010-01-11 10:17:23 UTC (rev 47243)
+++ scummvm/trunk/sound/audiostream.cpp	2010-01-11 10:17:55 UTC (rev 47244)
@@ -222,9 +222,8 @@
     : _parent(parent), _disposeAfterUse(disposeAfterUse),
       _start(start.convertToFramerate(getRate())),
        _pos(0, getRate() * (isStereo() ? 2 : 1)),
-      _length(end.convertToFramerate(getRate())) {
-	// TODO: This really looks like Timestamp::operator-
-	_length = Timestamp(_length.secs() - _start.secs(), _length.numberOfFrames() - _start.numberOfFrames(), getRate());
+      _length((start - end).convertToFramerate(getRate())) {
+
 	_parent->seek(_start);
 }
 
@@ -247,8 +246,7 @@
 		return false;
 	}
 
-	// TODO: This really looks like Timestamp::operator+
-	if (_parent->seek(Timestamp(_pos.secs() + _start.secs(), _pos.numberOfFrames() + _start.numberOfFrames(), getRate()))) {
+	if (_parent->seek(_pos + _start)) {
 		return true;
 	} else {
 		_pos = _length;

Modified: scummvm/trunk/sound/audiostream.h
===================================================================
--- scummvm/trunk/sound/audiostream.h	2010-01-11 10:17:23 UTC (rev 47243)
+++ scummvm/trunk/sound/audiostream.h	2010-01-11 10:17:55 UTC (rev 47244)
@@ -292,7 +292,8 @@
 	bool _disposeAfterUse;
 
 	const Timestamp _start;
-	Timestamp _pos, _length;
+	const Timestamp _length;
+	Timestamp _pos;
 };
 
 /**

Modified: scummvm/trunk/sound/timestamp.cpp
===================================================================
--- scummvm/trunk/sound/timestamp.cpp	2010-01-11 10:17:23 UTC (rev 47243)
+++ scummvm/trunk/sound/timestamp.cpp	2010-01-11 10:17:55 UTC (rev 47244)
@@ -36,7 +36,7 @@
 	return b;
 }
 
-Timestamp::Timestamp(uint32 ms, int fr) {
+Timestamp::Timestamp(uint ms, uint fr) {
 	assert(fr > 0);
 
 	_secs = ms / 1000;
@@ -44,20 +44,21 @@
 	_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 @@
 		// 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 @@
 		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 @@
 
 	// 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);
 
-	if (_numberOfFrames < 0) {
-		int secsub = 1 + (-_numberOfFrames / _framerate);
+	ts.normalize();
 
-		_numberOfFrames += _framerate * secsub;
-		_secs -= secsub;
+	return ts;
+}
+
+void Timestamp::addIntern(const Timestamp &ts) {
+	_secs += ts._secs;
+
+	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 @@
 		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);
 }
 
 

Modified: scummvm/trunk/sound/timestamp.h
===================================================================
--- scummvm/trunk/sound/timestamp.h	2010-01-11 10:17:23 UTC (rev 47243)
+++ scummvm/trunk/sound/timestamp.h	2010-01-11 10:17:55 UTC (rev 47244)
@@ -42,17 +42,21 @@
 	 * The seconds part of this timestamp.
 	 * The total time in seconds represented by this timestamp can be
 	 * computed as follows:
-	 *   _secs + (double)_numberOfFrames / _framerate
+	 *   _secs + (double)_numFrames / _framerate
 	 */
-	uint _secs;
+	int _secs;
 
 	/**
 	 * The number of frames which together with _secs encodes
 	 * the timestamp. The total number of frames represented
 	 * by this timestamp is computed as follows:
-	 *   _numberOfFrames + _secs * _framerate
+	 *   _numFrames + _secs * _framerate
+	 *
+	 * This is always a value greater or equal to zero.
+	 * The only reason this is an int and not an uint is to
+	 * allow intermediate negative values.
 	 */
-	int _numberOfFrames;
+	int _numFrames;
 
 	/**
 	 * The internal framerate, i.e. the number of frames per second.
@@ -61,13 +65,13 @@
 	 * This way, we ensure that we can store both frames and
 	 * milliseconds without any rounding losses.
 	 */
-	int _framerate;
+	uint _framerate;
 
 	/**
 	 * Factor by which the original framerate specified by the client
 	 * code was multipled to obtain the internal _framerate value.
 	 */
-	int _framerateFactor;
+	uint _framerateFactor;
 
 public:
 	/**
@@ -75,7 +79,7 @@
 	 * @param msecs     starting time in milliseconds
 	 * @param framerate number of frames per second (must be > 0)
 	 */
-	Timestamp(uint32 msecs, int framerate);
+	Timestamp(uint msecs, uint framerate);
 
 	/**
 	 * Set up a timestamp with a given time, frames and framerate.
@@ -83,14 +87,14 @@
 	 * @param frames    starting frames
 	 * @param framerate number of frames per second (must be > 0)
 	 */
-	Timestamp(uint secs, int frames, int framerate);
+	Timestamp(uint secs, uint frames, uint framerate);
 
 	/**
 	 * 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;
+	Timestamp convertToFramerate(uint newFramerate) const;
 
 	/**
 	 * Check whether to timestamps describe the exact same moment
@@ -118,6 +122,16 @@
 	 */
 	Timestamp addMsecs(int msecs) const;
 
+
+	// unary minus
+	Timestamp operator-() const;
+
+	Timestamp operator+(const Timestamp &ts) const;
+	Timestamp operator-(const Timestamp &ts) const;
+
+//	Timestamp &operator+=(const Timestamp &ts);
+//	Timestamp &operator-=(const Timestamp &ts);
+
 	/**
 	 * Computes the number of frames between this timestamp and ts.
 	 * The frames are with respect to the framerate used by this
@@ -132,13 +146,13 @@
 	 * Return the time in milliseconds described by this timestamp,
 	 * rounded down.
 	 */
-	uint32 msecs() const;
+	int msecs() const;
 
 	/**
 	 * Return the time in seconds described by this timestamp,
 	 * rounded down.
 	 */
-	inline uint32 secs() const {
+	inline int secs() const {
 		return _secs;
 	}
 
@@ -146,7 +160,7 @@
 	 * Return the time in frames described by this timestamp.
 	 */
 	inline int totalNumberOfFrames() const {
-		return _numberOfFrames / _framerateFactor + _secs * (_framerate / _framerateFactor);
+		return _numFrames / (int)_framerateFactor + _secs * (int)(_framerate / _framerateFactor);
 	}
 
 	/**
@@ -155,17 +169,30 @@
 	 * This method returns the latter number.
 	 */
 	inline int numberOfFrames() const {
-		return _numberOfFrames / _framerateFactor;
+		return _numFrames / (int)_framerateFactor;
 	}
 
 	/** Return the framerate used by this timestamp. */
-	inline int framerate() const { return _framerate / _framerateFactor; }
+	inline uint framerate() const { return _framerate / _framerateFactor; }
 
 protected:
 
+	/**
+	 * Compare this timestamp to another one and return
+	 * a value similar to strcmp.
+	 */
 	int cmp(const Timestamp &ts) const;
 
-	void addFramesIntern(int frames);
+	/**
+	 * Normalize this timestamp by making _numFrames non-negative
+	 * and reducing it modulo _framerate.
+	 */
+	void normalize();
+
+	/**
+	 * Add another timestamp to this one and normalize the result.
+	 */
+	void addIntern(const Timestamp &ts);
 };
 
 

Modified: scummvm/trunk/test/sound/timestamp.h
===================================================================
--- scummvm/trunk/test/sound/timestamp.h	2010-01-11 10:17:23 UTC (rev 47243)
+++ scummvm/trunk/test/sound/timestamp.h	2010-01-11 10:17:55 UTC (rev 47244)
@@ -59,24 +59,27 @@
 		const Audio::Timestamp a(1234, 60);
 		const Audio::Timestamp b(5678, 60);
 
-		TS_ASSERT_EQUALS(a.msecs(), (uint32)1234);
-		TS_ASSERT_EQUALS(b.msecs(), (uint32)5678);
+		TS_ASSERT_EQUALS(a.msecs(), 1234);
+		TS_ASSERT_EQUALS(b.msecs(), 5678);
 
+		TS_ASSERT_EQUALS(a.secs(), 1);
+		TS_ASSERT_EQUALS(b.secs(), 5);
+
 		TS_ASSERT_EQUALS(a.msecsDiff(b), 1234 - 5678);
 		TS_ASSERT_EQUALS(b.msecsDiff(a), 5678 - 1234);
 
 		TS_ASSERT_EQUALS(a.frameDiff(b), (1234 - 5678) * 60 / 1000);
 		TS_ASSERT_EQUALS(b.frameDiff(a), (5678 - 1234) * 60 / 1000);
 
-		TS_ASSERT_EQUALS(a.addFrames(1).msecs(), (uint32)(1234 + 1000 * 1/60));
-		TS_ASSERT_EQUALS(a.addFrames(59).msecs(), (uint32)(1234 + 1000 * 59/60));
-		TS_ASSERT_EQUALS(a.addFrames(60).msecs(), (uint32)(1234 + 1000 * 60/60));
+		TS_ASSERT_EQUALS(a.addFrames(1).msecs(), (1234 + 1000 * 1/60));
+		TS_ASSERT_EQUALS(a.addFrames(59).msecs(), (1234 + 1000 * 59/60));
+		TS_ASSERT_EQUALS(a.addFrames(60).msecs(), (1234 + 1000 * 60/60));
 
 		// As soon as we go back even by only one frame, the msec value
 		// has to drop by at least one.
-		TS_ASSERT_EQUALS(a.addFrames(-1).msecs(), (uint32)(1234 - 1000 * 1/60 - 1));
-		TS_ASSERT_EQUALS(a.addFrames(-59).msecs(), (uint32)(1234 - 1000 * 59/60 - 1));
-		TS_ASSERT_EQUALS(a.addFrames(-60).msecs(), (uint32)(1234 - 1000 * 60/60));
+		TS_ASSERT_EQUALS(a.addFrames(-1).msecs(), (1234 - 1000 * 1/60 - 1));
+		TS_ASSERT_EQUALS(a.addFrames(-59).msecs(), (1234 - 1000 * 59/60 - 1));
+		TS_ASSERT_EQUALS(a.addFrames(-60).msecs(), (1234 - 1000 * 60/60));
 	}
 
 	void test_more_add_diff() {
@@ -88,7 +91,39 @@
 		}
 	}
 
+	void test_negate() {
+		const Audio::Timestamp a = Audio::Timestamp(0, 60).addFrames(13);
+		const Audio::Timestamp b = -a;
 
+		TS_ASSERT_EQUALS(a.msecs() + 1, -b.msecs());
+		TS_ASSERT_EQUALS(a.totalNumberOfFrames(), -b.totalNumberOfFrames());
+		TS_ASSERT_EQUALS(a.numberOfFrames(), 60 - b.numberOfFrames());
+	}
+
+	void test_add_sub() {
+		const Audio::Timestamp a = Audio::Timestamp(0, 60).addFrames(13);
+		const Audio::Timestamp b = -a;
+		const Audio::Timestamp c = Audio::Timestamp(0, 60).addFrames(20);
+
+		TS_ASSERT_EQUALS((a+a).secs(), 0);
+		TS_ASSERT_EQUALS((a+a).numberOfFrames(), 2*13);
+
+		TS_ASSERT_EQUALS((a+b).secs(), 0);
+		TS_ASSERT_EQUALS((a+b).numberOfFrames(), 0);
+
+		TS_ASSERT_EQUALS((a+c).secs(), 0);
+		TS_ASSERT_EQUALS((a+c).numberOfFrames(), 13+20);
+
+		TS_ASSERT_EQUALS((a-a).secs(), 0);
+		TS_ASSERT_EQUALS((a-a).numberOfFrames(), 0);
+
+		TS_ASSERT_EQUALS((a-b).secs(), 0);
+		TS_ASSERT_EQUALS((a-b).numberOfFrames(), 2*13);
+
+		TS_ASSERT_EQUALS((a-c).secs(), -1);
+		TS_ASSERT_EQUALS((a-c).numberOfFrames(), 60 + (13 - 20));
+	}
+
 	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);
@@ -188,18 +223,18 @@
 		const Audio::Timestamp b = a.addFrames(11025);
 		const Audio::Timestamp c = Audio::Timestamp(1500, 22050);
 
-		TS_ASSERT_EQUALS(a.secs(), (uint32)0);
-		TS_ASSERT_EQUALS(a.msecs(), (uint32)0);
+		TS_ASSERT_EQUALS(a.secs(), 0);
+		TS_ASSERT_EQUALS(a.msecs(), 0);
 		TS_ASSERT_EQUALS(a.numberOfFrames(), 0);
 		TS_ASSERT_EQUALS(a.totalNumberOfFrames(), 0);
 
-		TS_ASSERT_EQUALS(b.secs(), (uint32)0);
-		TS_ASSERT_EQUALS(b.msecs(), (uint32)500);
+		TS_ASSERT_EQUALS(b.secs(), 0);
+		TS_ASSERT_EQUALS(b.msecs(), 500);
 		TS_ASSERT_EQUALS(b.numberOfFrames(), 11025);
 		TS_ASSERT_EQUALS(b.totalNumberOfFrames(), 11025);
 
-		TS_ASSERT_EQUALS(c.secs(), (uint32)1);
-		TS_ASSERT_EQUALS(c.msecs(), (uint32)1500);
+		TS_ASSERT_EQUALS(c.secs(), 1);
+		TS_ASSERT_EQUALS(c.msecs(), 1500);
 		TS_ASSERT_EQUALS(c.numberOfFrames(), 11025);
 		TS_ASSERT_EQUALS(c.totalNumberOfFrames(), 33075);
 	}


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