diff --git a/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp b/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp index 08902e1c3f..49f50b6880 100644 --- a/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp +++ b/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp @@ -42,7 +42,6 @@ void AudioCommonConfig::Load() #else file.Get("Config", "Backend", &sBackend, BACKEND_NULLSOUND); #endif - file.Get("Config", "Frequency", &iFrequency, 48000); file.Get("Config", "Volume", &m_Volume, 100); } @@ -55,7 +54,6 @@ void AudioCommonConfig::SaveSettings() file.Set("Config", "EnableJIT", m_EnableJIT); file.Set("Config", "DumpAudio", m_DumpAudio); file.Set("Config", "Backend", sBackend); - file.Set("Config", "Frequency", iFrequency); file.Set("Config", "Volume", m_Volume); file.Save(File::GetUserPath(F_DSPCONFIG_IDX)); diff --git a/Source/Core/AudioCommon/Src/AudioCommonConfig.h b/Source/Core/AudioCommon/Src/AudioCommonConfig.h index 76c50c6408..48807b3ffd 100644 --- a/Source/Core/AudioCommon/Src/AudioCommonConfig.h +++ b/Source/Core/AudioCommon/Src/AudioCommonConfig.h @@ -37,7 +37,6 @@ struct AudioCommonConfig bool m_DumpAudio; int m_Volume; std::string sBackend; - int iFrequency; // Load from given file void Load(); diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index eefc62e346..94112c130d 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -46,6 +46,11 @@ bool OpenALStream::Start() pContext = alcCreateContext(pDevice, NULL); if (pContext) { + // Used to determine an appropriate period size (2x period = total buffer size) + //ALCint refresh; + //alcGetIntegerv(pDevice, ALC_REFRESH, 1, &refresh); + //period_size_in_millisec = 1000 / refresh; + alcMakeContextCurrent(pContext); thread = std::thread(std::mem_fun(&OpenALStream::SoundLoop), this); bReturn = true; @@ -90,7 +95,7 @@ void OpenALStream::Stop() // Clean up buffers and sources alDeleteSources(1, &uiSource); uiSource = 0; - alDeleteBuffers(OAL_NUM_BUFFERS, uiBuffers); + alDeleteBuffers(numBuffers, uiBuffers); ALCcontext *pContext = alcGetCurrentContext(); ALCdevice *pDevice = alcGetContextsDevice(pContext); @@ -133,19 +138,20 @@ void OpenALStream::SoundLoop() Common::SetCurrentThreadName("Audio thread - openal"); u32 ulFrequency = m_mixer->GetSampleRate(); + numBuffers = Core::g_CoreStartupParameter.iLatency + 2; // OpenAL requires a minimum of two buffers - memset(uiBuffers, 0, OAL_NUM_BUFFERS * sizeof(ALuint)); + memset(uiBuffers, 0, numBuffers * sizeof(ALuint)); uiSource = 0; // Generate some AL Buffers for streaming - alGenBuffers(OAL_NUM_BUFFERS, (ALuint *)uiBuffers); + alGenBuffers(numBuffers, (ALuint *)uiBuffers); // Generate a Source to playback the Buffers alGenSources(1, &uiSource); // Short Silence - memset(sampleBuffer, 0, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_NUM_BUFFERS); + memset(sampleBuffer, 0, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * numBuffers); memset(realtimeBuffer, 0, OAL_MAX_SAMPLES * 4); - for (int i = 0; i < OAL_NUM_BUFFERS; i++) + for (int i = 0; i < numBuffers; i++) { #if !defined(__APPLE__) if (Core::g_CoreStartupParameter.bDPL2Decoder) @@ -154,7 +160,7 @@ void OpenALStream::SoundLoop() #endif alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, 4 * 2 * 2, ulFrequency); } - alSourceQueueBuffers(uiSource, OAL_NUM_BUFFERS, uiBuffers); + alSourceQueueBuffers(uiSource, numBuffers, uiBuffers); alSourcePlay(uiSource); // Set the default sound volume as saved in the config file. @@ -166,7 +172,7 @@ void OpenALStream::SoundLoop() ALint iBuffersFilled = 0; ALint iBuffersProcessed = 0; ALint iState = 0; - ALuint uiBufferTemp[OAL_NUM_BUFFERS] = {0}; + ALuint uiBufferTemp[OAL_MAX_BUFFERS] = {0}; soundTouch.setChannels(2); soundTouch.setSampleRate(ulFrequency); @@ -216,7 +222,7 @@ void OpenALStream::SoundLoop() soundTouch.setSetting(SETTING_SEQUENCE_MS, (int)(1 / (rate * rate))); soundTouch.setTempo(rate); } - unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_NUM_BUFFERS); + unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_MAX_BUFFERS); if (nSamples > 0) { // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer) @@ -236,14 +242,14 @@ void OpenALStream::SoundLoop() if (surround_capable) { // Convert the samples from short to float for the dpl2 decoder - float dest[OAL_MAX_SAMPLES * 2 * 2 * OAL_NUM_BUFFERS]; + float dest[OAL_MAX_SAMPLES * 2 * 2 * OAL_MAX_BUFFERS]; for (u32 i = 0; i < nSamples; ++i) { dest[i * 2 + 0] = (float)sampleBuffer[i * 2 + 0] / (1<<16); dest[i * 2 + 1] = (float)sampleBuffer[i * 2 + 1] / (1<<16); } - float dpl2[OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_NUM_BUFFERS]; + float dpl2[OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; dpl2decode(dest, nSamples, dpl2); alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_51CHN32, dpl2, nSamples * SIZE_FLOAT * SURROUND_CHANNELS, ulFrequency); @@ -273,7 +279,7 @@ void OpenALStream::SoundLoop() } iBuffersFilled++; - if (iBuffersFilled == OAL_NUM_BUFFERS) + if (iBuffersFilled == numBuffers) { alSourcePlay(uiSource); ALenum err = alGetError(); diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h index f325d6b63a..a808fcefc9 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.h +++ b/Source/Core/AudioCommon/Src/OpenALStream.h @@ -44,8 +44,8 @@ // 16 bit Stereo #define SFX_MAX_SOURCE 1 -#define OAL_NUM_BUFFERS 16 -#define OAL_MAX_SAMPLES 512 +#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 #endif @@ -75,10 +75,12 @@ private: Common::Event soundSyncEvent; short realtimeBuffer[OAL_MAX_SAMPLES * 2]; - soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_NUM_BUFFERS]; - ALuint uiBuffers[OAL_NUM_BUFFERS]; + soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; + ALuint uiBuffers[OAL_MAX_BUFFERS]; ALuint uiSource; ALfloat fVolume; + + u8 numBuffers; #else public: OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {} diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index d4b79774ef..210769c8a5 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -228,6 +228,7 @@ void SConfig::SaveSettings() ini.Set("Core", "EnableCheats", m_LocalCoreStartupParameter.bEnableCheats); ini.Set("Core", "SelectedLanguage", m_LocalCoreStartupParameter.SelectedLanguage); ini.Set("Core", "DPL2Decoder", m_LocalCoreStartupParameter.bDPL2Decoder); + ini.Set("Core", "Latency", m_LocalCoreStartupParameter.iLatency); ini.Set("Core", "MemcardA", m_strMemoryCardA); ini.Set("Core", "MemcardB", m_strMemoryCardB); ini.Set("Core", "SlotA", m_EXIDevice[0]); @@ -369,6 +370,7 @@ void SConfig::LoadSettings() ini.Get("Core", "EnableCheats", &m_LocalCoreStartupParameter.bEnableCheats, false); ini.Get("Core", "SelectedLanguage", &m_LocalCoreStartupParameter.SelectedLanguage, 0); ini.Get("Core", "DPL2Decoder", &m_LocalCoreStartupParameter.bDPL2Decoder, true); + ini.Get("Core", "Latency", &m_LocalCoreStartupParameter.iLatency, 14); ini.Get("Core", "MemcardA", &m_strMemoryCardA); ini.Get("Core", "MemcardB", &m_strMemoryCardB); ini.Get("Core", "SlotA", (int*)&m_EXIDevice[0], EXIDEVICE_MEMORYCARD); diff --git a/Source/Core/Core/Src/CoreParameter.cpp b/Source/Core/Core/Src/CoreParameter.cpp index 64a3fc54d8..b8294ce815 100644 --- a/Source/Core/Core/Src/CoreParameter.cpp +++ b/Source/Core/Core/Src/CoreParameter.cpp @@ -49,7 +49,7 @@ SCoreStartupParameter::SCoreStartupParameter() bEnableCheats(false), bMergeBlocks(false), bRunCompareServer(false), bRunCompareClient(false), - bDPL2Decoder(true), + bDPL2Decoder(true), iLatency(14), bMMU(false), bMMUBAT(false), iTLBHack(0), bVBeam(false), bFastDiscSpeed(false), SelectedLanguage(0), bWii(false), bDisableWiimoteSpeaker(false), @@ -86,6 +86,7 @@ void SCoreStartupParameter::LoadDefaults() SelectedLanguage = 0; bWii = false; bDPL2Decoder = true; + iLatency = 14; iPosX = 100; iPosY = 100; diff --git a/Source/Core/Core/Src/CoreParameter.h b/Source/Core/Core/Src/CoreParameter.h index b67bf24b20..0dd8b68f22 100644 --- a/Source/Core/Core/Src/CoreParameter.h +++ b/Source/Core/Core/Src/CoreParameter.h @@ -108,6 +108,7 @@ struct SCoreStartupParameter bool bMergeBlocks; bool bDPL2Decoder; + int iLatency; bool bRunCompareServer; bool bRunCompareClient; diff --git a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp index 817610ea0f..7981c677a8 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp @@ -251,7 +251,7 @@ void DSPHLE::InitMixer() unsigned int AISampleRate, DACSampleRate; AudioInterface::Callback_GetSampleRate(AISampleRate, DACSampleRate); delete soundStream; - soundStream = AudioCommon::InitSoundStream(new HLEMixer(this, AISampleRate, DACSampleRate, ac_Config.iFrequency), m_hWnd); + soundStream = AudioCommon::InitSoundStream(new HLEMixer(this, AISampleRate, DACSampleRate, 48000), m_hWnd); if(!soundStream) PanicAlert("Error starting up sound stream"); // Mixer is initialized m_InitMixer = true; diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp index a44ff65f21..b5ca788e72 100644 --- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp +++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp @@ -204,7 +204,7 @@ void DSPLLE::InitMixer() unsigned int AISampleRate, DACSampleRate; AudioInterface::Callback_GetSampleRate(AISampleRate, DACSampleRate); delete soundStream; - soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DACSampleRate, ac_Config.iFrequency), m_hWnd); + soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DACSampleRate, 48000), m_hWnd); if(!soundStream) PanicAlert("Error starting up sound stream"); // Mixer is initialized m_InitMixer = true; diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index 78fc886c10..ddc8025d88 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -121,7 +121,7 @@ EVT_CHECKBOX(ID_DSPTHREAD, CConfigMain::AudioSettingsChanged) EVT_CHECKBOX(ID_ENABLE_THROTTLE, CConfigMain::AudioSettingsChanged) EVT_CHECKBOX(ID_DUMP_AUDIO, CConfigMain::AudioSettingsChanged) EVT_CHECKBOX(ID_DPL2DECODER, CConfigMain::AudioSettingsChanged) -EVT_CHOICE(ID_FREQUENCY, CConfigMain::AudioSettingsChanged) +EVT_SLIDER(ID_LATENCY, CConfigMain::AudioSettingsChanged) EVT_CHOICE(ID_BACKEND, CConfigMain::AudioSettingsChanged) EVT_SLIDER(ID_VOLUME, CConfigMain::AudioSettingsChanged) @@ -218,6 +218,8 @@ void CConfigMain::UpdateGUI() // Disable stuff on AudioPage DSPEngine->Disable(); DSPThread->Disable(); + DPL2Decoder->Disable(); + LatencySlider->Disable(); // Disable stuff on GamecubePage GCSystemLang->Disable(); @@ -365,8 +367,9 @@ void CConfigMain::InitializeGUIValues() DSPThread->SetValue(startup_params.bDSPThread); DumpAudio->SetValue(ac_Config.m_DumpAudio ? true : false); DPL2Decoder->SetValue(startup_params.bDPL2Decoder); - FrequencySelection->SetSelection( - FrequencySelection->FindString(wxString::Format(_("%d Hz"), ac_Config.iFrequency))); + LatencySlider->Enable(std::string(ac_Config.sBackend) == BACKEND_OPENAL); + LatencySlider->SetValue(startup_params.iLatency); + LatencyText->SetLabel(wxString::Format(wxT("%d"), startup_params.iLatency)); // add backends to the list AddAudioBackends(); @@ -511,7 +514,6 @@ void CConfigMain::InitializeGUITooltips() // Audio tooltips DSPThread->SetToolTip(_("Run DSP LLE on a dedicated thread (not recommended).")); - FrequencySelection->SetToolTip(_("Changing this will have no effect while the emulator is running!")); BackendSelection->SetToolTip(_("Changing this will have no effect while the emulator is running!")); // Gamecube - Devices @@ -527,6 +529,8 @@ void CConfigMain::InitializeGUITooltips() #elif defined(_WIN32) DPL2Decoder->SetToolTip(_("Enables Dolby Pro Logic II emulation using 5.1 surround. OpenAL backend only. May need to rename soft_oal.dll to OpenAL32.dll to make it work.")); #endif + + LatencySlider->SetToolTip(_("Sets the latency (in ms). Higher values may reduce audio crackling. OpenAL backend only.")); } void CConfigMain::CreateGUIControls() @@ -630,13 +634,14 @@ void CConfigMain::CreateGUIControls() wxDefaultPosition, wxDefaultSize, 0); BackendSelection = new wxChoice(AudioPage, ID_BACKEND, wxDefaultPosition, wxDefaultSize, wxArrayBackends, 0, wxDefaultValidator, wxEmptyString); - FrequencySelection = new wxChoice(AudioPage, ID_FREQUENCY); - FrequencySelection->Append(wxString::Format(_("%d Hz"), 48000)); - FrequencySelection->Append(wxString::Format(_("%d Hz"), 32000)); + LatencySlider = new wxSlider(AudioPage, ID_LATENCY, 0, 0, 30, + wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL); + LatencyText = new wxStaticText(AudioPage, wxID_ANY, wxT(""), + wxDefaultPosition, wxDefaultSize, 0); if (Core::GetState() != Core::CORE_UNINITIALIZED) { - FrequencySelection->Disable(); + LatencySlider->Disable(); BackendSelection->Disable(); DPL2Decoder->Disable(); } @@ -655,8 +660,9 @@ void CConfigMain::CreateGUIControls() wxGridBagSizer *sBackend = new wxGridBagSizer(); sBackend->Add(TEXT_BOX(AudioPage, _("Audio Backend:")), wxGBPosition(0, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL|wxALL, 5); sBackend->Add(BackendSelection, wxGBPosition(0, 1), wxDefaultSpan, wxALL, 5); - sBackend->Add(TEXT_BOX(AudioPage, _("Sample Rate:")), wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL|wxALL, 5); - sBackend->Add(FrequencySelection, wxGBPosition(1, 1), wxDefaultSpan, wxALL, 5); + sBackend->Add(TEXT_BOX(AudioPage, _("Latency:")), wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL|wxALL, 5); + sBackend->Add(LatencySlider, wxGBPosition(1, 1), wxDefaultSpan, wxALL, 5); + sBackend->Add(LatencyText, wxGBPosition(1, 2), wxDefaultSpan, wxALL, 5); wxStaticBoxSizer *sbBackend = new wxStaticBoxSizer(wxHORIZONTAL, AudioPage, _("Backend Settings")); sbBackend->Add(sBackend, 0, wxEXPAND); @@ -946,17 +952,19 @@ void CConfigMain::AudioSettingsChanged(wxCommandEvent& event) case ID_BACKEND: VolumeSlider->Enable(SupportsVolumeChanges(std::string(BackendSelection->GetStringSelection().mb_str()))); + LatencySlider->Enable(std::string(BackendSelection->GetStringSelection().mb_str()) == BACKEND_OPENAL); + DPL2Decoder->Enable(std::string(BackendSelection->GetStringSelection().mb_str()) == BACKEND_OPENAL); ac_Config.sBackend = BackendSelection->GetStringSelection().mb_str(); ac_Config.Update(); break; + case ID_LATENCY: + SConfig::GetInstance().m_LocalCoreStartupParameter.iLatency = LatencySlider->GetValue(); + LatencyText->SetLabel(wxString::Format(wxT("%d"), LatencySlider->GetValue())); + break; + default: ac_Config.m_DumpAudio = DumpAudio->GetValue(); - - long int frequency; - FrequencySelection->GetStringSelection().ToLong(&frequency); - ac_Config.iFrequency = frequency; - ac_Config.Update(); break; } } diff --git a/Source/Core/DolphinWX/Src/ConfigMain.h b/Source/Core/DolphinWX/Src/ConfigMain.h index 01a85fabeb..c0cdd632e4 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.h +++ b/Source/Core/DolphinWX/Src/ConfigMain.h @@ -80,7 +80,7 @@ private: ID_ENABLE_THROTTLE, ID_DUMP_AUDIO, ID_DPL2DECODER, - ID_FREQUENCY, + ID_LATENCY, ID_BACKEND, ID_VOLUME, @@ -156,12 +156,13 @@ private: wxBoxSizer* sAudioPage; // GC settings wxRadioBox* DSPEngine; wxSlider* VolumeSlider; - wxStaticText* VolumeText; + wxStaticText* VolumeText; wxCheckBox* DumpAudio; wxCheckBox* DPL2Decoder; wxArrayString wxArrayBackends; wxChoice* BackendSelection; - wxChoice* FrequencySelection; + wxSlider* LatencySlider; + wxStaticText* LatencyText; // Interface wxCheckBox* ConfirmStop;