diff options
Diffstat (limited to 'backends/mixer/sdl/sdl-mixer.cpp')
-rw-r--r-- | backends/mixer/sdl/sdl-mixer.cpp | 175 |
1 files changed, 42 insertions, 133 deletions
diff --git a/backends/mixer/sdl/sdl-mixer.cpp b/backends/mixer/sdl/sdl-mixer.cpp index 04a97ce5cf..aa87fcb345 100644 --- a/backends/mixer/sdl/sdl-mixer.cpp +++ b/backends/mixer/sdl/sdl-mixer.cpp @@ -26,51 +26,55 @@ #if defined(WIN32) || defined(UNIX) || defined(MACOSX) #include "backends/mixer/sdl/sdl-mixer.h" - +#include "common/system.h" #include "common/config-manager.h" //#define SAMPLES_PER_SEC 11025 #define SAMPLES_PER_SEC 22050 //#define SAMPLES_PER_SEC 44100 -SdlMixerImpl::SdlMixerImpl(OSystem *system) +SdlMixerManager::SdlMixerManager() : -#if MIXER_DOUBLE_BUFFERING - _soundMutex(0), _soundCond(0), _soundThread(0), - _soundThreadIsRunning(false), _soundThreadShouldQuit(false), -#endif - MixerImpl(system, getSamplesPerSec()) { - if (_openAudio) { - setReady(true); - -#if MIXER_DOUBLE_BUFFERING - initThreadedMixer(_obtainedRate.samples * 4); -#endif + _mixer(0) { - // start the sound system - SDL_PauseAudio(0); - } - else { - setReady(false); - } } -SdlMixerImpl::~SdlMixerImpl() { - setReady(false); +SdlMixerManager::~SdlMixerManager() { + _mixer->setReady(false); SDL_CloseAudio(); -#if MIXER_DOUBLE_BUFFERING - deinitThreadedMixer(); -#endif + delete _mixer; } -uint SdlMixerImpl::getSamplesPerSec() { - +void SdlMixerManager::init() { + // Start SDL Audio subsystem if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) { error("Could not initialize SDL: %s", SDL_GetError()); } + // Get the desired audio specs + SDL_AudioSpec desired = getAudioSpec(); + + // Start SDL audio with the desired specs + if (SDL_OpenAudio(&desired, &_obtainedRate) != 0) { + warning("Could not open audio device: %s", SDL_GetError()); + + _mixer = new Audio::MixerImpl(g_system, desired.freq); + assert(_mixer); + _mixer->setReady(false); + } else { + debug(1, "Output sample rate: %d Hz", _obtainedRate.freq); + + _mixer = new Audio::MixerImpl(g_system, _obtainedRate.freq); + assert(_mixer); + _mixer->setReady(true); + + startAudio(); + } +} + +SDL_AudioSpec SdlMixerManager::getAudioSpec() { SDL_AudioSpec desired; // Determine the desired output sampling frequency. @@ -93,122 +97,27 @@ uint SdlMixerImpl::getSamplesPerSec() { desired.format = AUDIO_S16SYS; desired.channels = 2; desired.samples = (uint16)samples; - desired.callback = mixSdlCallback; + desired.callback = sdlCallback; desired.userdata = this; - if (SDL_OpenAudio(&desired, &_obtainedRate) != 0) { - warning("Could not open audio device: %s", SDL_GetError()); - _openAudio = 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 = _obtainedRate.freq; - debug(1, "Output sample rate: %d Hz", samplesPerSec); - _openAudio = true; - } - return samplesPerSec; + return desired; } -#if MIXER_DOUBLE_BUFFERING - -void SdlMixerImpl::mixerProducerThread() { - byte nextSoundBuffer; - - SDL_LockMutex(_soundMutex); - while (true) { - // Wait till we are allowed to produce data - SDL_CondWait(_soundCond, _soundMutex); - - if (_soundThreadShouldQuit) - break; - - // Generate samples and put them into the next buffer - nextSoundBuffer = _activeSoundBuf ^ 1; - mixCallback(_soundBuffers[nextSoundBuffer], _soundBufSize); - - // Swap buffers - _activeSoundBuf = nextSoundBuffer; - } - SDL_UnlockMutex(_soundMutex); +void SdlMixerManager::startAudio() { + // Start the sound system + SDL_PauseAudio(0); } -int SDLCALL SdlMixerImpl::mixerProducerThreadEntry(void *arg) { - SdlMixerImpl *mixer = (SdlMixerImpl *)arg; - assert(mixer); - mixer->mixerProducerThread(); - return 0; +void SdlMixerManager::callbackHandler(byte *samples, int len) { + assert(_mixer); + _mixer->mixCallback(samples, len); } +void SdlMixerManager::sdlCallback(void *this_, byte *samples, int len) { + SdlMixerManager *manager = (SdlMixerManager *)this_; + assert(manager); -void SdlMixerImpl::initThreadedMixer(uint bufSize) { - _soundThreadIsRunning = false; - _soundThreadShouldQuit = false; - - // Create mutex and condition variable - _soundMutex = SDL_CreateMutex(); - _soundCond = SDL_CreateCond(); - - // Create two sound buffers - _activeSoundBuf = 0; - _soundBufSize = bufSize; - _soundBuffers[0] = (byte *)calloc(1, bufSize); - _soundBuffers[1] = (byte *)calloc(1, bufSize); - - _soundThreadIsRunning = true; - - // Finally start the thread - _soundThread = SDL_CreateThread(mixerProducerThreadEntry, this); -} - -void SdlMixerImpl::deinitThreadedMixer() { - // Kill thread?? _soundThread - - if (_soundThreadIsRunning) { - // Signal the producer thread to end, and wait for it to actually finish. - _soundThreadShouldQuit = true; - SDL_CondBroadcast(_soundCond); - SDL_WaitThread(_soundThread, NULL); - - // Kill the mutex & cond variables. - // Attention: AT this point, the mixer callback must not be running - // anymore, else we will crash! - SDL_DestroyMutex(_soundMutex); - SDL_DestroyCond(_soundCond); - - _soundThreadIsRunning = false; - - free(_soundBuffers[0]); - free(_soundBuffers[1]); - } + manager->callbackHandler(samples, len); } - -void SdlMixerImpl::mixSdlCallback(void *arg, byte *samples, int len) { - SdlMixerImpl *mixer = (SdlMixerImpl *)arg; - assert(mixer); - - assert((int)mixer->getSoundBufSize() == len); - - // Lock mutex, to ensure our data is not overwritten by the producer thread - g_system->lockMutex((OSystem::MutexRef)mixer->getSoundMutex()); - - // Copy data from the current sound buffer - memcpy(samples, mixer->getActiveSoundBuf(), len); - - // Unlock mutex and wake up the produced thread - g_system->unlockMutex((OSystem::MutexRef)mixer->getSoundMutex()); - SDL_CondSignal(mixer->getSoundCond()); -} - -#else - -void SdlMixerImpl::mixSdlCallback(void *sys, byte *samples, int len) { - Audio::MixerImpl *mixer = (Audio::MixerImpl *)sys; - assert(mixer); - mixer->mixCallback(samples, len); -} - -#endif - #endif |