[Scummvm-cvs-logs] CVS: residual/mixer mixer.cpp,1.5,1.6 mixer.h,1.4,1.5

Pawel Kolodziejski aquadran at users.sourceforge.net
Fri Dec 10 17:55:33 CET 2004


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

Modified Files:
	mixer.cpp mixer.h 
Log Message:
synced mixer with main tree and adapt code

Index: mixer.cpp
===================================================================
RCS file: /cvsroot/scummvm/residual/mixer/mixer.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- mixer.cpp	10 Dec 2004 20:33:31 -0000	1.5
+++ mixer.cpp	10 Dec 2004 21:13:02 -0000	1.6
@@ -33,11 +33,13 @@
 	SoundMixer *_mixer;
 	PlayingSoundHandle *_handle;
 	bool _autofreeStream;
-	const bool _isMusic;
+	bool _permanent;
 	byte _volume;
 	int8 _balance;
 	bool _paused;
 	int _id;
+	uint32 _samplesConsumed;
+	uint32 _samplesDecoded;
 
 protected:
 	RateConverter *_converter;
@@ -46,17 +48,17 @@
 public:
 
 	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);
+	Channel(SoundMixer *mixer, PlayingSoundHandle *handle, AudioStream *input, bool autofreeStream, bool isMusic, bool reverseStereo = false, int id = -1, bool permanent = false);
 	virtual ~Channel();
 
 	void mix(int16 *data, uint len);
 
+	bool isPermanent() const {
+		return _permanent;
+	}
 	bool isFinished() const {
 		return _input->endOfStream();
 	}
-	bool isMusicChannel() const {
-		return _isMusic;
-	}
 	void pause(bool paused) {
 		_paused = paused;
 	}
@@ -72,20 +74,13 @@
 	int getId() const {
 		return _id;
 	}
+	uint32 getElapsedTime();
 };
 
-class ChannelStream : public Channel {
-public:
-	ChannelStream(SoundMixer *mixer, PlayingSoundHandle *handle, uint rate, byte flags, uint32 buffer_size);
-	void append(void *sound, uint32 size);
-
-	void finish();
-};
 
 SoundMixer::SoundMixer() {
 	_mutex = createMutex();
-	_premixParam = NULL;
-	_premixProc = NULL;
+	_premixChannel = NULL;
 	_outputRate = 22050;
 	_globalVolume = 0;
 	_paused = false;
@@ -98,16 +93,23 @@
 
 SoundMixer::~SoundMixer() {
 	SDL_CloseAudio();
-	stopAll();
+	stopAll(true);
+
+	delete _premixChannel;
+	_premixChannel = NULL;
+
 	deleteMutex(_mutex);
 }
 
+bool SoundMixer::isPaused() {
+	return _paused;
+}
+
 bool SoundMixer::setSoundProc(SoundProc proc, void *param) {
 	SDL_AudioSpec desired;
 
 	memset(&desired, 0, sizeof(desired));
 
-	/* only one format supported at the moment */
 	desired.freq = 22050;
 	desired.format = AUDIO_S16SYS;
 	desired.channels = 2;
@@ -123,76 +125,29 @@
 	return true;
 }
 
-void SoundMixer::setupPremix(PremixProc *proc, void *param) {
-	StackLock lock(_mutex);
-	_premixParam = param;
-	_premixProc = proc;
-}
-
-void SoundMixer::newStream(PlayingSoundHandle *handle, uint rate, byte flags, uint32 buffer_size, byte volume, int8 balance) {
-	StackLock lock(_mutex);
-
-	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.isActive())
-		return;
-
-	int index = handle.getIndex();
-
-	if ((index < 0) || (index >= NUM_CHANNELS)) {
-		warning("soundMixer::appendStream has invalid index %d", index);
-		return;
-	}
-
-	ChannelStream *chan;
-	chan = dynamic_cast<ChannelStream *>(_channels[index]);
-	if (!chan) {
-		error("Trying to append to nonexistant stream : %d", index);
-	} else {
-		chan->append(sound, size);
-	}
-}
-
-void SoundMixer::endStream(PlayingSoundHandle handle) {
+void SoundMixer::setupPremix(AudioStream *stream) {
 	StackLock lock(_mutex);
 
-	// Simply ignore stop requests for handles of sounds that already terminated
-	if (!handle.isActive())
-		return;
-
-	int index = handle.getIndex();
+	delete _premixChannel;
+	_premixChannel = NULL;
 
-	if ((index < 0) || (index >= NUM_CHANNELS)) {
-		warning("soundMixer::endStream has invalid index %d", index);
+	if (stream == NULL)
 		return;
-	}
 
-	ChannelStream *chan;
-	chan = dynamic_cast<ChannelStream *>(_channels[index]);
-	if (!chan) {
-		error("Trying to end a nonexistant streamer : %d", index);
-	} else {
-		chan->finish();
-	}
+	// Create the channel
+	_premixChannel = new Channel(this, NULL, stream, false, true);
 }
 
 void SoundMixer::insertChannel(PlayingSoundHandle *handle, Channel *chan) {
-
 	int index = -1;
+
 	for (int i = 0; i != NUM_CHANNELS; i++) {
-		if (_channels[i] == 0) {
+		if (_channels[i] == NULL) {
 			index = i;
 			break;
 		}
 	}
-	if(index == -1) {
+	if (index == -1) {
 		warning("SoundMixer::out of mixer slots");
 		delete chan;
 		return;
@@ -203,13 +158,14 @@
 		handle->setIndex(index);
 }
 
-void SoundMixer::playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id, byte volume, int8 balance, 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] != 0 && _channels[i]->getId() == id) {
+			if (_channels[i] != NULL && _channels[i]->getId() == id) {
 				if ((flags & SoundMixer::FLAG_AUTOFREE) != 0)
 					free(sound);
 				return;
@@ -236,18 +192,19 @@
 	insertChannel(handle, chan);
 }
 
-void SoundMixer::playInputStream(PlayingSoundHandle *handle, AudioStream *input, bool isMusic, byte volume, int8 balance, int id, bool autofreeStream) {
+void SoundMixer::playInputStream(PlayingSoundHandle *handle, AudioStream *input, bool isMusic,
+			int id, byte volume, int8 balance, bool autofreeStream, bool permanent) {
 	StackLock lock(_mutex);
 
-	if (input == 0) {
-		warning("input stream is 0");
+	if (input == NULL) {
+		warning("input stream is NULL");
 		return;
 	}
 
 	// Prevent duplicate sounds
 	if (id != -1) {
 		for (int i = 0; i != NUM_CHANNELS; i++)
-			if (_channels[i] != 0 && _channels[i]->getId() == id) {
+			if (_channels[i] != NULL && _channels[i]->getId() == id) {
 				if (autofreeStream)
 					delete input;
 				return;
@@ -255,7 +212,7 @@
 	}
 
 	// Create the channel
-	Channel *chan = new Channel(this, handle, input, autofreeStream, isMusic, false, id);
+	Channel *chan = new Channel(this, handle, input, autofreeStream, isMusic, false, id, permanent);
 	chan->setVolume(volume);
 	chan->setBalance(balance);
 	insertChannel(handle, chan);
@@ -268,18 +225,19 @@
 	memset(buf, 0, 2 * len * sizeof(int16));
 
 	if (!_paused) {
-		if (_premixProc)
-			_premixProc(_premixParam, buf, len);
+		if (_premixChannel)
+			_premixChannel->mix(buf, len);
 
 		// now mix all channels
-		for (int i = 0; i != NUM_CHANNELS; i++)
+		for (int i = 0; i != NUM_CHANNELS; i++) {
 			if (_channels[i]) {
 				if (_channels[i]->isFinished()) {
 					delete _channels[i];
-					_channels[i] = 0;
+					_channels[i] = NULL;
 				} else if (!_channels[i]->isPaused())
 					_channels[i]->mix(buf, len);
 			}
+		}
 	}
 }
 
@@ -291,21 +249,24 @@
 	((SoundMixer *)s)->mix((int16 *)samples, len >> 2);
 }
 
-void SoundMixer::stopAll() {
+void SoundMixer::stopAll(bool force) {
 	StackLock lock(_mutex);
-	for (int i = 0; i != NUM_CHANNELS; i++)
-		if (_channels[i] != 0) {
-			delete _channels[i];
-			_channels[i] = 0;
+	for (int i = 0; i != NUM_CHANNELS; i++) {
+		if (_channels[i] != NULL) {
+			if (force || !_channels[i]->isPermanent()) {
+				delete _channels[i];
+				_channels[i] = NULL;
+			}
 		}
+	}
 }
 
 void SoundMixer::stopID(int id) {
 	StackLock lock(_mutex);
 	for (int i = 0; i != NUM_CHANNELS; i++) {
-		if (_channels[i] != 0 && _channels[i]->getId() == id) {
+		if (_channels[i] != NULL && _channels[i]->getId() == id) {
 			delete _channels[i];
-			_channels[i] = 0;
+			_channels[i] = NULL;
 		}
 	}
 }
@@ -326,7 +287,7 @@
 
 	if (_channels[index]) {
 		delete _channels[index];
-		_channels[index] = 0;
+		_channels[index] = NULL;
 	}
 }
 
@@ -371,7 +332,7 @@
 void SoundMixer::pauseID(int id, bool paused) {
 	StackLock lock(_mutex);
 	for (int i = 0; i != NUM_CHANNELS; i++) {
-		if (_channels[i] != 0 && _channels[i]->getId() == id) {
+		if (_channels[i] != NULL && _channels[i]->getId() == id) {
 			_channels[i]->pause(paused);
 			return;
 		}
@@ -396,26 +357,37 @@
 		_channels[index]->pause(paused);
 }
 
+bool SoundMixer::isSoundIDActive(int id) {
+	StackLock lock(_mutex);
+	for (int i = 0; i != NUM_CHANNELS; i++)
+		if (_channels[i] && _channels[i]->getId() == id)
+			return true;
+	return false;
+}
+
 void SoundMixer::setVolume(int volume) {
 	// Check range
 	if (volume > 256)
 		volume = 256;
 	else if (volume < 0)
 		volume = 0;
-
+	
 	_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) {
+	: _mixer(mixer), _handle(handle), _autofreeStream(true),
+	  _volume(255), _balance(0), _paused(false), _id(id), _samplesConsumed(0),
+	  _samplesDecoded(0), _converter(0), _input(NULL) {
 	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) {
+				bool autofreeStream, bool isMusic, bool reverseStereo, int id, bool permanent)
+	: _mixer(mixer), _handle(handle), _autofreeStream(autofreeStream),
+	  _volume(255), _balance(0), _paused(false), _id(id), _samplesConsumed(0),
+	  _samplesDecoded(0), _converter(0), _input(input), _permanent(permanent) {
 	assert(mixer);
 	assert(input);
 
@@ -465,24 +437,10 @@
 			vol_r = vol / 255;
 		}
 
-		_converter->flow(*_input, data, len, vol_l, vol_r);
-	}
-}
-
-ChannelStream::ChannelStream(SoundMixer *mixer, PlayingSoundHandle *handle,
-							uint rate, byte flags, uint32 buffer_size)
-	: Channel(mixer, handle, true) {
-	// Create the input stream
-	_input = makeAppendableAudioStream(rate, flags, buffer_size);
-
-	// Get a rate converter instance
-	_converter = makeRateConverter(_input->getRate(), mixer->getOutputRate(), _input->isStereo(), (flags & SoundMixer::FLAG_REVERSE_STEREO) != 0);
-}
+		_samplesConsumed = _samplesDecoded;
 
-void ChannelStream::finish() {
-	((AppendableAudioStream *)_input)->finish();
-}
+		_converter->flow(*_input, data, len, vol_l, vol_r);
 
-void ChannelStream::append(void *data, uint32 len) {
-	((AppendableAudioStream *)_input)->append((const byte *)data, len);
+		_samplesDecoded += len;
+	}
 }

Index: mixer.h
===================================================================
RCS file: /cvsroot/scummvm/residual/mixer/mixer.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- mixer.h	24 Feb 2004 08:20:45 -0000	1.4
+++ mixer.h	10 Dec 2004 21:13:03 -0000	1.5
@@ -37,103 +37,219 @@
 	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);
-
 	enum {
-		NUM_CHANNELS = 16
+		/** unsigned samples (default: signed) */
+		FLAG_UNSIGNED = 1 << 0,
+
+		/** sound is 16 bits wide (default: 8bit) */
+		FLAG_16BITS = 1 << 1,
+
+		/** sample is little endian (default: big endian) */
+		FLAG_LITTLE_ENDIAN = 1 << 2,
+
+		/** sound is in stereo (default: mono) */
+		FLAG_STEREO = 1 << 3,
+
+		/** reverse the left and right stereo channel */
+		FLAG_REVERSE_STEREO = 1 << 4,
+
+		/** sound buffer is freed automagically at the end of playing */
+		FLAG_AUTOFREE = 1 << 5,
+
+		/** loop the audio */
+		FLAG_LOOP = 1 << 6
 	};
 
+private:
 	enum {
-		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 */
+		NUM_CHANNELS = 16
 	};
 
-private:
 	MutexRef _mutex;
 
-	void *_premixParam;
-	PremixProc *_premixProc;
+	Channel *_premixChannel;
 
 	uint _outputRate;
+
 	int _globalVolume;
-	bool _paused;
-	bool _mixerReady;
 
+	bool _paused;
+	
 	Channel *_channels[NUM_CHANNELS];
 
+	bool _mixerReady;
+
 public:
 	SoundMixer();
 	~SoundMixer();
 
+
+
+	/**
+	 * Is the mixer ready and setup? This may not be the case on systems which
+	 * don't support digital sound output. In that case, the mixer proc may
+	 * never be called. That in turn can cause breakage in games which use the
+	 * premix callback for syncing. In particular, the Adlib MIDI emulation...
+	 *
+	 * @return whether the mixer is ready and setup
+	 */
 	bool isReady() const { return _mixerReady; };
 
-	void setupPremix(PremixProc *proc, void *param);
 
-	// start playing a raw sound
-	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);
+	/**
+	 * Set the premix stream. This is mainly used for the adlib music, but
+	 * is not limited to it. The premix stream is invoked by the mixer whenever
+	 * it needs to generate any data, before any other mixing takes place.
+	 */
+	void setupPremix(AudioStream *stream);
 
-	/** Start a new stream. */
-	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);
 
-	/** Mark a stream as finished - it will play all its remaining data, then stop. */
-	void endStream(PlayingSoundHandle handle);
+	/**
+	 * Start playing the given raw sound data.
+	 * Internally, this simply creates an audio input stream wrapping the data
+	 * (using the makeLinearInputStream factory function), which is then
+	 * passed on to playInputStream.
+	 */
+	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);
 
-	/** stop all currently playing sounds */
-	void stopAll();
+	/**
+	 * Start playing the given audio input stream.
+	 */
+	void playInputStream(PlayingSoundHandle *handle, AudioStream *input, bool isMusic,
+				int id = -1, byte volume = 255, int8 balance = 0,
+				bool autofreeStream = true, bool permanent = false);
 
-	/** stop playing the sound with given ID  */
+
+
+	/**
+	 * Stop all currently playing sounds.
+	 */
+	void stopAll(bool force = false);
+
+	/**
+	 * Stop playing the sound with given ID.
+	 *
+	 * @param id the ID of the sound to affect
+	 */
 	void stopID(int id);
 
-	/** stop playing the channel for the given handle */
+	/**
+	 * Stop playing the sound corresponding to the given handle.
+	 *
+	 * @param handle the sound to affect
+	 */
 	void stopHandle(PlayingSoundHandle handle);
 
-	/** pause/unpause all channels */
+
+
+	/**
+	 * Pause/unpause the mixer (this temporarily stops all audio processing,
+	 * including all regular channels and the premix channel).
+	 *
+	 * @param paused true to pause the mixer, false to unpause it
+	 */
 	void pauseAll(bool paused);
 
-	/** pause/unpause the sound with the given ID */
+	/**
+	 * Pause/unpause the sound with the given ID.
+	 *
+	 * @param id the ID of the sound to affect
+	 * @param paused true to pause the sound, false to unpause it
+	 */
 	void pauseID(int id, bool paused);
 
-	/** pause/unpause the channel for the given handle */
+	/**
+	 * Pause/unpause the sound corresponding to the given handle.
+	 *
+	 * @param handle the sound to affect
+	 * @param paused true to pause the sound, false to unpause it
+	 */
 	void pauseHandle(PlayingSoundHandle handle, bool paused);
 
-	/** set the channel volume for the given handle (0 - 255) */
+
+
+	/**
+	 * Check if a sound with the given ID is active.
+	 *
+	 * @param id the ID of the sound to query
+	 * @return true if the sound is active
+	 */
+	bool isSoundIDActive(int id);
+
+	/**
+	 * Check if the mixer is paused (using pauseAll).
+	 *
+	 * @return true if the mixer is paused
+	 */
+	bool isPaused();
+
+
+
+	/**
+	 * Set the channel volume for the given handle.
+	 *
+	 * @param handle the sound to affect
+	 * @param volume the new channel volume (0 - 255)
+	 */
 	void setChannelVolume(PlayingSoundHandle handle, byte volume);
 
-	/** set the channel balance for the given handle (-127 ... 0 ... 127) (left ... center ... right)*/
+	/**
+	 * Set the channel balance for the given handle.
+	 *
+	 * @param handle the sound to affect
+	 * @param balance the new channel balance:
+	 *        (-127 ... 0 ... 127) corresponds to (left ... center ... right)
+	 */
 	void setChannelBalance(PlayingSoundHandle handle, int8 balance);
 
-	/** set the global volume, 0-256 */
+	/**
+	 * Get approximation of for how long the channel has been playing.
+	 */
+	uint32 getSoundElapsedTime(PlayingSoundHandle handle);
+
+	/**
+	 * Set the global volume.
+	 *
+	 * @param volume the new global volume, 0-256
+	 */
 	void setVolume(int volume);
 
-	/** query the global volume, 0-256 */
+	/**
+	 * Query the global volume.
+	 *
+	 * @return the global music volume, 0-256
+	 */
 	int getVolume() const { return _globalVolume; }
 
-	/** query the output rate in kHz */
+	/**
+	 * Query the system's audio output sample rate. This returns
+	 * the same value as OSystem::getOutputSampleRate().
+	 *
+	 * @return the output sample rate in Hz
+	 */
 	uint getOutputRate() const { return _outputRate; }
 
 private:
+	typedef void (*SoundProc)(void *param, byte *buf, int len);
 	bool setSoundProc(SoundProc proc, void *param);
 
 	void insertChannel(PlayingSoundHandle *handle, Channel *chan);
 
-	/** main mixer method */
+	/**
+	 * Internal main method -- all the actual mixing work is done from here.
+	 */
 	void mix(int16 * buf, uint len);
 
+	/**
+	 * The mixer callback function, passed on to OSystem::setSoundCallback().
+	 * This simply calls the mix() method.
+	 */
 	static void mixCallback(void *s, byte *samples, int len);
 };
 





More information about the Scummvm-git-logs mailing list