diff options
| author | Max Horn | 2008-06-28 15:28:29 +0000 | 
|---|---|---|
| committer | Max Horn | 2008-06-28 15:28:29 +0000 | 
| commit | c45d632f3b8c2d8c8aa46b05db758898de863e97 (patch) | |
| tree | 7b8fee1589eb6a733aea389b305752ee7d63562b | |
| parent | e68efca5a19fd738a78a61ea21efd19280521f31 (diff) | |
| download | scummvm-rg350-c45d632f3b8c2d8c8aa46b05db758898de863e97.tar.gz scummvm-rg350-c45d632f3b8c2d8c8aa46b05db758898de863e97.tar.bz2 scummvm-rg350-c45d632f3b8c2d8c8aa46b05db758898de863e97.zip  | |
Patch ##1956946 (Audio::Mixer internal API revision) with some tweaks
svn-id: r32828
| -rw-r--r-- | backends/platform/gp2x/gp2x-common.h | 4 | ||||
| -rw-r--r-- | backends/platform/gp2x/gp2x.cpp | 7 | ||||
| -rw-r--r-- | backends/platform/psp/osys_psp.cpp | 4 | ||||
| -rw-r--r-- | backends/platform/sdl/sdl.cpp | 51 | ||||
| -rw-r--r-- | backends/platform/sdl/sdl.h | 10 | ||||
| -rw-r--r-- | backends/platform/symbian/src/SymbianOS.cpp | 69 | ||||
| -rw-r--r-- | backends/platform/symbian/src/SymbianOS.h | 9 | ||||
| -rw-r--r-- | backends/platform/wince/wince-sdl.cpp | 45 | ||||
| -rw-r--r-- | backends/platform/wince/wince-sdl.h | 5 | ||||
| -rw-r--r-- | common/system.h | 9 | ||||
| -rw-r--r-- | sound/mixer.cpp | 83 | ||||
| -rw-r--r-- | sound/mixer.h | 85 | ||||
| -rw-r--r-- | sound/mixer_intern.h | 154 | 
13 files changed, 336 insertions, 199 deletions
diff --git a/backends/platform/gp2x/gp2x-common.h b/backends/platform/gp2x/gp2x-common.h index 78d1296bc7..7e0ea88e0b 100644 --- a/backends/platform/gp2x/gp2x-common.h +++ b/backends/platform/gp2x/gp2x-common.h @@ -37,7 +37,7 @@  #include <SDL_gp2x.h>  namespace Audio { -	class Mixer; +	class MixerImpl;  }  namespace Common { @@ -367,7 +367,7 @@ protected:  	Common::SaveFileManager *_savefile;  	FilesystemFactory *getFilesystemFactory(); -	Audio::Mixer *_mixer; +	Audio::MixerImpl *_mixer;  	SDL_TimerID _timerID;  	Common::TimerManager *_timer; diff --git a/backends/platform/gp2x/gp2x.cpp b/backends/platform/gp2x/gp2x.cpp index 8735ea757e..1f330cf2d4 100644 --- a/backends/platform/gp2x/gp2x.cpp +++ b/backends/platform/gp2x/gp2x.cpp @@ -40,7 +40,7 @@  #include "backends/timer/default/default-timer.h"  #include "backends/plugins/posix/posix-provider.h"  #include "backends/fs/posix/posix-fs-factory.h" // for getFilesystemFactory() -#include "sound/mixer.h" +#include "sound/mixer_intern.h"  #include <stdio.h>  #include <stdlib.h> @@ -225,8 +225,7 @@ void OSystem_GP2X::initBackend() {  	// Create and hook up the mixer, if none exists yet (we check for this to  	// allow subclasses to provide their own).  	if (_mixer == 0) { -		_mixer = new Audio::Mixer(); -		setSoundCallback(Audio::Mixer::mixCallback, _mixer); +		setupMixer();  	}  	// Create and hook up the timer manager, if none exists yet (we check for @@ -445,7 +444,7 @@ void OSystem_GP2X::deleteMutex(MutexRef mutex) {  #pragma mark --- Audio ---  #pragma mark - -bool OSystem_GP2X::setSoundCallback(SoundProc proc, void *param) { +void OSystem_GP2X::setupMixer() {  	SDL_AudioSpec desired;  	SDL_AudioSpec obtained; diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp index aff5373510..2d18b4bfd6 100644 --- a/backends/platform/psp/osys_psp.cpp +++ b/backends/platform/psp/osys_psp.cpp @@ -34,7 +34,7 @@  #include "backends/timer/default/default-timer.h"  #include "graphics/surface.h"  #include "graphics/scaler.h" -#include "sound/mixer.h" +#include "sound/mixer_intern.h"  #include <pspgu.h> @@ -99,7 +99,7 @@ OSystem_PSP::~OSystem_PSP() {  void OSystem_PSP::initBackend() {  	_savefile = new DefaultSaveFileManager(); -	_mixer = new Audio::Mixer(); +	_mixer = new Audio::MixerImpl(this);  	_timer = new DefaultTimerManager();  	setSoundCallback(Audio::Mixer::mixCallback, _mixer);  	setTimerCallback(&timer_handler, 10); diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index 60f8d3c95c..290fe63663 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -30,7 +30,7 @@  #include "backends/saves/default/default-saves.h"  #include "backends/timer/default/default-timer.h" -#include "sound/mixer.h" +#include "sound/mixer_intern.h"  #include "icons/scummvm.xpm" @@ -131,9 +131,7 @@ void OSystem_SDL::initBackend() {  	// Create and hook up the mixer, if none exists yet (we check for this to  	// allow subclasses to provide their own).  	if (_mixer == 0) { -		_mixer = new Audio::Mixer(); -		bool result = setSoundCallback(Audio::Mixer::mixCallback, _mixer); -		_mixer->setReady(result); +		setupMixer();  	}  	// Create and hook up the timer manager, if none exists yet (we check for @@ -391,7 +389,15 @@ void OSystem_SDL::deleteMutex(MutexRef mutex) {  #pragma mark --- Audio ---  #pragma mark - -bool OSystem_SDL::setSoundCallback(SoundProc proc, void *param) { +void OSystem_SDL::mixCallback(void *sys, byte *samples, int len) { +	OSystem_SDL *this_ = (OSystem_SDL *)sys; +	assert(this_); + +	if (this_->_mixer) +		this_->_mixer->mixCallback(samples, len); +} + +void OSystem_SDL::setupMixer() {  	SDL_AudioSpec desired;  	SDL_AudioSpec obtained; @@ -415,23 +421,30 @@ bool OSystem_SDL::setSoundCallback(SoundProc proc, void *param) {  	desired.format = AUDIO_S16SYS;  	desired.channels = 2;  	desired.samples = (uint16)samples; -	desired.callback = proc; -	desired.userdata = param; +	desired.callback = mixCallback; +	desired.userdata = this; + +	// Create the mixer instance +	assert(!_mixer); +	_mixer = new Audio::MixerImpl(this); +	assert(_mixer); +  	if (SDL_OpenAudio(&desired, &obtained) != 0) {  		warning("Could not open audio device: %s", SDL_GetError()); -		return false; +		_samplesPerSec = 0; +		_mixer->setReady(false); +	} else { +		// Note: This should be the obtained output rate, but it seems that at +		// least on some platforms SDL will lie and claim it did get the rate +		// even if it didn't. Probably only happens for "weird" rates, though. +		_samplesPerSec = obtained.freq; +		debug(1, "Output sample rate: %d Hz", _samplesPerSec); +	 +		// Tell the mixer that we are ready and start the sound processing +		_mixer->setOutputRate(_samplesPerSec); +		_mixer->setReady(true); +		SDL_PauseAudio(0);  	} -	// Note: This should be the obtained output rate, but it seems that at -	// least on some platforms SDL will lie and claim it did get the rate -	// even if it didn't. Probably only happens for "weird" rates, though. -	_samplesPerSec = obtained.freq; -	debug(1, "Output sample rate: %d Hz", _samplesPerSec); -	SDL_PauseAudio(0); -	return true; -} - -int OSystem_SDL::getOutputSampleRate() const { -	return _samplesPerSec;  }  Audio::Mixer *OSystem_SDL::getMixer() { diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h index 2cbadae2f4..8a94a17b00 100644 --- a/backends/platform/sdl/sdl.h +++ b/backends/platform/sdl/sdl.h @@ -38,7 +38,7 @@  namespace Audio { -	class Mixer; +	class MixerImpl;  }  namespace Common { @@ -134,8 +134,9 @@ public:  	virtual bool pollEvent(Common::Event &event); // overloaded by CE backend  	// Set function that generates samples -	typedef void (*SoundProc)(void *param, byte *buf, int len); -	virtual bool setSoundCallback(SoundProc proc, void *param); // overloaded by CE backend +	virtual void setupMixer(); +	static void mixCallback(void *s, byte *samples, int len); +  	virtual Audio::Mixer *getMixer();  	// Poll CD status @@ -186,7 +187,6 @@ public:  	virtual void setWindowCaption(const char *caption);  	virtual bool openCD(int drive); -	virtual int getOutputSampleRate() const;  	virtual bool hasFeature(Feature f);  	virtual void setFeatureState(Feature f, bool enable); @@ -371,7 +371,7 @@ protected:  	Common::SaveFileManager *_savefile; -	Audio::Mixer *_mixer; +	Audio::MixerImpl *_mixer;  	SDL_TimerID _timerID;  	Common::TimerManager *_timer; diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp index d3e92731db..dfeb24d825 100644 --- a/backends/platform/symbian/src/SymbianOS.cpp +++ b/backends/platform/symbian/src/SymbianOS.cpp @@ -173,11 +173,8 @@ void OSystem_SDL_Symbian::quit() {  	OSystem_SDL::quit();  } -bool OSystem_SDL_Symbian::setSoundCallback(SoundProc proc, void *param) { +void OSystem_SDL_Symbian::setupMixer() { -	// First save the proc and param -	_sound_proc_param = param; -	_sound_proc = proc;  	SDL_AudioSpec desired;  	SDL_AudioSpec obtained; @@ -207,48 +204,53 @@ bool OSystem_SDL_Symbian::setSoundCallback(SoundProc proc, void *param) {  	desired.format = AUDIO_S16SYS;  	desired.channels = 2;  	desired.samples = (uint16)samples; -#ifdef S60  	desired.callback = symbianMixCallback;  	desired.userdata = this; -#else -	desired.callback = proc; -	desired.userdata = param; -#endif + +	// Create the mixer instance +	assert(!_mixer); +	_mixer = new Audio::MixerImpl(this); +	assert(_mixer); +  	if (SDL_OpenAudio(&desired, &obtained) != 0) {  		warning("Could not open audio device: %s", SDL_GetError()); -		return false; -	} -	// Note: This should be the obtained output rate, but it seems that at -	// least on some platforms SDL will lie and claim it did get the rate -	// even if it didn't. Probably only happens for "weird" rates, though. -	_samplesPerSec = obtained.freq; -	_channels = obtained.channels; - -	// Need to create mixbuffer for stereo mix to downmix -	if (_channels != 2) { -		_stereo_mix_buffer = new byte [obtained.size*2];//*2 for stereo values +		_samplesPerSec = 0; +		_mixer->setReady(false); +	} else { +		// Note: This should be the obtained output rate, but it seems that at +		// least on some platforms SDL will lie and claim it did get the rate +		// even if it didn't. Probably only happens for "weird" rates, though. +		_samplesPerSec = obtained.freq; +		_channels = obtained.channels; +	 +		// Need to create mixbuffer for stereo mix to downmix +		if (_channels != 2) { +			_stereo_mix_buffer = new byte [obtained.size*2];//*2 for stereo values +		} +	 +		// Tell the mixer that we are ready and start the sound processing +		_mixer->setOutputRate(_samplesPerSec); +		_mixer->setReady(true); +		SDL_PauseAudio(0);  	} - -	SDL_PauseAudio(0); -	return true;  }  /**   * The mixer callback function, passed on to OSystem::setSoundCallback().   * This simply calls the mix() method.   */ -void OSystem_SDL_Symbian::symbianMixCallback(void *s, byte *samples, int len) { -	static_cast <OSystem_SDL_Symbian*>(s)->symbianMix(samples,len); -} +void OSystem_SDL_Symbian::symbianMixCallback(void *sys, byte *samples, int len) { +	OSystem_SDL_Symbian *this_ = (OSystem_SDL_Symbian *)sys; +	assert(this_); +	if (!this_->_mixer) +		return; -/** - * Actual mixing implementation - */ -void OSystem_SDL_Symbian::symbianMix(byte *samples, int len) { +#ifdef S60  	// If not stereo then we need to downmix  	if (_channels != 2) { -		_sound_proc(_sound_proc_param, _stereo_mix_buffer, len * 2); +		this_->_mixer->mixCallback(_stereo_mix_buffer, len * 2); +  		int16 *bitmixDst = (int16 *)samples;  		int16 *bitmixSrc = (int16 *)_stereo_mix_buffer; @@ -258,9 +260,12 @@ void OSystem_SDL_Symbian::symbianMix(byte *samples, int len) {  			bitmixSrc += 2;  		}  	} else -		_sound_proc(_sound_proc_param, samples, len); +#else +	this_->_mixer->mixCallback(samples, len); +#endif  } +  /**   * This is an implementation by the remapKey function   * @param SDL_Event to remap diff --git a/backends/platform/symbian/src/SymbianOS.h b/backends/platform/symbian/src/SymbianOS.h index 77e42cd476..71d24f6286 100644 --- a/backends/platform/symbian/src/SymbianOS.h +++ b/backends/platform/symbian/src/SymbianOS.h @@ -58,7 +58,7 @@ public:  	// This function is overridden by the symbian port in order to provide MONO audio  	// downmix is done by supplying our own audiocallback  	// -	virtual bool setSoundCallback(SoundProc proc, void *param); // overloaded by CE backend +	virtual void setupMixer(); // overloaded by CE backend  	// Overloaded from SDL_Commmon  	void quit(); @@ -70,11 +70,6 @@ protected:  	//  	static void symbianMixCallback(void *s, byte *samples, int len); -	// -	// Actual mixing implementation -	// -	void symbianMix(byte *samples, int len); -  	virtual FilesystemFactory *getFilesystemFactory();  public:  	// vibration support @@ -121,8 +116,6 @@ protected:  	// Audio  	int _channels; -	SoundProc _sound_proc; -	void *_sound_proc_param;  	byte *_stereo_mix_buffer;  	// Used to handle joystick navi zones diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp index 8cf5fac279..470c4ef435 100644 --- a/backends/platform/wince/wince-sdl.cpp +++ b/backends/platform/wince/wince-sdl.cpp @@ -35,7 +35,7 @@  #include "base/main.h"  #include "base/plugins.h" -#include "sound/mixer.h" +#include "sound/mixer_intern.h"  #include "sound/fmopl.h"  #include "backends/timer/default/default-timer.h" @@ -404,7 +404,7 @@ void OSystem_WINCE3::initBackend()  	// Instantiate our own sound mixer  	// mixer init is postponed until a game engine is selected.  	if (_mixer == 0) { -		_mixer = new Audio::Mixer(); +		_mixer = new Audio::Mixer(this);  	}  	// Create the timer. CE SDL does not support multiple timers (SDL_AddTimer). @@ -770,7 +770,7 @@ void OSystem_WINCE3::create_toolbar() {  	_toolbarHandler.setVisible(false);  } -bool OSystem_WINCE3::setSoundCallback(SoundProc proc, void *param) { +void OSystem_WINCE3::setupMixer(SoundProc proc, void *param) {  	SDL_AudioSpec desired;  	int thread_priority; @@ -785,12 +785,16 @@ bool OSystem_WINCE3::setSoundCallback(SoundProc proc, void *param) {  	desired.channels = 2;  	desired.samples = 128;  	desired.callback = private_sound_proc; -	desired.userdata = param; +	desired.userdata = this; + +	// Create the mixer instance +	assert(!_mixer); +	_mixer = new Audio::MixerImpl(this); +	assert(_mixer);  	// Add sound thread priority -	if (!ConfMan.hasKey("sound_thread_priority")) { +	if (!ConfMan.hasKey("sound_thread_priority"))  		thread_priority = THREAD_PRIORITY_NORMAL; -	}  	else  		thread_priority = ConfMan.getInt("sound_thread_priority"); @@ -799,16 +803,24 @@ bool OSystem_WINCE3::setSoundCallback(SoundProc proc, void *param) {  	SDL_CloseAudio();  	if (SDL_OpenAudio(&desired, NULL) != 0) {  		warning("Could not open audio device: %s", SDL_GetError()); -		return false; -	} -	else +		_mixer->setReady(false); + +	} else {  		debug(1, "Sound opened OK, mixing at %d Hz", _sampleRate); -	SDL_PauseAudio(0); -	return true; + +		// Tell the mixer that we are ready and start the sound processing +		_mixer->setOutputRate(_sampleRate); +		_mixer->setReady(true); +		SDL_PauseAudio(0); +	}  }  void OSystem_WINCE3::private_sound_proc(void *param, byte *buf, int len) { -	(*_originalSoundProc)(param, buf, len); +	OSystem_WINCE3 *this_ = (OSystem_WINCE3 *)param; +	assert(this_); + +	if (this_->_mixer) +		this_->_mixer->mixCallback(buf, len);  	if (!_soundMaster)  		memset(buf, 0, len);  } @@ -838,7 +850,7 @@ bool OSystem_WINCE3::checkOggHighSampleRate() {  }  #endif -void OSystem_WINCE3::get_sample_rate() { +void OSystem_WINCE3::compute_sample_rate() {  	// Force at least medium quality FM synthesis for FOTAQ  	Common::String gameid(ConfMan.get("gameid"));  	if (gameid == "queen") { @@ -875,9 +887,8 @@ void OSystem_WINCE3::setWindowCaption(const char *caption) {  	//update_game_settings();  	// finalize mixer init -	get_sample_rate(); -	bool result = setSoundCallback(Audio::Mixer::mixCallback, _mixer); -	_mixer->setReady(result); +	compute_sample_rate(); +	setupMixer();  	// handle the actual event  	OSystem_SDL::setWindowCaption(caption); @@ -1050,7 +1061,7 @@ void OSystem_WINCE3::update_game_settings() {  		}  	} -	get_sample_rate(); +	compute_sample_rate();  }  void OSystem_WINCE3::initSize(uint w, uint h) { diff --git a/backends/platform/wince/wince-sdl.h b/backends/platform/wince/wince-sdl.h index daa7e832f6..8853c156d8 100644 --- a/backends/platform/wince/wince-sdl.h +++ b/backends/platform/wince/wince-sdl.h @@ -82,7 +82,7 @@ public:  	// Overloaded from SDL_Commmon  	void quit();  	// Overloaded from SDL_Commmon (master volume and sample rate subtleties) -	bool setSoundCallback(SoundProc proc, void *param); +	void setupMixer();  	// Overloaded from OSystem  	//void engineInit();  	void getTimeAndDate(struct tm &t) const; @@ -160,13 +160,12 @@ private:  #endif  	static void private_sound_proc(void *param, byte *buf, int len); -	static SoundProc _originalSoundProc;  	bool update_scalers();  	void create_toolbar();  	void update_game_settings();  	void check_mappings(); -	void get_sample_rate(); +	void compute_sample_rate();  	void retrieve_mouse_location(int &x, int &y); diff --git a/common/system.h b/common/system.h index 4fc4c0625b..b895a5cfba 100644 --- a/common/system.h +++ b/common/system.h @@ -814,15 +814,6 @@ public:  	 */  	virtual Audio::Mixer *getMixer() = 0; -	/** -	 * Determine the output sample rate. Audio data provided by the sound -	 * callback will be played using this rate. -	 * @note Client code other than the sound mixer should _not_ use this -	 *       method. Instead, call Mixer::getOutputRate()! -	 * @return the output sample rate -	 */ -	virtual int getOutputSampleRate() const = 0; -  	//@} diff --git a/sound/mixer.cpp b/sound/mixer.cpp index fc5b21cf32..27e031f108 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -27,7 +27,7 @@  #include "common/util.h"  #include "common/system.h" -#include "sound/mixer.h" +#include "sound/mixer_intern.h"  #include "sound/rate.h"  #include "sound/audiostream.h" @@ -103,32 +103,38 @@ public:  #pragma mark - -Mixer::Mixer() { -	_syst = g_system; +MixerImpl::MixerImpl(OSystem *system) +	: _syst(system), _sampleRate(0), _mixerReady(false), _handleSeed(0) { -	_handleSeed = 0; - -	int i = 0; +	int i;  	for (i = 0; i < ARRAYSIZE(_volumeForSoundType); i++)  		_volumeForSoundType[i] = kMaxMixerVolume;  	for (i = 0; i != NUM_CHANNELS; i++)  		_channels[i] = 0; - -	_mixerReady = false;  } -Mixer::~Mixer() { +MixerImpl::~MixerImpl() {  	for (int i = 0; i != NUM_CHANNELS; i++)  		delete _channels[i];  } -uint Mixer::getOutputRate() const { -	return (uint)_syst->getOutputSampleRate(); +void MixerImpl::setReady(bool ready) { +	_mixerReady = ready; +} + +uint MixerImpl::getOutputRate() const { +	return _sampleRate; +} + +void MixerImpl::setOutputRate(uint sampleRate) { +	if (_sampleRate != 0 && _sampleRate != sampleRate) +		error("Changing the Audio::Mixer output sample rate is not supported"); +	_sampleRate = sampleRate;  } -void Mixer::insertChannel(SoundHandle *handle, Channel *chan) { +void MixerImpl::insertChannel(SoundHandle *handle, Channel *chan) {  	int index = -1;  	for (int i = 0; i != NUM_CHANNELS; i++) { @@ -138,7 +144,7 @@ void Mixer::insertChannel(SoundHandle *handle, Channel *chan) {  		}  	}  	if (index == -1) { -		warning("Mixer::out of mixer slots"); +		warning("MixerImpl::out of mixer slots");  		delete chan;  		return;  	} @@ -151,7 +157,7 @@ void Mixer::insertChannel(SoundHandle *handle, Channel *chan) {  	}  } -void Mixer::playRaw( +void MixerImpl::playRaw(  			SoundType type,  			SoundHandle *handle,  			void *sound, @@ -166,7 +172,7 @@ void Mixer::playRaw(  	playInputStream(type, handle, input, id, volume, balance, true, false, ((flags & Mixer::FLAG_REVERSE_STEREO) != 0));  } -void Mixer::playInputStream( +void MixerImpl::playInputStream(  			SoundType type,  			SoundHandle *handle,  			AudioStream *input, @@ -198,8 +204,13 @@ void Mixer::playInputStream(  	insertChannel(handle, chan);  } -void Mixer::mix(int16 *buf, uint len) { +void MixerImpl::mixCallback(byte *samples, uint len) { +	assert(samples); +  	Common::StackLock lock(_mutex); +	 +	int16 *buf = (int16 *)samples; +	len >>= 2;  	// Since the mixer callback has been called, the mixer must be ready...  	_mixerReady = true; @@ -218,15 +229,7 @@ void Mixer::mix(int16 *buf, uint len) {  		}  } -void Mixer::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). -	((Mixer *)s)->mix((int16 *)samples, len >> 2); -} - -void Mixer::stopAll() { +void MixerImpl::stopAll() {  	Common::StackLock lock(_mutex);  	for (int i = 0; i != NUM_CHANNELS; i++) {  		if (_channels[i] != 0 && !_channels[i]->isPermanent()) { @@ -236,7 +239,7 @@ void Mixer::stopAll() {  	}  } -void Mixer::stopID(int id) { +void MixerImpl::stopID(int id) {  	Common::StackLock lock(_mutex);  	for (int i = 0; i != NUM_CHANNELS; i++) {  		if (_channels[i] != 0 && _channels[i]->getId() == id) { @@ -246,7 +249,7 @@ void Mixer::stopID(int id) {  	}  } -void Mixer::stopHandle(SoundHandle handle) { +void MixerImpl::stopHandle(SoundHandle handle) {  	Common::StackLock lock(_mutex);  	// Simply ignore stop requests for handles of sounds that already terminated @@ -258,7 +261,7 @@ void Mixer::stopHandle(SoundHandle handle) {  	_channels[index] = 0;  } -void Mixer::setChannelVolume(SoundHandle handle, byte volume) { +void MixerImpl::setChannelVolume(SoundHandle handle, byte volume) {  	Common::StackLock lock(_mutex);  	const int index = handle._val % NUM_CHANNELS; @@ -268,7 +271,7 @@ void Mixer::setChannelVolume(SoundHandle handle, byte volume) {  	_channels[index]->setVolume(volume);  } -void Mixer::setChannelBalance(SoundHandle handle, int8 balance) { +void MixerImpl::setChannelBalance(SoundHandle handle, int8 balance) {  	Common::StackLock lock(_mutex);  	const int index = handle._val % NUM_CHANNELS; @@ -278,7 +281,7 @@ void Mixer::setChannelBalance(SoundHandle handle, int8 balance) {  	_channels[index]->setBalance(balance);  } -uint32 Mixer::getSoundElapsedTime(SoundHandle handle) { +uint32 MixerImpl::getSoundElapsedTime(SoundHandle handle) {  	Common::StackLock lock(_mutex);  	const int index = handle._val % NUM_CHANNELS; @@ -288,7 +291,7 @@ uint32 Mixer::getSoundElapsedTime(SoundHandle handle) {  	return _channels[index]->getElapsedTime();  } -void Mixer::pauseAll(bool paused) { +void MixerImpl::pauseAll(bool paused) {  	Common::StackLock lock(_mutex);  	for (int i = 0; i != NUM_CHANNELS; i++) {  		if (_channels[i] != 0) { @@ -297,7 +300,7 @@ void Mixer::pauseAll(bool paused) {  	}  } -void Mixer::pauseID(int id, bool paused) { +void MixerImpl::pauseID(int id, bool paused) {  	Common::StackLock lock(_mutex);  	for (int i = 0; i != NUM_CHANNELS; i++) {  		if (_channels[i] != 0 && _channels[i]->getId() == id) { @@ -307,7 +310,7 @@ void Mixer::pauseID(int id, bool paused) {  	}  } -void Mixer::pauseHandle(SoundHandle handle, bool paused) { +void MixerImpl::pauseHandle(SoundHandle handle, bool paused) {  	Common::StackLock lock(_mutex);  	// Simply ignore (un)pause requests for sounds that already terminated @@ -318,7 +321,7 @@ void Mixer::pauseHandle(SoundHandle handle, bool paused) {  	_channels[index]->pause(paused);  } -bool Mixer::isSoundIDActive(int id) { +bool MixerImpl::isSoundIDActive(int id) {  	Common::StackLock lock(_mutex);  	for (int i = 0; i != NUM_CHANNELS; i++)  		if (_channels[i] && _channels[i]->getId() == id) @@ -326,7 +329,7 @@ bool Mixer::isSoundIDActive(int id) {  	return false;  } -int Mixer::getSoundID(SoundHandle handle) { +int MixerImpl::getSoundID(SoundHandle handle) {  	Common::StackLock lock(_mutex);  	const int index = handle._val % NUM_CHANNELS;  	if (_channels[index] && _channels[index]->_handle._val == handle._val) @@ -334,13 +337,13 @@ int Mixer::getSoundID(SoundHandle handle) {  	return 0;  } -bool Mixer::isSoundHandleActive(SoundHandle handle) { +bool MixerImpl::isSoundHandleActive(SoundHandle handle) {  	Common::StackLock lock(_mutex);  	const int index = handle._val % NUM_CHANNELS;  	return _channels[index] && _channels[index]->_handle._val == handle._val;  } -bool Mixer::hasActiveChannelOfType(SoundType type) { +bool MixerImpl::hasActiveChannelOfType(SoundType type) {  	Common::StackLock lock(_mutex);  	for (int i = 0; i != NUM_CHANNELS; i++)  		if (_channels[i] && _channels[i]->_type == type) @@ -348,7 +351,7 @@ bool Mixer::hasActiveChannelOfType(SoundType type) {  	return false;  } -void Mixer::setVolumeForSoundType(SoundType type, int volume) { +void MixerImpl::setVolumeForSoundType(SoundType type, int volume) {  	assert(0 <= type && type < ARRAYSIZE(_volumeForSoundType));  	// Check range @@ -363,7 +366,7 @@ void Mixer::setVolumeForSoundType(SoundType type, int volume) {  	_volumeForSoundType[type] = volume;  } -int Mixer::getVolumeForSoundType(SoundType type) const { +int MixerImpl::getVolumeForSoundType(SoundType type) const {  	assert(0 <= type && type < ARRAYSIZE(_volumeForSoundType));  	return _volumeForSoundType[type]; @@ -443,7 +446,7 @@ uint32 Channel::getElapsedTime() {  	// Convert the number of samples into a time duration. To avoid  	// overflow, this has to be done in a somewhat non-obvious way. -	uint rate = _mixer->getOutputRate(); +	uint32 rate = _mixer->getOutputRate();  	uint32 seconds = _samplesConsumed / rate;  	uint32 milliseconds = (1000 * (_samplesConsumed % rate)) / rate; diff --git a/sound/mixer.h b/sound/mixer.h index 26ae0898fd..28988256b3 100644 --- a/sound/mixer.h +++ b/sound/mixer.h @@ -38,6 +38,7 @@ namespace Audio {  class AudioStream;  class Channel;  class Mixer; +class MixerImpl;  /**   * A SoundHandle instances corresponds to a specific sound @@ -47,7 +48,7 @@ class Mixer;   */  class SoundHandle {  	friend class Channel; -	friend class Mixer; +	friend class MixerImpl;  	uint32 _val;  public:  	inline SoundHandle() : _val(0xFFFFFFFF) {} @@ -104,24 +105,9 @@ public:  		kMaxMixerVolume = 256  	}; -private: -	enum { -		NUM_CHANNELS = 16 -	}; - -	OSystem *_syst; -	Common::Mutex _mutex; - -	int _volumeForSoundType[4]; - -	uint32 _handleSeed; -	Channel *_channels[NUM_CHANNELS]; - -	bool _mixerReady; -  public: -	Mixer(); -	~Mixer(); +	Mixer() {} +	virtual ~Mixer() {} @@ -132,8 +118,10 @@ public:  	 * sync with an audio stream. In particular, the Adlib MIDI emulation...  	 *  	 * @return whether the mixer is ready and setup +	 * +	 * @todo get rid of this?  	 */ -	bool isReady() const { return _mixerReady; } +	virtual bool isReady() const = 0; @@ -143,12 +131,12 @@ public:  	 * (using the makeLinearInputStream factory function), which is then  	 * passed on to playInputStream.  	 */ -	void playRaw( +	virtual void playRaw(  		SoundType type,  		SoundHandle *handle,  		void *sound, uint32 size, uint rate, byte flags,  		int id = -1, byte volume = kMaxChannelVolume, int8 balance = 0, -		uint32 loopStart = 0, uint32 loopEnd = 0); +		uint32 loopStart = 0, uint32 loopEnd = 0) = 0;  	/**  	 * Start playing the given audio input stream. @@ -170,35 +158,35 @@ public:  	 *                  not stop this particular stream  	 * @param reverseStereo	a flag indicating whether left and right channels shall be swapped  	 */ -	void playInputStream( +	virtual void playInputStream(  		SoundType type,  		SoundHandle *handle,  		AudioStream *input,  		int id = -1, byte volume = kMaxChannelVolume, int8 balance = 0,  		bool autofreeStream = true,  		bool permanent = false, -		bool reverseStereo = false); +		bool reverseStereo = false) = 0;  	/**  	 * Stop all currently playing sounds.  	 */ -	void stopAll(); +	virtual void stopAll() = 0;  	/**  	 * Stop playing the sound with given ID.  	 *  	 * @param id the ID of the sound to affect  	 */ -	void stopID(int id); +	virtual void stopID(int id) = 0;  	/**  	 * Stop playing the sound corresponding to the given handle.  	 *  	 * @param handle the sound to affect  	 */ -	void stopHandle(SoundHandle handle); +	virtual void stopHandle(SoundHandle handle) = 0; @@ -208,7 +196,7 @@ public:  	 *  	 * @param paused true to pause everything, false to unpause  	 */ -	void pauseAll(bool paused); +	virtual void pauseAll(bool paused) = 0;  	/**  	 * Pause/unpause the sound with the given ID. @@ -216,7 +204,7 @@ public:  	 * @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); +	virtual void pauseID(int id, bool paused) = 0;  	/**  	 * Pause/unpause the sound corresponding to the given handle. @@ -224,7 +212,7 @@ public:  	 * @param handle the sound to affect  	 * @param paused true to pause the sound, false to unpause it  	 */ -	void pauseHandle(SoundHandle handle, bool paused); +	virtual void pauseHandle(SoundHandle handle, bool paused) = 0; @@ -234,7 +222,7 @@ public:  	 * @param id the ID of the sound to query  	 * @return true if the sound is active  	 */ -	bool isSoundIDActive(int id); +	virtual bool isSoundIDActive(int id) = 0;  	/**  	 * Get the sound ID of handle sound @@ -242,7 +230,7 @@ public:  	 * @param handle sound to query  	 * @return sound ID if active  	 */ -	int getSoundID(SoundHandle handle); +	virtual int getSoundID(SoundHandle handle) = 0;  	/**  	 * Check if a sound with the given handle is active. @@ -250,7 +238,7 @@ public:  	 * @param handle sound to query  	 * @return true if the sound is active  	 */ -	bool isSoundHandleActive(SoundHandle handle); +	virtual bool isSoundHandleActive(SoundHandle handle) = 0; @@ -260,7 +248,7 @@ public:  	 * @param handle the sound to affect  	 * @param volume the new channel volume (0 - kMaxChannelVolume)  	 */ -	void setChannelVolume(SoundHandle handle, byte volume); +	virtual void setChannelVolume(SoundHandle handle, byte volume) = 0;  	/**  	 * Set the channel balance for the given handle. @@ -269,12 +257,12 @@ public:  	 * @param balance the new channel balance:  	 *        (-127 ... 0 ... 127) corresponds to (left ... center ... right)  	 */ -	void setChannelBalance(SoundHandle handle, int8 balance); +	virtual void setChannelBalance(SoundHandle handle, int8 balance) = 0;  	/**  	 * Get approximation of for how long the channel has been playing.  	 */ -	uint32 getSoundElapsedTime(SoundHandle handle); +	virtual uint32 getSoundElapsedTime(SoundHandle handle) = 0;  	/**  	 * Check whether any channel of the given sound type is active. @@ -284,7 +272,7 @@ public:  	 * @param  type the sound type to look for  	 * @return true if any channels of the specified type are active.  	 */ -	bool hasActiveChannelOfType(SoundType type); +	virtual bool hasActiveChannelOfType(SoundType type) = 0;  	/**  	 * Set the volume for the given sound type. @@ -292,7 +280,7 @@ public:  	 * @param type the sound type  	 * @param volume the new global volume, 0 - kMaxMixerVolume  	 */ -	void setVolumeForSoundType(SoundType type, int volume); +	virtual void setVolumeForSoundType(SoundType type, int volume) = 0;  	/**  	 * Query the global volume. @@ -300,7 +288,7 @@ public:  	 * @param type the sound type  	 * @return the global music volume, 0 - kMaxMixerVolume  	 */ -	int getVolumeForSoundType(SoundType type) const; +	virtual int getVolumeForSoundType(SoundType type) const = 0;  	/**  	 * Query the system's audio output sample rate. This returns @@ -308,26 +296,7 @@ public:  	 *  	 * @return the output sample rate in Hz  	 */ -	uint getOutputRate() const; - -protected: -	void insertChannel(SoundHandle *handle, Channel *chan); - -	/** -	 * Internal main method -- all the actual mixing work is done from here. -	 */ -	void mix(int16 * buf, uint len); - -	// FIXME: temporary "public" to allow access to mixCallback -	// from within OSystem::makeMixer() -public: -	/** -	 * The mixer callback function, passed on to OSystem::setSoundCallback(). -	 * This simply calls the mix() method. -	 */ -	static void mixCallback(void *s, byte *samples, int len); - -	void setReady(bool ready) { _mixerReady = ready; } +	virtual uint getOutputRate() const = 0;  }; diff --git a/sound/mixer_intern.h b/sound/mixer_intern.h new file mode 100644 index 0000000000..46ba97e66c --- /dev/null +++ b/sound/mixer_intern.h @@ -0,0 +1,154 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef SOUND_MIXER_INTERN_H +#define SOUND_MIXER_INTERN_H + +#include "common/scummsys.h" +#include "common/mutex.h" +#include "sound/mixer.h" + +namespace Audio { + +/** + * The (default) implementation of the ScummVM audio mixing subsystem. + * + * Backends are responsible for allocating (and later releasing) an instance + * of this class, which engines can access via OSystem::getMixer(). + * + * Initialisation of instances of this class usually happens as follows: + * 1) Creat a new Audio::MixerImpl instance. + * 2) Set the hardware output sample rate via the setSampleRate() method. + * 3) Hook up the mixCallback() in a suitable audio processing thread/callback. + * 4) Change the mixer into ready mode via setReady(true). + * 5) Start audio processing (e.g. by resuming the audio thread, if applicable). + * + * In the future, we might make it possible for backends to provide + * (partial) alternative implementations of the mixer, e.g. to make + * better use of native sound mixing support on low-end devices. + * + * @see OSystem::getMixer() + */ +class MixerImpl : public Mixer { +private: +	enum { +		NUM_CHANNELS = 16 +	}; + +	OSystem *_syst; +	Common::Mutex _mutex; + +	uint _sampleRate; +	bool _mixerReady; +	uint32 _handleSeed; + +	int _volumeForSoundType[4]; +	Channel *_channels[NUM_CHANNELS]; + + +public: +	MixerImpl(OSystem *system); +	~MixerImpl(); + +	virtual bool isReady() const { return _mixerReady; } + +	virtual void playRaw( +		SoundType type, +		SoundHandle *handle, +		void *sound, uint32 size, uint rate, byte flags, +		int id = -1, byte volume = 255, int8 balance = 0, +		uint32 loopStart = 0, uint32 loopEnd = 0); + +	virtual void playInputStream( +		SoundType type, +		SoundHandle *handle, +		AudioStream *input, +		int id = -1, byte volume = 255, int8 balance = 0, +		bool autofreeStream = true, +		bool permanent = false, +		bool reverseStereo = false); + + + +	virtual void stopAll(); +	virtual void stopID(int id); +	virtual void stopHandle(SoundHandle handle); + +	virtual void pauseAll(bool paused); +	virtual void pauseID(int id, bool paused); +	virtual void pauseHandle(SoundHandle handle, bool paused); + +	virtual bool isSoundIDActive(int id); +	virtual int getSoundID(SoundHandle handle); + +	virtual bool isSoundHandleActive(SoundHandle handle); + +	virtual void setChannelVolume(SoundHandle handle, byte volume); +	virtual void setChannelBalance(SoundHandle handle, int8 balance); + +	virtual uint32 getSoundElapsedTime(SoundHandle handle); + +	virtual bool hasActiveChannelOfType(SoundType type); + +	virtual void setVolumeForSoundType(SoundType type, int volume); +	virtual int getVolumeForSoundType(SoundType type) const; + +	virtual uint getOutputRate() const; + +protected: +	void insertChannel(SoundHandle *handle, Channel *chan); + +public: +	/** +	 * The mixer callback function, to be called at regular intervals by +	 * the backend (e.g. from an audio mixing thread). All the actual mixing +	 * work is done from here. +	 */ +	void mixCallback(byte *samples, uint len); + +	/** +	 * Set the internal 'is ready' flag of the mixer. +	 * Backends should invoke Mixer::setReady(true) once initialisation of +	 * their audio system has been completed (and in particular, *after* +	 * setOutputRate() has been called). +	 */ +	void setReady(bool ready); +	 +	/** +	 * Set the output sample rate. +	 * +	 * @param sampleRate	the new output sample rate +	 * +	 * @note Right now, this can be done exactly ONCE. That is, the mixer +	 * currently does not support changing the output sample rate after it +	 * has been set for the first time.  This may change in the future. +	 */ +	void setOutputRate(uint sampleRate); +}; + + +} // End of namespace Audio + +#endif  | 
