summaryrefslogtreecommitdiff
path: root/Source/Core/AudioCommon/OpenALStream.cpp
diff options
context:
space:
mode:
authorshuffle2 <godisgovernment@gmail.com>2016-10-02 21:00:10 -0700
committerGitHub <noreply@github.com>2016-10-02 21:00:10 -0700
commit7f4106646e2f8b35478b26cd4ef822d4305bd955 (patch)
treeb88f8a2627e8bc2bb5fa7aa87625dc58ff96e0fa /Source/Core/AudioCommon/OpenALStream.cpp
parent25f983cb21c6afb0603d9ee982dc082fbd9a22a6 (diff)
parent8fa79f38971ebd2fab9e0c95e969e4a1f174fd8e (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.cpp252
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();
- }
}
}