diff options
| author | shuffle2 <godisgovernment@gmail.com> | 2016-10-02 21:00:10 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-10-02 21:00:10 -0700 |
| commit | 7f4106646e2f8b35478b26cd4ef822d4305bd955 (patch) | |
| tree | b88f8a2627e8bc2bb5fa7aa87625dc58ff96e0fa /Source/Core/AudioCommon/OpenALStream.cpp | |
| parent | 25f983cb21c6afb0603d9ee982dc082fbd9a22a6 (diff) | |
| parent | 8fa79f38971ebd2fab9e0c95e969e4a1f174fd8e (diff) | |
Merge pull request #4271 from ligfx/audiofix
OpenAL: Don't request samples if buffers are full
Diffstat (limited to 'Source/Core/AudioCommon/OpenALStream.cpp')
| -rw-r--r-- | Source/Core/AudioCommon/OpenALStream.cpp | 252 |
1 files changed, 105 insertions, 147 deletions
diff --git a/Source/Core/AudioCommon/OpenALStream.cpp b/Source/Core/AudioCommon/OpenALStream.cpp index c3679f47b7..56cd2bf61e 100644 --- a/Source/Core/AudioCommon/OpenALStream.cpp +++ b/Source/Core/AudioCommon/OpenALStream.cpp @@ -159,44 +159,15 @@ void OpenALStream::SoundLoop() // Generate a Source to playback the Buffers alGenSources(1, &uiSource); - // Short Silence - if (float32_capable) - memset(sampleBuffer, 0, OAL_MAX_SAMPLES * numBuffers * FRAME_SURROUND_FLOAT); - else - memset(sampleBuffer, 0, OAL_MAX_SAMPLES * numBuffers * FRAME_SURROUND_SHORT); - - memset(realtimeBuffer, 0, OAL_MAX_SAMPLES * FRAME_STEREO_SHORT); - - for (int i = 0; i < numBuffers; i++) - { - if (surround_capable) - { - if (float32_capable) - alBufferData(uiBuffers[i], AL_FORMAT_51CHN32, sampleBuffer, 4 * FRAME_SURROUND_FLOAT, - ulFrequency); - else - alBufferData(uiBuffers[i], AL_FORMAT_51CHN16, sampleBuffer, 4 * FRAME_SURROUND_SHORT, - ulFrequency); - } - else - { - 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); // TODO: Error handling // ALenum err = alGetError(); - ALint iBuffersFilled = 0; - ALint iBuffersProcessed = 0; + unsigned int nextBuffer = 0; + unsigned int numBuffersQueued = 0; ALint iState = 0; - ALuint uiBufferTemp[OAL_MAX_BUFFERS] = {0}; soundTouch.setChannels(2); soundTouch.setSampleRate(ulFrequency); @@ -209,6 +180,28 @@ void OpenALStream::SoundLoop() while (m_run_thread.IsSet()) { + // Block until we have a free buffer + int numBuffersProcessed; + alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &numBuffersProcessed); + if (numBuffers == numBuffersQueued && !numBuffersProcessed) + { + soundSyncEvent.Wait(); + continue; + } + + // Remove the Buffer from the Queue. + if (numBuffersProcessed) + { + ALuint unqueuedBufferIds[OAL_MAX_BUFFERS]; + alSourceUnqueueBuffers(uiSource, numBuffersProcessed, unqueuedBufferIds); + ALenum err = alGetError(); + if (err != 0) + { + ERROR_LOG(AUDIO, "Error unqueuing buffers: %08x", err); + } + numBuffersQueued -= numBuffersProcessed; + } + // num_samples_to_render in this update - depends on SystemTimers::AUDIO_DMA_PERIOD. const u32 stereo_16_bit_size = 4; const u32 dma_length = 32; @@ -232,155 +225,120 @@ void OpenALStream::SoundLoop() soundTouch.putSamples(dest, numSamples); - if (iBuffersProcessed == iBuffersFilled) + double rate = (double)m_mixer->GetCurrentSpeed(); + if (rate <= 0) { - alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed); - iBuffersFilled = 0; + Core::RequestRefreshInfo(); + rate = (double)m_mixer->GetCurrentSpeed(); } - if (iBuffersProcessed) + // Place a lower limit of 10% speed. When a game boots up, there will be + // many silence samples. These do not need to be timestretched. + if (rate > 0.10) { - double rate = (double)m_mixer->GetCurrentSpeed(); - if (rate <= 0) + soundTouch.setTempo(rate); + if (rate > 10) { - Core::RequestRefreshInfo(); - rate = (double)m_mixer->GetCurrentSpeed(); - } - - // Place a lower limit of 10% speed. When a game boots up, there will be - // many silence samples. These do not need to be timestretched. - if (rate > 0.10) - { - soundTouch.setTempo(rate); - if (rate > 10) - { - soundTouch.clear(); - } + soundTouch.clear(); } + } - unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * numBuffers); + unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * numBuffers); - if (nSamples <= minSamples) - continue; + if (nSamples <= minSamples) + continue; - // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued - // Buffer) - if (iBuffersFilled == 0) + if (surround_capable) + { + float dpl2[OAL_MAX_SAMPLES * OAL_MAX_BUFFERS * SURROUND_CHANNELS]; + DPL2Decode(sampleBuffer, nSamples, dpl2); + + // zero-out the subwoofer channel - DPL2Decode generates a pretty + // good 5.0 but not a good 5.1 output. Sadly there is not a 5.0 + // AL_FORMAT_50CHN32 to make this super-explicit. + // DPL2Decode output: LEFTFRONT, RIGHTFRONT, CENTREFRONT, (sub), LEFTREAR, RIGHTREAR + for (u32 i = 0; i < nSamples; ++i) { - alSourceUnqueueBuffers(uiSource, iBuffersProcessed, uiBufferTemp); - ALenum err = alGetError(); - if (err != 0) - { - ERROR_LOG(AUDIO, "Error unqueuing buffers: %08x", err); - } + dpl2[i * SURROUND_CHANNELS + 3 /*sub/lfe*/] = 0.0f; } - if (surround_capable) + if (float32_capable) { - float dpl2[OAL_MAX_SAMPLES * OAL_MAX_BUFFERS * SURROUND_CHANNELS]; - DPL2Decode(sampleBuffer, nSamples, dpl2); - - // zero-out the subwoofer channel - DPL2Decode generates a pretty - // good 5.0 but not a good 5.1 output. Sadly there is not a 5.0 - // AL_FORMAT_50CHN32 to make this super-explicit. - // DPL2Decode output: LEFTFRONT, RIGHTFRONT, CENTREFRONT, (sub), LEFTREAR, RIGHTREAR - for (u32 i = 0; i < nSamples; ++i) - { - dpl2[i * SURROUND_CHANNELS + 3 /*sub/lfe*/] = 0.0f; - } + alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN32, dpl2, + nSamples * FRAME_SURROUND_FLOAT, ulFrequency); + } + else + { + short surround_short[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; + for (u32 i = 0; i < nSamples * SURROUND_CHANNELS; ++i) + surround_short[i] = (short)((float)dpl2[i] * (1 << 15)); - if (float32_capable) - { - alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_51CHN32, dpl2, - nSamples * FRAME_SURROUND_FLOAT, ulFrequency); - } - else - { - short surround_short[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; - for (u32 i = 0; i < nSamples * SURROUND_CHANNELS; ++i) - surround_short[i] = (short)((float)dpl2[i] * (1 << 15)); + alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN16, surround_short, + nSamples * FRAME_SURROUND_SHORT, ulFrequency); + } - alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_51CHN16, surround_short, - nSamples * FRAME_SURROUND_SHORT, 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); + } + } + else + { + if (float32_capable) + { + alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO_FLOAT32, sampleBuffer, + nSamples * FRAME_STEREO_FLOAT, 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; + float32_capable = false; } else if (err != 0) { - ERROR_LOG(AUDIO, "Error occurred while buffering data: %08x", err); + ERROR_LOG(AUDIO, "Error occurred while buffering float32 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) - { - float32_capable = false; - } - else if (err != 0) - { - ERROR_LOG(AUDIO, "Error occurred while buffering float32 data: %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 << 15)); - else - { - // 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 << 15)); - - alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, stereo, - nSamples * FRAME_STEREO_SHORT, ulFrequency); - } + alBufferData(uiBuffers[nextBuffer], 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); - } - } + alSourceQueueBuffers(uiSource, 1, &uiBuffers[nextBuffer]); + ALenum err = alGetError(); + if (err != 0) + { + ERROR_LOG(AUDIO, "Error queuing buffers: %08x", err); + } + numBuffersQueued++; + nextBuffer = (nextBuffer + 1) % numBuffers; - alGetSourcei(uiSource, AL_SOURCE_STATE, &iState); - if (iState != AL_PLAYING) + alGetSourcei(uiSource, AL_SOURCE_STATE, &iState); + if (iState != AL_PLAYING) + { + // Buffer underrun occurred, resume playback + alSourcePlay(uiSource); + err = alGetError(); + if (err != 0) { - // Buffer underrun occurred, resume playback - alSourcePlay(uiSource); - err = alGetError(); - if (err != 0) - { - ERROR_LOG(AUDIO, "Error occurred resuming playback: %08x", err); - } + ERROR_LOG(AUDIO, "Error occurred resuming playback: %08x", err); } } - else - { - soundSyncEvent.Wait(); - } } } |
