From e82295daa3749c92f76907417cdc1222b33dcf7f Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 27 May 2008 13:15:51 +0000 Subject: Implemented getTotalPlayTime for MP3InputStream. svn-id: r32322 --- sound/mp3.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'sound/mp3.cpp') diff --git a/sound/mp3.cpp b/sound/mp3.cpp index 72ed361926..706c9d90ec 100644 --- a/sound/mp3.cpp +++ b/sound/mp3.cpp @@ -63,6 +63,8 @@ protected: const mad_timer_t _endTime; mad_timer_t _totalTime; + int32 _totalPlayTime; + mad_stream _stream; mad_frame _frame; mad_synth _synth; @@ -87,6 +89,7 @@ public: bool endOfData() const { return _state == MP3_STATE_EOS; } bool isStereo() const { return MAD_NCHANNELS(&_frame.header) == 2; } int getRate() const { return _frame.header.samplerate; } + int32 getTotalPlayTime() const { return _totalPlayTime; } protected: void decodeMP3Data(); @@ -111,6 +114,70 @@ MP3InputStream::MP3InputStream(Common::SeekableReadStream *inStream, bool dispos // may read a few bytes beyond the end of the input buffer). memset(_buf + BUFFER_SIZE, 0, MAD_BUFFER_GUARD); + // 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_stream_init(&_stream); + mad_frame_init(&_frame); + + // Reset the stream data + _inStream->seek(0, SEEK_SET); + + // Update state + _state = MP3_STATE_READY; + + // Read the first few sample bytes + readMP3Data(); + + do { + // If necessary, load more data into the stream decoder + if (_stream.error == MAD_ERROR_BUFLEN) + readMP3Data(); + + while (_state == MP3_STATE_READY) { + _stream.error = MAD_ERROR_NONE; + + // Decode the next header. Note: mad_frame_decode would do this for us, too. + // However, for seeking we don't want to decode the full frame (else it would + // be far too slow). + if (mad_header_decode(&_frame.header, &_stream) == -1) { + if (_stream.error == MAD_ERROR_BUFLEN) { + break; // Read more data + } else if (MAD_RECOVERABLE(_stream.error)) { + debug(6, "MP3InputStream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream)); + continue; + } else { + warning("MP3InputStream: Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream)); + break; + } + } + + // Sum up the total playback time so far + mad_timer_add(&length, _frame.header.duration); + } + } while (_state != MP3_STATE_EOS); + + mad_synth_finish(&_synth); + mad_frame_finish(&_frame); + + // Reinit stream + _state = MP3_STATE_INIT; + } + + _totalPlayTime = mad_timer_count(length, MAD_UNITS_MILLISECONDS); + + if (numLoops) + _totalPlayTime *= numLoops; + else + _totalPlayTime = kUnknownPlayTime; + // Decode the first chunk of data. This is necessary so that _frame // is setup and isStereo() and getRate() return correct results. decodeMP3Data(); -- cgit v1.2.3 From 9d13d90d4f1dfc2bfd20a018fc1fe0405a108743 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 27 May 2008 13:28:47 +0000 Subject: - Cleanup code for FlacInputStream::getTotalPlayTime - Reset input stream position in MP3InputStream after calculating total play time svn-id: r32323 --- sound/mp3.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sound/mp3.cpp') diff --git a/sound/mp3.cpp b/sound/mp3.cpp index 706c9d90ec..eea725ce3a 100644 --- a/sound/mp3.cpp +++ b/sound/mp3.cpp @@ -169,11 +169,14 @@ MP3InputStream::MP3InputStream(Common::SeekableReadStream *inStream, bool dispos // Reinit stream _state = MP3_STATE_INIT; + + // Reset the stream data + _inStream->seek(0, SEEK_SET); } _totalPlayTime = mad_timer_count(length, MAD_UNITS_MILLISECONDS); - if (numLoops) + if (numLoops && mad_timer_sign(length) >= 0) _totalPlayTime *= numLoops; else _totalPlayTime = kUnknownPlayTime; -- cgit v1.2.3