aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorMax Horn2010-01-11 10:17:55 +0000
committerMax Horn2010-01-11 10:17:55 +0000
commit590481b12daf2287b37fdae757f8cca349912754 (patch)
tree9349d173d37353c567f9f5f971e861e91dd59b17 /sound
parent87cdc86580625abc12bbd4fde71764e4fd88a357 (diff)
downloadscummvm-rg350-590481b12daf2287b37fdae757f8cca349912754.tar.gz
scummvm-rg350-590481b12daf2287b37fdae757f8cca349912754.tar.bz2
scummvm-rg350-590481b12daf2287b37fdae757f8cca349912754.zip
Improve support for negative Timestamps, and add + and - operators
svn-id: r47244
Diffstat (limited to 'sound')
-rw-r--r--sound/audiostream.cpp8
-rw-r--r--sound/audiostream.h3
-rw-r--r--sound/timestamp.cpp130
-rw-r--r--sound/timestamp.h57
4 files changed, 142 insertions, 56 deletions
diff --git a/sound/audiostream.cpp b/sound/audiostream.cpp
index 6d72b83dd1..3fcfbe14c0 100644
--- a/sound/audiostream.cpp
+++ b/sound/audiostream.cpp
@@ -222,9 +222,8 @@ SubSeekableAudioStream::SubSeekableAudioStream(SeekableAudioStream *parent, cons
: _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 @@ bool SubSeekableAudioStream::seek(const Timestamp &where) {
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;
diff --git a/sound/audiostream.h b/sound/audiostream.h
index 1788561510..83bada8740 100644
--- a/sound/audiostream.h
+++ b/sound/audiostream.h
@@ -292,7 +292,8 @@ private:
bool _disposeAfterUse;
const Timestamp _start;
- Timestamp _pos, _length;
+ const Timestamp _length;
+ Timestamp _pos;
};
/**
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);
}
diff --git a/sound/timestamp.h b/sound/timestamp.h
index 7c3b81ca32..0b55135355 100644
--- a/sound/timestamp.h
+++ b/sound/timestamp.h
@@ -42,17 +42,21 @@ protected:
* 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 @@ protected:
* 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 @@ public:
* @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 @@ public:
* @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 @@ public:
*/
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 @@ public:
* 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 @@ public:
* 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 @@ public:
* 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);
};