diff --git a/Source/Core/AudioCommon/OpenALStream.cpp b/Source/Core/AudioCommon/OpenALStream.cpp index 21b2ae0acc..8276cd266f 100644 --- a/Source/Core/AudioCommon/OpenALStream.cpp +++ b/Source/Core/AudioCommon/OpenALStream.cpp @@ -138,7 +138,7 @@ void OpenALStream::Stop() // Clean up buffers and sources palDeleteSources(1, &uiSource); uiSource = 0; - palDeleteBuffers(numBuffers, uiBuffers); + palDeleteBuffers(OAL_BUFFERS, uiBuffers.data()); ALCcontext* pContext = palcGetCurrentContext(); ALCdevice* pDevice = palcGetContextsDevice(pContext); @@ -230,16 +230,43 @@ void OpenALStream::SoundLoop() bool fixed32_capable = IsCreativeXFi(); u32 ulFrequency = m_mixer->GetSampleRate(); - numBuffers = SConfig::GetInstance().iLatency + 2; // OpenAL requires a minimum of two buffers - memset(uiBuffers, 0, numBuffers * sizeof(ALuint)); + u32 frames_per_buffer; + // Can't have zero samples per buffer + if (SConfig::GetInstance().iLatency > 0) + { + frames_per_buffer = ulFrequency / 1000 * SConfig::GetInstance().iLatency / OAL_BUFFERS; + } + else + { + frames_per_buffer = ulFrequency / 1000 * 1 / OAL_BUFFERS; + } + + if (frames_per_buffer > OAL_MAX_FRAMES) + { + frames_per_buffer = OAL_MAX_FRAMES; + } + + // DPL2 needs a minimum number of samples to work (FWRDURATION) + if (use_surround && frames_per_buffer < 240) + { + frames_per_buffer = 240; + } + + INFO_LOG(AUDIO, "Using %d buffers, each with %d audio frames for a total of %d.", OAL_BUFFERS, + frames_per_buffer, frames_per_buffer * OAL_BUFFERS); + + // Should we make these larger just in case the mixer ever sends more samples + // than what we request? + realtimeBuffer.resize(frames_per_buffer * STEREO_CHANNELS); + sampleBuffer.resize(frames_per_buffer * STEREO_CHANNELS); uiSource = 0; // Clear error state before querying or else we get false positives. ALenum err = palGetError(); // Generate some AL Buffers for streaming - palGenBuffers(numBuffers, (ALuint*)uiBuffers); + palGenBuffers(OAL_BUFFERS, (ALuint*)uiBuffers.data()); err = CheckALError("generating buffers"); // Generate a Source to playback the Buffers @@ -261,7 +288,7 @@ void OpenALStream::SoundLoop() // Block until we have a free buffer int numBuffersProcessed; palGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &numBuffersProcessed); - if (numBuffers == numBuffersQueued && !numBuffersProcessed) + if (OAL_BUFFERS == numBuffersQueued && !numBuffersProcessed) { soundSyncEvent.Wait(); continue; @@ -270,21 +297,21 @@ void OpenALStream::SoundLoop() // Remove the Buffer from the Queue. if (numBuffersProcessed) { - ALuint unqueuedBufferIds[OAL_MAX_BUFFERS]; + ALuint unqueuedBufferIds[OAL_BUFFERS]; palSourceUnqueueBuffers(uiSource, numBuffersProcessed, unqueuedBufferIds); err = CheckALError("unqueuing buffers"); numBuffersQueued -= numBuffersProcessed; } - unsigned int numSamples = OAL_MAX_SAMPLES; + unsigned int numSamples = frames_per_buffer; if (use_surround) { // DPL2 accepts 240 samples minimum (FWRDURATION) unsigned int minSamples = 240; - float dpl2[OAL_MAX_SAMPLES * OAL_MAX_BUFFERS * SURROUND_CHANNELS]; + float dpl2[OAL_MAX_FRAMES * SURROUND_CHANNELS]; numSamples = m_mixer->MixSurround(dpl2, numSamples); if (numSamples < minSamples) @@ -306,7 +333,7 @@ void OpenALStream::SoundLoop() } else if (fixed32_capable) { - int surround_int32[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; + int surround_int32[OAL_MAX_FRAMES * SURROUND_CHANNELS]; for (u32 i = 0; i < numSamples * SURROUND_CHANNELS; ++i) { @@ -327,7 +354,7 @@ void OpenALStream::SoundLoop() } else { - short surround_short[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; + short surround_short[OAL_MAX_FRAMES * SURROUND_CHANNELS]; for (u32 i = 0; i < numSamples * SURROUND_CHANNELS; ++i) { @@ -355,7 +382,7 @@ void OpenALStream::SoundLoop() } else { - numSamples = m_mixer->Mix(realtimeBuffer, numSamples); + numSamples = m_mixer->Mix(realtimeBuffer.data(), numSamples); // Convert the samples from short to float for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i) @@ -366,7 +393,7 @@ void OpenALStream::SoundLoop() if (float32_capable) { - palBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO_FLOAT32, sampleBuffer, + palBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO_FLOAT32, sampleBuffer.data(), numSamples * FRAME_STEREO_FLOAT, ulFrequency); err = CheckALError("buffering float32 data"); @@ -378,7 +405,7 @@ void OpenALStream::SoundLoop() else if (fixed32_capable) { // Clamping is not necessary here, samples are always between (-1,1) - int stereo_int32[OAL_MAX_SAMPLES * STEREO_CHANNELS * OAL_MAX_BUFFERS]; + int stereo_int32[OAL_MAX_FRAMES * STEREO_CHANNELS]; for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i) stereo_int32[i] = (int)((float)sampleBuffer[i] * (INT64_C(1) << 31)); @@ -388,7 +415,7 @@ void OpenALStream::SoundLoop() else { // Convert the samples from float to short - short stereo[OAL_MAX_SAMPLES * STEREO_CHANNELS * OAL_MAX_BUFFERS]; + short stereo[OAL_MAX_FRAMES * STEREO_CHANNELS]; for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i) stereo[i] = (short)((float)sampleBuffer[i] * (1 << 15)); @@ -401,7 +428,7 @@ void OpenALStream::SoundLoop() err = CheckALError("queuing buffers"); numBuffersQueued++; - nextBuffer = (nextBuffer + 1) % numBuffers; + nextBuffer = (nextBuffer + 1) % OAL_BUFFERS; palGetSourcei(uiSource, AL_SOURCE_STATE, &iState); if (iState != AL_PLAYING) diff --git a/Source/Core/AudioCommon/OpenALStream.h b/Source/Core/AudioCommon/OpenALStream.h index 78c0a616a1..ee7ae47813 100644 --- a/Source/Core/AudioCommon/OpenALStream.h +++ b/Source/Core/AudioCommon/OpenALStream.h @@ -17,9 +17,9 @@ #include #include -#define SFX_MAX_SOURCE 1 -#define OAL_MAX_BUFFERS 32 -#define OAL_MAX_SAMPLES 256 +// OpenAL requires a minimum of two buffers, three or more recommended +#define OAL_BUFFERS 3 +#define OAL_MAX_FRAMES 4096 #define STEREO_CHANNELS 2 #define SURROUND_CHANNELS 6 // number of channels in surround mode #define SIZE_SHORT 2 @@ -72,12 +72,11 @@ private: Common::Event soundSyncEvent; - short realtimeBuffer[OAL_MAX_SAMPLES * STEREO_CHANNELS]; - float sampleBuffer[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; - ALuint uiBuffers[OAL_MAX_BUFFERS]; + std::vector realtimeBuffer; + std::vector sampleBuffer; + std::array uiBuffers; ALuint uiSource; ALfloat fVolume; - u8 numBuffers; #endif // _WIN32 }; diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index 19af3de572..c2e6940042 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -254,7 +254,7 @@ void SConfig::SaveCoreSettings(IniFile& ini) core->Set("SelectedLanguage", SelectedLanguage); core->Set("OverrideGCLang", bOverrideGCLanguage); core->Set("DPL2Decoder", bDPL2Decoder); - core->Set("Latency", iLatency); + core->Set("AudioLatency", iLatency); core->Set("AudioStretch", m_audio_stretch); core->Set("AudioStretchMaxLatency", m_audio_stretch_max_latency); core->Set("MemcardAPath", m_strMemoryCardA); @@ -568,7 +568,7 @@ void SConfig::LoadCoreSettings(IniFile& ini) core->Get("SelectedLanguage", &SelectedLanguage, 0); core->Get("OverrideGCLang", &bOverrideGCLanguage, false); core->Get("DPL2Decoder", &bDPL2Decoder, false); - core->Get("Latency", &iLatency, 5); + core->Get("AudioLatency", &iLatency, 20); core->Get("AudioStretch", &m_audio_stretch, false); core->Get("AudioStretchMaxLatency", &m_audio_stretch_max_latency, 80); core->Get("MemcardAPath", &m_strMemoryCardA); @@ -831,7 +831,7 @@ void SConfig::LoadDefaults() bOverrideGCLanguage = false; bWii = false; bDPL2Decoder = false; - iLatency = 14; + iLatency = 20; m_audio_stretch = false; m_audio_stretch_max_latency = 80; diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index 9a97b68df0..e40b6bf320 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -109,7 +109,7 @@ struct SConfig : NonCopyable bool bCopyWiiSaveNetplay = true; bool bDPL2Decoder = false; - int iLatency = 14; + int iLatency = 20; bool m_audio_stretch = false; int m_audio_stretch_max_latency = 80; diff --git a/Source/Core/DolphinWX/Config/AudioConfigPane.cpp b/Source/Core/DolphinWX/Config/AudioConfigPane.cpp index 5e940ffb22..c9f3c6b0e1 100644 --- a/Source/Core/DolphinWX/Config/AudioConfigPane.cpp +++ b/Source/Core/DolphinWX/Config/AudioConfigPane.cpp @@ -45,8 +45,8 @@ void AudioConfigPane::InitializeGUI() m_audio_backend_choice = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_audio_backend_strings); m_audio_latency_spinctrl = - new wxSpinCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 30); - m_audio_latency_label = new wxStaticText(this, wxID_ANY, _("Latency:")); + new wxSpinCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 200); + m_audio_latency_label = new wxStaticText(this, wxID_ANY, _("Latency (ms):")); m_stretch_checkbox = new wxCheckBox(this, wxID_ANY, _("Enable Audio Stretching")); m_stretch_label = new wxStaticText(this, wxID_ANY, _("Buffer Size:"));