From adb83cfabe77a04052412d2fd631e341c72319a2 Mon Sep 17 00:00:00 2001 From: John Peterson Date: Sun, 9 Jun 2013 09:43:27 +0200 Subject: [PATCH] Clarifying the OpenAL loop because it isn't as clear as it can be --- Source/Core/AudioCommon/Src/OpenALStream.cpp | 202 +++++++++---------- Source/Core/AudioCommon/Src/OpenALStream.h | 19 +- 2 files changed, 108 insertions(+), 113 deletions(-) diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index b1e601dfe7..754df6139a 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -97,7 +97,7 @@ void OpenALStream::SetVolume(int volume) fVolume = (float)volume / 100.0f; if (uiSource) - alSourcef(uiSource, AL_GAIN, fVolume); + alSourcef(uiSource, AL_GAIN, fVolume); } void OpenALStream::Update() @@ -124,6 +124,15 @@ void OpenALStream::SoundLoop() { Common::SetCurrentThreadName("Audio thread - openal"); + bool surround_capable = Core::g_CoreStartupParameter.bDPL2Decoder; +#if defined(__APPLE__) + bool float32_capable = false; + // OSX does not have the alext AL_FORMAT_51CHN32 yet. + surround_capable = false; +#else + bool float32_capable = true; +#endif + u32 ulFrequency = m_mixer->GetSampleRate(); numBuffers = Core::g_CoreStartupParameter.iLatency + 2; // OpenAL requires a minimum of two buffers @@ -136,22 +145,20 @@ void OpenALStream::SoundLoop() alGenSources(1, &uiSource); // Short Silence - memset(sampleBuffer, 0, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * numBuffers); - memset(realtimeBuffer, 0, OAL_MAX_SAMPLES * 4); + memset(sampleBuffer, 0, OAL_MAX_SAMPLES * numBuffers * FRAME_SURROUND_FLOAT); + memset(realtimeBuffer, 0, OAL_MAX_SAMPLES * FRAME_STEREO_SHORT); for (int i = 0; i < numBuffers; i++) { -#if !defined(__APPLE__) - if (Core::g_CoreStartupParameter.bDPL2Decoder) - alBufferData(uiBuffers[i], AL_FORMAT_51CHN32, sampleBuffer, 4 * SIZE_FLOAT * SURROUND_CHANNELS, ulFrequency); + if (surround_capable) + alBufferData(uiBuffers[i], AL_FORMAT_51CHN32, sampleBuffer, 4 * FRAME_SURROUND_FLOAT, ulFrequency); else -#endif - alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, 4 * 2 * 2, ulFrequency); + alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, 4 * FRAME_STEREO_SHORT, ulFrequency); } alSourceQueueBuffers(uiSource, numBuffers, uiBuffers); alSourcePlay(uiSource); - + // Set the default sound volume as saved in the config file. - alSourcef(uiSource, AL_GAIN, fVolume); + alSourcef(uiSource, AL_GAIN, fVolume); // TODO: Error handling //ALenum err = alGetError(); @@ -170,14 +177,7 @@ void OpenALStream::SoundLoop() soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 28); soundTouch.setSetting(SETTING_OVERLAP_MS, 12); - bool surround_capable = Core::g_CoreStartupParameter.bDPL2Decoder; -#if defined(__APPLE__) - bool float32_capable = false; -#else - bool float32_capable = true; -#endif - - while (!threadData) + while (!threadData) { // num_samples_to_render in this update - depends on SystemTimers::AUDIO_DMA_PERIOD. const u32 stereo_16_bit_size = 4; @@ -193,12 +193,9 @@ void OpenALStream::SoundLoop() numSamples = m_mixer->Mix(realtimeBuffer, numSamples); // Convert the samples from short to float - float dest[OAL_MAX_SAMPLES * 2 * 2 * OAL_MAX_BUFFERS]; - for (u32 i = 0; i < numSamples; ++i) - { - dest[i * 2 + 0] = (float)realtimeBuffer[i * 2 + 0] / (1 << 16); - dest[i * 2 + 1] = (float)realtimeBuffer[i * 2 + 1] / (1 << 16); - } + float dest[OAL_MAX_SAMPLES * STEREO_CHANNELS]; + for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i) + dest[i] = (float)realtimeBuffer[i] / (1 << 16); soundTouch.putSamples(dest, numSamples); @@ -230,101 +227,94 @@ void OpenALStream::SoundLoop() } } - unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * SIZE_FLOAT * OAL_MAX_BUFFERS); + unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * numBuffers); - if (nSamples > minSamples) + if (nSamples < minSamples) + continue; + + // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer) + if (iBuffersFilled == 0) { - // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer) - if (iBuffersFilled == 0) - { - alSourceUnqueueBuffers(uiSource, iBuffersProcessed, uiBufferTemp); - ALenum err = alGetError(); - if (err != 0) - { - ERROR_LOG(AUDIO, "Error unqueuing buffers: %08x", err); - } - } -#if defined(__APPLE__) - // OSX does not have the alext AL_FORMAT_51CHN32 yet. - surround_capable = false; -#else - if (surround_capable) - { - float dpl2[OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; - dpl2decode(sampleBuffer, nSamples, dpl2); - - alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_51CHN32, dpl2, nSamples * SIZE_FLOAT * SURROUND_CHANNELS, ulFrequency); - ALenum err = alGetError(); - if (err == AL_INVALID_ENUM) - { - // 5.1 is not supported by the host, fallback to stereo - WARN_LOG(AUDIO, "Unable to set 5.1 surround mode. Updating OpenAL Soft might fix this issue."); - surround_capable = false; - } - else if (err != 0) - { - ERROR_LOG(AUDIO, "Error occurred while buffering data: %08x", err); - } - } -#endif - if (!surround_capable) - { -#if !defined(__APPLE__) - if (float32_capable) - { - alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO_FLOAT32, sampleBuffer, nSamples * 4 * 2, ulFrequency); - ALenum err = alGetError(); - if (err == AL_INVALID_ENUM) - { - float32_capable = false; - } - else if (err != 0) - { - ERROR_LOG(AUDIO, "Error occurred while buffering float32 data: %08x", err); - } - } -#endif - if (!float32_capable) - { - // Convert the samples from float to short - short stereo[OAL_MAX_SAMPLES * 2 * 2 * OAL_MAX_BUFFERS]; - for (u32 i = 0; i < nSamples; ++i) - { - stereo[i * 2 + 0] = (short)((float)sampleBuffer[i * 2 + 0] * (1 << 16)); - stereo[i * 2 + 1] = (short)((float)sampleBuffer[i * 2 + 1] * (1 << 16)); - } - alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, stereo, nSamples * 2 * 2, ulFrequency); - } - } - - alSourceQueueBuffers(uiSource, 1, &uiBufferTemp[iBuffersFilled]); + alSourceUnqueueBuffers(uiSource, iBuffersProcessed, uiBufferTemp); ALenum err = alGetError(); if (err != 0) { - ERROR_LOG(AUDIO, "Error queuing buffers: %08x", err); + ERROR_LOG(AUDIO, "Error unqueuing buffers: %08x", err); } - iBuffersFilled++; + } - if (iBuffersFilled == numBuffers) + if (surround_capable) + { + float dpl2[OAL_MAX_SAMPLES * OAL_MAX_BUFFERS * SURROUND_CHANNELS]; + dpl2decode(sampleBuffer, nSamples, dpl2); + alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_51CHN32, dpl2, nSamples * FRAME_SURROUND_FLOAT, ulFrequency); + ALenum err = alGetError(); + if (err == AL_INVALID_ENUM) { - alSourcePlay(uiSource); - err = alGetError(); - if (err != 0) + // 5.1 is not supported by the host, fallback to stereo + WARN_LOG(AUDIO, "Unable to set 5.1 surround mode. Updating OpenAL Soft might fix this issue."); + surround_capable = false; + } + else if (err != 0) + { + ERROR_LOG(AUDIO, "Error occurred while buffering data: %08x", err); + } + } + + else + { + if (float32_capable) + { + alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO_FLOAT32, sampleBuffer, nSamples * FRAME_STEREO_FLOAT, ulFrequency); + ALenum err = alGetError(); + if (err == AL_INVALID_ENUM) { - ERROR_LOG(AUDIO, "Error occurred during playback: %08x", err); + float32_capable = false; + } + else if (err != 0) + { + ERROR_LOG(AUDIO, "Error occurred while buffering float32 data: %08x", err); } } - alGetSourcei(uiSource, AL_SOURCE_STATE, &iState); - if (iState != AL_PLAYING) + else { - // Buffer underrun occurred, resume playback - alSourcePlay(uiSource); - err = alGetError(); - if (err != 0) - { - ERROR_LOG(AUDIO, "Error occurred resuming playback: %08x", err); - } + // Convert the samples from float to short + short stereo[OAL_MAX_SAMPLES * STEREO_CHANNELS * OAL_MAX_BUFFERS]; + for (u32 i = 0; i < nSamples * STEREO_CHANNELS; ++i) + stereo[i] = (short)((float)sampleBuffer[i] * (1 << 16)); + + alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, stereo, nSamples * FRAME_STEREO_SHORT, ulFrequency); + } + } + + alSourceQueueBuffers(uiSource, 1, &uiBufferTemp[iBuffersFilled]); + ALenum err = alGetError(); + if (err != 0) + { + ERROR_LOG(AUDIO, "Error queuing buffers: %08x", err); + } + iBuffersFilled++; + + if (iBuffersFilled == numBuffers) + { + alSourcePlay(uiSource); + err = alGetError(); + if (err != 0) + { + ERROR_LOG(AUDIO, "Error occurred during playback: %08x", err); + } + } + + alGetSourcei(uiSource, AL_SOURCE_STATE, &iState); + if (iState != AL_PLAYING) + { + // Buffer underrun occurred, resume playback + alSourcePlay(uiSource); + err = alGetError(); + if (err != 0) + { + ERROR_LOG(AUDIO, "Error occurred resuming playback: %08x", err); } } } diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h index 42371db045..24217169bd 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.h +++ b/Source/Core/AudioCommon/Src/OpenALStream.h @@ -30,11 +30,16 @@ #include // 16 bit Stereo -#define SFX_MAX_SOURCE 1 -#define OAL_MAX_BUFFERS 32 -#define OAL_MAX_SAMPLES 256 -#define SURROUND_CHANNELS 6 // number of channels in surround mode -#define SIZE_FLOAT 4 // size of a float in bytes +#define SFX_MAX_SOURCE 1 +#define OAL_MAX_BUFFERS 32 +#define OAL_MAX_SAMPLES 256 +#define STEREO_CHANNELS 2 +#define SURROUND_CHANNELS 6 // number of channels in surround mode +#define SIZE_SHORT 2 +#define SIZE_FLOAT 4 // size of a float in bytes +#define FRAME_STEREO_SHORT STEREO_CHANNELS * SIZE_SHORT +#define FRAME_STEREO_FLOAT STEREO_CHANNELS * SIZE_FLOAT +#define FRAME_SURROUND_FLOAT SURROUND_CHANNELS * SIZE_FLOAT #endif class OpenALStream: public SoundStream @@ -61,8 +66,8 @@ private: std::thread thread; Common::Event soundSyncEvent; - short realtimeBuffer[OAL_MAX_SAMPLES * 2]; - soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; + short realtimeBuffer[OAL_MAX_SAMPLES * STEREO_CHANNELS]; + soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; ALuint uiBuffers[OAL_MAX_BUFFERS]; ALuint uiSource; ALfloat fVolume;