From 6df1dacca8ffdf7109e0d914751eed6e8185b172 Mon Sep 17 00:00:00 2001 From: skidau Date: Mon, 7 Jan 2013 12:16:04 +1100 Subject: OpenAL for Windows initial commit --- Source/Core/AudioCommon/AudioCommon.vcxproj | 48 ++++++++++++++++------------- 1 file changed, 26 insertions(+), 22 deletions(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj b/Source/Core/AudioCommon/AudioCommon.vcxproj index 0c5f256c19..4bcee7559b 100644 --- a/Source/Core/AudioCommon/AudioCommon.vcxproj +++ b/Source/Core/AudioCommon/AudioCommon.vcxproj @@ -114,7 +114,10 @@ true - + + OpenAL32.lib;dsound.lib;dxerr.lib + ..\..\..\Externals\OpenAL\Win32;%(AdditionalLibraryDirectories) + @@ -123,7 +126,10 @@ true - + + OpenAL32.lib;dsound.lib;dxerr.lib + ..\..\..\Externals\OpenAL\Win64;%(AdditionalLibraryDirectories) + @@ -134,7 +140,10 @@ true true - + + OpenAL32.lib;dsound.lib;dxerr.lib + ..\..\..\Externals\OpenAL\Win32;%(AdditionalLibraryDirectories) + @@ -145,7 +154,10 @@ true true - + + OpenAL32.lib;dsound.lib;dxerr.lib + ..\..\..\Externals\OpenAL\Win32;%(AdditionalLibraryDirectories) + @@ -156,7 +168,10 @@ true true - + + OpenAL32.lib;dsound.lib;dxerr.lib + ..\..\..\Externals\OpenAL\Win64;%(AdditionalLibraryDirectories) + @@ -167,17 +182,13 @@ true true - + + OpenAL32.lib;dsound.lib;dxerr.lib + ..\..\..\Externals\OpenAL\Win64;%(AdditionalLibraryDirectories) + - - true - true - true - true - true - true - + @@ -189,14 +200,7 @@ - - true - true - true - true - true - true - + -- cgit v1.2.3 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 +++++++++++++-------- Source/Core/AudioCommon/Src/OpenALStream.h | 1 - 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'Source/Core/AudioCommon') 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(); } } diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h index 2c0d75b510..a9c1f51399 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.h +++ b/Source/Core/AudioCommon/Src/OpenALStream.h @@ -38,7 +38,6 @@ #define SFX_MAX_SOURCE 1 #define OAL_NUM_BUFFERS 16 #define OAL_MAX_SAMPLES 512 // AyuanX: Don't make it too large, as larger buffer means longer delay -#define OAL_THRESHOLD 128 // Some games are quite sensitive to delay #endif class OpenALStream: public SoundStream -- 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/AudioCommon.vcxproj | 24 ++++----- Source/Core/AudioCommon/Src/Mixer.h | 5 ++ Source/Core/AudioCommon/Src/OpenALStream.cpp | 79 ++++++++++++++++++++-------- Source/Core/AudioCommon/Src/OpenALStream.h | 12 ++++- 4 files changed, 83 insertions(+), 37 deletions(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj b/Source/Core/AudioCommon/AudioCommon.vcxproj index 4bcee7559b..85608330dd 100644 --- a/Source/Core/AudioCommon/AudioCommon.vcxproj +++ b/Source/Core/AudioCommon/AudioCommon.vcxproj @@ -115,8 +115,8 @@ true - OpenAL32.lib;dsound.lib;dxerr.lib - ..\..\..\Externals\OpenAL\Win32;%(AdditionalLibraryDirectories) + SoundTouchD.lib;OpenAL32.lib;dsound.lib;dxerr.lib + ..\..\..\Externals\OpenAL\Win32;..\..\..\Externals\SoundTouch\Win32;%(AdditionalLibraryDirectories) @@ -127,8 +127,8 @@ true - OpenAL32.lib;dsound.lib;dxerr.lib - ..\..\..\Externals\OpenAL\Win64;%(AdditionalLibraryDirectories) + SoundTouchD.lib;OpenAL32.lib;dsound.lib;dxerr.lib + ..\..\..\Externals\OpenAL\Win64;..\..\..\Externals\SoundTouch\Win64;%(AdditionalLibraryDirectories) @@ -141,8 +141,8 @@ true - OpenAL32.lib;dsound.lib;dxerr.lib - ..\..\..\Externals\OpenAL\Win32;%(AdditionalLibraryDirectories) + SoundTouch.lib;OpenAL32.lib;dsound.lib;dxerr.lib + ..\..\..\Externals\OpenAL\Win32;..\..\..\Externals\SoundTouch\Win32;%(AdditionalLibraryDirectories) @@ -155,8 +155,8 @@ true - OpenAL32.lib;dsound.lib;dxerr.lib - ..\..\..\Externals\OpenAL\Win32;%(AdditionalLibraryDirectories) + SoundTouch.lib;OpenAL32.lib;dsound.lib;dxerr.lib + ..\..\..\Externals\OpenAL\Win32;..\..\..\Externals\SoundTouch\Win32;%(AdditionalLibraryDirectories) @@ -169,8 +169,8 @@ true - OpenAL32.lib;dsound.lib;dxerr.lib - ..\..\..\Externals\OpenAL\Win64;%(AdditionalLibraryDirectories) + SoundTouch.lib;OpenAL32.lib;dsound.lib;dxerr.lib + ..\..\..\Externals\OpenAL\Win64;..\..\..\Externals\SoundTouch\Win64;%(AdditionalLibraryDirectories) @@ -183,8 +183,8 @@ true - OpenAL32.lib;dsound.lib;dxerr.lib - ..\..\..\Externals\OpenAL\Win64;%(AdditionalLibraryDirectories) + SoundTouch.lib;OpenAL32.lib;dsound.lib;dxerr.lib + ..\..\..\Externals\OpenAL\Win64;..\..\..\Externals\SoundTouch\Win64;%(AdditionalLibraryDirectories) diff --git a/Source/Core/AudioCommon/Src/Mixer.h b/Source/Core/AudioCommon/Src/Mixer.h index da456d5bf7..c1a387cf49 100644 --- a/Source/Core/AudioCommon/Src/Mixer.h +++ b/Source/Core/AudioCommon/Src/Mixer.h @@ -92,6 +92,9 @@ public: std::mutex& MixerCritical() { return m_csMixing; } + volatile float GetCurrentSpeed() const { return m_speed; } + void UpdateSpeed(volatile float val) { m_speed = val; } + protected: unsigned int m_sampleRate; unsigned int m_aiSampleRate; @@ -113,6 +116,8 @@ protected: bool m_AIplaying; std::mutex m_csMixing; + + volatile float m_speed; // Current rate of the emulation (1.0 = 100% speed) private: }; 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(); } } diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h index a9c1f51399..c6dfe519ae 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.h +++ b/Source/Core/AudioCommon/Src/OpenALStream.h @@ -34,10 +34,16 @@ #include #endif +#include "../../Core/Src/Core.h" +#include "../../Core/Src/HW/SystemTimers.h" +#include "../../Core/Src/HW/AudioInterface.h" +#include "../../../../Externals/SoundTouch/STTypes.h" +#include "../../../../Externals/SoundTouch/SoundTouch.h" + // 16 bit Stereo #define SFX_MAX_SOURCE 1 #define OAL_NUM_BUFFERS 16 -#define OAL_MAX_SAMPLES 512 // AyuanX: Don't make it too large, as larger buffer means longer delay +#define OAL_MAX_SAMPLES 512 #endif class OpenALStream: public SoundStream @@ -63,8 +69,10 @@ public: private: std::thread thread; Common::Event soundSyncEvent; - + Common::Event mainSyncEvent; + short realtimeBuffer[OAL_MAX_SAMPLES * 2]; + soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * 2 * OAL_NUM_BUFFERS]; ALuint uiBuffers[OAL_NUM_BUFFERS]; ALuint uiSource; ALfloat fVolume; -- cgit v1.2.3 From 91fe5cc821b0532154dc5a8a34869f13284394c5 Mon Sep 17 00:00:00 2001 From: skidau Date: Wed, 9 Jan 2013 23:45:13 +1100 Subject: Build fix Added SoundTouch as a dependency of AudioCommon. Removed the "soundtouch_config.h" include on Linux and OSX. --- Source/Core/AudioCommon/AudioCommon.vcxproj | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj b/Source/Core/AudioCommon/AudioCommon.vcxproj index 85608330dd..5a6896f5e2 100644 --- a/Source/Core/AudioCommon/AudioCommon.vcxproj +++ b/Source/Core/AudioCommon/AudioCommon.vcxproj @@ -216,6 +216,14 @@ + + {68a5dd20-7057-448b-8fe0-b6ac8d205509} + true + true + false + true + false + {c87a4178-44f6-49b2-b7aa-c79af1b8c534} true -- 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') 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/CMakeLists.txt | 2 +- Source/Core/AudioCommon/Src/OpenALStream.cpp | 3 +-- Source/Core/AudioCommon/Src/OpenALStream.h | 10 +++++----- 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/CMakeLists.txt b/Source/Core/AudioCommon/CMakeLists.txt index be8c58d14a..93547681b0 100644 --- a/Source/Core/AudioCommon/CMakeLists.txt +++ b/Source/Core/AudioCommon/CMakeLists.txt @@ -18,7 +18,7 @@ endif(AO_FOUND) if(OPENAL_FOUND) set(SRCS ${SRCS} Src/OpenALStream.cpp Src/aldlist.cpp) - set(LIBS ${LIBS} ${OPENAL_LIBRARY}) + set(LIBS ${LIBS} ${OPENAL_LIBRARY} SoundTouch ) endif(OPENAL_FOUND) if(PULSEAUDIO_FOUND) 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 diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h index c6dfe519ae..6f39c8a49c 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.h +++ b/Source/Core/AudioCommon/Src/OpenALStream.h @@ -34,11 +34,11 @@ #include #endif -#include "../../Core/Src/Core.h" -#include "../../Core/Src/HW/SystemTimers.h" -#include "../../Core/Src/HW/AudioInterface.h" -#include "../../../../Externals/SoundTouch/STTypes.h" -#include "../../../../Externals/SoundTouch/SoundTouch.h" +#include "Core.h" +#include "HW/SystemTimers.h" +#include "HW/AudioInterface.h" +#include +#include // 16 bit Stereo #define SFX_MAX_SOURCE 1 -- cgit v1.2.3 From d34c847eddf72c8a928472c7512cddad02a8d853 Mon Sep 17 00:00:00 2001 From: skidau Date: Thu, 10 Jan 2013 07:43:59 +1100 Subject: Fixed the include directories in Audio Common for the Windows build. --- Source/Core/AudioCommon/AudioCommon.vcxproj | 2 +- Source/Core/AudioCommon/Src/OpenALStream.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj b/Source/Core/AudioCommon/AudioCommon.vcxproj index 5a6896f5e2..bc004268ea 100644 --- a/Source/Core/AudioCommon/AudioCommon.vcxproj +++ b/Source/Core/AudioCommon/AudioCommon.vcxproj @@ -161,7 +161,7 @@ - ..\Common\Src;%(AdditionalIncludeDirectories) + ..\Core\Src;..\Common\Src;..\..\..\Externals;%(AdditionalIncludeDirectories) true diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h index 6f39c8a49c..c775d31cf2 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.h +++ b/Source/Core/AudioCommon/Src/OpenALStream.h @@ -24,8 +24,8 @@ #if defined HAVE_OPENAL && HAVE_OPENAL #ifdef _WIN32 -#include "../../../../Externals/OpenAL/include/al.h" -#include "../../../../Externals/OpenAL/include/alc.h" +#include +#include #elif defined __APPLE__ #include #include -- cgit v1.2.3 From ad28986d510cfe7e064acd9f95d1de0d08b36325 Mon Sep 17 00:00:00 2001 From: skidau Date: Thu, 10 Jan 2013 07:55:13 +1100 Subject: Fixed the include directories in Audio Common for the Windows 32bit build. --- Source/Core/AudioCommon/AudioCommon.vcxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj b/Source/Core/AudioCommon/AudioCommon.vcxproj index bc004268ea..2e13aedb46 100644 --- a/Source/Core/AudioCommon/AudioCommon.vcxproj +++ b/Source/Core/AudioCommon/AudioCommon.vcxproj @@ -133,7 +133,7 @@ - ..\Common\Src;%(AdditionalIncludeDirectories) + ..\Core\Src;..\Common\Src;..\..\..\Externals;%(AdditionalIncludeDirectories) true -- cgit v1.2.3 From 488a679ca71c63645598743c08c318164a6c38ae Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 9 Jan 2013 17:39:19 -0600 Subject: use pulseaudio "simple" api --- Source/Core/AudioCommon/CMakeLists.txt | 3 +- Source/Core/AudioCommon/Src/PulseAudioStream.cpp | 288 ++++------------------- Source/Core/AudioCommon/Src/PulseAudioStream.h | 23 +- 3 files changed, 52 insertions(+), 262 deletions(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/CMakeLists.txt b/Source/Core/AudioCommon/CMakeLists.txt index be8c58d14a..b2005515cf 100644 --- a/Source/Core/AudioCommon/CMakeLists.txt +++ b/Source/Core/AudioCommon/CMakeLists.txt @@ -23,7 +23,8 @@ endif(OPENAL_FOUND) if(PULSEAUDIO_FOUND) set(SRCS ${SRCS} Src/PulseAudioStream.cpp) - set(LIBS ${LIBS} ${PULSEAUDIO_LIBRARIES}) +# TODO: remove hacks + set(LIBS ${LIBS} ${PULSEAUDIO_LIBRARIES} pulse-simple) endif(PULSEAUDIO_FOUND) if(WIN32) diff --git a/Source/Core/AudioCommon/Src/PulseAudioStream.cpp b/Source/Core/AudioCommon/Src/PulseAudioStream.cpp index 4851b4bd12..82b7ee5fa9 100644 --- a/Source/Core/AudioCommon/Src/PulseAudioStream.cpp +++ b/Source/Core/AudioCommon/Src/PulseAudioStream.cpp @@ -22,31 +22,31 @@ #include "PulseAudioStream.h" -#define BUFFER_SIZE 4096 -#define BUFFER_SIZE_BYTES (BUFFER_SIZE * 4) - -PulseAudio::PulseAudio(CMixer *mixer) - : SoundStream(mixer), thread_running(false), mainloop(NULL) - , context(NULL), stream(NULL), iVolume(100) +namespace { - mix_buffer = new u8[BUFFER_SIZE_BYTES]; +const size_t BUFFER_SAMPLES = 512; +const size_t CHANNEL_COUNT = 2; +const size_t BUFFER_SIZE = BUFFER_SAMPLES * CHANNEL_COUNT; } -PulseAudio::~PulseAudio() -{ - delete [] mix_buffer; -} +PulseAudio::PulseAudio(CMixer *mixer) + : SoundStream(mixer) + , mix_buffer(BUFFER_SIZE) + , thread() + , run_thread() + , pa() +{} bool PulseAudio::Start() { - thread_running = true; + run_thread = true; thread = std::thread(std::mem_fun(&PulseAudio::SoundLoop), this); return true; } void PulseAudio::Stop() { - thread_running = false; + run_thread = false; thread.join(); } @@ -60,260 +60,54 @@ void PulseAudio::SoundLoop() { Common::SetCurrentThreadName("Audio thread - pulse"); - thread_running = PulseInit(); - - while (thread_running) - { - int frames_to_deliver = 512; - m_mixer->Mix((short *)mix_buffer, frames_to_deliver); - if (!Write(mix_buffer, frames_to_deliver * 4)) - ERROR_LOG(AUDIO, "PulseAudio failure writing data"); - } - PulseShutdown(); -} - -bool PulseAudio::PulseInit() -{ - // The Sample format to use - const pa_sample_spec ss = - { - PA_SAMPLE_S16LE, - m_mixer->GetSampleRate(), - 2 - }; - - mainloop = pa_threaded_mainloop_new(); - - context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "dolphin-emu"); - pa_context_set_state_callback(context, ContextStateCB, this); - - if (pa_context_connect(context, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0) + if (PulseInit()) { - ERROR_LOG(AUDIO, "PulseAudio failed to connect context: %s", - pa_strerror(pa_context_errno(context))); - return false; - } - - pa_threaded_mainloop_lock(mainloop); - pa_threaded_mainloop_start(mainloop); - - for (;;) - { - pa_context_state_t state; - - state = pa_context_get_state(context); - - if (state == PA_CONTEXT_READY) - break; - - if (!PA_CONTEXT_IS_GOOD(state)) + while (run_thread) { - ERROR_LOG(AUDIO, "PulseAudio context state failure: %s", - pa_strerror(pa_context_errno(context))); - pa_threaded_mainloop_unlock(mainloop); - return false; + m_mixer->Mix(&mix_buffer[0], mix_buffer.size() / CHANNEL_COUNT); + Write(&mix_buffer[0], mix_buffer.size() * sizeof(s16)); } - // Wait until the context is ready - pa_threaded_mainloop_wait(mainloop); + PulseShutdown(); } - - if (!(stream = pa_stream_new(context, "emulator", &ss, NULL))) - { - ERROR_LOG(AUDIO, "PulseAudio failed to create playback stream: %s", - pa_strerror(pa_context_errno(context))); - pa_threaded_mainloop_unlock(mainloop); - return false; - } - - // Set callbacks for the playback stream - pa_stream_set_state_callback(stream, StreamStateCB, this); - pa_stream_set_write_callback(stream, StreamWriteCB, this); - - if (pa_stream_connect_playback(stream, NULL, NULL, PA_STREAM_NOFLAGS, NULL, NULL) < 0) - { - ERROR_LOG(AUDIO, "PulseAudio failed to connect playback stream: %s", - pa_strerror(pa_context_errno(context))); - pa_threaded_mainloop_unlock(mainloop); - return false; - } - - for (;;) - { - pa_stream_state_t state; - - state = pa_stream_get_state(stream); - - if (state == PA_STREAM_READY) - break; - - if (!PA_STREAM_IS_GOOD(state)) - { - ERROR_LOG(AUDIO, "PulseAudio stream state failure: %s", - pa_strerror(pa_context_errno(context))); - pa_threaded_mainloop_unlock(mainloop); - return false; - } - - // Wait until the stream is ready - pa_threaded_mainloop_wait(mainloop); - } - - pa_threaded_mainloop_unlock(mainloop); - - SetVolume(iVolume); - - NOTICE_LOG(AUDIO, "Pulse successfully initialized."); - return true; } -void PulseAudio::PulseShutdown() +bool PulseAudio::PulseInit() { - if (mainloop) - pa_threaded_mainloop_stop(mainloop); + pa_sample_spec ss = {}; + ss.format = PA_SAMPLE_S16LE; + ss.channels = 2; + ss.rate = m_mixer->GetSampleRate(); - if (stream) - pa_stream_unref(stream); + int error; + pa = pa_simple_new(nullptr, "dolphin-emu", PA_STREAM_PLAYBACK, + nullptr, "audio", &ss, nullptr, nullptr, &error); - if (context) + if (!pa) { - pa_context_disconnect(context); - pa_context_unref(context); - } - - if (mainloop) - pa_threaded_mainloop_free(mainloop); -} - -void PulseAudio::SignalMainLoop() -{ - pa_threaded_mainloop_signal(mainloop, 0); -} - -void PulseAudio::ContextStateCB(pa_context *c, void *userdata) -{ - switch (pa_context_get_state(c)) - { - case PA_CONTEXT_READY: - case PA_CONTEXT_TERMINATED: - case PA_CONTEXT_FAILED: - ((PulseAudio *)userdata)->SignalMainLoop(); - break; - - default: - break; + ERROR_LOG(AUDIO, "PulseAudio failed to initialize: %s", + pa_strerror(error)); + return false; } -} - -void PulseAudio::StreamStateCB(pa_stream *s, void * userdata) -{ - switch (pa_stream_get_state(s)) + else { - case PA_STREAM_READY: - case PA_STREAM_TERMINATED: - case PA_STREAM_FAILED: - ((PulseAudio *)userdata)->SignalMainLoop(); - break; - - default: - break; + NOTICE_LOG(AUDIO, "Pulse successfully initialized."); + //SetVolume(iVolume); + return true; } } -void PulseAudio::StreamWriteCB(pa_stream *s, size_t length, void *userdata) -{ - ((PulseAudio *)userdata)->SignalMainLoop(); -} - -static bool StateIsGood(pa_context *context, pa_stream *stream) +void PulseAudio::PulseShutdown() { - if (!context || !PA_CONTEXT_IS_GOOD(pa_context_get_state(context)) || - !stream || !PA_STREAM_IS_GOOD(pa_stream_get_state(stream))) - { - if ((context && pa_context_get_state(context) == PA_CONTEXT_FAILED) || - (stream && pa_stream_get_state(stream) == PA_STREAM_FAILED)) - { - ERROR_LOG(AUDIO, "PulseAudio state failure: %s", - pa_strerror(pa_context_errno(context))); - } - else - { - ERROR_LOG(AUDIO, "PulseAudio state failure: %s", - pa_strerror(PA_ERR_BADSTATE)); - } - return false; - } - return true; + pa_simple_free(pa); } -bool PulseAudio::Write(const void *data, size_t length) +void PulseAudio::Write(const void *data, size_t length) { - if (!data || length == 0 || !stream) - return false; - - pa_threaded_mainloop_lock(mainloop); - - if (!StateIsGood(context, stream)) + int error; + if (pa_simple_write(pa, data, length, &error) < 0) { - pa_threaded_mainloop_unlock(mainloop); - return false; + ERROR_LOG(AUDIO, "PulseAudio failed to write data: %s", + pa_strerror(error)); } - - while (length > 0) - { - size_t l; - int r; - - while (!(l = pa_stream_writable_size(stream))) - { - pa_threaded_mainloop_wait(mainloop); - if (!StateIsGood(context, stream)) - { - pa_threaded_mainloop_unlock(mainloop); - return false; - } - } - - if (l == (size_t)-1) - { - ERROR_LOG(AUDIO, "PulseAudio invalid stream: %s", - pa_strerror(pa_context_errno(context))); - pa_threaded_mainloop_unlock(mainloop); - return false; - } - - if (l > length) - l = length; - - r = pa_stream_write(stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE); - if (r < 0) - { - ERROR_LOG(AUDIO, "PulseAudio error writing to stream: %s", - pa_strerror(pa_context_errno(context))); - pa_threaded_mainloop_unlock(mainloop); - return false; - } - - data = (const uint8_t*) data + l; - length -= l; - } - - pa_threaded_mainloop_unlock(mainloop); - return true; -} - -void PulseAudio::SetVolume(int volume) -{ - iVolume = volume; - - if (!stream) - return; - - pa_cvolume cvolume; - const pa_channel_map *channels = pa_stream_get_channel_map(stream); - pa_cvolume_set(&cvolume, channels->channels, - iVolume * (PA_VOLUME_NORM - PA_VOLUME_MUTED) / 100); - - pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), - &cvolume, NULL, this); } diff --git a/Source/Core/AudioCommon/Src/PulseAudioStream.h b/Source/Core/AudioCommon/Src/PulseAudioStream.h index f3a5a43e79..38399e2506 100644 --- a/Source/Core/AudioCommon/Src/PulseAudioStream.h +++ b/Source/Core/AudioCommon/Src/PulseAudioStream.h @@ -19,7 +19,8 @@ #define _PULSE_AUDIO_STREAM_H #if defined(HAVE_PULSEAUDIO) && HAVE_PULSEAUDIO -#include +#include +#include #endif #include "Common.h" @@ -27,16 +28,16 @@ #include "Thread.h" +#include + class PulseAudio : public SoundStream { #if defined(HAVE_PULSEAUDIO) && HAVE_PULSEAUDIO public: PulseAudio(CMixer *mixer); - virtual ~PulseAudio(); virtual bool Start(); virtual void Stop(); - virtual void SetVolume(int volume); static bool isValid() {return true;} @@ -46,22 +47,16 @@ public: private: virtual void SoundLoop(); + bool PulseInit(); void PulseShutdown(); - bool Write(const void *data, size_t bytes); - void SignalMainLoop(); - static void ContextStateCB(pa_context *c, void *userdata); - static void StreamStateCB(pa_stream *s, void * userdata); - static void StreamWriteCB(pa_stream *s, size_t length, void *userdata); + void Write(const void *data, size_t bytes); - u8 *mix_buffer; + std::vector mix_buffer; std::thread thread; - volatile bool thread_running; + volatile bool run_thread; - pa_threaded_mainloop *mainloop; - pa_context *context; - pa_stream *stream; - int iVolume; + pa_simple* pa; #else public: PulseAudio(CMixer *mixer) : SoundStream(mixer) {} -- cgit v1.2.3 From 5c371549d319ae125fcfa6278e2ac569b21c0f78 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 9 Jan 2013 18:39:28 -0600 Subject: fix cmake hacks --- Source/Core/AudioCommon/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/CMakeLists.txt b/Source/Core/AudioCommon/CMakeLists.txt index b2005515cf..be8c58d14a 100644 --- a/Source/Core/AudioCommon/CMakeLists.txt +++ b/Source/Core/AudioCommon/CMakeLists.txt @@ -23,8 +23,7 @@ endif(OPENAL_FOUND) if(PULSEAUDIO_FOUND) set(SRCS ${SRCS} Src/PulseAudioStream.cpp) -# TODO: remove hacks - set(LIBS ${LIBS} ${PULSEAUDIO_LIBRARIES} pulse-simple) + set(LIBS ${LIBS} ${PULSEAUDIO_LIBRARIES}) endif(PULSEAUDIO_FOUND) if(WIN32) -- cgit v1.2.3 From 2c1c538fda491f97a735902e00987537db1d3487 Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Thu, 10 Jan 2013 18:43:15 +0100 Subject: Disable the OpenAL and Pulseaudio audio backends They are currently broken and cause sound issues which are not present in other backends: * OpenAL plays music 2x too fast in Zelda UCode games with HLE * Pulse backend uses a lot of CPU power and slows down emulation significantly Both backends are currently being re-implemented in separate branches of Dolphin, so this should be a temporary removal. --- Source/Core/AudioCommon/Src/AudioCommon.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/Src/AudioCommon.cpp b/Source/Core/AudioCommon/Src/AudioCommon.cpp index 8a568448a3..b21aec45ba 100644 --- a/Source/Core/AudioCommon/Src/AudioCommon.cpp +++ b/Source/Core/AudioCommon/Src/AudioCommon.cpp @@ -102,16 +102,12 @@ namespace AudioCommon backends.push_back(BACKEND_DIRECTSOUND); if (XAudio2::isValid()) backends.push_back(BACKEND_XAUDIO2); - if (OpenALStream::isValid()) - backends.push_back(BACKEND_OPENAL); if (AOSound::isValid()) backends.push_back(BACKEND_AOSOUND); if (AlsaSound::isValid()) backends.push_back(BACKEND_ALSA); if (CoreAudioSound::isValid()) backends.push_back(BACKEND_COREAUDIO); - if (PulseAudio::isValid()) - backends.push_back(BACKEND_PULSEAUDIO); return backends; } -- cgit v1.2.3 From 202c005e61c12e546a69fb290ace57e170196c6a Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 10 Jan 2013 13:00:50 -0600 Subject: Remove commented code. No longer supporting setting volume with PulseAudio. --- Source/Core/AudioCommon/Src/PulseAudioStream.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/Src/PulseAudioStream.cpp b/Source/Core/AudioCommon/Src/PulseAudioStream.cpp index 82b7ee5fa9..923a338190 100644 --- a/Source/Core/AudioCommon/Src/PulseAudioStream.cpp +++ b/Source/Core/AudioCommon/Src/PulseAudioStream.cpp @@ -92,7 +92,6 @@ bool PulseAudio::PulseInit() else { NOTICE_LOG(AUDIO, "Pulse successfully initialized."); - //SetVolume(iVolume); return true; } } -- 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/AudioCommon.vcxproj | 10 +- .../Core/AudioCommon/AudioCommon.vcxproj.filters | 2 + Source/Core/AudioCommon/CMakeLists.txt | 1 + Source/Core/AudioCommon/Src/DPL2Decoder.cpp | 397 +++++++++++++++++++++ Source/Core/AudioCommon/Src/DPL2Decoder.h | 24 ++ Source/Core/AudioCommon/Src/OpenALStream.cpp | 85 ++++- Source/Core/AudioCommon/Src/OpenALStream.h | 6 +- 7 files changed, 510 insertions(+), 15 deletions(-) create mode 100644 Source/Core/AudioCommon/Src/DPL2Decoder.cpp create mode 100644 Source/Core/AudioCommon/Src/DPL2Decoder.h (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj b/Source/Core/AudioCommon/AudioCommon.vcxproj index 2e13aedb46..a983005318 100644 --- a/Source/Core/AudioCommon/AudioCommon.vcxproj +++ b/Source/Core/AudioCommon/AudioCommon.vcxproj @@ -109,7 +109,7 @@ - ..\Common\Src;%(AdditionalIncludeDirectories) + ..\Core\Src;..\Common\Src;..\..\..\Externals;%(AdditionalIncludeDirectories) true @@ -121,7 +121,7 @@ - ..\Common\Src;%(AdditionalIncludeDirectories) + ..\Core\Src;..\Common\Src;..\..\..\Externals;%(AdditionalIncludeDirectories) true @@ -147,7 +147,7 @@ - ..\Common\Src;%(AdditionalIncludeDirectories) + ..\Core\Src;..\Common\Src;..\..\..\Externals;%(AdditionalIncludeDirectories) true @@ -175,7 +175,7 @@ - ..\Common\Src;%(AdditionalIncludeDirectories) + ..\Core\Src;..\Common\Src;..\..\..\Externals;%(AdditionalIncludeDirectories) true @@ -192,6 +192,7 @@ + @@ -204,6 +205,7 @@ + diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj.filters b/Source/Core/AudioCommon/AudioCommon.vcxproj.filters index 7e098ecb85..af5fe12220 100644 --- a/Source/Core/AudioCommon/AudioCommon.vcxproj.filters +++ b/Source/Core/AudioCommon/AudioCommon.vcxproj.filters @@ -21,6 +21,7 @@ SoundStreams + @@ -44,6 +45,7 @@ SoundStreams + diff --git a/Source/Core/AudioCommon/CMakeLists.txt b/Source/Core/AudioCommon/CMakeLists.txt index 93547681b0..0e610bd847 100644 --- a/Source/Core/AudioCommon/CMakeLists.txt +++ b/Source/Core/AudioCommon/CMakeLists.txt @@ -1,5 +1,6 @@ set(SRCS Src/AudioCommon.cpp Src/AudioCommonConfig.cpp + Src/DPL2Decoder.cpp Src/Mixer.cpp Src/WaveFile.cpp Src/NullSoundStream.cpp) diff --git a/Source/Core/AudioCommon/Src/DPL2Decoder.cpp b/Source/Core/AudioCommon/Src/DPL2Decoder.cpp new file mode 100644 index 0000000000..4efedc4b44 --- /dev/null +++ b/Source/Core/AudioCommon/Src/DPL2Decoder.cpp @@ -0,0 +1,397 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// Dolby Pro Logic 2 decoder from ffdshow-tryout +// * Copyright 2001 Anders Johansson ajh@atri.curtin.edu.au +// * Copyright (c) 2004-2006 Milan Cutka +// * based on mplayer HRTF plugin by ylai + +#include +#include +#include "DPL2Decoder.h" + +#define M_PI 3.14159265358979323846 +#define M_SQRT1_2 0.70710678118654752440 + +int olddelay = -1; +unsigned int oldfreq = 0; +unsigned int dlbuflen; +int cyc_pos; +float l_fwr, r_fwr, lpr_fwr, lmr_fwr; +std::vector fwrbuf_l, fwrbuf_r; +float adapt_l_gain, adapt_r_gain, adapt_lpr_gain, adapt_lmr_gain; +std::vector lf, rf, lr, rr, cf, cr; +float LFE_buf[256]; +unsigned int lfe_pos; +float *filter_coefs_lfe; +unsigned int len125; + +template static _ftype_t dotproduct(int count,const T *buf,const _ftype_t *coefficients) +{ + float sum0=0,sum1=0,sum2=0,sum3=0; + for (;count>=4;buf+=4,coefficients+=4,count-=4) + { + sum0+=buf[0]*coefficients[0]; + sum1+=buf[1]*coefficients[1]; + sum2+=buf[2]*coefficients[2]; + sum3+=buf[3]*coefficients[3]; + } + while (count--) sum0+= *buf++ * *coefficients++; + return sum0+sum1+sum2+sum3; +} + +template static T firfilter(const T *buf, int pos, int len, int count, const float *coefficients) +{ + int count1, count2; + + if (pos >= count) + { + pos -= count; + count1 = count; count2 = 0; + } + else + { + count2 = pos; + count1 = count - pos; + pos = len - count1; + } + + // high part of window + const T *ptr = &buf[pos]; + + float r1=dotproduct(count1,ptr,coefficients);coefficients+=count1; + float r2=dotproduct(count2,buf,coefficients); + return T(r1+r2); +} + +template inline const T& limit(const T& val, const T& min, const T& max) +{ + if (val < min) { + return min; + } else if (val > max) { + return max; + } else { + return val; + } +} + +/* +// Hamming +// 2*pi*k +// w(k) = 0.54 - 0.46*cos(------), where 0 <= k < N +// N-1 +// +// n window length +// w buffer for the window parameters +*/ +void hamming(int n, float* w) +{ + int i; + float k = float(2*M_PI/((float)(n-1))); // 2*pi/(N-1) + + // Calculate window coefficients + for (i=0; i Fs/2 +flags window and filter type as defined in filter.h +variables are ored together: i.e. LP|HAMMING will give a +low pass filter designed using a hamming window +opt beta constant used only when designing using kaiser windows + +returns 0 if OK, -1 if fail +*/ +float* design_fir(unsigned int *n, float* fc, float opt) +{ + unsigned int o = *n & 1; // Indicator for odd filter length + unsigned int end = ((*n + 1) >> 1) - o; // Loop end + unsigned int i; // Loop index + + float k1 = 2 * float(M_PI); // 2*pi*fc1 + float k2 = 0.5f * (float)(1 - o);// Constant used if the filter has even length + float g = 0.0f; // Gain + float t1; // Temporary variables + float fc1; // Cutoff frequencies + + // Sanity check + if(*n==0) return NULL; + fc[0]=limit(fc[0],float(0.001),float(1)); + + float *w=(float*)calloc(sizeof(float),*n); + + // Get window coefficients + hamming(*n,w); + + fc1=*fc; + // Cutoff frequency must be < 0.5 where 0.5 <=> Fs/2 + fc1 = ((fc1 <= 1.0) && (fc1 > 0.0)) ? fc1/2 : 0.25f; + k1 *= fc1; + + // Low pass filter + + // If the filter length is odd, there is one point which is exactly + // in the middle. The value at this point is 2*fCutoff*sin(x)/x, + // where x is zero. To make sure nothing strange happens, we set this + // value separately. + if (o) + { + w[end] = fc1 * w[end] * 2.0f; + g=w[end]; + } + + // Create filter + for (i=0 ; i M9_03DB * lpr_fwr ? lmr_fwr : M9_03DB * lpr_fwr; + float lpr_gain = (lpr_fwr + lmr_lim_fwr) / (1 + lpr_fwr + lpr_fwr); + float lmr_gain = (lpr_fwr + lmr_lim_fwr) / (1 + lmr_lim_fwr + lmr_lim_fwr); + float lmr_unlim_gain = (lpr_fwr + lmr_fwr) / (1 + lmr_fwr + lmr_fwr); + float lpr, lmr; + float l_agc, r_agc, lpr_agc, lmr_agc; + float f, d_gain, c_gain, c_agc_cfk; + + /*** AXIS NO. 1: (Lt, Rt) -> (C, Ls, Rs) ***/ + /* AGC adaption */ + d_gain = (fabs(l_gain - *adapt_l_gain) + fabs(r_gain - *adapt_r_gain)) * 0.5f; + f = d_gain * (1.0f / MATAGCTRIG); + f = MATAGCDECAY - MATAGCDECAY / (1 + f * f); + *adapt_l_gain = (1 - f) * *adapt_l_gain + f * l_gain; + *adapt_r_gain = (1 - f) * *adapt_r_gain + f * r_gain; + /* Matrix */ + l_agc = in[il] * passive_lock(*adapt_l_gain); + r_agc = in[ir] * passive_lock(*adapt_r_gain); + cf[k] = (l_agc + r_agc) * (float)M_SQRT1_2; + if (decode_rear) + { + lr[kr] = rr[kr] = (l_agc - r_agc) * (float)M_SQRT1_2; + /* Stereo rear channel is steered with the same AGC steering as + the decoding matrix. Note this requires a fast updating AGC + at the order of 20 ms (which is the case here). */ + lr[kr] *= (l_fwr + l_fwr) / (1 + l_fwr + r_fwr); + rr[kr] *= (r_fwr + r_fwr) / (1 + l_fwr + r_fwr); + } + + /*** AXIS NO. 2: (Lt + Rt, Lt - Rt) -> (L, R) ***/ + lpr = (in[il] + in[ir]) * (float)M_SQRT1_2; + lmr = (in[il] - in[ir]) * (float)M_SQRT1_2; + /* AGC adaption */ + d_gain = fabs(lmr_unlim_gain - *adapt_lmr_gain); + f = d_gain * (1.0f / MATAGCTRIG); + f = MATAGCDECAY - MATAGCDECAY / (1 + f * f); + *adapt_lpr_gain = (1 - f) * *adapt_lpr_gain + f * lpr_gain; + *adapt_lmr_gain = (1 - f) * *adapt_lmr_gain + f * lmr_gain; + /* Matrix */ + lpr_agc = lpr * passive_lock(*adapt_lpr_gain); + lmr_agc = lmr * passive_lock(*adapt_lmr_gain); + lf[k] = (lpr_agc + lmr_agc) * (float)M_SQRT1_2; + rf[k] = (lpr_agc - lmr_agc) * (float)M_SQRT1_2; + + /*** CENTER FRONT CANCELLATION ***/ + /* A heuristic approach exploits that Lt + Rt gain contains the + information about Lt, Rt correlation. This effectively reshapes + the front and rear "cones" to concentrate Lt + Rt to C and + introduce Lt - Rt in L, R. */ + /* 0.67677 is the empirical lower bound for lpr_gain. */ + c_gain = 8 * (*adapt_lpr_gain - 0.67677f); + c_gain = c_gain > 0 ? c_gain : 0; + /* c_gain should not be too high, not even reaching full + cancellation (~ 0.50 - 0.55 at current AGC implementation), or + the center will sound too narrow. */ + c_gain = MATCOMPGAIN / (1 + c_gain * c_gain); + c_agc_cfk = c_gain * cf[k]; + lf[k] -= c_agc_cfk; + rf[k] -= c_agc_cfk; + cf[k] += c_agc_cfk + c_agc_cfk; +} + +void dpl2decode(float *samples, int numsamples, float *out) +{ + static const unsigned int FWRDURATION = 240; /* FWR average duration (samples) */ + static const unsigned int cfg_delay = 0; + static const unsigned int fmt_freq = 48000; + static const unsigned int fmt_nchannels = 2; // input channels + + int cur = 0; + + if (olddelay != cfg_delay || oldfreq != fmt_freq) + { + done(); + olddelay = cfg_delay; + oldfreq = fmt_freq; + dlbuflen = std::max(FWRDURATION, (fmt_freq * cfg_delay / 1000)); //+(len7000-1); + cyc_pos = dlbuflen - 1; + fwrbuf_l.resize(dlbuflen); + fwrbuf_r.resize(dlbuflen); + lf.resize(dlbuflen); + rf.resize(dlbuflen); + lr.resize(dlbuflen); + rr.resize(dlbuflen); + cf.resize(dlbuflen); + cr.resize(dlbuflen); + filter_coefs_lfe = calc_coefficients_125Hz_lowpass(fmt_freq); + lfe_pos = 0; + memset(LFE_buf, 0, sizeof(LFE_buf)); + } + + float *in = samples; // Input audio data + float *end = in + numsamples * fmt_nchannels; // Loop end + + while (in < end) + { + const int k = cyc_pos; + + const int fwr_pos = (k + FWRDURATION) % dlbuflen; + /* Update the full wave rectified total amplitude */ + /* Input matrix decoder */ + l_fwr += fabs(in[0]) - fabs(fwrbuf_l[fwr_pos]); + r_fwr += fabs(in[1]) - fabs(fwrbuf_r[fwr_pos]); + lpr_fwr += fabs(in[0] + in[1]) - fabs(fwrbuf_l[fwr_pos] + fwrbuf_r[fwr_pos]); + lmr_fwr += fabs(in[0] - in[1]) - fabs(fwrbuf_l[fwr_pos] - fwrbuf_r[fwr_pos]); + + /* Matrix encoded 2 channel sources */ + fwrbuf_l[k] = in[0]; + fwrbuf_r[k] = in[1]; + matrix_decode(in, k, 0, 1, true, dlbuflen, + l_fwr, r_fwr, + lpr_fwr, lmr_fwr, + &adapt_l_gain, &adapt_r_gain, + &adapt_lpr_gain, &adapt_lmr_gain, + &lf[0], &rf[0], &lr[0], &rr[0], &cf[0]); + + out[cur + 0] = lf[k]; + out[cur + 1] = rf[k]; + out[cur + 2] = cf[k]; + LFE_buf[lfe_pos] = (out[0] + out[1]) / 2; + out[cur + 3] = firfilter(LFE_buf, lfe_pos, len125, len125, filter_coefs_lfe); + lfe_pos++; + if (lfe_pos == len125) + { + lfe_pos = 0; + } + out[cur + 4] = lr[k]; + out[cur + 5] = rr[k]; + // Next sample... + in += 2; + cur += 6; + cyc_pos--; + if (cyc_pos < 0) + { + cyc_pos += dlbuflen; + } + } +} + +void dpl2reset() +{ + olddelay = -1; + oldfreq = 0; + filter_coefs_lfe = NULL; +} diff --git a/Source/Core/AudioCommon/Src/DPL2Decoder.h b/Source/Core/AudioCommon/Src/DPL2Decoder.h new file mode 100644 index 0000000000..eee8fbf15e --- /dev/null +++ b/Source/Core/AudioCommon/Src/DPL2Decoder.h @@ -0,0 +1,24 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _DPL2DECODER_H_ +#define _DPL2DECODER_H_ + +void dpl2decode(float *samples, int numsamples, float *out); +void dpl2reset(); + +#endif // _DPL2DECODER_H_ 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 diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h index c775d31cf2..b342e0a49e 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.h +++ b/Source/Core/AudioCommon/Src/OpenALStream.h @@ -26,12 +26,14 @@ #ifdef _WIN32 #include #include +#include #elif defined __APPLE__ #include #include #else #include #include +#include #endif #include "Core.h" @@ -44,6 +46,8 @@ #define SFX_MAX_SOURCE 1 #define OAL_NUM_BUFFERS 16 #define OAL_MAX_SAMPLES 512 +#define SURROUND_CHANNELS 6 // number of channels in surround mode +#define SIZE_FLOAT 4 // size of a float in bytes #endif class OpenALStream: public SoundStream @@ -72,7 +76,7 @@ private: Common::Event mainSyncEvent; short realtimeBuffer[OAL_MAX_SAMPLES * 2]; - soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * 2 * OAL_NUM_BUFFERS]; + soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_NUM_BUFFERS]; ALuint uiBuffers[OAL_NUM_BUFFERS]; ALuint uiSource; ALfloat fVolume; -- cgit v1.2.3 From ed5a68a5040416fe744119069960d1e29b3518eb Mon Sep 17 00:00:00 2001 From: skidau Date: Fri, 11 Jan 2013 14:20:22 +1100 Subject: Build fix --- Source/Core/AudioCommon/Src/DPL2Decoder.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/Src/DPL2Decoder.cpp b/Source/Core/AudioCommon/Src/DPL2Decoder.cpp index 4efedc4b44..a5d2720878 100644 --- a/Source/Core/AudioCommon/Src/DPL2Decoder.cpp +++ b/Source/Core/AudioCommon/Src/DPL2Decoder.cpp @@ -22,6 +22,9 @@ #include #include +#include +#include +#include #include "DPL2Decoder.h" #define M_PI 3.14159265358979323846 @@ -315,7 +318,7 @@ void matrix_decode(const float *in, const int k, const int il, void dpl2decode(float *samples, int numsamples, float *out) { static const unsigned int FWRDURATION = 240; /* FWR average duration (samples) */ - static const unsigned int cfg_delay = 0; + static const int cfg_delay = 0; static const unsigned int fmt_freq = 48000; static const unsigned int fmt_nchannels = 2; // input channels -- 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') 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 ++++- Source/Core/AudioCommon/Src/OpenALStream.h | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'Source/Core/AudioCommon') 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))); diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h index b342e0a49e..f325d6b63a 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.h +++ b/Source/Core/AudioCommon/Src/OpenALStream.h @@ -73,7 +73,6 @@ public: private: std::thread thread; Common::Event soundSyncEvent; - Common::Event mainSyncEvent; short realtimeBuffer[OAL_MAX_SAMPLES * 2]; soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_NUM_BUFFERS]; -- cgit v1.2.3 From dcc216a02728fc258a0b9fb1a8d6f779c8680aba Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 11 Jan 2013 22:22:55 -0500 Subject: 'count' parameter for AddStereoSamples and AddStereoSamplesBE in WaveFile should be unsigned. Doesn't make sense to have them signed. --- Source/Core/AudioCommon/Src/WaveFile.cpp | 31 ++++++++++++++++++++++--------- Source/Core/AudioCommon/Src/WaveFile.h | 4 ++-- 2 files changed, 24 insertions(+), 11 deletions(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/Src/WaveFile.cpp b/Source/Core/AudioCommon/Src/WaveFile.cpp index 802f3f7417..d98348b8bf 100644 --- a/Source/Core/AudioCommon/Src/WaveFile.cpp +++ b/Source/Core/AudioCommon/Src/WaveFile.cpp @@ -100,39 +100,52 @@ void WaveFileWriter::Write4(const char *ptr) file.WriteBytes(ptr, 4); } -void WaveFileWriter::AddStereoSamples(const short *sample_data, int count) +void WaveFileWriter::AddStereoSamples(const short *sample_data, u32 count) { if (!file) PanicAlertT("WaveFileWriter - file not open."); - if (skip_silence) { + + if (skip_silence) + { bool all_zero = true; - for (int i = 0; i < count * 2; i++) - if (sample_data[i]) all_zero = false; - if (all_zero) return; + + for (u32 i = 0; i < count * 2; i++) + { + if (sample_data[i]) + all_zero = false; + } + + if (all_zero) + return; } + file.WriteBytes(sample_data, count * 4); audio_size += count * 4; } -void WaveFileWriter::AddStereoSamplesBE(const short *sample_data, int count) +void WaveFileWriter::AddStereoSamplesBE(const short *sample_data, u32 count) { if (!file) PanicAlertT("WaveFileWriter - file not open."); if (count > BUF_SIZE * 2) - PanicAlert("WaveFileWriter - buffer too small (count = %i).", count); + PanicAlert("WaveFileWriter - buffer too small (count = %u).", count); if (skip_silence) { bool all_zero = true; - for (int i = 0; i < count * 2; i++) + + for (u32 i = 0; i < count * 2; i++) + { if (sample_data[i]) all_zero = false; + } + if (all_zero) return; } - for (int i = 0; i < count * 2; i++) + for (u32 i = 0; i < count * 2; i++) conv_buffer[i] = Common::swap16((u16)sample_data[i]); file.WriteBytes(conv_buffer, count * 4); diff --git a/Source/Core/AudioCommon/Src/WaveFile.h b/Source/Core/AudioCommon/Src/WaveFile.h index 72a090814b..11fbb4ced5 100644 --- a/Source/Core/AudioCommon/Src/WaveFile.h +++ b/Source/Core/AudioCommon/Src/WaveFile.h @@ -50,8 +50,8 @@ public: void SetSkipSilence(bool skip) { skip_silence = skip; } - void AddStereoSamples(const short *sample_data, int count); - void AddStereoSamplesBE(const short *sample_data, int count); // big endian + void AddStereoSamples(const short *sample_data, u32 count); + void AddStereoSamplesBE(const short *sample_data, u32 count); // big endian u32 GetAudioSize() { return audio_size; } }; -- 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/AudioCommonConfig.cpp | 2 -- Source/Core/AudioCommon/Src/AudioCommonConfig.h | 1 - Source/Core/AudioCommon/Src/OpenALStream.cpp | 28 ++++++++++++++--------- Source/Core/AudioCommon/Src/OpenALStream.h | 10 ++++---- 4 files changed, 23 insertions(+), 18 deletions(-) (limited to 'Source/Core/AudioCommon') 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) {} -- cgit v1.2.3 From 020ab743a90c165e836d4bb3cce57cb60443ad7e Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 13 Jan 2013 22:20:33 -0600 Subject: re-enable PulseAudio backend --- Source/Core/AudioCommon/Src/AudioCommon.cpp | 14 ++++++++------ Source/Core/AudioCommon/Src/PulseAudioStream.cpp | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/Src/AudioCommon.cpp b/Source/Core/AudioCommon/Src/AudioCommon.cpp index b21aec45ba..5660edca0a 100644 --- a/Source/Core/AudioCommon/Src/AudioCommon.cpp +++ b/Source/Core/AudioCommon/Src/AudioCommon.cpp @@ -96,18 +96,20 @@ namespace AudioCommon { std::vector backends; - if (NullSound::isValid()) + if (NullSound::isValid()) backends.push_back(BACKEND_NULLSOUND); - if (DSound::isValid()) + if (DSound::isValid()) backends.push_back(BACKEND_DIRECTSOUND); - if (XAudio2::isValid()) + if (XAudio2::isValid()) backends.push_back(BACKEND_XAUDIO2); - if (AOSound::isValid()) + if (AOSound::isValid()) backends.push_back(BACKEND_AOSOUND); - if (AlsaSound::isValid()) + if (AlsaSound::isValid()) backends.push_back(BACKEND_ALSA); - if (CoreAudioSound::isValid()) + if (CoreAudioSound::isValid()) backends.push_back(BACKEND_COREAUDIO); + if (PulseAudio::isValid()) + backends.push_back(BACKEND_PULSEAUDIO); return backends; } diff --git a/Source/Core/AudioCommon/Src/PulseAudioStream.cpp b/Source/Core/AudioCommon/Src/PulseAudioStream.cpp index 923a338190..faa94c22e0 100644 --- a/Source/Core/AudioCommon/Src/PulseAudioStream.cpp +++ b/Source/Core/AudioCommon/Src/PulseAudioStream.cpp @@ -77,7 +77,7 @@ bool PulseAudio::PulseInit() pa_sample_spec ss = {}; ss.format = PA_SAMPLE_S16LE; ss.channels = 2; - ss.rate = m_mixer->GetSampleRate(); + ss.rate = m_mixer->GetSampleRate(); int error; pa = pa_simple_new(nullptr, "dolphin-emu", PA_STREAM_PLAYBACK, -- 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') 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 799b032b98000f2a7ada1a11ab8a001eb0c58882 Mon Sep 17 00:00:00 2001 From: skidau Date: Tue, 15 Jan 2013 23:14:11 +1100 Subject: Readd the OpenAL option. The OpenAL backend requires OpenAL Soft to be installed: http://kcat.strangesoft.net/openal.html You may need to rename soft_oal.dll to OpenAL32.dll in the Dolphin folder. Windows users may also need to update their OpenAL drivers by downloading them from http://connect.creativelabs.com/openal/Downloads/oalinst.zip --- Source/Core/AudioCommon/Src/AudioCommon.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/Src/AudioCommon.cpp b/Source/Core/AudioCommon/Src/AudioCommon.cpp index 5660edca0a..99ae42b93a 100644 --- a/Source/Core/AudioCommon/Src/AudioCommon.cpp +++ b/Source/Core/AudioCommon/Src/AudioCommon.cpp @@ -110,6 +110,8 @@ namespace AudioCommon backends.push_back(BACKEND_COREAUDIO); if (PulseAudio::isValid()) backends.push_back(BACKEND_PULSEAUDIO); + if (OpenALStream::isValid()) + backends.push_back(BACKEND_OPENAL); return backends; } -- 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') 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') 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 1cf7cbb936a47d305f5d82e75f2f6f57c8553a8a Mon Sep 17 00:00:00 2001 From: lioncash Date: Tue, 15 Jan 2013 12:47:13 -0500 Subject: Fix a clear bug in aldlist.cpp. Properly clears itself now. --- Source/Core/AudioCommon/Src/aldlist.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/Src/aldlist.cpp b/Source/Core/AudioCommon/Src/aldlist.cpp index 69d42148ae..5e2e072f7b 100644 --- a/Source/Core/AudioCommon/Src/aldlist.cpp +++ b/Source/Core/AudioCommon/Src/aldlist.cpp @@ -48,7 +48,7 @@ ALDeviceList::ALDeviceList() const char *actualDeviceName = NULL; // DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support - vDeviceInfo.empty(); + vDeviceInfo.clear(); vDeviceInfo.reserve(10); defaultDeviceIndex = 0; @@ -151,7 +151,7 @@ ALDeviceList::~ALDeviceList() } } - vDeviceInfo.empty(); + vDeviceInfo.clear(); } /* -- cgit v1.2.3 From 196c2867adc1f80d1037b0b87e9d99e775cad375 Mon Sep 17 00:00:00 2001 From: Rachel Bryk Date: Wed, 16 Jan 2013 20:16:56 -0500 Subject: Move DSP settings to dolphin.ini --- Source/Core/AudioCommon/AudioCommon.vcxproj | 2 - .../Core/AudioCommon/AudioCommon.vcxproj.filters | 2 - Source/Core/AudioCommon/CMakeLists.txt | 1 - Source/Core/AudioCommon/Src/AudioCommon.cpp | 22 +++++-- Source/Core/AudioCommon/Src/AudioCommon.h | 3 +- Source/Core/AudioCommon/Src/AudioCommonConfig.cpp | 68 ---------------------- Source/Core/AudioCommon/Src/AudioCommonConfig.h | 51 ---------------- 7 files changed, 18 insertions(+), 131 deletions(-) delete mode 100644 Source/Core/AudioCommon/Src/AudioCommonConfig.cpp delete mode 100644 Source/Core/AudioCommon/Src/AudioCommonConfig.h (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj b/Source/Core/AudioCommon/AudioCommon.vcxproj index a983005318..abb5dbf505 100644 --- a/Source/Core/AudioCommon/AudioCommon.vcxproj +++ b/Source/Core/AudioCommon/AudioCommon.vcxproj @@ -191,7 +191,6 @@ - @@ -204,7 +203,6 @@ - diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj.filters b/Source/Core/AudioCommon/AudioCommon.vcxproj.filters index af5fe12220..30ff35a073 100644 --- a/Source/Core/AudioCommon/AudioCommon.vcxproj.filters +++ b/Source/Core/AudioCommon/AudioCommon.vcxproj.filters @@ -3,7 +3,6 @@ - @@ -26,7 +25,6 @@ - diff --git a/Source/Core/AudioCommon/CMakeLists.txt b/Source/Core/AudioCommon/CMakeLists.txt index 0e610bd847..3b6d0cea4d 100644 --- a/Source/Core/AudioCommon/CMakeLists.txt +++ b/Source/Core/AudioCommon/CMakeLists.txt @@ -1,5 +1,4 @@ set(SRCS Src/AudioCommon.cpp - Src/AudioCommonConfig.cpp Src/DPL2Decoder.cpp Src/Mixer.cpp Src/WaveFile.cpp diff --git a/Source/Core/AudioCommon/Src/AudioCommon.cpp b/Source/Core/AudioCommon/Src/AudioCommon.cpp index 99ae42b93a..e14b9ac45e 100644 --- a/Source/Core/AudioCommon/Src/AudioCommon.cpp +++ b/Source/Core/AudioCommon/Src/AudioCommon.cpp @@ -27,6 +27,10 @@ #include "OpenALStream.h" #include "PulseAudioStream.h" #include "../../Core/Src/Movie.h" +#include "../../Core/Src/ConfigManager.h" + +// This shouldn't be a global, at least not here. +SoundStream *soundStream; namespace AudioCommon { @@ -34,7 +38,7 @@ namespace AudioCommon { // TODO: possible memleak with mixer - std::string backend = ac_Config.sBackend; + std::string backend = SConfig::GetInstance().sBackend; if (backend == BACKEND_OPENAL && OpenALStream::isValid()) soundStream = new OpenALStream(mixer); else if (backend == BACKEND_NULLSOUND && NullSound::isValid()) @@ -54,10 +58,10 @@ namespace AudioCommon if (soundStream != NULL) { - ac_Config.Update(); + UpdateSoundStream(); if (soundStream->Start()) { - if (ac_Config.m_DumpAudio) + if (SConfig::GetInstance().m_DumpAudio) { std::string audio_file_name = File::GetUserPath(D_DUMPAUDIO_IDX) + "audiodump.wav"; File::CreateFullPath(audio_file_name); @@ -82,7 +86,7 @@ namespace AudioCommon if (soundStream) { soundStream->Stop(); - if (ac_Config.m_DumpAudio) + if (SConfig::GetInstance().m_DumpAudio) soundStream->GetMixer()->StopLogAudio(); //soundStream->StopLogAudio(); delete soundStream; @@ -122,7 +126,7 @@ namespace AudioCommon { return true; } - return ac_Config.m_EnableJIT; + return SConfig::GetInstance().m_EnableJIT; } void PauseAndLock(bool doLock, bool unpauseOnUnlock) @@ -143,4 +147,12 @@ namespace AudioCommon } } } + void UpdateSoundStream() + { + if (soundStream) + { + soundStream->GetMixer()->SetThrottle(SConfig::GetInstance().m_Framelimit == 2); + soundStream->SetVolume(SConfig::GetInstance().m_Volume); + } + } } diff --git a/Source/Core/AudioCommon/Src/AudioCommon.h b/Source/Core/AudioCommon/Src/AudioCommon.h index e7a111b0a1..b7b32e7498 100644 --- a/Source/Core/AudioCommon/Src/AudioCommon.h +++ b/Source/Core/AudioCommon/Src/AudioCommon.h @@ -19,14 +19,12 @@ #define _AUDIO_COMMON_H_ #include "Common.h" -#include "AudioCommonConfig.h" #include "SoundStream.h" class CMixer; extern SoundStream *soundStream; -extern AudioCommonConfig ac_Config; // UDSPControl union UDSPControl @@ -60,6 +58,7 @@ namespace AudioCommon std::vector GetSoundBackends(); bool UseJIT(); void PauseAndLock(bool doLock, bool unpauseOnUnlock=true); + void UpdateSoundStream(); } #endif // _AUDIO_COMMON_H_ diff --git a/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp b/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp deleted file mode 100644 index 49f50b6880..0000000000 --- a/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "AudioCommon.h" -#include "CommonPaths.h" -#include "FileUtil.h" -#include "../../Core/Src/ConfigManager.h" - -AudioCommonConfig ac_Config; - -// This shouldn't be a global, at least not here. -SoundStream *soundStream; - -// Load from given file -void AudioCommonConfig::Load() -{ - IniFile file; - file.Load(File::GetUserPath(F_DSPCONFIG_IDX)); - - file.Get("Config", "EnableJIT", &m_EnableJIT, true); - file.Get("Config", "DumpAudio", &m_DumpAudio, false); -#if defined __linux__ && HAVE_ALSA - file.Get("Config", "Backend", &sBackend, BACKEND_ALSA); -#elif defined __APPLE__ - file.Get("Config", "Backend", &sBackend, BACKEND_COREAUDIO); -#elif defined _WIN32 - file.Get("Config", "Backend", &sBackend, BACKEND_DIRECTSOUND); -#else - file.Get("Config", "Backend", &sBackend, BACKEND_NULLSOUND); -#endif - file.Get("Config", "Volume", &m_Volume, 100); -} - -// Set the values for the file -void AudioCommonConfig::SaveSettings() -{ - IniFile file; - file.Load(File::GetUserPath(F_DSPCONFIG_IDX)); - - file.Set("Config", "EnableJIT", m_EnableJIT); - file.Set("Config", "DumpAudio", m_DumpAudio); - file.Set("Config", "Backend", sBackend); - file.Set("Config", "Volume", m_Volume); - - file.Save(File::GetUserPath(F_DSPCONFIG_IDX)); -} - -// Update according to the values (stream/mixer) -void AudioCommonConfig::Update() { - if (soundStream) { - soundStream->GetMixer()->SetThrottle(SConfig::GetInstance().m_Framelimit == 2); - soundStream->SetVolume(m_Volume); - } -} diff --git a/Source/Core/AudioCommon/Src/AudioCommonConfig.h b/Source/Core/AudioCommon/Src/AudioCommonConfig.h deleted file mode 100644 index 48807b3ffd..0000000000 --- a/Source/Core/AudioCommon/Src/AudioCommonConfig.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef _AUDIO_COMMON_CONFIG_H_ -#define _AUDIO_COMMON_CONFIG_H_ - -#include -#include "IniFile.h" - -// Backend Types -#define BACKEND_NULLSOUND "No audio output" -#define BACKEND_ALSA "ALSA" -#define BACKEND_AOSOUND "AOSound" -#define BACKEND_COREAUDIO "CoreAudio" -#define BACKEND_DIRECTSOUND "DSound" -#define BACKEND_OPENAL "OpenAL" -#define BACKEND_PULSEAUDIO "Pulse" -#define BACKEND_XAUDIO2 "XAudio2" - -struct AudioCommonConfig -{ - bool m_EnableJIT; - bool m_DumpAudio; - int m_Volume; - std::string sBackend; - - // Load from given file - void Load(); - - // Self explanatory - void SaveSettings(); - - // Update according to the values (stream/mixer) - void Update(); -}; - -#endif //AUDIO_COMMON_CONFIG -- cgit v1.2.3 From c4bd6329c003686fd43002fc4f78f735166b6cbd Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 18 Jan 2013 23:42:37 -0500 Subject: Fully fix that clear bug in aldlist.cpp. Seems I missed part. Corrected it. --- Source/Core/AudioCommon/Src/aldlist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/Src/aldlist.cpp b/Source/Core/AudioCommon/Src/aldlist.cpp index 5e2e072f7b..fa11fe3282 100644 --- a/Source/Core/AudioCommon/Src/aldlist.cpp +++ b/Source/Core/AudioCommon/Src/aldlist.cpp @@ -146,7 +146,7 @@ ALDeviceList::~ALDeviceList() { for (u32 i = 0; i < vDeviceInfo.size(); i++) { if (vDeviceInfo[i].pvstrExtensions) { - vDeviceInfo[i].pvstrExtensions->empty(); + vDeviceInfo[i].pvstrExtensions->clear(); delete vDeviceInfo[i].pvstrExtensions; } } -- 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/AOSoundStream.cpp | 2 +- Source/Core/AudioCommon/Src/DSoundStream.cpp | 2 +- Source/Core/AudioCommon/Src/OpenALStream.cpp | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/Src/AOSoundStream.cpp b/Source/Core/AudioCommon/Src/AOSoundStream.cpp index 99ae2e661c..276938c3e2 100644 --- a/Source/Core/AudioCommon/Src/AOSoundStream.cpp +++ b/Source/Core/AudioCommon/Src/AOSoundStream.cpp @@ -63,7 +63,7 @@ bool AOSound::Start() { memset(realtimeBuffer, 0, sizeof(realtimeBuffer)); - thread = std::thread(std::mem_fun(&AOSound::SoundLoop), this); + thread = std::thread(std::mem_fn(&AOSound::SoundLoop), this); return true; } diff --git a/Source/Core/AudioCommon/Src/DSoundStream.cpp b/Source/Core/AudioCommon/Src/DSoundStream.cpp index b252dc90c5..c0c54e00f5 100644 --- a/Source/Core/AudioCommon/Src/DSoundStream.cpp +++ b/Source/Core/AudioCommon/Src/DSoundStream.cpp @@ -135,7 +135,7 @@ bool DSound::Start() dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, DSBLOCK_ENTIREBUFFER); memset(p1, 0, num1); dsBuffer->Unlock(p1, num1, 0, 0); - thread = std::thread(std::mem_fun(&DSound::SoundLoop), this); + thread = std::thread(std::mem_fn(&DSound::SoundLoop), this); return true; } 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/AOSoundStream.cpp | 2 +- Source/Core/AudioCommon/Src/DSoundStream.cpp | 2 +- Source/Core/AudioCommon/Src/OpenALStream.cpp | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'Source/Core/AudioCommon') diff --git a/Source/Core/AudioCommon/Src/AOSoundStream.cpp b/Source/Core/AudioCommon/Src/AOSoundStream.cpp index 276938c3e2..99ae2e661c 100644 --- a/Source/Core/AudioCommon/Src/AOSoundStream.cpp +++ b/Source/Core/AudioCommon/Src/AOSoundStream.cpp @@ -63,7 +63,7 @@ bool AOSound::Start() { memset(realtimeBuffer, 0, sizeof(realtimeBuffer)); - thread = std::thread(std::mem_fn(&AOSound::SoundLoop), this); + thread = std::thread(std::mem_fun(&AOSound::SoundLoop), this); return true; } diff --git a/Source/Core/AudioCommon/Src/DSoundStream.cpp b/Source/Core/AudioCommon/Src/DSoundStream.cpp index c0c54e00f5..b252dc90c5 100644 --- a/Source/Core/AudioCommon/Src/DSoundStream.cpp +++ b/Source/Core/AudioCommon/Src/DSoundStream.cpp @@ -135,7 +135,7 @@ bool DSound::Start() dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, DSBLOCK_ENTIREBUFFER); memset(p1, 0, num1); dsBuffer->Unlock(p1, num1, 0, 0); - thread = std::thread(std::mem_fn(&DSound::SoundLoop), this); + thread = std::thread(std::mem_fun(&DSound::SoundLoop), this); return true; } 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