[Scummvm-cvs-logs] CVS: scummvm/sound audiostream.cpp,1.22,1.23 audiostream.h,1.16,1.17 mixer.cpp,1.100,1.101 rate.cpp,1.23,1.24

Max Horn fingolfin at users.sourceforge.net
Mon Aug 4 15:16:03 CEST 2003


Update of /cvsroot/scummvm/scummvm/sound
In directory sc8-pr-cvs1:/tmp/cvs-serv31332

Modified Files:
	audiostream.cpp audiostream.h mixer.cpp rate.cpp 
Log Message:
renamed eof -> eos (end of stream); hid MP3/Vorbis stream classes completly (by providing factory methods); new readBuffer method for AudioInputStream for improved speed of the mixer; new MusicStream class (subclassed for MP3/Vorbis sound) which offers a getRate method; some other tweaks

Index: audiostream.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/audiostream.cpp,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- audiostream.cpp	4 Aug 2003 16:28:41 -0000	1.22
+++ audiostream.cpp	4 Aug 2003 22:15:15 -0000	1.23
@@ -47,17 +47,7 @@
 	const byte *_loopPtr;
 	const byte *_loopEnd;
 
-public:
-	LinearMemoryStream(const byte *ptr, uint len, uint loopOffset, uint loopLen)
-		: _ptr(ptr), _end(ptr+len), _loopPtr(0), _loopEnd(0) {
-		if (loopLen) {
-			_loopPtr = _ptr + loopOffset;
-			_loopEnd = _loopPtr + loopLen;
-		}
-		if (stereo)	// Stereo requires even sized data
-			assert(len % 2 == 0);
-	}
-	int16 read() {
+	inline int16 readIntern() {
 		//assert(_ptr < _end);
 		int16 val = readSample<is16Bit, isUnsigned>(_ptr);
 		_ptr += (is16Bit ? 2 : 1);
@@ -67,12 +57,36 @@
 		}
 		return val;
 	}
-	bool eof() const {
-		return _ptr >= _end;
+	inline bool eosIntern() const	{ return _ptr >= _end; };
+public:
+	LinearMemoryStream(const byte *ptr, uint len, uint loopOffset, uint loopLen)
+		: _ptr(ptr), _end(ptr+len), _loopPtr(0), _loopEnd(0) {
+		if (loopLen) {
+			_loopPtr = _ptr + loopOffset;
+			_loopEnd = _loopPtr + loopLen;
+		}
+		if (stereo)	// Stereo requires even sized data
+			assert(len % 2 == 0);
 	}
-	bool isStereo() const {
-		return stereo;
+	int readBuffer(int16 *buffer, int numSamples) {
+		int samples = 0;
+		do {
+			const int len = MIN(numSamples, (_end - _ptr) / (is16Bit ? 2 : 1));
+			for (; samples < len; samples++) {
+				*buffer++ = readSample<is16Bit, isUnsigned>(_ptr);
+				_ptr += (is16Bit ? 2 : 1);
+			}
+			if (_loopPtr && _ptr == _end) {
+				_ptr = _loopPtr;
+				_end = _loopEnd;
+			}
+		} while (samples < numSamples && !eosIntern());
+		return samples;
 	}
+
+	int16 read()				{ return readIntern(); }
+	bool eos() const			{ return eosIntern(); }
+	bool isStereo() const		{ return stereo; }
 };
 
 
@@ -90,14 +104,16 @@
 	byte *_pos;
 	byte *_end;
 	
+	inline int16 readIntern();
+	inline bool eosIntern() const { return _end == _pos; };
 public:
 	WrappedMemoryStream(uint bufferSize);
-	~WrappedMemoryStream() { free(_bufferStart); }
-	int16 read();
-	bool eof() const;
-	bool isStereo() const {
-		return stereo;
-	}
+	~WrappedMemoryStream()		{ free(_bufferStart); }
+	int readBuffer(int16 *buffer, int numSamples);
+
+	int16 read()				{ return readIntern(); }
+	bool eos() const			{ return eosIntern(); }
+	bool isStereo() const		{ return stereo; }
 
 	void append(const byte *data, uint32 len);
 };
@@ -113,7 +129,7 @@
 }
 
 template<bool stereo, bool is16Bit, bool isUnsigned>
-int16 WrappedMemoryStream<stereo, is16Bit, isUnsigned>::read() {
+inline int16 WrappedMemoryStream<stereo, is16Bit, isUnsigned>::readIntern() {
 	//assert(_pos != _end);
 	int16 val = readSample<is16Bit, isUnsigned>(_pos);
 	_pos += (is16Bit ? 2 : 1);
@@ -126,8 +142,12 @@
 }
 
 template<bool stereo, bool is16Bit, bool isUnsigned>
-bool WrappedMemoryStream<stereo, is16Bit, isUnsigned>::eof() const {
-	return _end == _pos;
+int WrappedMemoryStream<stereo, is16Bit, isUnsigned>::readBuffer(int16 *buffer, int numSamples) {
+	int samples;
+	for (samples = 0; samples < numSamples && !eosIntern(); samples++) {
+		*buffer++ = readIntern();
+	}
+	return samples;
 }
 
 template<bool stereo, bool is16Bit, bool isUnsigned>
@@ -160,6 +180,37 @@
 
 
 #ifdef USE_MAD
+class MP3InputStream : public MusicStream {
+	struct mad_stream _stream;
+	struct mad_frame _frame;
+	struct mad_synth _synth;
+	mad_timer_t _duration;
+	uint32 _posInFrame;
+	uint32 _bufferSize;
+	int _size;
+	bool _isStereo;
+	int _curChannel;
+	File *_file;
+	byte *_ptr;
+	int _rate;
+	bool _initialized;
+
+	bool init();
+	void refill();
+	inline int16 readIntern();
+	inline bool eosIntern() const;
+public:
+	MP3InputStream(File *file, mad_timer_t duration, uint size = 0);
+	~MP3InputStream();
+	int readBuffer(int16 *buffer, int numSamples);
+
+	int16 read()				{ return readIntern(); }
+	bool eos() const			{ return eosIntern(); }
+	bool isStereo() const		{ return _isStereo; }
+	
+	int getRate() const			{ return _rate; }
+};
+
 
 /**
  * Playback the MP3 data in the given file for the specified duration.
@@ -299,7 +350,7 @@
 	_posInFrame = 0;
 }
 
-bool MP3InputStream::eof() const {
+inline bool MP3InputStream::eosIntern() const {
 	return (_size < 0 || _posInFrame >= _synth.pcm.length);
 }
 
@@ -317,7 +368,7 @@
 	return sample >> (MAD_F_FRACBITS + 1 - 16);
 }
 
-int16 MP3InputStream::read() {
+inline int16 MP3InputStream::readIntern() {
 	if (_size < 0 || _posInFrame >= _synth.pcm.length) {	// EOF
 		return 0;
 	}
@@ -343,6 +394,18 @@
 	return sample;
 }
 
+int MP3InputStream::readBuffer(int16 *buffer, int numSamples) {
+	int samples;
+	for (samples = 0; samples < numSamples && !eosIntern(); samples++) {
+		*buffer++ = readIntern();
+	}
+	return samples;
+}
+
+MusicStream *makeMP3Stream(File *file, mad_timer_t duration, uint size) {
+	return new MP3InputStream(file, duration, size);
+}
+
 #endif
 
 
@@ -353,6 +416,29 @@
 
 #ifdef USE_VORBIS
 
+class VorbisInputStream : public MusicStream {
+	OggVorbis_File *_ov_file;
+	int _end_pos;
+	bool _eofFlag;
+	int _numChannels;
+	int16 _buffer[4096];
+	int16 *_pos;
+	
+	void refill();
+	inline int16 readIntern();
+	inline bool eosIntern() const;
+public:
+	VorbisInputStream(OggVorbis_File *file, int duration);
+	int readBuffer(int16 *buffer, int numSamples);
+
+	int16 read()				{ return readIntern(); }
+	bool eos() const			{ return eosIntern(); }
+	bool isStereo() const		{ return _numChannels >= 2; }
+	
+	int getRate() const			{ return ov_info(_ov_file, -1)->rate; }
+};
+
+
 #ifdef CHUNKSIZE
 #define VORBIS_TREMOR
 #endif
@@ -371,14 +457,14 @@
 	_eofFlag = false;
 }
 
-int16 VorbisInputStream::read() {
+inline int16 VorbisInputStream::readIntern() {
 	if (_pos >= _buffer + ARRAYSIZE(_buffer)) {
 		refill();
 	}
 	return *_pos++;
 }
 
-bool VorbisInputStream::eof() const {
+inline bool VorbisInputStream::eosIntern() const {
 	if (_eofFlag)
 		return true;
 	if (_pos < _buffer + ARRAYSIZE(_buffer))
@@ -386,6 +472,14 @@
 	return (_end_pos <= ov_pcm_tell(_ov_file));
 }
 
+int VorbisInputStream::readBuffer(int16 *buffer, int numSamples) {
+	int samples;
+	for (samples = 0; samples < numSamples && !eosIntern(); samples++) {
+		*buffer++ = readIntern();
+	}
+	return samples;
+}
+
 void VorbisInputStream::refill() {
 	// Read the samples
 	uint len_left = sizeof(_buffer);
@@ -424,6 +518,10 @@
 	}
 
 	_pos = _buffer;
+}
+
+MusicStream *makeVorbisStream(OggVorbis_File *file, int duration) {
+	return new VorbisInputStream(file, duration);
 }
 
 #endif

Index: audiostream.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/audiostream.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- audiostream.h	2 Aug 2003 18:13:37 -0000	1.16
+++ audiostream.h	4 Aug 2003 22:15:15 -0000	1.17
@@ -24,6 +24,7 @@
 
 #include "stdafx.h"
 #include "common/scummsys.h"
+#include "common/util.h"
 #ifdef USE_MAD
 #include <mad.h>
 #endif
@@ -47,10 +48,34 @@
 public:
 	virtual ~AudioInputStream() {}
 
+	/**
+	 * Fill the given buffer with up to numSamples samples.
+	 * Returns the actual number of samples read, or -1 if
+	 * a critical error occured (note: you *must* check if
+	 * this value is less than what you requested, this can
+	 * happend when the stream is fully used up).
+	 * For stereo stream, buffer will be filled with interleaved
+	 * left and right channel samples.
+	 *
+	 * For maximum efficency, subclasses should always override
+	 * the default implementation!
+	 */
+	virtual int readBuffer(int16 *buffer, int numSamples) {
+		int samples;
+		for (samples = 0; samples < numSamples && !eos(); samples++) {
+			*buffer++ = read();
+		}
+		return samples;
+	}
+
+	/** Read a singel (16 bit signed) sample from the stream. */
 	virtual int16 read() = 0;
-	//virtual int size() const = 0;
+	
+	/** Is this a stereo stream? */
 	virtual bool isStereo() const = 0;
-	virtual bool eof() const = 0;
+	
+	/* End of stream reached? */
+	virtual bool eos() const = 0;
 
 	virtual int getRate() const { return -1; }
 };
@@ -65,64 +90,34 @@
 	int _len;
 public:
 	ZeroInputStream(uint len) : _len(len) { }
+	int readBuffer(int16 *buffer, int numSamples) {
+		int samples = MIN(_len, numSamples);
+		memset(buffer, 0, samples * 2);
+		_len -= samples;
+		return samples;
+	}
 	int16 read() { assert(_len > 0); _len--; return 0; }
 	int size() const { return _len; }
 	bool isStereo() const { return false; }
-	bool eof() const { return _len <= 0; }
-};
-
-#ifdef USE_MAD
-class MP3InputStream : public AudioInputStream {
-	struct mad_stream _stream;
-	struct mad_frame _frame;
-	struct mad_synth _synth;
-	mad_timer_t _duration;
-	uint32 _posInFrame;
-	uint32 _bufferSize;
-	int _size;
-	bool _isStereo;
-	int _curChannel;
-	File *_file;
-	byte *_ptr;
-	int _rate;
-	bool _initialized;
-
-	bool init();
-	void refill();
-public:
-	MP3InputStream(File *file, mad_timer_t duration, uint size = 0);
-	~MP3InputStream();
-	int16 read();
-	bool eof() const;
-	bool isStereo() const { return _isStereo; }
-	
-	int getRate() const { return _rate; }
+	bool eos() const { return _len <= 0; }
 };
-#endif
-
 
-#ifdef USE_VORBIS
-class VorbisInputStream : public AudioInputStream {
-	OggVorbis_File *_ov_file;
-	int _end_pos;
-	bool _eofFlag;
-	int _numChannels;
-	int16 _buffer[4096];
-	int16 *_pos;
-	
-	void refill();
+class MusicStream : public AudioInputStream {
 public:
-	VorbisInputStream(OggVorbis_File *file, int duration);
-	int16 read();
-	bool eof() const;
-	bool isStereo() const { return _numChannels >= 2; }
+	virtual int getRate() const = 0;
 };
-#endif
-
 
 
 AudioInputStream *makeLinearInputStream(byte _flags, const byte *ptr, uint32 len, uint loopOffset, uint loopLen);
 WrappedAudioInputStream *makeWrappedInputStream(byte _flags, uint32 len);
+
+#ifdef USE_MAD
+MusicStream *makeMP3Stream(File *file, mad_timer_t duration, uint size = 0);
+#endif
+
+#ifdef USE_VORBIS
+MusicStream *makeVorbisStream(OggVorbis_File *file, int duration);
+#endif
 
 
 #endif

Index: mixer.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/mixer.cpp,v
retrieving revision 1.100
retrieving revision 1.101
diff -u -d -r1.100 -r1.101
--- mixer.cpp	2 Aug 2003 19:09:51 -0000	1.100
+++ mixer.cpp	4 Aug 2003 22:15:15 -0000	1.101
@@ -709,7 +709,7 @@
 	assert(_input);
 	assert(_converter);
 
-	if (_input->eof()) {
+	if (_input->eos()) {
 		// TODO: call drain method
 		destroy();
 		return;
@@ -820,7 +820,7 @@
 	assert(_input);
 	assert(_converter);
 
-	if (_input->eof()) {
+	if (_input->eos()) {
 		// TODO: call drain method
 
 		// Normally, the stream stays around even if all its data is used up.
@@ -929,7 +929,7 @@
 ChannelMP3::ChannelMP3(SoundMixer *mixer, PlayingSoundHandle *handle, File *file, uint size)
 	: Channel(mixer, handle) {
 	// Create the input stream
-	_input = new MP3InputStream(file, mad_timer_zero, size);
+	_input = makeMP3Stream(file, mad_timer_zero, size);
 
 	// Get a rate converter instance
 //printf("ChannelMP3: inrate %d, outrate %d, stereo %d\n", _input->getRate(), mixer->getOutputRate(), _input->isStereo());
@@ -951,7 +951,7 @@
 	assert(_input);
 	assert(_converter);
 
-	if (_input->eof()) {
+	if (_input->eos()) {
 		// TODO: call drain method
 		destroy();
 		return;
@@ -1013,7 +1013,7 @@
 ChannelMP3CDMusic::ChannelMP3CDMusic(SoundMixer *mixer, PlayingSoundHandle *handle, File *file, mad_timer_t duration) 
 	: Channel(mixer, handle) {
 	// Create the input stream
-	_input = new MP3InputStream(file, duration, 0);
+	_input = makeMP3Stream(file, duration, 0);
 
 	// Get a rate converter instance
 //printf("ChannelMP3CDMusic: inrate %d, outrate %d, stereo %d\n", _input->getRate(), mixer->getOutputRate(), _input->isStereo());
@@ -1034,7 +1034,7 @@
 	assert(_input);
 	assert(_converter);
 
-	if (_input->eof()) {
+	if (_input->eos()) {
 		// TODO: call drain method
 		destroy();
 		return;
@@ -1158,15 +1158,11 @@
 ChannelVorbis::ChannelVorbis(SoundMixer *mixer, PlayingSoundHandle *handle, OggVorbis_File *ov_file, int duration, bool is_cd_track)
 	: Channel(mixer, handle) {
 #ifdef SOX_HACK
-	vorbis_info *vi;
-	
 	// Create the input stream
-	_input = new VorbisInputStream(ov_file, duration);
+	_input = makeVorbisStream(ov_file, duration);
 
 	// Get a rate converter instance
-	vi = ov_info(ov_file, -1);
-	assert(vi->channels == 1 || vi->channels == 2);
-	_converter = makeRateConverter(vi->rate, mixer->getOutputRate(), _input->isStereo());
+	_converter = makeRateConverter(_input->getRate(), mixer->getOutputRate(), _input->isStereo());
 #else
 	_ov_file = ov_file;
 
@@ -1187,7 +1183,7 @@
 	assert(_input);
 	assert(_converter);
 
-	if (_input->eof()) {
+	if (_input->eos()) {
 		// TODO: call drain method
 		destroy();
 		return;

Index: rate.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/rate.cpp,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- rate.cpp	2 Aug 2003 19:17:54 -0000	1.23
+++ rate.cpp	4 Aug 2003 22:15:16 -0000	1.24
@@ -30,9 +30,20 @@
 #include "stdafx.h"
 #include "sound/rate.h"
 
-
+/**
+ * The precision of the fractional computations used by the rate converter.
+ * Normally you should never have to modify this value.
+ */
 #define FRAC_BITS 16
 
+/**
+ * The size of the intermediate input cache. Bigger values may increase
+ * performance, but only until some point (depends largely on cache size,
+ * target processor and various other factors), at which it will decrease
+ * again.
+ */
+#define INTERMEDIATE_BUFFER_SIZE 512
+
 
 /**
  * Audio rate converter based on simple linear Interpolation.
@@ -48,7 +59,9 @@
 template<bool stereo, bool reverseStereo>
 class LinearRateConverter : public RateConverter {
 protected:
-	bool _reverseStereo;
+	st_sample_t inBuf[INTERMEDIATE_BUFFER_SIZE];
+	const st_sample_t *inPtr;
+	int inLen;
 
 	/** fractional position of the output stream in input stream unit */
 	unsigned long opos, opos_frac;
@@ -101,6 +114,8 @@
 
 	ilast[0] = ilast[1] = 0;
 	icur[0] = icur[1] = 0;
+	
+	inLen = 0;
 }
 
 /*
@@ -112,6 +127,9 @@
 {
 	st_sample_t *ostart, *oend;
 	st_sample_t out[2], tmpOut;
+	
+	const int numChannels = stereo ? 2 : 1;
+	int i;
 
 	ostart = obuf;
 	oend = obuf + osamp * 2;
@@ -120,16 +138,17 @@
 
 		// read enough input samples so that ipos > opos
 		while (ipos <= opos) {
-
-			// Abort if we reached the end of the input buffer
-			if (input.eof())
-				goto the_end;
-
-			ilast[0] = icur[0];
-			icur[0] = input.read();
-			if (stereo) {
-				ilast[1] = icur[1];
-				icur[1] = input.read();
+			// Check if we have to refill the buffer
+			if (inLen == 0) {
+				inPtr = inBuf;
+				inLen = input.readBuffer(inBuf, ARRAYSIZE(inBuf));
+				if (inLen <= 0)
+					goto the_end;
+			}
+			for (i = 0; i < numChannels; i++) {
+				ilast[i] = icur[i];
+				icur[i] = *inPtr++;
+				inLen--;
 			}
 			ipos++;
 		}
@@ -185,7 +204,10 @@
 		int16 tmp[2];
 		st_size_t len = osamp;
 		assert(input.isStereo() == stereo);
-		while (!input.eof() && len--) {
+
+// TODO: use readBuffer
+
+		while (!input.eos() && len--) {
 			tmp[0] = tmp[1] = (input.read() * vol) >> 8;
 			if (stereo)
 				tmp[reverseStereo ? 0 : 1] = (input.read() * vol) >> 8;





More information about the Scummvm-git-logs mailing list