[Scummvm-cvs-logs] SF.net SVN: scummvm: [26392] scummvm/trunk/sound/mp3.cpp

fingolfin at users.sourceforge.net fingolfin at users.sourceforge.net
Fri Apr 6 19:16:50 CEST 2007


Revision: 26392
          http://scummvm.svn.sourceforge.net/scummvm/?rev=26392&view=rev
Author:   fingolfin
Date:     2007-04-06 10:16:49 -0700 (Fri, 06 Apr 2007)

Log Message:
-----------
Changed the MP3 playback code again, this time hopefully fixing the problems in the MI Amiga demo

Modified Paths:
--------------
    scummvm/trunk/sound/mp3.cpp

Modified: scummvm/trunk/sound/mp3.cpp
===================================================================
--- scummvm/trunk/sound/mp3.cpp	2007-04-06 17:08:23 UTC (rev 26391)
+++ scummvm/trunk/sound/mp3.cpp	2007-04-06 17:16:49 UTC (rev 26392)
@@ -43,12 +43,18 @@
 
 class MP3InputStream : public AudioStream {
 protected:
+	enum State {
+		MP3_STATE_INIT,	// Need to init the decoder
+		MP3_STATE_READY,	// ready for processing data
+		MP3_STATE_EOS		// end of data reached (may need to loop)
+	};
+
 	Common::SeekableReadStream *_inStream;
 	bool _disposeAfterUse;
 	
 	uint _numLoops;
 	uint _posInFrame;
-	bool _eos;
+	State _state;
 	
 	const mad_timer_t _startTime;
 	const mad_timer_t _endTime;
@@ -75,14 +81,13 @@
 	
 	int readBuffer(int16 *buffer, const int numSamples);
 
-	bool endOfData() const		{ return _eos; }
+	bool endOfData() const		{ return _state == MP3_STATE_EOS; }
 	bool isStereo() const		{ return MAD_NCHANNELS(&_frame.header) == 2; }
 	int getRate() const			{ return _frame.header.samplerate; }
 
 protected:
-	void rewind();
 	void decodeMP3Data();
-	bool readMP3Data();
+	void readMP3Data();
 };
 
 MP3InputStream::MP3InputStream(Common::SeekableReadStream *inStream, bool dispose, mad_timer_t start, mad_timer_t end, uint numLoops) :
@@ -90,7 +95,7 @@
 	_disposeAfterUse(dispose),
 	_numLoops(numLoops),
 	_posInFrame(0),
-	_eos(false),
+	_state(MP3_STATE_INIT),
 	_startTime(start),
 	_endTime(end),
 	_totalTime(mad_timer_zero) {
@@ -103,57 +108,52 @@
 	// may read a few bytes beyond the end of the input buffer).
 	memset(_buf + BUFFER_SIZE, 0, MAD_BUFFER_GUARD);
 
-	// Init MAD
-	mad_stream_init(&_stream);
-	mad_frame_init(&_frame);
-	mad_synth_init(&_synth);
-
-	// Decode the first chunk of data.
+	// Decode the first chunk of data. This is necessary so that _frame
+	// is setup and isStereo() and getRate() return correct results.
 	decodeMP3Data();
 }
 
 MP3InputStream::~MP3InputStream() {
-	// Deinit MAD
-	mad_synth_finish(&_synth);
-	mad_frame_finish(&_frame);
-	mad_stream_finish(&_stream);
+	if (_state != MP3_STATE_INIT) {
+		// Deinit MAD
+		mad_synth_finish(&_synth);
+		mad_frame_finish(&_frame);
+		mad_stream_finish(&_stream);
+	}
 
 	if (_disposeAfterUse)
 		delete _inStream;
 }
 
-void MP3InputStream::rewind() {
-	// Start over again: reset the decoders, seek back to the start of the file, etc.
-
-	mad_synth_finish(&_synth);
-	mad_frame_finish(&_frame);
-	mad_stream_finish(&_stream);
-	
-	_inStream->seek(0, SEEK_SET);
-	_totalTime = mad_timer_zero;
-	_posInFrame = 0;
-	_eos = false;
-
-	// Reinit MAD
-	mad_stream_init(&_stream);
-	mad_frame_init(&_frame);
-	mad_synth_init(&_synth);
-}
-
 void MP3InputStream::decodeMP3Data() {
-	if (_eos)
-		return;
 
 	do {
-		// If necessary, load more data
-		if (_stream.buffer == NULL || _stream.error == MAD_ERROR_BUFLEN) {
-			if (!readMP3Data()) {
-				// We tried to read more data but failed -> end of stream reached
-				_eos = true;
-			}
+		if (_state == MP3_STATE_INIT) {
+			// Init MAD
+			mad_stream_init(&_stream);
+			mad_frame_init(&_frame);
+			mad_synth_init(&_synth);
+	
+			// Reset the stream data
+			_inStream->seek(0, SEEK_SET);
+			_totalTime = mad_timer_zero;
+			_posInFrame = 0;
+		
+			// Update state
+			_state = MP3_STATE_READY;
+	
+			// Read the first few sample bytes
+			readMP3Data();
 		}
+	
+		if (_state == MP3_STATE_EOS)
+			return;
 
-		while (!_eos) {
+		// 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.
@@ -180,7 +180,7 @@
 
 			// If an end time is specified and we are past it, stop
 			if (mad_timer_sign(_endTime) > 0 && mad_timer_compare(_totalTime, _endTime) >= 0) {
-				_eos = true;
+				_state = MP3_STATE_EOS;
 				break;
 			}
 			
@@ -206,25 +206,34 @@
 			break;
 		}
 	
-		if (_eos && _numLoops != 1) {
+		if (_state == MP3_STATE_EOS && _numLoops != 1) {
 			// If looping is on and there are loops left, rewind to the start
 			if (_numLoops != 0)
 				_numLoops--;
-			rewind();
+
+			// Deinit MAD
+			mad_synth_finish(&_synth);
+			mad_frame_finish(&_frame);
+			mad_stream_finish(&_stream);
+			
+			// Reset the decoder state to indicate we should start over
+			_state = MP3_STATE_INIT;
 		}
 
-	} while (!_eos && _stream.error == MAD_ERROR_BUFLEN);
+	} while (_state != MP3_STATE_EOS && _stream.error == MAD_ERROR_BUFLEN);
 	
 	if (_stream.error != MAD_ERROR_NONE)
-		_eos = true;
+		_state = MP3_STATE_EOS;
 }
 
-bool MP3InputStream::readMP3Data() {
+void MP3InputStream::readMP3Data() {
 	uint32 remaining = 0;
 
 	// Give up immediately if we already used up all data in the stream
-	if (_inStream->eos())
-		return false;
+	if (_inStream->eos()) {
+		_state = MP3_STATE_EOS;
+		return;
+	}
 
 	if (_stream.next_frame) {
 		// If there is still data in the MAD stream, we need to preserve it.
@@ -238,14 +247,13 @@
 	// Try to read the next block
 	uint32 size = _inStream->read(_buf + remaining, BUFFER_SIZE - remaining);
 	if (size <= 0) {
-		return false;
+		_state = MP3_STATE_EOS;
+		return;
 	}
 	
 	// Feed the data we just read into the stream decoder
 	_stream.error = MAD_ERROR_NONE;
 	mad_stream_buffer(&_stream, _buf, size + remaining);
-
-	return true;
 }
 
 
@@ -266,7 +274,7 @@
 int MP3InputStream::readBuffer(int16 *buffer, const int numSamples) {
 	int samples = 0;
 	// Keep going as long as we have input available
-	while (samples < numSamples && !_eos) {
+	while (samples < numSamples && _state != MP3_STATE_EOS) {
 		const int len = MIN(numSamples, samples + (int)(_synth.pcm.length - _posInFrame) * MAD_NCHANNELS(&_frame.header));
 		while (samples < len) {
 			*buffer++ = (int16)scale_sample(_synth.pcm.samples[0][_posInFrame]);


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