aboutsummaryrefslogtreecommitdiff
path: root/sound/mp3.cpp
diff options
context:
space:
mode:
authorJohannes Schickel2010-01-07 14:22:24 +0000
committerJohannes Schickel2010-01-07 14:22:24 +0000
commitb80779824f8fdec1bfbb59115cbcc01d07914a0b (patch)
treeb6993e0bcf4468fde4e67d63508d8f2623c66f8a /sound/mp3.cpp
parent49e53ade008eb9cce1de00c45e41dbc6b52f8c49 (diff)
downloadscummvm-rg350-b80779824f8fdec1bfbb59115cbcc01d07914a0b.tar.gz
scummvm-rg350-b80779824f8fdec1bfbb59115cbcc01d07914a0b.tar.bz2
scummvm-rg350-b80779824f8fdec1bfbb59115cbcc01d07914a0b.zip
- Strip custom looping code out of FLAC, Vorbis and MP3 streams
- Adapt the legacy make*Stream factories to use the new AudioStream subclasses - Change return value of make*Stream back to AudioStream * svn-id: r47111
Diffstat (limited to 'sound/mp3.cpp')
-rw-r--r--sound/mp3.cpp117
1 files changed, 28 insertions, 89 deletions
diff --git a/sound/mp3.cpp b/sound/mp3.cpp
index 7c590b0ef9..2ee4637a83 100644
--- a/sound/mp3.cpp
+++ b/sound/mp3.cpp
@@ -59,16 +59,9 @@ protected:
uint _posInFrame;
State _state;
- const mad_timer_t _startTime;
- const mad_timer_t _endTime;
+ Timestamp _length;
mad_timer_t _totalTime;
- int32 _totalPlayTime; // Length of one loop iteration
- uint32 _length; // Total length of the MP3 stream
-
- uint _numLoops; ///< Number of loops to play
- uint _numPlayedLoops; ///< Number of loops which have been played
-
mad_stream _stream;
mad_frame _frame;
mad_synth _synth;
@@ -82,10 +75,7 @@ protected:
public:
MP3InputStream(Common::SeekableReadStream *inStream,
- bool dispose,
- mad_timer_t start = mad_timer_zero,
- mad_timer_t end = mad_timer_zero,
- uint numLoops = 1);
+ bool dispose);
~MP3InputStream();
int readBuffer(int16 *buffer, const int numSamples);
@@ -95,15 +85,7 @@ public:
int getRate() const { return _frame.header.samplerate; }
bool seek(const Timestamp &where);
- // TODO: Maybe we can have a more precise implementation of this
- Timestamp getLength() const { return Timestamp(_totalPlayTime, getRate()); }
-
- void setNumLoops(uint numLoops) {
- _numLoops = numLoops;
- _numPlayedLoops = 0;
- }
- uint getNumPlayedLoops() { return _numPlayedLoops; }
-
+ Timestamp getLength() const { return _length; }
protected:
void decodeMP3Data();
void readMP3Data();
@@ -113,19 +95,14 @@ protected:
void deinitStream();
};
-MP3InputStream::MP3InputStream(Common::SeekableReadStream *inStream, bool dispose, mad_timer_t start, mad_timer_t end, uint numLoops) :
+MP3InputStream::MP3InputStream(Common::SeekableReadStream *inStream, bool dispose) :
_inStream(inStream),
_disposeAfterUse(dispose),
- _numLoops(numLoops),
_posInFrame(0),
_state(MP3_STATE_INIT),
- _startTime(start),
- _endTime(end),
+ _length(0, 1000),
_totalTime(mad_timer_zero) {
- // Make sure that either start < end, or end is zero (indicating "play until end")
- assert(mad_timer_compare(_startTime, _endTime) < 0 || mad_timer_sign(_endTime) == 0);
-
// The MAD_BUFFER_GUARD must always contain zeros (the reason
// for this is that the Layer III Huffman decoder of libMAD
// may read a few bytes beyond the end of the input buffer).
@@ -137,33 +114,13 @@ MP3InputStream::MP3InputStream(Common::SeekableReadStream *inStream, bool dispos
while (_state != MP3_STATE_EOS)
readHeader();
- _length = mad_timer_count(_totalTime, MAD_UNITS_MILLISECONDS);
+ _length = Timestamp(mad_timer_count(_totalTime, MAD_UNITS_MILLISECONDS), getRate());
deinitStream();
// Reinit stream
_state = MP3_STATE_INIT;
- // Calculate play time
- mad_timer_t length;
-
- mad_timer_set(&length, 0, 0, 1000);
- mad_timer_add(&length, start);
- mad_timer_negate(&length);
-
- if (mad_timer_sign(end) != 0) {
- mad_timer_add(&length, end);
- } else {
- mad_timer_set(&_totalTime, _length / 1000, _length % 1000, 1000);
- mad_timer_add(&length, _totalTime);
- _totalTime = mad_timer_zero;
- }
-
- _totalPlayTime = mad_timer_count(length, MAD_UNITS_MILLISECONDS);
-
- if (mad_timer_sign(length) < 0)
- _totalPlayTime = 0;
-
// Decode the first chunk of data. This is necessary so that _frame
// is setup and isStereo() and getRate() return correct results.
decodeMP3Data();
@@ -189,18 +146,9 @@ void MP3InputStream::decodeMP3Data() {
readMP3Data();
while (_state == MP3_STATE_READY) {
+ // TODO: Do we need to use readHeader, when we do not do any seeking here?
readHeader();
- // If we have not yet reached the start point, skip to the next frame
- if (mad_timer_compare(_totalTime, _startTime) < 0)
- continue;
-
- // If an end time is specified and we are past it, stop
- if (mad_timer_sign(_endTime) > 0 && mad_timer_compare(_totalTime, _endTime) >= 0) {
- _state = MP3_STATE_EOS;
- break;
- }
-
// Decode the next frame
if (mad_frame_decode(&_frame, &_stream) == -1) {
if (_stream.error == MAD_ERROR_BUFLEN) {
@@ -222,18 +170,6 @@ void MP3InputStream::decodeMP3Data() {
_posInFrame = 0;
break;
}
-
- if (_state == MP3_STATE_EOS) {
- ++_numPlayedLoops;
- // If looping is on and there are loops left, rewind to the start
- if (!_numLoops || _numPlayedLoops < _numLoops) {
- deinitStream();
-
- // Reset the decoder state to indicate we should start over
- _state = MP3_STATE_INIT;
- }
- }
-
} while (_state != MP3_STATE_EOS && _stream.error == MAD_ERROR_BUFLEN);
if (_stream.error != MAD_ERROR_NONE)
@@ -271,15 +207,15 @@ void MP3InputStream::readMP3Data() {
}
bool MP3InputStream::seek(const Timestamp &where) {
- const uint32 time = where.msecs();
-
- if (time == _length) {
+ if (where == _length) {
_state = MP3_STATE_EOS;
return true;
- } else if (time > _length) {
+ } else if (where > _length) {
return false;
}
+ const uint32 time = where.msecs();
+
mad_timer_t destination;
mad_timer_set(&destination, time / 1000, time % 1000, 1000);
@@ -402,33 +338,36 @@ int MP3InputStream::readBuffer(int16 *buffer, const int numSamples) {
#pragma mark --- MP3 factory functions ---
#pragma mark -
-SeekableAudioStream *makeMP3Stream(
+AudioStream *makeMP3Stream(
Common::SeekableReadStream *stream,
bool disposeAfterUse,
uint32 startTime,
uint32 duration,
uint numLoops) {
- mad_timer_t start;
- mad_timer_t end;
-
- // Both startTime and duration are given in milliseconds.
- // Calculate the appropriate mad_timer_t values from them.
- mad_timer_set(&start, startTime / 1000, startTime % 1000, 1000);
- if (duration == 0) {
- end = mad_timer_zero;
- } else {
- int endTime = startTime + duration;
- mad_timer_set(&end, endTime / 1000, endTime % 1000, 1000);
+ SeekableAudioStream *mp3 = new MP3InputStream(stream, disposeAfterUse);
+ assert(mp3);
+
+ if (startTime || duration) {
+ Timestamp start(startTime, 1000), end(startTime + duration, 1000);
+
+ if (!duration)
+ end = mp3->getLength();
+
+ mp3 = new SubSeekableAudioStream(mp3, start, end);
+ assert(mp3);
}
- return new MP3InputStream(stream, disposeAfterUse, start, end, numLoops);
+ if (numLoops)
+ return new LoopingAudioStream(mp3, numLoops);
+ else
+ return mp3;
}
SeekableAudioStream *makeMP3Stream(
Common::SeekableReadStream *stream,
bool disposeAfterUse) {
- return makeMP3Stream(stream, disposeAfterUse, 0, 0, 1);
+ return new MP3InputStream(stream, disposeAfterUse);
}
} // End of namespace Audio