diff options
| author | shuffle2 <godisgovernment@gmail.com> | 2017-06-27 01:18:06 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-06-27 01:18:06 -0700 |
| commit | 599a235a19392c6372adf303b3d20fdfeba5a7df (patch) | |
| tree | c072a978db40da20c0237e6fa96e0f04a3836aee /Source/Core/AudioCommon/OpenALStream.cpp | |
| parent | 0f3ee2f209be901a0b3de2d01d6eb3a47f4af888 (diff) | |
| parent | 749889236d0d7608fe8162b26846744f236b5054 (diff) | |
Merge pull request #5691 from ligfx/openalonlywindowsdynamic
OpenAL: only enable on Windows + dynamically load DLL
Diffstat (limited to 'Source/Core/AudioCommon/OpenALStream.cpp')
| -rw-r--r-- | Source/Core/AudioCommon/OpenALStream.cpp | 212 |
1 files changed, 134 insertions, 78 deletions
diff --git a/Source/Core/AudioCommon/OpenALStream.cpp b/Source/Core/AudioCommon/OpenALStream.cpp index 25dd14e7b2..21b2ae0acc 100644 --- a/Source/Core/AudioCommon/OpenALStream.cpp +++ b/Source/Core/AudioCommon/OpenALStream.cpp @@ -2,70 +2,126 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#ifdef _WIN32 + +#include <windows.h> #include <climits> #include <cstring> #include <thread> #include "AudioCommon/OpenALStream.h" -#include "AudioCommon/aldlist.h" #include "Common/Logging/Log.h" #include "Common/MsgHandler.h" #include "Common/Thread.h" #include "Core/ConfigManager.h" -#if defined HAVE_OPENAL && HAVE_OPENAL +static HMODULE s_openal_dll = nullptr; + +#define OPENAL_API_VISIT(X) \ + X(alBufferData) \ + X(alcCloseDevice) \ + X(alcCreateContext) \ + X(alcDestroyContext) \ + X(alcGetContextsDevice) \ + X(alcGetCurrentContext) \ + X(alcGetString) \ + X(alcIsExtensionPresent) \ + X(alcMakeContextCurrent) \ + X(alcOpenDevice) \ + X(alDeleteBuffers) \ + X(alDeleteSources) \ + X(alGenBuffers) \ + X(alGenSources) \ + X(alGetError) \ + X(alGetSourcei) \ + X(alGetString) \ + X(alIsExtensionPresent) \ + X(alSourcef) \ + X(alSourcei) \ + X(alSourcePlay) \ + X(alSourceQueueBuffers) \ + X(alSourceStop) \ + X(alSourceUnqueueBuffers) + +// Create func_t function pointer type and declare a nullptr-initialized static variable of that +// type named "pfunc". +#define DYN_FUNC_DECLARE(func) \ + typedef decltype(&func) func##_t; \ + static func##_t p##func = nullptr; + +// Attempt to load the function from the given module handle. +#define OPENAL_FUNC_LOAD(func) \ + p##func = (func##_t)::GetProcAddress(s_openal_dll, #func); \ + if (!p##func) \ + { \ + return false; \ + } -#ifdef _WIN32 -#pragma comment(lib, "openal32.lib") -#endif +OPENAL_API_VISIT(DYN_FUNC_DECLARE); + +static bool InitFunctions() +{ + OPENAL_API_VISIT(OPENAL_FUNC_LOAD); + return true; +} + +static bool InitLibrary() +{ + if (s_openal_dll) + return true; + + s_openal_dll = ::LoadLibrary(TEXT("openal32.dll")); + if (!s_openal_dll) + return false; + + if (!InitFunctions()) + { + ::FreeLibrary(s_openal_dll); + s_openal_dll = nullptr; + return false; + } + + return true; +} + +bool OpenALStream::isValid() +{ + return InitLibrary(); +} // // AyuanX: Spec says OpenAL1.1 is thread safe already // bool OpenALStream::Start() { - m_run_thread.Set(); - bool bReturn = false; - - ALDeviceList pDeviceList; - if (pDeviceList.GetNumDevices()) + if (!palcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT")) { - char* defDevName = pDeviceList.GetDeviceName(pDeviceList.GetDefaultDevice()); + PanicAlertT("OpenAL: can't find sound devices"); + return false; + } - INFO_LOG(AUDIO, "Found OpenAL device %s", defDevName); + const char* defaultDeviceName = palcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER); + INFO_LOG(AUDIO, "Found OpenAL device %s", defaultDeviceName); - ALCdevice* pDevice = alcOpenDevice(defDevName); - if (pDevice) - { - ALCcontext* pContext = alcCreateContext(pDevice, nullptr); - 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(&OpenALStream::SoundLoop, this); - bReturn = true; - } - else - { - alcCloseDevice(pDevice); - PanicAlertT("OpenAL: can't create context for device %s", defDevName); - } - } - else - { - PanicAlertT("OpenAL: can't open device %s", defDevName); - } + ALCdevice* pDevice = palcOpenDevice(defaultDeviceName); + if (!pDevice) + { + PanicAlertT("OpenAL: can't open device %s", defaultDeviceName); + return false; } - else + + ALCcontext* pContext = palcCreateContext(pDevice, nullptr); + if (!pContext) { - PanicAlertT("OpenAL: can't find sound devices"); + palcCloseDevice(pDevice); + PanicAlertT("OpenAL: can't create context for device %s", defaultDeviceName); + return false; } - return bReturn; + palcMakeContextCurrent(pContext); + m_run_thread.Set(); + thread = std::thread(&OpenALStream::SoundLoop, this); + return true; } void OpenALStream::Stop() @@ -76,20 +132,20 @@ void OpenALStream::Stop() thread.join(); - alSourceStop(uiSource); - alSourcei(uiSource, AL_BUFFER, 0); + palSourceStop(uiSource); + palSourcei(uiSource, AL_BUFFER, 0); // Clean up buffers and sources - alDeleteSources(1, &uiSource); + palDeleteSources(1, &uiSource); uiSource = 0; - alDeleteBuffers(numBuffers, uiBuffers); + palDeleteBuffers(numBuffers, uiBuffers); - ALCcontext* pContext = alcGetCurrentContext(); - ALCdevice* pDevice = alcGetContextsDevice(pContext); + ALCcontext* pContext = palcGetCurrentContext(); + ALCdevice* pDevice = palcGetContextsDevice(pContext); - alcMakeContextCurrent(nullptr); - alcDestroyContext(pContext); - alcCloseDevice(pDevice); + palcMakeContextCurrent(nullptr); + palcDestroyContext(pContext); + palcCloseDevice(pDevice); } void OpenALStream::SetVolume(int volume) @@ -97,7 +153,7 @@ void OpenALStream::SetVolume(int volume) fVolume = (float)volume / 100.0f; if (uiSource) - alSourcef(uiSource, AL_GAIN, fVolume); + palSourcef(uiSource, AL_GAIN, fVolume); } void OpenALStream::Update() @@ -111,17 +167,17 @@ void OpenALStream::Clear(bool mute) if (m_muted) { - alSourceStop(uiSource); + palSourceStop(uiSource); } else { - alSourcePlay(uiSource); + palSourcePlay(uiSource); } } static ALenum CheckALError(const char* desc) { - ALenum err = alGetError(); + ALenum err = palGetError(); if (err != AL_NO_ERROR) { @@ -157,15 +213,15 @@ static ALenum CheckALError(const char* desc) static bool IsCreativeXFi() { - return strstr(alGetString(AL_RENDERER), "X-Fi") != nullptr; + return strstr(palGetString(AL_RENDERER), "X-Fi") != nullptr; } void OpenALStream::SoundLoop() { Common::SetCurrentThreadName("Audio thread - openal"); - bool float32_capable = alIsExtensionPresent("AL_EXT_float32") != 0; - bool surround_capable = alIsExtensionPresent("AL_EXT_MCFORMATS") || IsCreativeXFi(); + bool float32_capable = palIsExtensionPresent("AL_EXT_float32") != 0; + bool surround_capable = palIsExtensionPresent("AL_EXT_MCFORMATS") || IsCreativeXFi(); bool use_surround = SConfig::GetInstance().bDPL2Decoder && surround_capable; // As there is no extension to check for 32-bit fixed point support @@ -180,18 +236,18 @@ void OpenALStream::SoundLoop() uiSource = 0; // Clear error state before querying or else we get false positives. - ALenum err = alGetError(); + ALenum err = palGetError(); // Generate some AL Buffers for streaming - alGenBuffers(numBuffers, (ALuint*)uiBuffers); + palGenBuffers(numBuffers, (ALuint*)uiBuffers); err = CheckALError("generating buffers"); // Generate a Source to playback the Buffers - alGenSources(1, &uiSource); + palGenSources(1, &uiSource); err = CheckALError("generating sources"); // Set the default sound volume as saved in the config file. - alSourcef(uiSource, AL_GAIN, fVolume); + palSourcef(uiSource, AL_GAIN, fVolume); // TODO: Error handling // ALenum err = alGetError(); @@ -204,7 +260,7 @@ void OpenALStream::SoundLoop() { // Block until we have a free buffer int numBuffersProcessed; - alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &numBuffersProcessed); + palGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &numBuffersProcessed); if (numBuffers == numBuffersQueued && !numBuffersProcessed) { soundSyncEvent.Wait(); @@ -215,7 +271,7 @@ void OpenALStream::SoundLoop() if (numBuffersProcessed) { ALuint unqueuedBufferIds[OAL_MAX_BUFFERS]; - alSourceUnqueueBuffers(uiSource, numBuffersProcessed, unqueuedBufferIds); + palSourceUnqueueBuffers(uiSource, numBuffersProcessed, unqueuedBufferIds); err = CheckALError("unqueuing buffers"); numBuffersQueued -= numBuffersProcessed; @@ -245,8 +301,8 @@ void OpenALStream::SoundLoop() if (float32_capable) { - alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN32, dpl2, - numSamples * FRAME_SURROUND_FLOAT, ulFrequency); + palBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN32, dpl2, + numSamples * FRAME_SURROUND_FLOAT, ulFrequency); } else if (fixed32_capable) { @@ -266,8 +322,8 @@ void OpenALStream::SoundLoop() surround_int32[i] = (int)dpl2[i]; } - alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN32, surround_int32, - numSamples * FRAME_SURROUND_INT32, ulFrequency); + palBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN32, surround_int32, + numSamples * FRAME_SURROUND_INT32, ulFrequency); } else { @@ -284,8 +340,8 @@ void OpenALStream::SoundLoop() surround_short[i] = (int)dpl2[i]; } - alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN16, surround_short, - numSamples * FRAME_SURROUND_SHORT, ulFrequency); + palBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN16, surround_short, + numSamples * FRAME_SURROUND_SHORT, ulFrequency); } err = CheckALError("buffering data"); @@ -310,8 +366,8 @@ void OpenALStream::SoundLoop() if (float32_capable) { - alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO_FLOAT32, sampleBuffer, - numSamples * FRAME_STEREO_FLOAT, ulFrequency); + palBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO_FLOAT32, sampleBuffer, + numSamples * FRAME_STEREO_FLOAT, ulFrequency); err = CheckALError("buffering float32 data"); if (err == AL_INVALID_ENUM) @@ -326,8 +382,8 @@ void OpenALStream::SoundLoop() for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i) stereo_int32[i] = (int)((float)sampleBuffer[i] * (INT64_C(1) << 31)); - alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO32, stereo_int32, - numSamples * FRAME_STEREO_INT32, ulFrequency); + palBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO32, stereo_int32, + numSamples * FRAME_STEREO_INT32, ulFrequency); } else { @@ -336,25 +392,25 @@ void OpenALStream::SoundLoop() for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i) stereo[i] = (short)((float)sampleBuffer[i] * (1 << 15)); - alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO16, stereo, - numSamples * FRAME_STEREO_SHORT, ulFrequency); + palBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO16, stereo, + numSamples * FRAME_STEREO_SHORT, ulFrequency); } } - alSourceQueueBuffers(uiSource, 1, &uiBuffers[nextBuffer]); + palSourceQueueBuffers(uiSource, 1, &uiBuffers[nextBuffer]); err = CheckALError("queuing buffers"); numBuffersQueued++; nextBuffer = (nextBuffer + 1) % numBuffers; - alGetSourcei(uiSource, AL_SOURCE_STATE, &iState); + palGetSourcei(uiSource, AL_SOURCE_STATE, &iState); if (iState != AL_PLAYING) { // Buffer underrun occurred, resume playback - alSourcePlay(uiSource); + palSourcePlay(uiSource); err = CheckALError("occurred resuming playback"); } } } -#endif // HAVE_OPENAL +#endif // _WIN32 |
