[Scummvm-cvs-logs] CVS: scummvm/sound mixer.cpp,1.73,1.74 mixer.h,1.33,1.34

Max Horn fingolfin at users.sourceforge.net
Thu Jul 24 18:20:02 CEST 2003


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

Modified Files:
	mixer.cpp mixer.h 
Log Message:
lots of mixer changes: replaced _volumeTable by _globalVolume (applying volume after resampling is more accurate); made more member vars of SoundMixer protected (and thus added some new getter methods); added (untested) support for a second (stereo) channel when playing MP3

Index: mixer.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/mixer.cpp,v
retrieving revision 1.73
retrieving revision 1.74
diff -u -d -r1.73 -r1.74
--- mixer.cpp	23 Jul 2003 13:16:58 -0000	1.73
+++ mixer.cpp	25 Jul 2003 01:19:14 -0000	1.74
@@ -26,7 +26,6 @@
 #include "common/file.h"
 #include "common/util.h"
 
-
 class Channel {
 protected:
 	SoundMixer *_mixer;
@@ -41,6 +40,11 @@
 		if (_handle)
 			*_handle = 0;
 	}
+	
+	/* len indicates the number of sample *pairs*. So a value of
+	   10 means that the buffer contains twice 10 sample, each
+	   16 bits, for a total of 40 bytes.
+	 */
 	virtual void mix(int16 *data, uint len) = 0;
 	void destroy() {
 		for (int i = 0; i != SoundMixer::NUM_CHANNELS; i++)
@@ -54,12 +58,12 @@
 
 class ChannelRaw : public Channel {
 	byte *_ptr;
+	byte _flags;
 	uint32 _pos;
 	uint32 _size;
 	uint32 _fpSpeed;
 	uint32 _fpPos;
 	uint32 _realSize, _rate;
-	byte _flags;
 	byte *_loop_ptr;
 	uint32 _loop_size;
 
@@ -170,7 +174,7 @@
 
 	_outputRate = 0;
 
-	_volumeTable = (int16 *)calloc(256 * sizeof(int16), 1);
+	_globalVolume = 0;
 	_musicVolume = 0;
 
 	_paused = false;
@@ -181,13 +185,17 @@
 
 SoundMixer::~SoundMixer() {
 	_syst->clear_sound_proc();
-	free(_volumeTable);
 	for (int i = 0; i != NUM_CHANNELS; i++) {
 		delete _channels[i];
 	}
 	_syst->delete_mutex(_mutex);
 }
 
+int SoundMixer::newStream(void *sound, uint32 size, uint rate, byte flags, uint32 buffer_size) {
+	StackLock lock(_mutex);
+	return insertChannel(NULL, new ChannelStream(this, 0, sound, size, rate, flags, buffer_size));
+}
+
 void SoundMixer::appendStream(int index, void *sound, uint32 size) {
 	StackLock lock(_mutex);
 
@@ -253,11 +261,6 @@
 	return insertChannel(handle, new ChannelRaw(this, handle, sound, size, rate, flags, id));
 }
 
-int SoundMixer::newStream(void *sound, uint32 size, uint rate, byte flags, uint32 buffer_size) {
-	StackLock lock(_mutex);
-	return insertChannel(NULL, new ChannelStream(this, 0, sound, size, rate, flags, buffer_size));
-}
-
 #ifdef USE_MAD
 int SoundMixer::playMP3(PlayingSoundHandle *handle, void *sound, uint32 size, byte flags) {
 	StackLock lock(_mutex);
@@ -298,7 +301,11 @@
 	}
 }
 
-void SoundMixer::onGenerateSamples(void *s, byte *samples, int len) {
+void SoundMixer::mixCallback(void *s, byte *samples, int len) {
+	assert(s);
+	assert(samples);
+	// Len is the number of bytes in the buffer; we divide it by
+	// four to get the number of samples (stereo 16 bit).
 	((SoundMixer *)s)->mix((int16 *)samples, len >> 2);
 }
 
@@ -311,7 +318,7 @@
 	if (rate == 0)
 		error("OSystem returned invalid sample rate");
 
-	return syst->set_sound_proc(onGenerateSamples, this, OSystem::SOUND_16BIT);
+	return syst->set_sound_proc(mixCallback, this, OSystem::SOUND_16BIT);
 }
 
 void SoundMixer::stopAll() {
@@ -376,13 +383,18 @@
 	return false;
 }
 
-bool SoundMixer::isActiveChannel(int index) {
+bool SoundMixer::isChannelActive(int index) {
 	StackLock lock(_mutex);
 	if (_channels[index])
 		return _channels[index]->isActive();
 	return false;
 }
 
+bool SoundMixer::isChannelUsed(int index) {
+	StackLock lock(_mutex);
+	return (_channels[index] != NULL);
+}
+
 void SoundMixer::setupPremix(void *param, PremixProc *proc) {
 	StackLock lock(_mutex);
 	_premixParam = param;
@@ -390,20 +402,13 @@
 }
 
 void SoundMixer::setVolume(int volume) {
-	int i;
-
 	// Check range
 	if (volume > 256)
 		volume = 256;
 	else if (volume < 0)
 		volume = 0;
 
-	// The volume table takes 8 bit unsigned data as index and returns 16 bit signed
-	for (i = 0; i < 128; i++)
-		_volumeTable[i] = i * volume;
-
-	for (i = -128; i < 0; i++)
-		_volumeTable[i + 256] = i * volume;
+	_globalVolume = volume;
 }
 
 void SoundMixer::setMusicVolume(int volume) {
@@ -481,13 +486,13 @@
 }
 
 static void mix_signed_mono_8(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
-								int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
+								int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
 	int inc = 1, result;
-	CubicInterpolator interp(vol_tab[*s], vol_tab[*(s + 1)], vol_tab[*(s + 2)]);
+	CubicInterpolator interp(*s, *(s + 1), *(s + 2));
 
 	do {
 		do {
-			result = interp.interpolate(fp_pos);
+			result = interp.interpolate(fp_pos) * volume / 256;
 
 			clamped_add_16(*data++, result);
 			clamped_add_16(*data++, result);
@@ -500,7 +505,7 @@
 		} while (!inc && len && (s < s_end));
 
 		if (s + 2 < s_end)
-			interp.feedData(vol_tab[*(s + 2)]);
+			interp.feedData(*(s + 2));
 		else
 			interp.feedData();
 
@@ -508,13 +513,13 @@
 }
 
 static void mix_unsigned_mono_8(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
-											int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
+											int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
 	int inc = 1, result;
-	CubicInterpolator interp(vol_tab[*s ^ 0x80], vol_tab[*(s + 1) ^ 0x80], vol_tab[*(s + 2) ^ 0x80]);
+	CubicInterpolator interp(*s ^ 0x80, *(s + 1) ^ 0x80, *(s + 2) ^ 0x80);
 
 	do {
 		do {
-			result = interp.interpolate(fp_pos);
+			result = interp.interpolate(fp_pos) * volume / 256;
 
 			clamped_add_16(*data++, result);
 			clamped_add_16(*data++, result);
@@ -527,7 +532,7 @@
 		} while (!inc && len && (s < s_end));
 
 		if (s + 2 < s_end)
-			interp.feedData(vol_tab[*(s + 2) ^ 0x80]);
+			interp.feedData(*(s + 2) ^ 0x80);
 		else
 			interp.feedData();
 
@@ -535,23 +540,23 @@
 }
 
 static void mix_signed_stereo_8(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
-										int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
+										int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
 	warning("Mixing stereo signed 8 bit is not supported yet ");
 }
 static void mix_unsigned_stereo_8(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
-										int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
+										int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
 	int inc = 1;
-	CubicInterpolator	left(vol_tab[*s ^ 0x80], vol_tab[*(s + 2) ^ 0x80], vol_tab[*(s + 4) ^ 0x80]);
-	CubicInterpolator	right(vol_tab[*(s + 1) ^ 0x80], vol_tab[*(s + 3) ^ 0x80], vol_tab[*(s + 5) ^ 0x80]);
+	CubicInterpolator	left(*s ^ 0x80, *(s + 2) ^ 0x80, *(s + 4) ^ 0x80);
+	CubicInterpolator	right(*(s + 1) ^ 0x80, *(s + 3) ^ 0x80, *(s + 5) ^ 0x80);
 
 	do {
 		do {
 			if (!reverse_stereo) {
-				clamped_add_16(*data++, left.interpolate(fp_pos));
-				clamped_add_16(*data++, right.interpolate(fp_pos));
+				clamped_add_16(*data++, left.interpolate(fp_pos) * volume / 256);
+				clamped_add_16(*data++, right.interpolate(fp_pos) * volume / 256);
 			} else {
-				clamped_add_16(*data++, right.interpolate(fp_pos));
-				clamped_add_16(*data++, left.interpolate(fp_pos));
+				clamped_add_16(*data++, right.interpolate(fp_pos) * volume / 256);
+				clamped_add_16(*data++, left.interpolate(fp_pos) * volume / 256);
 			}
 
 			fp_pos += fp_speed;
@@ -562,8 +567,8 @@
 		} while (!inc && len && (s < s_end));
 
 		if (s + 5 < s_end) {
-			left.feedData(vol_tab[*(s + 4) ^ 0x80]);
-			right.feedData(vol_tab[*(s + 5) ^ 0x80]);
+			left.feedData(*(s + 4) ^ 0x80);
+			right.feedData(*(s + 5) ^ 0x80);
 		} else {
 			left.feedData();
 			right.feedData();
@@ -572,8 +577,7 @@
 	} while (len && (s < s_end));
 }
 static void mix_signed_mono_16(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
-										 int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
-	unsigned char volume = ((int)vol_tab[1]);
+										 int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
 	do {
 		int16 sample = ((int16)READ_BE_UINT16(s) * volume) / 256;
 		fp_pos += fp_speed;
@@ -586,13 +590,11 @@
 	} while ((--len) && (s < s_end));
 }
 static void mix_unsigned_mono_16(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
-										 int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
+										 int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
 	warning("Mixing mono unsigned 16 bit is not supported yet ");
 }
 static void mix_signed_stereo_16(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
-										 int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
-	unsigned char volume = (int)vol_tab[1];
-
+										 int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
 	do {
 		int16 leftS = ((int16)READ_BE_UINT16(s) * volume) / 256;
 		int16 rightS = ((int16)READ_BE_UINT16(s+2) * volume) / 256;
@@ -610,12 +612,12 @@
 	} while ((--len) && (s < s_end));
 }
 static void mix_unsigned_stereo_16(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
-											 int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
+											 int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
 	warning("Mixing stereo unsigned 16 bit is not supported yet ");
 }
 
 typedef void MixProc(int16 *data, uint &len, byte *&s,
-                      uint32 &fp_pos, int fp_speed, const int16 *vol_tab,
+                      uint32 &fp_pos, int fp_speed, int volume,
                       byte *s_end, bool reverse_stereo);
 
 static MixProc *mixer_helper_table[8] = {
@@ -641,11 +643,12 @@
 ChannelRaw::ChannelRaw(SoundMixer *mixer, PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id)
 	: Channel(mixer, handle) {
 	_id = id;
-	_flags = flags;
 	_ptr = (byte *)sound;
+	_flags = flags;
+
 	_pos = 0;
 	_fpPos = 0;
-	_fpSpeed = (1 << 16) * rate / mixer->_outputRate;
+	_fpSpeed = (1 << 16) * rate / mixer->getOutputRate();
 	_realSize = size;
 
 	// adjust the magnitude to prevent division error
@@ -653,7 +656,7 @@
 		size >>= 1, rate = (rate >> 1) + 1;
 
 	_rate = rate;
-	_size = size * mixer->_outputRate / rate;
+	_size = size * mixer->getOutputRate() / rate;
 	if (_flags & SoundMixer::FLAG_16BITS)
 		_size = _size >> 1;
 	if (_flags & SoundMixer::FLAG_STEREO)
@@ -680,9 +683,7 @@
 	s = _ptr + _pos;
 	end = _ptr + _realSize;
 
-	const int16 *vol_tab = _mixer->_volumeTable;
-
-	mixer_helper_table[_flags & 0x07] (data, len, s, _fpPos, _fpSpeed, vol_tab, end, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
+	mixer_helper_table[_flags & 0x07] (data, len, s, _fpPos, _fpSpeed, _mixer->getVolume(), end, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
 
 	_pos = s - _ptr;
 
@@ -712,7 +713,7 @@
 	_endOfBuffer = _ptr + _bufferSize;
 	_pos = _ptr;
 	_fpPos = 0;
-	_fpSpeed = (1 << 16) * rate / mixer->_outputRate;
+	_fpSpeed = (1 << 16) * rate / mixer->getOutputRate();
 	_finished = false;
 
 	// adjust the magnitude to prevent division error
@@ -768,11 +769,10 @@
 		return;
 	}
 
-	const int16 *vol_tab = _mixer->_volumeTable;
 	MixProc *mixProc = mixer_helper_table[_flags & 0x07];
 
 	if (_pos < _endOfData) {
-		mixProc(data, len, _pos, _fpPos, _fpSpeed, vol_tab, _endOfData, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
+		mixProc(data, len, _pos, _fpPos, _fpSpeed, _mixer->getVolume(), _endOfData, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
 	} else {
 		int wrapOffset = 0;
 		const uint32 outLen = mixer_element_size[_flags & 0x07] * len;
@@ -785,7 +785,7 @@
 			memcpy(_endOfBuffer, _ptr, wrapOffset);
 		}
 
-		mixProc(data, len, _pos, _fpPos, _fpSpeed, vol_tab, _endOfBuffer + wrapOffset, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
+		mixProc(data, len, _pos, _fpPos, _fpSpeed, _mixer->getVolume(), _endOfBuffer + wrapOffset, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
 
 		// recover from wrap
 		if (wrapOffset)
@@ -796,7 +796,7 @@
 			//FIXME: what is wrong ?
 			warning("bad play sound in stream (wrap around)");
 			_pos = _ptr;
-			mixProc(data, len, _pos, _fpPos, _fpSpeed, vol_tab, _endOfData, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
+			mixProc(data, len, _pos, _fpPos, _fpSpeed, _mixer->getVolume(), _endOfData, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
 		}
 	}
 }
@@ -861,12 +861,9 @@
 }
 
 void ChannelMP3::mix(int16 *data, uint len) {
-	mad_fixed_t const * ch;
-	const int16 * vol_tab = _mixer->_volumeTable;
-	unsigned char volume = ((int)vol_tab[1]) / 8;
+	const int volume = _mixer->getVolume();
 
 	while (1) {
-		ch = _synth.pcm.samples[0] + _posInFrame;
 
 		/* Skip _silence_cut a the start */
 		if ((_posInFrame < _synth.pcm.length) && (_silenceCut > 0)) {
@@ -875,13 +872,15 @@
 			if (diff > _silenceCut)
 				diff = _silenceCut;
 			_silenceCut -= diff;
-			ch += diff;
 			_posInFrame += diff;
 		}
 
+		int16 sample;
 		while ((_posInFrame < _synth.pcm.length) && (len > 0)) {
-			int16 sample = (int16)((scale_sample(*ch++) * volume) / 32);
+			sample = (int16)((scale_sample(_synth.pcm.samples[0][_posInFrame]) * volume) / 256);
 			clamped_add_16(*data++, sample);
+			if (_synth.pcm.channels > 1)
+				sample = (int16)((scale_sample(_synth.pcm.samples[1][_posInFrame]) * volume) / 256);
 			clamped_add_16(*data++, sample);
 			len--;
 			_posInFrame++;
@@ -925,16 +924,15 @@
 }
 
 void ChannelMP3CDMusic::mix(int16 *data, uint len) {
-	mad_fixed_t const *ch;
 	mad_timer_t frame_duration;
-	unsigned char volume = _mixer->_musicVolume / 8;
+	int volume = _mixer->getMusicVolume();
 
 	if (!_initialized) {
 		int skip_loop;
 		// just skipped
 		memset(_ptr, 0, _bufferSize);
 		_size = _file->read(_ptr, _bufferSize);
-		if (!_size) {
+		if (_size <= 0) {
 			destroy();
 			return;
 		}
@@ -971,18 +969,24 @@
 	}
 
 	while (1) {
+	
+		// TODO: Check _synth.pcm.samplerate and perform rate conversion of appropriate
+		// TODO: Check _synth.pcm.channels to support stereo
+
 		// Get samples, play samples ...
-		ch = _synth.pcm.samples[0] + _posInFrame;
+		int16 sample;
 		while ((_posInFrame < _synth.pcm.length) && (len > 0)) {
-			int16 sample = (int16)((scale_sample(*ch++) * volume) / 32);
+			sample = (int16)((scale_sample(_synth.pcm.samples[0][_posInFrame]) * volume) / 256);
 			clamped_add_16(*data++, sample);
+			if (_synth.pcm.channels > 1)
+				sample = (int16)((scale_sample(_synth.pcm.samples[1][_posInFrame]) * volume) / 256);
 			clamped_add_16(*data++, sample);
 			len--;
 			_posInFrame++;
 		}
-		if (len == 0) {
+		if (len == 0)
 			return;
-		}
+
 		// See if we have finished
 		// May be incorrect to check the size at the end of a frame but I suppose
 		// they are short enough :)
@@ -1051,7 +1055,7 @@
 	uint len_left = len * channels * 2;
 	int16 *samples = new int16[len_left / 2];
 	char *read_pos = (char *) samples;
-	int volume = _is_cd_track ? _mixer->_musicVolume : _mixer->_volumeTable[1];
+	int volume = _is_cd_track ? _mixer->getMusicVolume() : _mixer->getVolume();
 
 	// Read the samples
 	while (len_left > 0) {

Index: mixer.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/mixer.h,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- mixer.h	24 Jul 2003 21:26:46 -0000	1.33
+++ mixer.h	25 Jul 2003 01:19:14 -0000	1.34
@@ -43,6 +43,7 @@
 class File;
 
 class SoundMixer {
+	friend class Channel;
 public:
 	typedef void PremixProc (void *param, int16 *data, uint len);
 
@@ -50,6 +51,16 @@
 		NUM_CHANNELS = 16
 	};
 
+	enum {
+		// Do *NOT* change any of these flags without looking at the code in mixer.cpp
+		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
+	};
+
 private:
 	OSystem *_syst;
 	OSystem::MutexRef _mutex;
@@ -57,10 +68,9 @@
 	void *_premixParam;
 	PremixProc *_premixProc;
 
-public:
 	uint _outputRate;
 
-	int16 *_volumeTable;
+	int _globalVolume;
 	int _musicVolume;
 
 	bool _paused;
@@ -72,15 +82,6 @@
 	~SoundMixer();
 
 	// start playing a raw sound
-	enum {
-		// Do *NOT* change any of these flags without looking at the code in mixer.cpp
-		FLAG_UNSIGNED = 1 << 0,         // unsigned samples
-		FLAG_STEREO = 1 << 1,           // sound is in stereo
-		FLAG_16BITS = 1 << 2,           // sound is 16 bits wide
-		FLAG_AUTOFREE = 1 << 3,         // sound buffer is freed automagically at the end of playing
-		FLAG_REVERSE_STEREO = 1 << 4,   // sound should be reverse stereo
-		FLAG_LOOP = 1 << 5              // loop the audio
-	};
 	int playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id = -1);
 #ifdef USE_MAD
 	int playMP3(PlayingSoundHandle *handle, void *sound, uint32 size, byte flags);
@@ -118,21 +119,33 @@
 	bool hasActiveSFXChannel();
 	
 	/** Check whether the specified channel is active. */
-	bool isActiveChannel(int index);
+	bool isChannelActive(int index);
+
+	/** Check whether the specified channel is in use. */
+	bool isChannelUsed(int index);
 
 	/** bind to the OSystem object => mixer will be
 	 * invoked automatically when samples need
 	 * to be generated */
 	bool bindToSystem(OSystem *syst);
 
+	/** pause - unpause */
+	void pause(bool paused);
+
 	/** set the global volume, 0-256 */
 	void setVolume(int volume);
+	
+	/** query the global volume, 0-256 */
+	int getVolume() const { return _globalVolume; }
 
 	/** set the music volume, 0-256 */
 	void setMusicVolume(int volume);
-
-	/** pause - unpause */
-	void pause(bool paused);
+	
+	/** query the music volume, 0-256 */
+	int getMusicVolume() const { return _musicVolume; }
+	
+	/** query the output rate in kHz */
+	uint getOutputRate() const { return _outputRate; }
 
 private:
 	int insertChannel(PlayingSoundHandle *handle, Channel *chan);
@@ -140,7 +153,7 @@
 	/** mix */
 	void mix(int16 * buf, uint len);
 
-	static void onGenerateSamples(void *s, byte *samples, int len);
+	static void mixCallback(void *s, byte *samples, int len);
 };
 
 #endif





More information about the Scummvm-git-logs mailing list