From c8c78e0aa9c7ec1ef738ca064daad5903a9e7b48 Mon Sep 17 00:00:00 2001 From: skidau Date: Mon, 7 Jan 2013 15:37:08 +1100 Subject: Implemented correct audio timing. Fixes issue 5493. --- Source/Core/AudioCommon/Src/OpenALStream.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'Source/Core/AudioCommon/Src/OpenALStream.cpp') diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index 2abd357782..4cc64a17de 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -19,6 +19,8 @@ #include "aldlist.h" #include "OpenALStream.h" +#include "../../Core/Src/HW/SystemTimers.h" +#include "../../Core/Src/HW/AudioInterface.h" #if defined HAVE_OPENAL && HAVE_OPENAL @@ -158,9 +160,16 @@ void OpenALStream::SoundLoop() iBuffersFilled = 0; } - unsigned int numSamples = m_mixer->GetNumSamples(); + // 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; + const u64 audio_dma_period = SystemTimers::GetTicksPerSecond() / (AudioInterface::GetAIDSampleRate() * stereo_16_bit_size / dma_length); + const u64 ais_samples_per_second = 48000 * stereo_16_bit_size; + const u64 num_samples_to_render = (audio_dma_period * ais_samples_per_second) / SystemTimers::GetTicksPerSecond(); - if (iBuffersProcessed && (numSamples >= OAL_THRESHOLD)) + unsigned int numSamples = (unsigned int)num_samples_to_render; + + if (iBuffersProcessed) { numSamples = (numSamples > OAL_MAX_SAMPLES) ? OAL_MAX_SAMPLES : numSamples; // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer) @@ -175,14 +184,10 @@ void OpenALStream::SoundLoop() if (iBuffersFilled == OAL_NUM_BUFFERS) alSourcePlay(uiSource); } - else if (numSamples >= OAL_THRESHOLD) + else { - ALint state = 0; - alGetSourcei(uiSource, AL_SOURCE_STATE, &state); - if (state == AL_STOPPED) - alSourcePlay(uiSource); + soundSyncEvent.Wait(); } - soundSyncEvent.Wait(); } } -- cgit v1.2.3 From 63b38be97c12e6b6f0ec39008f6b0dd06dbcf3f0 Mon Sep 17 00:00:00 2001 From: skidau Date: Wed, 9 Jan 2013 22:57:32 +1100 Subject: Added audio time stretching by using the SoundTouch library. --- Source/Core/AudioCommon/Src/OpenALStream.cpp | 79 ++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 23 deletions(-) (limited to 'Source/Core/AudioCommon/Src/OpenALStream.cpp') diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index 4cc64a17de..6f429db495 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -19,11 +19,12 @@ #include "aldlist.h" #include "OpenALStream.h" -#include "../../Core/Src/HW/SystemTimers.h" -#include "../../Core/Src/HW/AudioInterface.h" #if defined HAVE_OPENAL && HAVE_OPENAL +using namespace soundtouch; +SoundTouch soundTouch; + // // AyuanX: Spec says OpenAL1.1 is thread safe already // @@ -67,6 +68,7 @@ bool OpenALStream::Start() PanicAlertT("OpenAL: can't find sound devices"); } + soundTouch.clear(); return bReturn; } @@ -76,6 +78,8 @@ void OpenALStream::Stop() // kick the thread if it's waiting soundSyncEvent.Set(); + soundTouch.clear(); + thread.join(); alSourceStop(uiSource); @@ -105,6 +109,7 @@ void OpenALStream::SetVolume(int volume) void OpenALStream::Update() { soundSyncEvent.Set(); + mainSyncEvent.Wait(); } void OpenALStream::Clear(bool mute) @@ -113,6 +118,7 @@ void OpenALStream::Clear(bool mute) if(m_muted) { + soundTouch.clear(); alSourceStop(uiSource); } else @@ -136,9 +142,10 @@ void OpenALStream::SoundLoop() alGenSources(1, &uiSource); // Short Silence + memset(sampleBuffer, 0, OAL_MAX_SAMPLES * 4 * OAL_NUM_BUFFERS); memset(realtimeBuffer, 0, OAL_MAX_SAMPLES * 4); for (int i = 0; i < OAL_NUM_BUFFERS; i++) - alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, OAL_MAX_SAMPLES, ulFrequency); + alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, OAL_MAX_SAMPLES * 4, ulFrequency); alSourceQueueBuffers(uiSource, OAL_NUM_BUFFERS, uiBuffers); alSourcePlay(uiSource); @@ -152,42 +159,68 @@ void OpenALStream::SoundLoop() ALint iBuffersProcessed = 0; ALuint uiBufferTemp[OAL_NUM_BUFFERS] = {0}; + soundTouch.setChannels(2); + soundTouch.setSampleRate(ulFrequency); + soundTouch.setSetting(SETTING_USE_QUICKSEEK, 0); + soundTouch.setSetting(SETTING_USE_AA_FILTER, 0); + soundTouch.setSetting(SETTING_SEQUENCE_MS, 1); + soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 28); + soundTouch.setSetting(SETTING_OVERLAP_MS, 12); + while (!threadData) { - if (iBuffersProcessed == iBuffersFilled) - { - alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed); - iBuffersFilled = 0; - } - // 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; - const u64 audio_dma_period = SystemTimers::GetTicksPerSecond() / (AudioInterface::GetAIDSampleRate() * stereo_16_bit_size / dma_length); const u64 ais_samples_per_second = 48000 * stereo_16_bit_size; - const u64 num_samples_to_render = (audio_dma_period * ais_samples_per_second) / SystemTimers::GetTicksPerSecond(); + u64 audio_dma_period = SystemTimers::GetTicksPerSecond() / (AudioInterface::GetAIDSampleRate() * stereo_16_bit_size / dma_length); + u64 num_samples_to_render = (audio_dma_period * ais_samples_per_second) / SystemTimers::GetTicksPerSecond(); unsigned int numSamples = (unsigned int)num_samples_to_render; + numSamples = (numSamples > OAL_MAX_SAMPLES) ? OAL_MAX_SAMPLES : numSamples; + numSamples = m_mixer->Mix(realtimeBuffer, numSamples); + soundTouch.putSamples(realtimeBuffer, numSamples); + + if (iBuffersProcessed == iBuffersFilled) + { + alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed); + iBuffersFilled = 0; + } + if (iBuffersProcessed) { - numSamples = (numSamples > OAL_MAX_SAMPLES) ? OAL_MAX_SAMPLES : numSamples; - // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer) - if (iBuffersFilled == 0) - alSourceUnqueueBuffers(uiSource, iBuffersProcessed, uiBufferTemp); - - m_mixer->Mix(realtimeBuffer, numSamples); - alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, realtimeBuffer, numSamples * 4, ulFrequency); - alSourceQueueBuffers(uiSource, 1, &uiBufferTemp[iBuffersFilled]); - iBuffersFilled++; - - if (iBuffersFilled == OAL_NUM_BUFFERS) - alSourcePlay(uiSource); + float rate = m_mixer->GetCurrentSpeed(); + if (rate <= 0) + { + Core::RequestRefreshInfo(); + rate = m_mixer->GetCurrentSpeed(); + } + if (rate > 0) + { + // Adjust SETTING_SEQUENCE_MS to balance between lag vs hollow audio + soundTouch.setSetting(SETTING_SEQUENCE_MS, (int)pow(1 / rate, 2)); + soundTouch.setTempo(rate); + } + unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * 2 * OAL_NUM_BUFFERS); + if (nSamples > 0) + { + // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer) + if (iBuffersFilled == 0) + alSourceUnqueueBuffers(uiSource, iBuffersProcessed, uiBufferTemp); + alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, sampleBuffer, nSamples * 4, ulFrequency); + alSourceQueueBuffers(uiSource, 1, &uiBufferTemp[iBuffersFilled]); + iBuffersFilled++; + + if (iBuffersFilled == OAL_NUM_BUFFERS) + alSourcePlay(uiSource); + } } else { soundSyncEvent.Wait(); } + mainSyncEvent.Set(); } } -- cgit v1.2.3 From 8494a439c74bdd2eed60d7aba678761c1a8a7284 Mon Sep 17 00:00:00 2001 From: skidau Date: Thu, 10 Jan 2013 00:06:35 +1100 Subject: OSX build fix --- Source/Core/AudioCommon/Src/OpenALStream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/AudioCommon/Src/OpenALStream.cpp') diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index 6f429db495..85685b42cb 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -199,7 +199,7 @@ void OpenALStream::SoundLoop() if (rate > 0) { // Adjust SETTING_SEQUENCE_MS to balance between lag vs hollow audio - soundTouch.setSetting(SETTING_SEQUENCE_MS, (int)pow(1 / rate, 2)); + soundTouch.setSetting(SETTING_SEQUENCE_MS, (int)(1 / (rate * rate))); soundTouch.setTempo(rate); } unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * 2 * OAL_NUM_BUFFERS); -- cgit v1.2.3 From 01f4d9f386d225675d12cea7fedc1144dd2e02d4 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 9 Jan 2013 10:26:12 -0600 Subject: Fix include paths and compiling in Linux. Externals soundtouch is 1.7.1, while Ubuntu 12.10 is 1.6.x. Externals soundtouch is compiled with integer samples, while ubuntu is compiled with float samples. Float samples is probably the more common route. If you're going to use soundtouch, you should probably use SAMPLETYPE instead of explicitly choosing short. This probably breaks the windows build since its includes aren't setup. --- Source/Core/AudioCommon/Src/OpenALStream.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Source/Core/AudioCommon/Src/OpenALStream.cpp') diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index 85685b42cb..b0c856dcad 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -22,8 +22,7 @@ #if defined HAVE_OPENAL && HAVE_OPENAL -using namespace soundtouch; -SoundTouch soundTouch; +soundtouch::SoundTouch soundTouch; // // AyuanX: Spec says OpenAL1.1 is thread safe already -- cgit v1.2.3 From 80f4475e76be299e19ff88283d8f8aa02726506b Mon Sep 17 00:00:00 2001 From: skidau Date: Fri, 11 Jan 2013 14:03:09 +1100 Subject: Added a Dolby Pro Logic II (DPL2) decoder in the OpenAL backend. DPL2 audio is decoded to 5.1. Code adapted from ffdshow. Added an option in the DSP settings to disable the DPL2 decoder in case Dolphin incorrectly detects a 5.1 audio system. Updated the OpenAL files to OpenAL Soft 1.15.1 in the Windows build. Fixes issue 3023. --- Source/Core/AudioCommon/Src/OpenALStream.cpp | 85 ++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 10 deletions(-) (limited to 'Source/Core/AudioCommon/Src/OpenALStream.cpp') diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index b0c856dcad..8fb1f1b2c5 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -15,10 +15,9 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include - #include "aldlist.h" #include "OpenALStream.h" +#include "DPL2Decoder.h" #if defined HAVE_OPENAL && HAVE_OPENAL @@ -37,8 +36,10 @@ bool OpenALStream::Start() pDeviceList = new ALDeviceList(); if ((pDeviceList) && (pDeviceList->GetNumDevices())) { - char *defDevName = pDeviceList-> \ - GetDeviceName(pDeviceList->GetDefaultDevice()); + char *defDevName = pDeviceList->GetDeviceName(pDeviceList->GetDefaultDevice()); + + WARN_LOG(AUDIO, "Found OpenAL device %s", defDevName); + pDevice = alcOpenDevice(defDevName); if (pDevice) { @@ -52,8 +53,7 @@ bool OpenALStream::Start() else { alcCloseDevice(pDevice); - PanicAlertT("OpenAL: can't create context " - "for device %s", defDevName); + PanicAlertT("OpenAL: can't create context for device %s", defDevName); } } else @@ -67,6 +67,9 @@ bool OpenALStream::Start() PanicAlertT("OpenAL: can't find sound devices"); } + // Initialise DPL2 parameters + dpl2reset(); + soundTouch.clear(); return bReturn; } @@ -76,6 +79,7 @@ void OpenALStream::Stop() threadData = 1; // kick the thread if it's waiting soundSyncEvent.Set(); + mainSyncEvent.Set(); soundTouch.clear(); @@ -141,10 +145,15 @@ void OpenALStream::SoundLoop() alGenSources(1, &uiSource); // Short Silence - memset(sampleBuffer, 0, OAL_MAX_SAMPLES * 4 * OAL_NUM_BUFFERS); + memset(sampleBuffer, 0, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_NUM_BUFFERS); memset(realtimeBuffer, 0, OAL_MAX_SAMPLES * 4); for (int i = 0; i < OAL_NUM_BUFFERS; i++) - alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, OAL_MAX_SAMPLES * 4, ulFrequency); + { + if (Core::g_CoreStartupParameter.bDPL2Decoder) + alBufferData(uiBuffers[i], AL_FORMAT_51CHN32, sampleBuffer, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_NUM_BUFFERS, ulFrequency); + else + alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, OAL_MAX_SAMPLES * 4, ulFrequency); + } alSourceQueueBuffers(uiSource, OAL_NUM_BUFFERS, uiBuffers); alSourcePlay(uiSource); @@ -166,6 +175,8 @@ void OpenALStream::SoundLoop() soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 28); soundTouch.setSetting(SETTING_OVERLAP_MS, 12); + bool surround_capable = Core::g_CoreStartupParameter.bDPL2Decoder; + while (!threadData) { // num_samples_to_render in this update - depends on SystemTimers::AUDIO_DMA_PERIOD. @@ -201,18 +212,72 @@ void OpenALStream::SoundLoop() soundTouch.setSetting(SETTING_SEQUENCE_MS, (int)(1 / (rate * rate))); soundTouch.setTempo(rate); } - unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * 2 * OAL_NUM_BUFFERS); + unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_NUM_BUFFERS); if (nSamples > 0) { // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer) if (iBuffersFilled == 0) + { alSourceUnqueueBuffers(uiSource, iBuffersProcessed, uiBufferTemp); - alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, sampleBuffer, nSamples * 4, ulFrequency); + 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) + { + // Convert the samples from short to float for the dpl2 decoder + float dest[OAL_MAX_SAMPLES * 2 * OAL_NUM_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]; + dpl2decode(dest, 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 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) + { + alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, sampleBuffer, nSamples * 2 * 2, ulFrequency); + } + alSourceQueueBuffers(uiSource, 1, &uiBufferTemp[iBuffersFilled]); + ALenum err = alGetError(); + if (err != 0) + { + ERROR_LOG(AUDIO, "Error queuing buffers: %08x", err); + } iBuffersFilled++; if (iBuffersFilled == OAL_NUM_BUFFERS) + { alSourcePlay(uiSource); + ALenum err = alGetError(); + if (err != 0) + { + ERROR_LOG(AUDIO, "Error occurred during playback: %08x", err); + } + } } } else -- cgit v1.2.3 From 3632ce6df5d3c948f5e4c603c48f2d3c4e190eca Mon Sep 17 00:00:00 2001 From: skidau Date: Fri, 11 Jan 2013 19:42:03 +1100 Subject: Removed the synchronisation between the CPU thread and the audio thread. Added code to detect and resume from buffer underruns. Disabled the ability to change the DPL2 option after the game has started. Fixed a memory leak that occurred in the DPL2 decoder. Fixed the OSX build. --- Source/Core/AudioCommon/Src/OpenALStream.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'Source/Core/AudioCommon/Src/OpenALStream.cpp') diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index 8fb1f1b2c5..1895cd2199 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -79,7 +79,6 @@ void OpenALStream::Stop() threadData = 1; // kick the thread if it's waiting soundSyncEvent.Set(); - mainSyncEvent.Set(); soundTouch.clear(); @@ -112,7 +111,6 @@ void OpenALStream::SetVolume(int volume) void OpenALStream::Update() { soundSyncEvent.Set(); - mainSyncEvent.Wait(); } void OpenALStream::Clear(bool mute) @@ -149,10 +147,12 @@ void OpenALStream::SoundLoop() memset(realtimeBuffer, 0, OAL_MAX_SAMPLES * 4); for (int i = 0; i < OAL_NUM_BUFFERS; i++) { +#if !defined(__APPLE__) if (Core::g_CoreStartupParameter.bDPL2Decoder) - alBufferData(uiBuffers[i], AL_FORMAT_51CHN32, sampleBuffer, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_NUM_BUFFERS, ulFrequency); + alBufferData(uiBuffers[i], AL_FORMAT_51CHN32, sampleBuffer, 4 * SIZE_FLOAT * SURROUND_CHANNELS, ulFrequency); else - alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, OAL_MAX_SAMPLES * 4, ulFrequency); +#endif + alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, 4 * 2 * 2, ulFrequency); } alSourceQueueBuffers(uiSource, OAL_NUM_BUFFERS, uiBuffers); alSourcePlay(uiSource); @@ -165,6 +165,7 @@ void OpenALStream::SoundLoop() ALint iBuffersFilled = 0; ALint iBuffersProcessed = 0; + ALint iState = 0; ALuint uiBufferTemp[OAL_NUM_BUFFERS] = {0}; soundTouch.setChannels(2); @@ -232,7 +233,7 @@ void OpenALStream::SoundLoop() if (surround_capable) { // Convert the samples from short to float for the dpl2 decoder - float dest[OAL_MAX_SAMPLES * 2 * OAL_NUM_BUFFERS]; + float dest[OAL_MAX_SAMPLES * 2 * 2 * OAL_NUM_BUFFERS]; for (u32 i = 0; i < nSamples; ++i) { dest[i * 2 + 0] = (float)sampleBuffer[i * 2 + 0] / (1<<16); @@ -247,7 +248,7 @@ void OpenALStream::SoundLoop() if (err == AL_INVALID_ENUM) { // 5.1 is not supported by the host, fallback to stereo - WARN_LOG(AUDIO, "Unable set 5.1 surround mode. Updating OpenAL Soft might fix this issue."); + WARN_LOG(AUDIO, "Unable to set 5.1 surround mode. Updating OpenAL Soft might fix this issue."); surround_capable = false; } else if (err != 0) @@ -278,13 +279,24 @@ void OpenALStream::SoundLoop() 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); + ALenum err = alGetError(); + if (err != 0) + { + ERROR_LOG(AUDIO, "Error occurred resuming playback: %08x", err); + } + } } } else { soundSyncEvent.Wait(); } - mainSyncEvent.Set(); } } -- cgit v1.2.3 From 73140c7da75eae814c470c82a49c1a57d207032e Mon Sep 17 00:00:00 2001 From: skidau Date: Fri, 11 Jan 2013 23:06:20 +1100 Subject: Skipped timestretching if the emulator is running below 10% speed to prevent buffer overflows. --- Source/Core/AudioCommon/Src/OpenALStream.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Source/Core/AudioCommon/Src/OpenALStream.cpp') diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index 1895cd2199..eefc62e346 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -207,7 +207,10 @@ void OpenALStream::SoundLoop() Core::RequestRefreshInfo(); rate = m_mixer->GetCurrentSpeed(); } - if (rate > 0) + + // 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) { // Adjust SETTING_SEQUENCE_MS to balance between lag vs hollow audio soundTouch.setSetting(SETTING_SEQUENCE_MS, (int)(1 / (rate * rate))); -- cgit v1.2.3 From 1c462a1ecaa514912338735537284456f7cd835b Mon Sep 17 00:00:00 2001 From: skidau Date: Sun, 13 Jan 2013 00:05:30 +1100 Subject: Added a latency setting to the audio settings. Removed the Sample Rate setting. It is now hardcoded to 48000hz (accurate audio timing). Fixes issue 5672. --- Source/Core/AudioCommon/Src/OpenALStream.cpp | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'Source/Core/AudioCommon/Src/OpenALStream.cpp') 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(); -- cgit v1.2.3 From 6d4a566bc49ba29f52d58ec1bdbc020c67537bef Mon Sep 17 00:00:00 2001 From: skidau Date: Tue, 15 Jan 2013 22:29:26 +1100 Subject: Changed SoundTouch to use float samples, allowing SSE to be used. Made the DPL2 decoder disabled by default. Re-added the audio hack used by the Accurate VBeam emulation option. --- Source/Core/AudioCommon/Src/OpenALStream.cpp | 35 +++++++++++++++++++--------- 1 file changed, 24 insertions(+), 11 deletions(-) (limited to 'Source/Core/AudioCommon/Src/OpenALStream.cpp') diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index 94112c130d..489954e351 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -176,6 +176,7 @@ void OpenALStream::SoundLoop() soundTouch.setChannels(2); soundTouch.setSampleRate(ulFrequency); + soundTouch.setTempo(1.0); soundTouch.setSetting(SETTING_USE_QUICKSEEK, 0); soundTouch.setSetting(SETTING_USE_AA_FILTER, 0); soundTouch.setSetting(SETTING_SEQUENCE_MS, 1); @@ -197,7 +198,16 @@ void OpenALStream::SoundLoop() numSamples = (numSamples > OAL_MAX_SAMPLES) ? OAL_MAX_SAMPLES : numSamples; numSamples = m_mixer->Mix(realtimeBuffer, numSamples); - soundTouch.putSamples(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); + } + + soundTouch.putSamples(dest, numSamples); if (iBuffersProcessed == iBuffersFilled) { @@ -241,16 +251,8 @@ void OpenALStream::SoundLoop() #else if (surround_capable) { - // Convert the samples from short to float for the dpl2 decoder - 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_MAX_BUFFERS]; - dpl2decode(dest, nSamples, dpl2); + dpl2decode(sampleBuffer, nSamples, dpl2); alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_51CHN32, dpl2, nSamples * SIZE_FLOAT * SURROUND_CHANNELS, ulFrequency); ALenum err = alGetError(); @@ -268,7 +270,18 @@ void OpenALStream::SoundLoop() #endif if (!surround_capable) { - alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, sampleBuffer, nSamples * 2 * 2, ulFrequency); +#if defined(__APPLE__) + // 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); +#else + alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO_FLOAT32, sampleBuffer, nSamples * 4 * 2, ulFrequency); +#endif } alSourceQueueBuffers(uiSource, 1, &uiBufferTemp[iBuffersFilled]); -- cgit v1.2.3 From a9388ce2e2b7d235cc943f19e16bdccf99cb68b3 Mon Sep 17 00:00:00 2001 From: skidau Date: Wed, 16 Jan 2013 00:10:49 +1100 Subject: Added backwards compatibility with old OpenAL drivers. --- Source/Core/AudioCommon/Src/OpenALStream.cpp | 40 +++++++++++++++++++++------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'Source/Core/AudioCommon/Src/OpenALStream.cpp') diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index 489954e351..25bece8e8d 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -184,6 +184,11 @@ void OpenALStream::SoundLoop() 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) { @@ -270,18 +275,33 @@ void OpenALStream::SoundLoop() #endif if (!surround_capable) { -#if defined(__APPLE__) - // Convert the samples from float to short - short stereo[OAL_MAX_SAMPLES * 2 * 2 * OAL_MAX_BUFFERS]; - for (u32 i = 0; i < nSamples; ++i) + if (float32_capable) { - 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_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); + } + + } + + 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); + } - alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, stereo, nSamples * 2 * 2, ulFrequency); -#else - alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO_FLOAT32, sampleBuffer, nSamples * 4 * 2, ulFrequency); -#endif } alSourceQueueBuffers(uiSource, 1, &uiBufferTemp[iBuffersFilled]); -- cgit v1.2.3 From 7402a89e6e07ae2001e66e8a61cd7c6bf1700832 Mon Sep 17 00:00:00 2001 From: skidau Date: Wed, 16 Jan 2013 00:14:31 +1100 Subject: OSX build fix --- Source/Core/AudioCommon/Src/OpenALStream.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Source/Core/AudioCommon/Src/OpenALStream.cpp') diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index 25bece8e8d..cfe6a40630 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -275,6 +275,7 @@ void OpenALStream::SoundLoop() #endif if (!surround_capable) { +#if !defined(__APPLE__) if (float32_capable) { alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO_FLOAT32, sampleBuffer, nSamples * 4 * 2, ulFrequency); @@ -289,7 +290,7 @@ void OpenALStream::SoundLoop() } } - +#endif if (!float32_capable) { // Convert the samples from float to short -- cgit v1.2.3 From b7d32b0a3d810736b2e1151d6d8b9da85ebfbcf3 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 23 Jan 2013 23:29:50 -0500 Subject: mem_fun -> mem_fn. mem_fun is deprecated in C++11. Also it does everything mem_fun can do, but more conveniently. --- Source/Core/AudioCommon/Src/OpenALStream.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Source/Core/AudioCommon/Src/OpenALStream.cpp') diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index cfe6a40630..814f720e6e 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -15,6 +15,8 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ +#include + #include "aldlist.h" #include "OpenALStream.h" #include "DPL2Decoder.h" @@ -52,7 +54,7 @@ bool OpenALStream::Start() //period_size_in_millisec = 1000 / refresh; alcMakeContextCurrent(pContext); - thread = std::thread(std::mem_fun(&OpenALStream::SoundLoop), this); + thread = std::thread(std::mem_fn(&OpenALStream::SoundLoop), this); bReturn = true; } else @@ -72,7 +74,7 @@ bool OpenALStream::Start() PanicAlertT("OpenAL: can't find sound devices"); } - // Initialise DPL2 parameters + // Initialize DPL2 parameters dpl2reset(); soundTouch.clear(); -- cgit v1.2.3 From fe7e691d77550195f71ae2b7af67c6395493908d Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 23 Jan 2013 23:38:49 -0500 Subject: Revert "mem_fun -> mem_fn." This reverts commit b7d32b0a3d810736b2e1151d6d8b9da85ebfbcf3. OSX C++ std library in charge of holding back progress (as usual). --- Source/Core/AudioCommon/Src/OpenALStream.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'Source/Core/AudioCommon/Src/OpenALStream.cpp') diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index 814f720e6e..cfe6a40630 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -15,8 +15,6 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include - #include "aldlist.h" #include "OpenALStream.h" #include "DPL2Decoder.h" @@ -54,7 +52,7 @@ bool OpenALStream::Start() //period_size_in_millisec = 1000 / refresh; alcMakeContextCurrent(pContext); - thread = std::thread(std::mem_fn(&OpenALStream::SoundLoop), this); + thread = std::thread(std::mem_fun(&OpenALStream::SoundLoop), this); bReturn = true; } else @@ -74,7 +72,7 @@ bool OpenALStream::Start() PanicAlertT("OpenAL: can't find sound devices"); } - // Initialize DPL2 parameters + // Initialise DPL2 parameters dpl2reset(); soundTouch.clear(); -- cgit v1.2.3