[Scummvm-cvs-logs] CVS: residual/mixer audiostream.cpp,1.1,1.2 audiostream.h,1.1,1.2 mixer.cpp,1.2,1.3 mixer.h,1.2,1.3 rate.cpp,1.1,1.2 rate.h,1.1,1.2

Pawel Kolodziejski aquadran at users.sourceforge.net
Sun Feb 1 02:51:02 CET 2004


Update of /cvsroot/scummvm/residual/mixer
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21697/mixer

Modified Files:
	audiostream.cpp audiostream.h mixer.cpp mixer.h rate.cpp 
	rate.h 
Log Message:
synced with scummvm mixer

Index: audiostream.cpp
===================================================================
RCS file: /cvsroot/scummvm/residual/mixer/audiostream.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- audiostream.cpp	12 Dec 2003 21:17:31 -0000	1.1
+++ audiostream.cpp	1 Feb 2004 10:48:44 -0000	1.2
@@ -20,7 +20,6 @@
 #include "mixer.h"
 #include "audiostream.h"
 
-
 // This used to be an inline template function, but
 // buggy template function handling in MSVC6 forced
 // us to go with the macro approach. So far this is
@@ -29,28 +28,23 @@
 #define READSAMPLE(is16Bit, isUnsigned, ptr) \
 	((is16Bit ? READ_BE_UINT16(ptr) : (*ptr << 8)) ^ (isUnsigned ? 0x8000 : 0))
 
-template<bool stereo, bool is16Bit, bool isUnsigned>
-class LinearMemoryStream : public AudioInputStream {
+#define READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, ptr, isLE) \
+	((is16Bit ? (isLE ? READ_LE_UINT16(ptr) : READ_BE_UINT16(ptr)) : (*ptr << 8)) ^ (isUnsigned ? 0x8000 : 0))
+
+template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE>
+class LinearMemoryStream : public AudioStream {
 protected:
 	const byte *_ptr;
 	const byte *_end;
 	const byte *_loopPtr;
 	const byte *_loopEnd;
+	const int _rate;
+	const byte *_origPtr;
 
-	inline int16 readIntern() {
-		//assert(_ptr < _end);
-		int16 val = READSAMPLE(is16Bit, isUnsigned, _ptr);
-		_ptr += (is16Bit ? 2 : 1);
-		if (_loopPtr && eosIntern()) {
-			_ptr = _loopPtr;
-			_end = _loopEnd;
-		}
-		return val;
-	}
 	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) {
+	LinearMemoryStream(int rate, const byte *ptr, uint len, uint loopOffset, uint loopLen, bool autoFreeMemory)
+		: _ptr(ptr), _end(ptr+len), _loopPtr(0), _loopEnd(0), _rate(rate) {
 
 		// Verify the buffer sizes are sane
 		if (is16Bit && stereo)
@@ -64,21 +58,37 @@
 		}
 		if (stereo)	// Stereo requires even sized data
 			assert(len % 2 == 0);
+		
+		_origPtr = autoFreeMemory ? ptr : 0;
+	}
+	~LinearMemoryStream() {
+		free(const_cast<byte *>(_origPtr));
 	}
 	int readBuffer(int16 *buffer, const int numSamples);
 
-	int16 read()				{ return readIntern(); }
-	bool eos() const			{ return eosIntern(); }
+	int16 read() {
+		//assert(_ptr < _end);
+		int16 val = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _ptr, isLE);
+		_ptr += (is16Bit ? 2 : 1);
+		if (_loopPtr && eosIntern()) {
+			_ptr = _loopPtr;
+			_end = _loopEnd;
+		}
+		return val;
+	}
 	bool isStereo() const		{ return stereo; }
+	bool endOfData() const		{ return eosIntern(); }
+
+	int getRate() const			{ return _rate; }
 };
 
-template<bool stereo, bool is16Bit, bool isUnsigned>
-int LinearMemoryStream<stereo, is16Bit, isUnsigned>::readBuffer(int16 *buffer, const int numSamples) {
+template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE>
+int LinearMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffer, const int numSamples) {
 	int samples = 0;
 	while (samples < numSamples && !eosIntern()) {
 		const int len = MIN(numSamples, samples + (int)(_end - _ptr) / (is16Bit ? 2 : 1));
 		while (samples < len) {
-			*buffer++ = READSAMPLE(is16Bit, isUnsigned, _ptr);
+			*buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _ptr, isLE);
 			_ptr += (is16Bit ? 2 : 1);
 			samples++;
 		}
@@ -91,32 +101,40 @@
 	return samples;
 }
 
-// Wrapped memory stream, to be used by the ChannelStream class (and possibly others?)
+/**
+ * Wrapped memory stream.
+ */
 template<bool stereo, bool is16Bit, bool isUnsigned>
-class WrappedMemoryStream : public WrappedAudioInputStream {
+class AppendableMemoryStream : public AppendableAudioStream {
 protected:
 	byte *_bufferStart;
 	byte *_bufferEnd;
 	byte *_pos;
 	byte *_end;
+	bool _finalized;
+	const int _rate;
 
-	inline int16 readIntern();
 	inline bool eosIntern() const { return _end == _pos; };
 public:
-	WrappedMemoryStream(uint bufferSize);
-	~WrappedMemoryStream()		{ free(_bufferStart); }
+	AppendableMemoryStream(int rate, uint bufferSize);
+	~AppendableMemoryStream()		{ free(_bufferStart); }
 	int readBuffer(int16 *buffer, const int numSamples);
 
-	int16 read()				{ return readIntern(); }
-	bool eos() const			{ return eosIntern(); }
+	int16 read();
 	bool isStereo() const		{ return stereo; }
+	bool endOfStream() const	{ return _finalized && eosIntern(); }
+	bool endOfData() const		{ return eosIntern(); }
+
+	int getRate() const			{ return _rate; }
 
 	void append(const byte *data, uint32 len);
+	void finish()				{ _finalized = true; }
 };
 
 
 template<bool stereo, bool is16Bit, bool isUnsigned>
-WrappedMemoryStream<stereo, is16Bit, isUnsigned>::WrappedMemoryStream(uint bufferSize) {
+AppendableMemoryStream<stereo, is16Bit, isUnsigned>::AppendableMemoryStream(int rate, uint bufferSize)
+ : _finalized(false), _rate(rate) {
 
 	// Verify the buffer size is sane
 	if (is16Bit && stereo)
@@ -130,22 +148,27 @@
 }
 
 template<bool stereo, bool is16Bit, bool isUnsigned>
-inline int16 WrappedMemoryStream<stereo, is16Bit, isUnsigned>::readIntern() {
-	//assert(_pos != _end);
-	int16 val = READSAMPLE(is16Bit, isUnsigned, _pos);
-	_pos += (is16Bit ? 2 : 1);
+inline int16 AppendableMemoryStream<stereo, is16Bit, isUnsigned>::read() {
+	assert(!eosIntern());
 
 	// Wrap around?
 	if (_pos >= _bufferEnd)
 		_pos = _pos - (_bufferEnd - _bufferStart);
 
+	int16 val = READSAMPLE(is16Bit, isUnsigned, _pos);
+	_pos += (is16Bit ? 2 : 1);
+
 	return val;
 }
 
 template<bool stereo, bool is16Bit, bool isUnsigned>
-int WrappedMemoryStream<stereo, is16Bit, isUnsigned>::readBuffer(int16 *buffer, const int numSamples) {
+int AppendableMemoryStream<stereo, is16Bit, isUnsigned>::readBuffer(int16 *buffer, const int numSamples) {
 	int samples = 0;
 	while (samples < numSamples && !eosIntern()) {
+		// Wrap around?
+		if (_pos >= _bufferEnd)
+			_pos = _pos - (_bufferEnd - _bufferStart);
+
 		const byte *endMarker = (_pos > _end) ? _bufferEnd : _end;
 		const int len = MIN(numSamples, samples + (int)(endMarker - _pos) / (is16Bit ? 2 : 1));
 		while (samples < len) {
@@ -153,28 +176,28 @@
 			_pos += (is16Bit ? 2 : 1);
 			samples++;
 		}
-		// Wrap around?
-		if (_pos >= _bufferEnd)
-			_pos = _pos - (_bufferEnd - _bufferStart);
 	}
 	return samples;
 }
 
 template<bool stereo, bool is16Bit, bool isUnsigned>
-void WrappedMemoryStream<stereo, is16Bit, isUnsigned>::append(const byte *data, uint32 len) {
+void AppendableMemoryStream<stereo, is16Bit, isUnsigned>::append(const byte *data, uint32 len) {
 
 	// Verify the buffer size is sane
 	if (is16Bit && stereo)
 		assert((len & 3) == 0);
 	else if (is16Bit || stereo)
 		assert((len & 1) == 0);
+	
+	// Verify that the stream has not yet been finalized (by a call to finish())
+	assert(!_finalized);
 
 	if (_end + len > _bufferEnd) {
 		// Wrap-around case
 		uint32 size_to_end_of_buffer = _bufferEnd - _end;
 		len -= size_to_end_of_buffer;
 		if ((_end < _pos) || (_bufferStart + len >= _pos)) {
-			warning("WrappedMemoryStream: buffer overflow (A)");
+			warning("AppendableMemoryStream: buffer overflow (A)");
 			return;
 		}
 		memcpy(_end, data, size_to_end_of_buffer);
@@ -182,7 +205,7 @@
 		_end = _bufferStart + len;
 	} else {
 		if ((_end < _pos) && (_end + len >= _pos)) {
-			warning("WrappedMemoryStream: buffer overflow (B)");
+			warning("AppendableMemoryStream: buffer overflow (B)");
 			return;
 		}
 		memcpy(_end, data, len);
@@ -190,52 +213,92 @@
 	}
 }
 
-template<bool stereo>
-static AudioInputStream *makeLinearInputStream(const byte *ptr, uint32 len, bool is16Bit, bool isUnsigned, uint loopOffset, uint loopLen) {
-	if (isUnsigned) {
-		if (is16Bit)
-			return new LinearMemoryStream<stereo, true, true>(ptr, len, loopOffset, loopLen);
-		else
-			return new LinearMemoryStream<stereo, false, true>(ptr, len, loopOffset, loopLen);
-	} else {
-		if (is16Bit)
-			return new LinearMemoryStream<stereo, true, false>(ptr, len, loopOffset, loopLen);
-		else
-			return new LinearMemoryStream<stereo, false, false>(ptr, len, loopOffset, loopLen);
-	}
-}
 
-template<bool stereo>
-static WrappedAudioInputStream *makeWrappedInputStream(uint32 len, bool is16Bit, bool isUnsigned) {
-	if (isUnsigned) {
-		if (is16Bit)
-			return new WrappedMemoryStream<stereo, true, true>(len);
-		else
-			return new WrappedMemoryStream<stereo, false, true>(len);
-	} else {
-		if (is16Bit)
-			return new WrappedMemoryStream<stereo, true, false>(len);
-		else
-			return new WrappedMemoryStream<stereo, false, false>(len);
+#if 0
+// Work in progress!!! Not yet usable/finished/working/anything :-)
+
+class ProcInputStream : public AudioStream {
+public:
+	typedef void InputProc (void *refCon, int16 *data, uint len);
+
+private:
+	const int _rate;
+	const bool _isStereo;
+	InputProc *_proc;
+	void *_refCon;
+
+public:
+	ProcInputStream(int rate, bool stereo, InputProc *proc, void *refCon)
+		: _rate(rate), _isStereo(stereo), _proc(proc), _refCon(refCon) { }
+	int readBuffer(int16 *buffer, const int numSamples) {
+		(_proc)(_refCon, buffer, numSamples);
+		return numSamples;
 	}
-}
+	int16 read() {
+		int16 sample;
+		(_proc)(_refCon, &sample, 1);
+		return sample;
+	}
+	bool isStereo() const { return _isStereo; }
+	bool endOfData() const { return false; }
+	
+	int getRate() const { return _rate; }
+};
+#endif
 
-AudioInputStream *makeLinearInputStream(byte _flags, const byte *ptr, uint32 len, uint loopOffset, uint loopLen) {
-	const bool is16Bit = (_flags & SoundMixer::FLAG_16BITS) != 0;
+#define MAKE_LINEAR(STEREO, UNSIGNED) \
+		if (is16Bit) { \
+			if (isLE) \
+				return new LinearMemoryStream<STEREO, true, UNSIGNED, true>(rate, ptr, len, loopOffset, loopLen, autoFree); \
+			else  \
+				return new LinearMemoryStream<STEREO, true, UNSIGNED, false>(rate, ptr, len, loopOffset, loopLen, autoFree); \
+		} else \
+			return new LinearMemoryStream<STEREO, false, UNSIGNED, false>(rate, ptr, len, loopOffset, loopLen, autoFree)
+
+AudioStream *makeLinearInputStream(int rate, byte _flags, const byte *ptr, uint32 len, uint loopOffset, uint loopLen) {
+	const bool isStereo   = (_flags & SoundMixer::FLAG_STEREO) != 0;
+	const bool is16Bit    = (_flags & SoundMixer::FLAG_16BITS) != 0;
 	const bool isUnsigned = (_flags & SoundMixer::FLAG_UNSIGNED) != 0;
-	if (_flags & SoundMixer::FLAG_STEREO) {
-		return makeLinearInputStream<true>(ptr, len, is16Bit, isUnsigned, loopOffset, loopLen);
+	const bool isLE       = (_flags & SoundMixer::FLAG_LITTLE_ENDIAN) != 0;
+	const bool autoFree   = (_flags & SoundMixer::FLAG_AUTOFREE) != 0;
+	
+	if (isStereo) {
+		if (isUnsigned) {
+			MAKE_LINEAR(true, true);
+		} else {
+			MAKE_LINEAR(true, false);
+		}
 	} else {
-		return makeLinearInputStream<false>(ptr, len, is16Bit, isUnsigned, loopOffset, loopLen);
+		if (isUnsigned) {
+			MAKE_LINEAR(false, true);
+		} else {
+			MAKE_LINEAR(false, false);
+		}
 	}
 }
 
-WrappedAudioInputStream *makeWrappedInputStream(byte _flags, uint32 len) {
+#define MAKE_WRAPPED(STEREO, UNSIGNED) \
+		if (is16Bit) \
+			return new AppendableMemoryStream<STEREO, true, UNSIGNED>(rate, len); \
+		else \
+			return new AppendableMemoryStream<STEREO, false, UNSIGNED>(rate, len)
+
+AppendableAudioStream *makeAppendableAudioStream(int rate, byte _flags, uint32 len) {
+	const bool isStereo = (_flags & SoundMixer::FLAG_STEREO) != 0;
 	const bool is16Bit = (_flags & SoundMixer::FLAG_16BITS) != 0;
 	const bool isUnsigned = (_flags & SoundMixer::FLAG_UNSIGNED) != 0;
-	if (_flags & SoundMixer::FLAG_STEREO) {
-		return makeWrappedInputStream<true>(len, is16Bit, isUnsigned);
+	
+	if (isStereo) {
+		if (isUnsigned) {
+			MAKE_WRAPPED(true, true);
+		} else {
+			MAKE_WRAPPED(true, false);
+		}
 	} else {
-		return makeWrappedInputStream<false>(len, is16Bit, isUnsigned);
+		if (isUnsigned) {
+			MAKE_WRAPPED(false, true);
+		} else {
+			MAKE_WRAPPED(false, false);
+		}
 	}
 }

Index: audiostream.h
===================================================================
RCS file: /cvsroot/scummvm/residual/mixer/audiostream.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- audiostream.h	12 Dec 2003 21:17:31 -0000	1.1
+++ audiostream.h	1 Feb 2004 10:48:44 -0000	1.2
@@ -24,9 +24,9 @@
 /**
  * Generic input stream for the resampling code.
  */
-class AudioInputStream {
+class AudioStream {
 public:
-	virtual ~AudioInputStream() {}
+	virtual ~AudioStream() {}
 
 	/**
 	 * Fill the given buffer with up to numSamples samples.
@@ -36,37 +36,61 @@
 	 * happen 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, const int numSamples) {
-		int samples;
-		for (samples = 0; samples < numSamples && !eos(); samples++) {
-			*buffer++ = read();
-		}
-		return samples;
-	}
+	virtual int readBuffer(int16 *buffer, const int numSamples) = 0;
 
-	/** Read a singel (16 bit signed) sample from the stream. */
-	virtual int16 read() = 0;
+	/**
+	 * Read a single (16 bit signed) sample from the stream.
+	 */
+//	virtual int16 read() = 0;
 	
 	/** Is this a stereo stream? */
 	virtual bool isStereo() const = 0;
 	
-	/* End of stream reached? */
-	virtual bool eos() const = 0;
+	/**
+	 * End of data reached? If this returns true, it means that at this
+	 * time there is no data available in the stream. However there may be
+	 * more data in the future.
+	 * This is used by e.g. a rate converter to decide whether to keep on
+	 * converting data or stop.
+	 */
+	virtual bool endOfData() const = 0;
+	
+	/**
+	 * End of stream reached? If this returns true, it means that all data
+	 * in this stream is used up and no additional data will appear in it
+	 * in the future.
+	 * This is used by the mixer to decide whether a given stream shall be
+	 * removed from the list of active streams (and thus be destroyed).
+	 * By default this maps to endOfData()
+	 */
+	virtual bool endOfStream() const { return endOfData(); }
 
-	virtual int getRate() const { return -1; }
+	/** Sample rate of the stream. */
+	virtual int getRate() const = 0;
+
+	/**
+	 * This function returns the number of samples that were delivered to
+	 * the mixer which is a rough estimate of how moch time of the stream
+	 * has been played.
+	 * The exact value is not available as it needs information from the
+	 * audio device on how many samples have been already played
+	 * As our buffer is relatively short the estimate is exact enough
+	 * The return -1 is kind of a hack as this function is only required
+	 * for the video audio sync in the bs2 cutscenes I am to lazy to
+	 * implement it for all subclasses
+	 */
+	virtual int getSamplesPlayed() const { return -1; }
 };
 
-class WrappedAudioInputStream : public AudioInputStream {
+class AppendableAudioStream : public AudioStream {
 public:
 	virtual void append(const byte *data, uint32 len) = 0;
+	virtual void finish() = 0;
 };
 
-class ZeroInputStream : public AudioInputStream {
-protected:
+class ZeroInputStream : public AudioStream {
+private:
 	int _len;
 public:
 	ZeroInputStream(uint len) : _len(len) { }
@@ -77,18 +101,13 @@
 		return samples;
 	}
 	int16 read() { assert(_len > 0); _len--; return 0; }
-	int size() const { return _len; }
 	bool isStereo() const { return false; }
 	bool eos() const { return _len <= 0; }
+	
+	int getRate() const { return -1; }
 };
 
-class MusicStream : public AudioInputStream {
-public:
-	virtual int getRate() const = 0;
-};
-
-
-AudioInputStream *makeLinearInputStream(byte _flags, const byte *ptr, uint32 len, uint loopOffset, uint loopLen);
-WrappedAudioInputStream *makeWrappedInputStream(byte _flags, uint32 len);
+AudioStream *makeLinearInputStream(int rate, byte _flags, const byte *ptr, uint32 len, uint loopOffset, uint loopLen);
+AppendableAudioStream *makeAppendableAudioStream(int rate, byte _flags, uint32 len);
 
 #endif

Index: mixer.cpp
===================================================================
RCS file: /cvsroot/scummvm/residual/mixer/mixer.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- mixer.cpp	12 Dec 2003 21:38:10 -0000	1.2
+++ mixer.cpp	1 Feb 2004 10:48:44 -0000	1.3
@@ -29,84 +29,80 @@
  * Channels used by the sound mixer.
  */
 class Channel {
-protected:
+private:
 	SoundMixer *_mixer;
 	PlayingSoundHandle *_handle;
-	RateConverter *_converter;
-	AudioInputStream *_input;
+	bool _autofreeStream;
+	const bool _isMusic;
 	byte _volume;
-	int8 _pan;
+	int8 _balance;
 	bool _paused;
+	int _id;
+
+protected:
+	RateConverter *_converter;
+	AudioStream *_input;
 
 public:
-	int _id;
 
-	Channel(SoundMixer *mixer, PlayingSoundHandle *handle)
-		: _mixer(mixer), _handle(handle), _converter(0), _input(0), _volume(0), _pan(0), _paused(false), _id(-1) {
-		assert(mixer);
-	}
+	Channel(SoundMixer *mixer, PlayingSoundHandle *handle, bool isMusic, int id = -1);
+	Channel(SoundMixer *mixer, PlayingSoundHandle *handle, AudioStream *input, bool autofreeStream, bool isMusic, bool reverseStereo = false, int id = -1);
 	virtual ~Channel();
-	void destroy();
-	virtual void mix(int16 *data, uint len);
-	virtual void pause(bool paused) {
+
+	void mix(int16 *data, uint len);
+
+	bool isFinished() const {
+		return _input->endOfStream();
+	}
+	bool isMusicChannel() const {
+		return _isMusic;
+	}
+	void pause(bool paused) {
 		_paused = paused;
 	}
-	virtual bool isPaused() {
+	bool isPaused() {
 		return _paused;
 	}
-	virtual void setChannelVolume(const byte volume) {
+	void setVolume(const byte volume) {
 		_volume = volume;
 	}
-	virtual void setChannelPan(const int8 pan) {
-		_pan = pan;
+	void setBalance(const int8 balance) {
+		_balance = balance;
 	}
-	virtual int getVolume() const {
-		return _mixer->getVolume();
+	int getId() const {
+		return _id;
 	}
 };
 
-class ChannelRaw : public Channel {
-	byte *_ptr;
-public:
-	ChannelRaw(SoundMixer *mixer, PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, byte volume, int8 pan, int id, uint32 loopStart, uint32 loopEnd);
-	~ChannelRaw();
-};
-
 class ChannelStream : public Channel {
-	bool _finished;
 public:
-	ChannelStream(SoundMixer *mixer, PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, uint32 buffer_size, byte volume, int8 pan);
-	void mix(int16 *data, uint len);
+	ChannelStream(SoundMixer *mixer, PlayingSoundHandle *handle, uint rate, byte flags, uint32 buffer_size);
 	void append(void *sound, uint32 size);
-	void finish()					{ _finished = true; }
+
+	void finish();
 };
 
 SoundMixer::SoundMixer() {
-	_mutex = NULL;
-
+	_mutex = create_mutex();
 	_premixParam = NULL;
 	_premixProc = NULL;
-	int i = 0;
-
-	_outputRate = 0;
-
+	_outputRate = 22050;
 	_globalVolume = 0;
-
 	_paused = false;
 
-	for (i = 0; i != NUM_CHANNELS; i++)
+	for (int i = 0; i != NUM_CHANNELS; i++)
 		_channels[i] = NULL;
+
+	_mixerReady = setSoundProc(mixCallback, this);
 }
 
 SoundMixer::~SoundMixer() {
 	SDL_CloseAudio();
-	for (int i = 0; i != NUM_CHANNELS; i++) {
-		delete _channels[i];
-	}
+	stopAll();
 	delete_mutex(_mutex);
 }
 
-void set_sound_proc(SoundProc proc, void *param) {
+bool SoundMixer::setSoundProc(SoundProc proc, void *param) {
 	SDL_AudioSpec desired;
 
 	memset(&desired, 0, sizeof(desired));
@@ -118,20 +114,13 @@
 	desired.samples = 2048;
 	desired.callback = proc;
 	desired.userdata = param;
+
 	if (SDL_OpenAudio(&desired, NULL) != 0) {
-		return;
+		return false;
 	}
-	SDL_PauseAudio(0);
-}
-
-void SoundMixer::bindToSystem() {
-	_mutex = create_mutex();
-	_outputRate = 22050;
 
-	if (_outputRate == 0)
-		error("OSystem returned invalid sample rate");
-
-	set_sound_proc(mixCallback, this);
+	SDL_PauseAudio(0);
+	return true;
 }
 
 void SoundMixer::setupPremix(PremixProc *proc, void *param) {
@@ -140,18 +129,22 @@
 	_premixProc = proc;
 }
 
-int SoundMixer::newStream(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, uint32 buffer_size, byte volume, int8 pan) {
+void SoundMixer::newStream(PlayingSoundHandle *handle, uint rate, byte flags, uint32 buffer_size, byte volume, int8 balance) {
 	StackLock lock(_mutex);
-	return insertChannel(handle, new ChannelStream(this, handle, sound, size, rate, flags, buffer_size, volume, pan));
+
+	Channel *chan = new ChannelStream(this, handle, rate, flags, buffer_size);
+	chan->setVolume(volume);
+	chan->setBalance(balance);
+	insertChannel(handle, chan);
 }
 
 void SoundMixer::appendStream(PlayingSoundHandle handle, void *sound, uint32 size) {
 	StackLock lock(_mutex);
-	
-	if (handle == 0)
+
+	if (!handle.isActive())
 		return;
 
-	int index = handle - 1;
+	int index = handle.getIndex();
 
 	if ((index < 0) || (index >= NUM_CHANNELS)) {
 		warning("soundMixer::appendStream has invalid index %d", index);
@@ -159,9 +152,9 @@
 	}
 
 	ChannelStream *chan;
-	chan = (ChannelStream *)_channels[index];
+	chan = dynamic_cast<ChannelStream *>(_channels[index]);
 	if (!chan) {
-		error("Trying to append to nonexistant streamer : %d", index);
+		error("Trying to append to nonexistant stream : %d", index);
 	} else {
 		chan->append(sound, size);
 	}
@@ -171,10 +164,10 @@
 	StackLock lock(_mutex);
 
 	// Simply ignore stop requests for handles of sounds that already terminated
-	if (handle == 0)
+	if (!handle.isActive())
 		return;
 
-	int index = handle - 1;
+	int index = handle.getIndex();
 
 	if ((index < 0) || (index >= NUM_CHANNELS)) {
 		warning("soundMixer::endStream has invalid index %d", index);
@@ -182,7 +175,7 @@
 	}
 
 	ChannelStream *chan;
-	chan = (ChannelStream *)_channels[index];
+	chan = dynamic_cast<ChannelStream *>(_channels[index]);
 	if (!chan) {
 		error("Trying to end a nonexistant streamer : %d", index);
 	} else {
@@ -190,10 +183,11 @@
 	}
 }
 
-int SoundMixer::insertChannel(PlayingSoundHandle *handle, Channel *chan) {
+void SoundMixer::insertChannel(PlayingSoundHandle *handle, Channel *chan) {
+
 	int index = -1;
 	for (int i = 0; i != NUM_CHANNELS; i++) {
-		if (_channels[i] == NULL) {
+		if (_channels[i] == 0) {
 			index = i;
 			break;
 		}
@@ -201,43 +195,91 @@
 	if(index == -1) {
 		warning("SoundMixer::out of mixer slots");
 		delete chan;
-		return -1;
+		return;
 	}
 
 	_channels[index] = chan;
 	if (handle)
-		*handle = index + 1;
-	return index;
+		handle->setIndex(index);
 }
 
-int SoundMixer::playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id, byte volume, int8 pan, uint32 loopStart, uint32 loopEnd) {
+void SoundMixer::playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id, byte volume, int8 balance, uint32 loopStart, uint32 loopEnd) {
 	StackLock lock(_mutex);
 
 	// Prevent duplicate sounds
 	if (id != -1) {
 		for (int i = 0; i != NUM_CHANNELS; i++)
-			if (_channels[i] != NULL && _channels[i]->_id == id)
-				return -1;
+			if (_channels[i] != 0 && _channels[i]->getId() == id) {
+				if ((flags & SoundMixer::FLAG_AUTOFREE) != 0)
+					free(sound);
+				return;
+			}
 	}
 
-	return insertChannel(handle, new ChannelRaw(this, handle, sound, size, rate, flags, volume, pan, id, loopStart, loopEnd));
+	// Create the input stream
+	AudioStream *input;
+	if (flags & SoundMixer::FLAG_LOOP) {
+		if (loopEnd == 0) {
+			input = makeLinearInputStream(rate, flags, (byte *)sound, size, 0, size);
+		} else {
+			assert(loopStart < loopEnd && loopEnd <= size);
+			input = makeLinearInputStream(rate, flags, (byte *)sound, size, loopStart, loopEnd - loopStart);
+		}
+	} else {
+		input = makeLinearInputStream(rate, flags, (byte *)sound, size, 0, 0);
+	}
+
+	// Create the channel
+	Channel *chan = new Channel(this, handle, input, true, false, (flags & SoundMixer::FLAG_REVERSE_STEREO) != 0, id);
+	chan->setVolume(volume);
+	chan->setBalance(balance);
+	insertChannel(handle, chan);
 }
 
-void SoundMixer::mix(int16 *buf, uint len) {
+void SoundMixer::playInputStream(PlayingSoundHandle *handle, AudioStream *input, bool isMusic, byte volume, int8 balance, int id, bool autofreeStream) {
 	StackLock lock(_mutex);
 
-	if (_premixProc && !_paused) {
-		_premixProc(_premixParam, buf, len);
-	} else {
-		//  zero the buf out
-		memset(buf, 0, 2 * len * sizeof(int16));
+	if (input == 0) {
+		warning("input stream is 0");
+		return;
+	}
+
+	// Prevent duplicate sounds
+	if (id != -1) {
+		for (int i = 0; i != NUM_CHANNELS; i++)
+			if (_channels[i] != 0 && _channels[i]->getId() == id) {
+				if (autofreeStream)
+					delete input;
+				return;
+			}
 	}
 
+	// Create the channel
+	Channel *chan = new Channel(this, handle, input, autofreeStream, isMusic, false, id);
+	chan->setVolume(volume);
+	chan->setBalance(balance);
+	insertChannel(handle, chan);
+}
+
+void SoundMixer::mix(int16 *buf, uint len) {
+	StackLock lock(_mutex);
+
+	//  zero the buf
+	memset(buf, 0, 2 * len * sizeof(int16));
+
 	if (!_paused) {
+		if (_premixProc)
+			_premixProc(_premixParam, buf, len);
+
 		// now mix all channels
 		for (int i = 0; i != NUM_CHANNELS; i++)
-			if (_channels[i] && !_channels[i]->isPaused())
-				_channels[i]->mix(buf, len);
+			if (_channels[i]) {
+				if (_channels[i]->isFinished()) {
+					delete _channels[i];
+					_channels[i] = 0;
+				} else if (!_channels[i]->isPaused())
+					_channels[i]->mix(buf, len);
+			}
 	}
 }
 
@@ -252,27 +294,18 @@
 void SoundMixer::stopAll() {
 	StackLock lock(_mutex);
 	for (int i = 0; i != NUM_CHANNELS; i++)
-		if (_channels[i])
-			_channels[i]->destroy();
-}
-
-void SoundMixer::stopChannel(int index) {
-	if ((index < 0) || (index >= NUM_CHANNELS)) {
-		warning("soundMixer::stop has invalid index %d", index);
-		return;
-	}
-
-	StackLock lock(_mutex);
-	if (_channels[index])
-		_channels[index]->destroy();
+		if (_channels[i] != 0) {
+			delete _channels[i];
+			_channels[i] = 0;
+		}
 }
 
 void SoundMixer::stopID(int id) {
 	StackLock lock(_mutex);
 	for (int i = 0; i != NUM_CHANNELS; i++) {
-		if (_channels[i] != NULL && _channels[i]->_id == id) {
-			_channels[i]->destroy();
-			return;
+		if (_channels[i] != 0 && _channels[i]->getId() == id) {
+			delete _channels[i];
+			_channels[i] = 0;
 		}
 	}
 }
@@ -281,27 +314,29 @@
 	StackLock lock(_mutex);
 
 	// Simply ignore stop requests for handles of sounds that already terminated
-	if (handle == 0)
+	if (!handle.isActive())
 		return;
 
-	int index = handle - 1;
+	int index = handle.getIndex();
 
 	if ((index < 0) || (index >= NUM_CHANNELS)) {
 		warning("soundMixer::stopHandle has invalid index %d", index);
 		return;
 	}
 
-	if (_channels[index])
-		_channels[index]->destroy();
+	if (_channels[index]) {
+		delete _channels[index];
+		_channels[index] = 0;
+	}
 }
 
 void SoundMixer::setChannelVolume(PlayingSoundHandle handle, byte volume) {
 	StackLock lock(_mutex);
 
-	if (handle == 0)
+	if (!handle.isActive())
 		return;
 
-	int index = handle - 1;
+	int index = handle.getIndex();
 
 	if ((index < 0) || (index >= NUM_CHANNELS)) {
 		warning("soundMixer::setChannelVolume has invalid index %d", index);
@@ -309,45 +344,34 @@
 	}
 
 	if (_channels[index])
-		_channels[index]->setChannelVolume(volume);
+		_channels[index]->setVolume(volume);
 }
 
-void SoundMixer::setChannelPan(PlayingSoundHandle handle, int8 pan) {
+void SoundMixer::setChannelBalance(PlayingSoundHandle handle, int8 balance) {
 	StackLock lock(_mutex);
 
-	if (handle == 0)
+	if (!handle.isActive())
 		return;
 
-	int index = handle - 1;
+	int index = handle.getIndex();
 
 	if ((index < 0) || (index >= NUM_CHANNELS)) {
-		warning("soundMixer::setChannelVolume has invalid index %d", index);
+		warning("soundMixer::setChannelBalance has invalid index %d", index);
 		return;
 	}
 
 	if (_channels[index])
-		_channels[index]->setChannelPan(pan);
+		_channels[index]->setBalance(balance);
 }
 
 void SoundMixer::pauseAll(bool paused) {
 	_paused = paused;
 }
 
-void SoundMixer::pauseChannel(int index, bool paused) {
-	if ((index < 0) || (index >= NUM_CHANNELS)) {
-		warning("soundMixer::pauseChannel has invalid index %d", index);
-		return;
-	}
-
-	StackLock lock(_mutex);
-	if (_channels[index])
-		_channels[index]->pause(paused);
-}
-
 void SoundMixer::pauseID(int id, bool paused) {
 	StackLock lock(_mutex);
 	for (int i = 0; i != NUM_CHANNELS; i++) {
-		if (_channels[i] != NULL && _channels[i]->_id == id) {
+		if (_channels[i] != 0 && _channels[i]->getId() == id) {
 			_channels[i]->pause(paused);
 			return;
 		}
@@ -358,10 +382,10 @@
 	StackLock lock(_mutex);
 
 	// Simply ignore pause/unpause requests for handles of sound that alreayd terminated
-	if (handle == 0)
+	if (!handle.isActive())
 		return;
 
-	int index = handle - 1;
+	int index = handle.getIndex();
 
 	if ((index < 0) || (index >= NUM_CHANNELS)) {
 		warning("soundMixer::pauseHandle has invalid index %d", index);
@@ -382,18 +406,29 @@
 	_globalVolume = volume;
 }
 
+Channel::Channel(SoundMixer *mixer, PlayingSoundHandle *handle, bool isMusic, int id)
+	: _mixer(mixer), _handle(handle), _autofreeStream(true), _isMusic(isMusic),
+	  _volume(255), _balance(0), _paused(false), _id(id), _converter(0), _input(0) {
+	assert(mixer);
+}
+
+Channel::Channel(SoundMixer *mixer, PlayingSoundHandle *handle, AudioStream *input,
+				bool autofreeStream, bool isMusic, bool reverseStereo, int id)
+	: _mixer(mixer), _handle(handle), _autofreeStream(autofreeStream), _isMusic(isMusic),
+	  _volume(255), _balance(0), _paused(false), _id(id), _converter(0), _input(input) {
+	assert(mixer);
+	assert(input);
+
+	// Get a rate converter instance
+	_converter = makeRateConverter(_input->getRate(), mixer->getOutputRate(), _input->isStereo(), reverseStereo);
+}
+
 Channel::~Channel() {
 	delete _converter;
-	delete _input;
+	if (_autofreeStream)
+		delete _input;
 	if (_handle)
-		*_handle = 0;
-}
-
-void Channel::destroy() {
-	for (int i = 0; i != SoundMixer::NUM_CHANNELS; i++)
-		if (_mixer->_channels[i] == this)
-			_mixer->_channels[i] = 0;
-	delete this;
+		_handle->resetIndex();
 }
 
 /* len indicates the number of sample *pairs*. So a value of
@@ -402,99 +437,52 @@
  */
 void Channel::mix(int16 *data, uint len) {
 	assert(_input);
-	if (_input->eos()) {
+
+	if (_input->endOfData()) {
 		// TODO: call drain method
-		destroy();
 	} else {
 		assert(_converter);
 
-		// The pan value ranges from -127 to +127. That's 255 different values.
-		// From the channel pan/volume and the global volume, we compute the
-		// effective volume for the left and right channel.
-		// Note the slightly odd divisor: the 255 reflects the fact that
-		// the maximal value for _volume is 255, while the 254 is there
-		// because the maximal left/right pan value is 2*127 = 254.
-		// The value getVolume() returns is in the range 0 - 256.
+		// From the channel balance/volume and the global volume, we compute
+		// the effective volume for the left and right channel. Note the
+		// slightly odd divisor: the 255 reflects the fact that the maximal
+		// value for _volume is 255, while the 127 is there because the
+		// balance value ranges from -127 to 127.  The mixer (music/sound)
+		// volume is in the range 0 - 256.
 		// Hence, the vol_l/vol_r values will be in that range, too
 		
-		int vol = getVolume() * _volume;
-		st_volume_t vol_l = (127 - _pan) * vol / (255 * 254);
-		st_volume_t vol_r = (127 + _pan) * vol / (255 * 254);
-
-		_converter->flow(*_input, data, len, vol_l, vol_r);
-	}
-}
+		int vol = _mixer->getVolume() * _volume;
+		st_volume_t vol_l, vol_r;
 
-/* RAW mixer */
-ChannelRaw::ChannelRaw(SoundMixer *mixer, PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, byte volume, int8 pan, int id, uint32 loopStart, uint32 loopEnd)
-	: Channel(mixer, handle) {
-	_id = id;
-	_ptr = (byte *)sound;
-	_volume = volume;
-	_pan = pan;
-	
-	// Create the input stream
-	if (flags & SoundMixer::FLAG_LOOP) {
-		if (loopEnd == 0) {
-			_input = makeLinearInputStream(flags, _ptr, size, 0, size);
+		if (_balance == 0) {
+			vol_l = vol / 255;
+			vol_r = vol / 255;
+		} else if (_balance < 0) {
+			vol_l = vol / 255;
+			vol_r = ((127 + _balance) * vol) / (255 * 127);
 		} else {
-			assert(loopStart < loopEnd && loopEnd <= size);
-			_input = makeLinearInputStream(flags, _ptr, size, loopStart, loopEnd - loopStart);
+			vol_l = ((127 - _balance) * vol) / (255 * 127);
+			vol_r = vol / 255;
 		}
-	} else {
-		_input = makeLinearInputStream(flags, _ptr, size, 0, 0);
-	}
-
-	// Get a rate converter instance
-	_converter = makeRateConverter(rate, mixer->getOutputRate(), _input->isStereo(), (flags & SoundMixer::FLAG_REVERSE_STEREO) != 0);
 
-	if (!(flags & SoundMixer::FLAG_AUTOFREE))
-		_ptr = 0;
-}
-
-ChannelRaw::~ChannelRaw() {
-	free(_ptr);
+		_converter->flow(*_input, data, len, vol_l, vol_r);
+	}
 }
 
 ChannelStream::ChannelStream(SoundMixer *mixer, PlayingSoundHandle *handle,
-							void *sound, uint32 size, uint rate,
-							byte flags, uint32 buffer_size, byte volume, int8 pan)
-	: Channel(mixer, handle) {
-	_volume = volume;
-	_pan = pan;
-	assert(size <= buffer_size);
-
+							uint rate, byte flags, uint32 buffer_size)
+	: Channel(mixer, handle, true) {
 	// Create the input stream
-	_input = makeWrappedInputStream(flags, buffer_size);
-	
-	// Append the initial data
-	((WrappedAudioInputStream *)_input)->append((const byte *)sound, size);
+	_input = makeAppendableAudioStream(rate, flags, buffer_size);
 
 	// Get a rate converter instance
-	_converter = makeRateConverter(rate, mixer->getOutputRate(), _input->isStereo(), (flags & SoundMixer::FLAG_REVERSE_STEREO) != 0);
-
-	_finished = false;
+	_converter = makeRateConverter(_input->getRate(), mixer->getOutputRate(), _input->isStereo(), (flags & SoundMixer::FLAG_REVERSE_STEREO) != 0);
 }
 
-void ChannelStream::append(void *data, uint32 len) {
-	((WrappedAudioInputStream *)_input)->append((const byte *)data, len);
+void ChannelStream::finish() {
+	((AppendableAudioStream *)_input)->finish();
 }
 
-void ChannelStream::mix(int16 *data, uint len) {
-	assert(_input);
-	if (_input->eos()) {
-		// TODO: call drain method
-
-		// Normally, the stream stays around even if all its data is used up.
-		// This is in case more data is streamed into it. To make the stream
-		// go away, one can either stop() it (which takes effect immediately,
-		// ignoring any remaining sound data), or finish() it, which means
-		// it will finish playing before it terminates itself.
-		if (_finished) {
-			destroy();
-		}
-	} else {
-		// Invoke the parent implementation.
-		Channel::mix(data, len);
-	}
+void ChannelStream::append(void *data, uint32 len) {
+	((AppendableAudioStream *)_input)->append((const byte *)data, len);
 }

Index: mixer.h
===================================================================
RCS file: /cvsroot/scummvm/residual/mixer/mixer.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- mixer.h	12 Dec 2003 21:38:12 -0000	1.2
+++ mixer.h	1 Feb 2004 10:48:44 -0000	1.3
@@ -22,13 +22,24 @@
 #include "../bits.h"
 #include <SDL.h>
 
-typedef uint32 PlayingSoundHandle;
-typedef void (*SoundProc)(void *param, byte *buf, int len);
-
+class AudioStream;
 class Channel;
 
-class SoundMixer {
+class PlayingSoundHandle {
 	friend class Channel;
+	friend class SoundMixer;
+	int val;
+	int getIndex() const { return val - 1; }
+	void setIndex(int i) { val = i + 1; }
+	void resetIndex() { val = 0; }
+public:
+	PlayingSoundHandle() { resetIndex(); }
+	bool isActive() const { return val > 0; }
+};
+
+typedef void (*SoundProc)(void *param, byte *buf, int len);
+
+class SoundMixer {
 public:
 	typedef void PremixProc (void *param, int16 *data, uint len);
 
@@ -37,12 +48,13 @@
 	};
 
 	enum {
-		FLAG_UNSIGNED = 1 << 0,         // unsigned samples (default: signed)
-		FLAG_STEREO = 1 << 1,           // sound is in stereo (default: mono)
-		FLAG_16BITS = 1 << 2,           // sound is 16 bits wide (default: 8bit)
-		FLAG_AUTOFREE = 1 << 3,         // sound buffer is freed automagically at the end of playing
-		FLAG_REVERSE_STEREO = 1 << 4,   // reverse the left and right stereo channel
-		FLAG_LOOP = 1 << 5              // loop the audio
+		FLAG_UNSIGNED = 1 << 0,         /** unsigned samples (default: signed) */
+		FLAG_16BITS = 1 << 1,           /** sound is 16 bits wide (default: 8bit) */
+		FLAG_LITTLE_ENDIAN = 1 << 2,    /** sample is little endian (default: big endian) */
+		FLAG_STEREO = 1 << 3,           /** sound is in stereo (default: mono) */
+		FLAG_REVERSE_STEREO = 1 << 4,   /** reverse the left and right stereo channel */
+		FLAG_AUTOFREE = 1 << 5,         /** sound buffer is freed automagically at the end of playing */
+		FLAG_LOOP = 1 << 6              /** loop the audio */
 	};
 
 private:
@@ -52,10 +64,9 @@
 	PremixProc *_premixProc;
 
 	uint _outputRate;
-
 	int _globalVolume;
-
 	bool _paused;
+	bool _mixerReady;
 
 	Channel *_channels[NUM_CHANNELS];
 
@@ -63,16 +74,18 @@
 	SoundMixer();
 	~SoundMixer();
 
-	void bindToSystem();
+	bool isReady() const { return _mixerReady; };
 
 	void setupPremix(PremixProc *proc, void *param);
 
 	// start playing a raw sound
-	int playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags,
-				int id = -1, byte volume = 255, int8 pan = 0, uint32 loopStart = 0, uint32 loopEnd = 0);
+	void playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags,
+				int id = -1, byte volume = 255, int8 balance = 0, uint32 loopStart = 0, uint32 loopEnd = 0);
+
+	void playInputStream(PlayingSoundHandle *handle, AudioStream *input, bool isMusic, byte volume = 255, int8 balance = 0, int id = -1, bool autofreeStream = true);
 
 	/** Start a new stream. */
-	int newStream(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, uint32 buffer_size, byte volume = 255, int8 pan = 0);
+	void newStream(PlayingSoundHandle *handle, uint rate, byte flags, uint32 buffer_size, byte volume = 255, int8 balance = 0);
 
 	/** Append to an existing stream. */
 	void appendStream(PlayingSoundHandle handle, void *sound, uint32 size);
@@ -83,9 +96,6 @@
 	/** stop all currently playing sounds */
 	void stopAll();
 
-	/** stop playing the given channel */
-	void stopChannel(int channel);
-
 	/** stop playing the sound with given ID  */
 	void stopID(int id);
 
@@ -95,9 +105,6 @@
 	/** pause/unpause all channels */
 	void pauseAll(bool paused);
 
-	/** pause/unpause the given channel */
-	void pauseChannel(int index, bool paused);
-
 	/** pause/unpause the sound with the given ID */
 	void pauseID(int id, bool paused);
 
@@ -107,8 +114,8 @@
 	/** set the channel volume for the given handle (0 - 255) */
 	void setChannelVolume(PlayingSoundHandle handle, byte volume);
 
-	/** set the channel pan for the given handle (-127 ... 0 ... 127) (left ... center ... right)*/
-	void setChannelPan(PlayingSoundHandle handle, int8 pan);
+	/** set the channel balance for the given handle (-127 ... 0 ... 127) (left ... center ... right)*/
+	void setChannelBalance(PlayingSoundHandle handle, int8 balance);
 
 	/** set the global volume, 0-256 */
 	void setVolume(int volume);
@@ -120,10 +127,12 @@
 	uint getOutputRate() const { return _outputRate; }
 
 private:
-	int insertChannel(PlayingSoundHandle *handle, Channel *chan);
+	bool setSoundProc(SoundProc proc, void *param);
+
+	void insertChannel(PlayingSoundHandle *handle, Channel *chan);
 
 	/** main mixer method */
-	void mix(int16 *buf, uint len);
+	void mix(int16 * buf, uint len);
 
 	static void mixCallback(void *s, byte *samples, int len);
 };

Index: rate.cpp
===================================================================
RCS file: /cvsroot/scummvm/residual/mixer/rate.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- rate.cpp	12 Dec 2003 21:17:31 -0000	1.1
+++ rate.cpp	1 Feb 2004 10:48:44 -0000	1.2
@@ -42,7 +42,6 @@
  */
 #define INTERMEDIATE_BUFFER_SIZE 512
 
-
 /**
  * Audio rate converter based on simple linear Interpolation.
  *
@@ -77,13 +76,12 @@
 
 public:
 	LinearRateConverter(st_rate_t inrate, st_rate_t outrate);
-	int flow(AudioInputStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r);
+	int flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r);
 	int drain(st_sample_t *obuf, st_size_t osamp, st_volume_t vol) {
 		return (ST_SUCCESS);
 	}
 };
 
-
 /*
  * Prepare processing.
  */
@@ -121,7 +119,7 @@
  * Return number of samples processed.
  */
 template<bool stereo, bool reverseStereo>
-int LinearRateConverter<stereo, reverseStereo>::flow(AudioInputStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) {
+int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) {
 	st_sample_t *ostart, *oend;
 	st_sample_t out[2];
 
@@ -188,21 +186,51 @@
  */
 template<bool stereo, bool reverseStereo>
 class CopyRateConverter : public RateConverter {
+	st_sample_t *_buffer;
+	st_size_t _bufferSize;
 public:
-	virtual int flow(AudioInputStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) {
-		int16 tmp[2];
-		st_size_t len = osamp;
+	CopyRateConverter() : _buffer(0), _bufferSize(0) {}
+	~CopyRateConverter() {
+		free(_buffer);
+	}
+
+	virtual int flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) {
 		assert(input.isStereo() == stereo);
-		while (!input.eos() && len--) {
-			tmp[0] = tmp[1] = input.read();
-			if (stereo)
-				tmp[reverseStereo ? 0 : 1] = input.read();
+		
+		st_sample_t *ptr;
+		st_size_t len;
+		
+		if (stereo)
+			osamp *= 2;
+
+		// Reallocate temp buffer, if necessary
+		if (osamp > _bufferSize) {
+			free(_buffer);
+			_buffer = (st_sample_t *)malloc(osamp * 2);
+			_bufferSize = osamp;
+		}
+
+		// Read up to 'osamp' samples into our temporary buffer
+		len = input.readBuffer(_buffer, osamp);
+		
+		// Mix the data into the output buffer
+		ptr = _buffer;
+		while (len--) {
+			st_sample_t tmp0, tmp1;
+			tmp0 = tmp1 = *ptr++;
+			if (stereo) {
+				if (reverseStereo)
+					tmp0 = *ptr++;
+				else
+					tmp1 = *ptr++;
+				len--;
+			}
 
 			// output left channel
-			clampedAdd(*obuf++, (tmp[0] * (int)vol_l) >> 8);
+			clampedAdd(*obuf++, (tmp0 * (int)vol_l) >> 8);
 	
 			// output right channel
-			clampedAdd(*obuf++, (tmp[1] * (int)vol_r) >> 8);
+			clampedAdd(*obuf++, (tmp1 * (int)vol_r) >> 8);
 		}
 		return (ST_SUCCESS);
 	}
@@ -223,6 +251,7 @@
 				return new LinearRateConverter<true, false>(inrate, outrate);
 		} else
 			return new LinearRateConverter<false, false>(inrate, outrate);
+		//return new ResampleRateConverter(inrate, outrate, 1);
 	} else {
 		if (stereo) {
 			if (reverseStereo)

Index: rate.h
===================================================================
RCS file: /cvsroot/scummvm/residual/mixer/rate.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- rate.h	12 Dec 2003 21:17:31 -0000	1.1
+++ rate.h	1 Feb 2004 10:48:44 -0000	1.2
@@ -20,7 +20,7 @@
 
 #include "../bits.h"
 
-class AudioInputStream;
+class AudioStream;
 
 typedef int16 st_sample_t;
 typedef uint16 st_volume_t;
@@ -64,7 +64,7 @@
 public:
 	RateConverter() {}
 	virtual ~RateConverter() {}
-	virtual int flow(AudioInputStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) = 0;
+	virtual int flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) = 0;
 	virtual int drain(st_sample_t *obuf, st_size_t osamp, st_volume_t vol) = 0;
 };
 





More information about the Scummvm-git-logs mailing list