From f75a00efe24d6a48f45ed6f4425143dea7777ac6 Mon Sep 17 00:00:00 2001 From: SirLynix Date: Mon, 4 Dec 2023 00:23:39 +0100 Subject: [PATCH] Audio: Fix loading of OpenAL extensions (pointers are context-local) --- .github/workflows/macos-build.yml | 2 - include/Nazara/Audio/OpenALBuffer.hpp | 3 +- include/Nazara/Audio/OpenALBuffer.inl | 5 +- include/Nazara/Audio/OpenALDevice.hpp | 34 +++- include/Nazara/Audio/OpenALDevice.inl | 24 +++ include/Nazara/Audio/OpenALLibrary.hpp | 1 + include/Nazara/Audio/OpenALSource.hpp | 3 +- include/Nazara/Audio/OpenALSource.inl | 5 +- src/Nazara/Audio/OpenALBuffer.cpp | 30 +-- src/Nazara/Audio/OpenALDevice.cpp | 247 +++++++++++++++++++++---- src/Nazara/Audio/OpenALLibrary.cpp | 12 +- src/Nazara/Audio/OpenALSource.cpp | 164 +++++++++------- 12 files changed, 388 insertions(+), 142 deletions(-) diff --git a/.github/workflows/macos-build.yml b/.github/workflows/macos-build.yml index b1b6a2878..895105243 100644 --- a/.github/workflows/macos-build.yml +++ b/.github/workflows/macos-build.yml @@ -80,8 +80,6 @@ jobs: - name: Run unit tests if: matrix.confs.mode != 'releasedbg' run: xmake run UnitTests - env: - NAZARA_NO_AUDIO: 1 # Setup installation configuration - name: Configure xmake for installation diff --git a/include/Nazara/Audio/OpenALBuffer.hpp b/include/Nazara/Audio/OpenALBuffer.hpp index f11b9d8ee..8d69ced52 100644 --- a/include/Nazara/Audio/OpenALBuffer.hpp +++ b/include/Nazara/Audio/OpenALBuffer.hpp @@ -22,7 +22,7 @@ namespace Nz class NAZARA_AUDIO_API OpenALBuffer final : public AudioBuffer { public: - inline OpenALBuffer(std::shared_ptr device, OpenALLibrary& library, ALuint bufferId); + inline OpenALBuffer(std::shared_ptr device, ALuint bufferId); OpenALBuffer(const OpenALBuffer&) = delete; OpenALBuffer(OpenALBuffer&&) = delete; ~OpenALBuffer(); @@ -44,7 +44,6 @@ namespace Nz const OpenALDevice& GetDevice() const; ALuint m_bufferId; - OpenALLibrary& m_library; }; } diff --git a/include/Nazara/Audio/OpenALBuffer.inl b/include/Nazara/Audio/OpenALBuffer.inl index ffe5e2518..903d57d99 100644 --- a/include/Nazara/Audio/OpenALBuffer.inl +++ b/include/Nazara/Audio/OpenALBuffer.inl @@ -6,10 +6,9 @@ namespace Nz { - inline OpenALBuffer::OpenALBuffer(std::shared_ptr device, OpenALLibrary& library, ALuint bufferId) : + inline OpenALBuffer::OpenALBuffer(std::shared_ptr device, ALuint bufferId) : AudioBuffer(std::move(device)), - m_bufferId(bufferId), - m_library(library) + m_bufferId(bufferId) { } diff --git a/include/Nazara/Audio/OpenALDevice.hpp b/include/Nazara/Audio/OpenALDevice.hpp index 4de603ff7..a437b5539 100644 --- a/include/Nazara/Audio/OpenALDevice.hpp +++ b/include/Nazara/Audio/OpenALDevice.hpp @@ -31,9 +31,13 @@ namespace Nz Max = SourceLatency }; + using ALFunction = void(*)(void); + class NAZARA_AUDIO_API OpenALDevice : public AudioDevice { friend OpenALLibrary; + struct SymbolLoader; + friend SymbolLoader; public: OpenALDevice(OpenALLibrary& library, ALCdevice* device); @@ -41,11 +45,18 @@ namespace Nz OpenALDevice(OpenALDevice&&) = delete; ~OpenALDevice(); + bool ClearErrorFlag() const; + std::shared_ptr CreateBuffer() override; std::shared_ptr CreateSource() override; + inline bool DidLastCallSucceed() const; + float GetDopplerFactor() const override; + inline ALFunction GetFunctionByIndex(std::size_t funcIndex) const; float GetGlobalVolume() const override; + inline OpenALLibrary& GetLibrary(); + inline const OpenALLibrary& GetLibrary() const; Vector3f GetListenerDirection(Vector3f* up = nullptr) const override; Vector3f GetListenerPosition() const override; Quaternionf GetListenerRotation() const override; @@ -58,6 +69,9 @@ namespace Nz void MakeContextCurrent() const; + template void PrintFunctionCall(std::size_t funcIndex, Args... args) const; + bool ProcessErrorFlag() const; + void SetDopplerFactor(float dopplerFactor) override; void SetGlobalVolume(float volume) override; void SetListenerDirection(const Vector3f& direction, const Vector3f& up = Vector3f::Up()) override; @@ -70,14 +84,30 @@ namespace Nz OpenALDevice& operator=(const OpenALDevice&) = delete; OpenALDevice& operator=(OpenALDevice&&) = delete; + // We give each device its own set of function pointer, even though regular OpenAL extensions are always the same (for a set library). + // This makes it easier to wrap them (for error handling), and extension pointers are device-local anyway. +#define NAZARA_AUDIO_AL_ALC_FUNCTION(name) decltype(&::name) name; +#include + private: - EnumArray m_audioFormatValues; - EnumArray m_extensionStatus; + enum class FunctionIndex + { +#define NAZARA_AUDIO_AL_ALC_FUNCTION(name) name, +#include + + Count + }; + + std::array m_originalFunctionPointer; std::string m_renderer; std::string m_vendor; + EnumArray m_audioFormatValues; + EnumArray m_extensionStatus; OpenALLibrary& m_library; MovablePtr m_context; MovablePtr m_device; + mutable bool m_didCollectErrors; + mutable bool m_hadAnyError; }; } diff --git a/include/Nazara/Audio/OpenALDevice.inl b/include/Nazara/Audio/OpenALDevice.inl index 47f80b026..e22f3b30d 100644 --- a/include/Nazara/Audio/OpenALDevice.inl +++ b/include/Nazara/Audio/OpenALDevice.inl @@ -7,6 +7,30 @@ namespace Nz { + inline bool OpenALDevice::DidLastCallSucceed() const + { + if (!m_didCollectErrors) + ProcessErrorFlag(); + + return !m_hadAnyError; + } + + inline ALFunction OpenALDevice::GetFunctionByIndex(std::size_t funcIndex) const + { + assert(funcIndex < m_originalFunctionPointer.size()); + return m_originalFunctionPointer[funcIndex]; + } + + inline OpenALLibrary& OpenALDevice::GetLibrary() + { + return m_library; + } + + inline const OpenALLibrary& OpenALDevice::GetLibrary() const + { + return m_library; + } + inline bool OpenALDevice::IsExtensionSupported(OpenALExtension extension) const { return m_extensionStatus[extension]; diff --git a/include/Nazara/Audio/OpenALLibrary.hpp b/include/Nazara/Audio/OpenALLibrary.hpp index e50bae8bc..1d420e2c4 100644 --- a/include/Nazara/Audio/OpenALLibrary.hpp +++ b/include/Nazara/Audio/OpenALLibrary.hpp @@ -44,6 +44,7 @@ namespace Nz OpenALLibrary& operator=(OpenALLibrary&&) = delete; #define NAZARA_AUDIO_AL_ALC_FUNCTION(name) decltype(&::name) name; +#define NAZARA_AUDIO_AL_EXT_FUNCTION(name) #include private: diff --git a/include/Nazara/Audio/OpenALSource.hpp b/include/Nazara/Audio/OpenALSource.hpp index f47398ac2..1c7299613 100644 --- a/include/Nazara/Audio/OpenALSource.hpp +++ b/include/Nazara/Audio/OpenALSource.hpp @@ -23,7 +23,7 @@ namespace Nz class NAZARA_AUDIO_API OpenALSource final : public AudioSource { public: - inline OpenALSource(std::shared_ptr device, OpenALLibrary& library, ALuint sourceId); + inline OpenALSource(std::shared_ptr device, ALuint sourceId); OpenALSource(const OpenALSource&) = delete; OpenALSource(OpenALSource&&) = delete; ~OpenALSource(); @@ -76,7 +76,6 @@ namespace Nz std::shared_ptr m_currentBuffer; std::vector> m_queuedBuffers; ALuint m_sourceId; - OpenALLibrary& m_library; }; } diff --git a/include/Nazara/Audio/OpenALSource.inl b/include/Nazara/Audio/OpenALSource.inl index 49d3d2a4b..2a91cf280 100644 --- a/include/Nazara/Audio/OpenALSource.inl +++ b/include/Nazara/Audio/OpenALSource.inl @@ -6,10 +6,9 @@ namespace Nz { - inline OpenALSource::OpenALSource(std::shared_ptr device, OpenALLibrary& library, ALuint sourceId) : + inline OpenALSource::OpenALSource(std::shared_ptr device, ALuint sourceId) : AudioSource(std::move(device)), - m_sourceId(sourceId), - m_library(library) + m_sourceId(sourceId) { } } diff --git a/src/Nazara/Audio/OpenALBuffer.cpp b/src/Nazara/Audio/OpenALBuffer.cpp index 0f61edd2b..e843049ea 100644 --- a/src/Nazara/Audio/OpenALBuffer.cpp +++ b/src/Nazara/Audio/OpenALBuffer.cpp @@ -12,18 +12,20 @@ namespace Nz { OpenALBuffer::~OpenALBuffer() { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); - m_library.alDeleteBuffers(1, &m_bufferId); + device.alDeleteBuffers(1, &m_bufferId); } UInt64 OpenALBuffer::GetSampleCount() const { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); ALint bits, size; - m_library.alGetBufferi(m_bufferId, AL_BITS, &bits); - m_library.alGetBufferi(m_bufferId, AL_SIZE, &size); + device.alGetBufferi(m_bufferId, AL_BITS, &bits); + device.alGetBufferi(m_bufferId, AL_SIZE, &size); UInt64 sampleCount = 0; if (bits != 0) @@ -34,20 +36,22 @@ namespace Nz UInt64 OpenALBuffer::GetSize() const { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); ALint size; - m_library.alGetBufferi(m_bufferId, AL_SIZE, &size); + device.alGetBufferi(m_bufferId, AL_SIZE, &size); return SafeCast(size); } UInt32 OpenALBuffer::GetSampleRate() const { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); ALint sampleRate; - m_library.alGetBufferi(m_bufferId, AL_FREQUENCY, &sampleRate); + device.alGetBufferi(m_bufferId, AL_FREQUENCY, &sampleRate); return SafeCast(sampleRate); } @@ -55,7 +59,7 @@ namespace Nz bool OpenALBuffer::IsCompatibleWith(const AudioDevice& device) const { // OpenAL buffers are shared among contexts and thus devices - return device.GetSubSystemIdentifier() == &m_library; + return device.GetSubSystemIdentifier() == &GetDevice().GetLibrary(); } bool OpenALBuffer::Reset(AudioFormat format, UInt64 sampleCount, UInt32 sampleRate, const void* samples) @@ -72,11 +76,11 @@ namespace Nz device.MakeContextCurrent(); // We empty the error stack - while (m_library.alGetError() != AL_NO_ERROR); + while (device.alGetError() != AL_NO_ERROR); - m_library.alBufferData(m_bufferId, alFormat, samples, SafeCast(sampleCount * sizeof(Int16)), SafeCast(sampleRate)); + device.alBufferData(m_bufferId, alFormat, samples, SafeCast(sampleCount * sizeof(Int16)), SafeCast(sampleRate)); - if (ALenum lastError = m_library.alGetError(); lastError != AL_NO_ERROR) + if (ALenum lastError = device.alGetError(); lastError != AL_NO_ERROR) { NazaraErrorFmt("failed to reset OpenAL buffer: {0}", std::to_string(lastError)); return false; diff --git a/src/Nazara/Audio/OpenALDevice.cpp b/src/Nazara/Audio/OpenALDevice.cpp index ebf3133b4..44c141963 100644 --- a/src/Nazara/Audio/OpenALDevice.cpp +++ b/src/Nazara/Audio/OpenALDevice.cpp @@ -7,29 +7,134 @@ #include #include #include +#include +#include +#include #include #include #include namespace Nz { - namespace + namespace NAZARA_ANONYMOUS_NAMESPACE { - thread_local ALCcontext* s_currentContext; + constexpr std::array s_functionNames = { +#define NAZARA_AUDIO_AL_ALC_FUNCTION(name) #name, +#include + }; + + thread_local const OpenALDevice* s_currentALDevice; + + template + struct ALWrapper; + + template + struct ALWrapper + { + static auto WrapErrorHandling() + { + return [](Args... args) -> Ret + { + const OpenALDevice* device = s_currentALDevice; //< pay TLS cost once + assert(device); + + FuncType funcPtr = reinterpret_cast(device->GetFunctionByIndex(FuncIndex)); + + if constexpr (std::is_same_v) + { + funcPtr(args...); + + if (device->ProcessErrorFlag()) + device->PrintFunctionCall(FuncIndex, args...); + } + else + { + Ret r = funcPtr(args...); + + if (device->ProcessErrorFlag()) + device->PrintFunctionCall(FuncIndex, args...); + + return r; + } + }; + } + }; } + struct OpenALDevice::SymbolLoader + { + SymbolLoader(OpenALDevice& parent) : + device(parent) + { + } + + template + bool Load(Func& func, const char* funcName, FuncType libraryPtr) + { + NAZARA_USE_ANONYMOUS_NAMESPACE + + ALFunction originalFuncPtr; + if constexpr (ContextFunction) + originalFuncPtr = BitCast(device.m_library.alcGetProcAddress(device.m_device, funcName)); + else + originalFuncPtr = BitCast(device.m_library.alGetProcAddress(funcName)); + + // Fallback in case of faulty OpenAL implementations not returning core functions through alGetProcAddress/alcGetProcAddress + if (!originalFuncPtr) + originalFuncPtr = reinterpret_cast(libraryPtr); + + func = reinterpret_cast(originalFuncPtr); + + if (func && wrapErrorHandling) + { + if constexpr ( + FuncIndex != UnderlyingCast(FunctionIndex::alGetError) && //< Prevent infinite recursion + FuncIndex != UnderlyingCast(FunctionIndex::alcCloseDevice) && //< alcDestroyContext is called with no context + FuncIndex != UnderlyingCast(FunctionIndex::alcDestroyContext)) //< alcDestroyContext is called with no context + { + using Wrapper = ALWrapper; + func = Wrapper::WrapErrorHandling(); + } + } + + device.m_originalFunctionPointer[FuncIndex] = originalFuncPtr; + + return func != nullptr; + } + + OpenALDevice& device; + bool wrapErrorHandling = false; + }; + + OpenALDevice::OpenALDevice(OpenALLibrary& library, ALCdevice* device) : m_library(library), m_device(device) { + NAZARA_USE_ANONYMOUS_NAMESPACE + m_context = m_library.alcCreateContext(device, nullptr); if (!m_context) throw std::runtime_error("failed to create OpenAL context"); - MakeContextCurrent(); + // Don't use MakeContextCurrent as device pointers are not loaded yet + if (m_library.alcMakeContextCurrent(m_context) != AL_TRUE) + throw std::runtime_error("failed to activate OpenAL context"); - m_renderer = reinterpret_cast(m_library.alGetString(AL_RENDERER)); - m_vendor = reinterpret_cast(m_library.alGetString(AL_VENDOR)); + s_currentALDevice = this; + + SymbolLoader loader(*this); +#ifdef NAZARA_DEBUG + loader.wrapErrorHandling = true; +#endif + +#define NAZARA_AUDIO_AL_FUNCTION(name) loader.Load(name, #name, library.name); +#define NAZARA_AUDIO_ALC_FUNCTION(name) loader.Load(name, #name, library.name); +#define NAZARA_AUDIO_AL_EXT_FUNCTION(name) loader.Load(name, #name, nullptr); +#include + + m_renderer = reinterpret_cast(alGetString(AL_RENDERER)); + m_vendor = reinterpret_cast(alGetString(AL_VENDOR)); // We complete the formats table m_audioFormatValues.fill(0); @@ -40,13 +145,13 @@ namespace Nz // "The presence of an enum value does not guarantee the applicability of an extension to the current context." if (library.alIsExtensionPresent("AL_EXT_MCFORMATS")) { - m_audioFormatValues[AudioFormat::I16_Quad] = m_library.alGetEnumValue("AL_FORMAT_QUAD16"); - m_audioFormatValues[AudioFormat::I16_5_1] = m_library.alGetEnumValue("AL_FORMAT_51CHN16"); - m_audioFormatValues[AudioFormat::I16_6_1] = m_library.alGetEnumValue("AL_FORMAT_61CHN16"); - m_audioFormatValues[AudioFormat::I16_7_1] = m_library.alGetEnumValue("AL_FORMAT_71CHN16"); + m_audioFormatValues[AudioFormat::I16_Quad] = alGetEnumValue("AL_FORMAT_QUAD16"); + m_audioFormatValues[AudioFormat::I16_5_1] = alGetEnumValue("AL_FORMAT_51CHN16"); + m_audioFormatValues[AudioFormat::I16_6_1] = alGetEnumValue("AL_FORMAT_61CHN16"); + m_audioFormatValues[AudioFormat::I16_7_1] = alGetEnumValue("AL_FORMAT_71CHN16"); } else if (library.alIsExtensionPresent("AL_LOKI_quadriphonic")) - m_audioFormatValues[AudioFormat::I16_Quad] = m_library.alGetEnumValue("AL_FORMAT_QUAD16_LOKI"); + m_audioFormatValues[AudioFormat::I16_Quad] = alGetEnumValue("AL_FORMAT_QUAD16_LOKI"); m_extensionStatus.fill(false); if (library.alIsExtensionPresent("AL_SOFT_source_latency")) @@ -57,49 +162,65 @@ namespace Nz OpenALDevice::~OpenALDevice() { + NAZARA_USE_ANONYMOUS_NAMESPACE + MakeContextCurrent(); - m_library.alcDestroyContext(m_context); - m_library.alcCloseDevice(m_device); + alcDestroyContext(m_context); + alcCloseDevice(m_device); - if (s_currentContext == m_context) - s_currentContext = nullptr; + if (s_currentALDevice == this) + s_currentALDevice = nullptr; + } + + bool OpenALDevice::ClearErrorFlag() const + { + NAZARA_USE_ANONYMOUS_NAMESPACE + + assert(s_currentALDevice == this); + + alGetError(); + + m_didCollectErrors = false; + m_hadAnyError = false; + + return true; } std::shared_ptr OpenALDevice::CreateBuffer() { MakeContextCurrent(); - m_library.alGetError(); // Clear error flags + ClearErrorFlag(); ALuint bufferId = 0; - m_library.alGenBuffers(1, &bufferId); + alGenBuffers(1, &bufferId); - if (ALenum lastError = m_library.alGetError(); lastError != AL_NO_ERROR) + if (!DidLastCallSucceed()) { - NazaraErrorFmt("failed to create OpenAL buffer: {0}", TranslateOpenALError(lastError)); + NazaraError("failed to create OpenAL buffer"); return {}; } - return std::make_shared(shared_from_this(), m_library, bufferId); + return std::make_shared(shared_from_this(), bufferId); } std::shared_ptr OpenALDevice::CreateSource() { MakeContextCurrent(); - m_library.alGetError(); // Clear error flags + ClearErrorFlag(); ALuint sourceId = 0; - m_library.alGenSources(1, &sourceId); + alGenSources(1, &sourceId); - if (ALenum lastError = m_library.alGetError(); lastError != AL_NO_ERROR) + if (!DidLastCallSucceed()) { - NazaraErrorFmt("failed to create OpenAL source: {0}", TranslateOpenALError(lastError)); + NazaraError("failed to create OpenAL buffer"); return {}; } - return std::make_shared(shared_from_this(), m_library, sourceId); + return std::make_shared(shared_from_this(), sourceId); } /*! @@ -110,7 +231,7 @@ namespace Nz { MakeContextCurrent(); - return m_library.alGetFloat(AL_DOPPLER_FACTOR); + return alGetFloat(AL_DOPPLER_FACTOR); } /*! @@ -122,7 +243,7 @@ namespace Nz MakeContextCurrent(); ALfloat gain = 0.f; - m_library.alGetListenerf(AL_GAIN, &gain); + alGetListenerf(AL_GAIN, &gain); return gain; } @@ -140,7 +261,7 @@ namespace Nz MakeContextCurrent(); ALfloat orientation[6]; - m_library.alGetListenerfv(AL_ORIENTATION, orientation); + alGetListenerfv(AL_ORIENTATION, orientation); if (up) (*up) = Vector3f(orientation[3], orientation[4], orientation[5]); @@ -159,7 +280,7 @@ namespace Nz MakeContextCurrent(); Vector3f position; - m_library.alGetListenerfv(AL_POSITION, &position.x); + alGetListenerfv(AL_POSITION, &position.x); return position; } @@ -177,7 +298,7 @@ namespace Nz MakeContextCurrent(); ALfloat orientation[6]; - m_library.alGetListenerfv(AL_ORIENTATION, orientation); + alGetListenerfv(AL_ORIENTATION, orientation); Vector3f forward(orientation[0], orientation[1], orientation[2]); Vector3f up(orientation[3], orientation[4], orientation[5]); @@ -196,20 +317,68 @@ namespace Nz MakeContextCurrent(); Vector3f velocity; - m_library.alGetListenerfv(AL_VELOCITY, &velocity.x); + alGetListenerfv(AL_VELOCITY, &velocity.x); return velocity; } void OpenALDevice::MakeContextCurrent() const { - if (s_currentContext != m_context) + NAZARA_USE_ANONYMOUS_NAMESPACE + + if (s_currentALDevice != this) { m_library.alcMakeContextCurrent(m_context); - s_currentContext = m_context; + s_currentALDevice = this; } } + template + void OpenALDevice::PrintFunctionCall(std::size_t funcIndex, Args... args) const + { + NAZARA_USE_ANONYMOUS_NAMESPACE + + std::stringstream ss; + ss << s_functionNames[funcIndex] << "("; + if constexpr (sizeof...(args) > 0) + { + bool first = true; + auto PrintParam = [&](auto value) + { + if (!first) + ss << ", "; + + ss << +value; + first = false; + }; + + (PrintParam(args), ...); + } + ss << ")"; + NazaraDebug(ss.str()); + } + + bool OpenALDevice::ProcessErrorFlag() const + { + NAZARA_USE_ANONYMOUS_NAMESPACE + + assert(s_currentALDevice == this); + + bool hasAnyError = false; + + if (ALuint lastError = alGetError(); lastError != AL_NO_ERROR) + { + hasAnyError = true; + + NazaraErrorFmt("OpenAL error: {0}", TranslateOpenALError(lastError)); + } + + m_didCollectErrors = true; + m_hadAnyError = hasAnyError; + + return hasAnyError; + } + /*! * \brief Gets the speed of sound * \return Speed of sound @@ -218,7 +387,7 @@ namespace Nz { MakeContextCurrent(); - return m_library.alGetFloat(AL_SPEED_OF_SOUND); + return alGetFloat(AL_SPEED_OF_SOUND); } const void* OpenALDevice::GetSubSystemIdentifier() const @@ -249,7 +418,7 @@ namespace Nz { MakeContextCurrent(); - m_library.alDopplerFactor(dopplerFactor); + alDopplerFactor(dopplerFactor); } /*! @@ -261,7 +430,7 @@ namespace Nz { MakeContextCurrent(); - m_library.alListenerf(AL_GAIN, volume); + alListenerf(AL_GAIN, volume); } /*! @@ -282,7 +451,7 @@ namespace Nz up.x, up.y, up.z }; - m_library.alListenerfv(AL_ORIENTATION, orientation); + alListenerfv(AL_ORIENTATION, orientation); } /*! @@ -296,7 +465,7 @@ namespace Nz { MakeContextCurrent(); - m_library.alListenerfv(AL_POSITION, &position.x); + alListenerfv(AL_POSITION, &position.x); } /*! @@ -310,7 +479,7 @@ namespace Nz { MakeContextCurrent(); - m_library.alListenerfv(AL_VELOCITY, &velocity.x); + alListenerfv(AL_VELOCITY, &velocity.x); } /*! @@ -322,6 +491,6 @@ namespace Nz { MakeContextCurrent(); - m_library.alSpeedOfSound(speed); + alSpeedOfSound(speed); } } diff --git a/src/Nazara/Audio/OpenALLibrary.cpp b/src/Nazara/Audio/OpenALLibrary.cpp index c51aa1b5a..d01d82ee8 100644 --- a/src/Nazara/Audio/OpenALLibrary.cpp +++ b/src/Nazara/Audio/OpenALLibrary.cpp @@ -23,13 +23,6 @@ namespace Nz auto PostLoad = [&] { - // Load ext -#define NAZARA_AUDIO_AL_ALC_FUNCTION(name) -#define NAZARA_AUDIO_AL_EXT_BEGIN(ext) if (alIsExtensionPresent(#ext)) { -#define NAZARA_AUDIO_AL_EXT_END() } -#define NAZARA_AUDIO_AL_EXT_FUNCTION(name) name = reinterpret_cast(alGetProcAddress(#name)); -#include - m_hasCaptureSupport = alcIsExtensionPresent(nullptr, "ALC_EXT_CAPTURE"); m_isLoaded = true; @@ -79,8 +72,6 @@ namespace Nz try { #define NAZARA_AUDIO_AL_ALC_FUNCTION(name) name = reinterpret_cast(LoadSymbol(#name, false)); -#define NAZARA_AUDIO_AL_EXT_BEGIN(name) -#define NAZARA_AUDIO_AL_EXT_END(name) #define NAZARA_AUDIO_AL_EXT_FUNCTION(name) #include } @@ -104,8 +95,6 @@ namespace Nz // Load core #define NAZARA_AUDIO_AL_ALC_FUNCTION(name) name = &::name; -#define NAZARA_AUDIO_AL_EXT_BEGIN(name) -#define NAZARA_AUDIO_AL_EXT_END(name) #define NAZARA_AUDIO_AL_EXT_FUNCTION(name) #include @@ -142,6 +131,7 @@ namespace Nz return; #define NAZARA_AUDIO_AL_ALC_FUNCTION(name) name = nullptr; +#define NAZARA_AUDIO_AL_EXT_FUNCTION(name) #include m_library.Unload(); diff --git a/src/Nazara/Audio/OpenALSource.cpp b/src/Nazara/Audio/OpenALSource.cpp index 3d4503bfe..f18ccab45 100644 --- a/src/Nazara/Audio/OpenALSource.cpp +++ b/src/Nazara/Audio/OpenALSource.cpp @@ -15,63 +15,72 @@ namespace Nz { OpenALSource::~OpenALSource() { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); - m_library.alDeleteSources(1, &m_sourceId); + device.alDeleteSources(1, &m_sourceId); } void OpenALSource::EnableLooping(bool loop) { - GetDevice().MakeContextCurrent(); - m_library.alSourcei(m_sourceId, AL_LOOPING, loop); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); + + device.alSourcei(m_sourceId, AL_LOOPING, loop); } void OpenALSource::EnableSpatialization(bool spatialization) { - GetDevice().MakeContextCurrent(); - m_library.alSourcei(m_sourceId, AL_SOURCE_RELATIVE, !spatialization); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); + + device.alSourcei(m_sourceId, AL_SOURCE_RELATIVE, !spatialization); } float OpenALSource::GetAttenuation() const { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); ALfloat attenuation; - m_library.alGetSourcefv(m_sourceId, AL_ROLLOFF_FACTOR, &attenuation); + device.alGetSourcefv(m_sourceId, AL_ROLLOFF_FACTOR, &attenuation); return attenuation; } float OpenALSource::GetMinDistance() const { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); ALfloat minDistance; - m_library.alGetSourcefv(m_sourceId, AL_REFERENCE_DISTANCE, &minDistance); + device.alGetSourcefv(m_sourceId, AL_REFERENCE_DISTANCE, &minDistance); return minDistance; } float OpenALSource::GetPitch() const { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); ALfloat pitch; - m_library.alGetSourcefv(m_sourceId, AL_PITCH, &pitch); + device.alGetSourcefv(m_sourceId, AL_PITCH, &pitch); return pitch; } Time OpenALSource::GetPlayingOffset() const { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); #ifdef AL_SOFT_source_latency if (GetDevice().IsExtensionSupported(OpenALExtension::SourceLatency)) { // alGetSourcedvSOFT has extra precision thanks to double ALdouble playingOffset; - m_library.alGetSourcedvSOFT(m_sourceId, AL_SEC_OFFSET, &playingOffset); + device.alGetSourcedvSOFT(m_sourceId, AL_SEC_OFFSET, &playingOffset); return Time::Seconds(playingOffset); } @@ -79,7 +88,7 @@ namespace Nz #endif { ALfloat playingOffset; - m_library.alGetSourcefv(m_sourceId, AL_SEC_OFFSET, &playingOffset); + device.alGetSourcefv(m_sourceId, AL_SEC_OFFSET, &playingOffset); return Time::Seconds(playingOffset); } @@ -87,20 +96,23 @@ namespace Nz Vector3f OpenALSource::GetPosition() const { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); Vector3f position; - m_library.alGetSourcefv(m_sourceId, AL_POSITION, &position.x); + device.alGetSourcefv(m_sourceId, AL_POSITION, &position.x); return position; } UInt32 OpenALSource::GetSampleOffset() const { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); + ALint samples = 0; - m_library.alGetSourcei(m_sourceId, AL_SAMPLE_OFFSET, &samples); + device.alGetSourcei(m_sourceId, AL_SAMPLE_OFFSET, &samples); return SafeCast(samples); } @@ -111,10 +123,11 @@ namespace Nz #ifdef AL_SOFT_source_latency if (GetDevice().IsExtensionSupported(OpenALExtension::SourceLatency)) { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); std::array values; - m_library.alGetSourcei64vSOFT(m_sourceId, AL_SAMPLE_OFFSET_LATENCY_SOFT, values.data()); + device.alGetSourcei64vSOFT(m_sourceId, AL_SAMPLE_OFFSET_LATENCY_SOFT, values.data()); offsetWithLatency.sampleOffset = ((values[0] & 0xFFFFFFFF00000000) >> 32) * 1'000; offsetWithLatency.sourceLatency = Time::Nanoseconds(values[1] / 1'000); @@ -132,20 +145,22 @@ namespace Nz Vector3f OpenALSource::GetVelocity() const { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); Vector3f velocity; - m_library.alGetSourcefv(m_sourceId, AL_VELOCITY, &velocity.x); + device.alGetSourcefv(m_sourceId, AL_VELOCITY, &velocity.x); return velocity; } SoundStatus OpenALSource::GetStatus() const { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); ALint state; - m_library.alGetSourcei(m_sourceId, AL_SOURCE_STATE, &state); + device.alGetSourcei(m_sourceId, AL_SOURCE_STATE, &state); switch (state) { @@ -168,30 +183,33 @@ namespace Nz float OpenALSource::GetVolume() const { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); ALfloat volume; - m_library.alGetSourcefv(m_sourceId, AL_GAIN, &volume); + device.alGetSourcefv(m_sourceId, AL_GAIN, &volume); return volume; } bool OpenALSource::IsLooping() const { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); ALint looping; - m_library.alGetSourcei(m_sourceId, AL_LOOPING, &looping); + device.alGetSourcei(m_sourceId, AL_LOOPING, &looping); return looping == AL_TRUE; } bool OpenALSource::IsSpatializationEnabled() const { - GetDevice().MakeContextCurrent(); + const OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); ALint relative; - m_library.alGetSourcei(m_sourceId, AL_SOURCE_RELATIVE, &relative); + device.alGetSourcei(m_sourceId, AL_SOURCE_RELATIVE, &relative); return relative == AL_FALSE; } @@ -203,33 +221,38 @@ namespace Nz std::shared_ptr newBuffer = std::static_pointer_cast(std::move(audioBuffer)); - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); + ALuint bufferId = newBuffer->GetBufferId(); - m_library.alSourceQueueBuffers(m_sourceId, 1, &bufferId); + device.alSourceQueueBuffers(m_sourceId, 1, &bufferId); m_queuedBuffers.emplace_back(std::move(newBuffer)); } void OpenALSource::Pause() { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); - m_library.alSourcePause(m_sourceId); + device.alSourcePause(m_sourceId); } void OpenALSource::Play() { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); - m_library.alSourcePlay(m_sourceId); + device.alSourcePlay(m_sourceId); } void OpenALSource::SetAttenuation(float attenuation) { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); - m_library.alSourcef(m_sourceId, AL_ROLLOFF_FACTOR, attenuation); + device.alSourcef(m_sourceId, AL_ROLLOFF_FACTOR, attenuation); } void OpenALSource::SetBuffer(std::shared_ptr audioBuffer) @@ -238,90 +261,100 @@ namespace Nz std::shared_ptr newBuffer = std::static_pointer_cast(std::move(audioBuffer)); - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); if (newBuffer) - m_library.alSourcei(m_sourceId, AL_BUFFER, newBuffer->GetBufferId()); + device.alSourcei(m_sourceId, AL_BUFFER, newBuffer->GetBufferId()); else - m_library.alSourcei(m_sourceId, AL_BUFFER, AL_NONE); + device.alSourcei(m_sourceId, AL_BUFFER, AL_NONE); m_currentBuffer = std::move(newBuffer); } void OpenALSource::SetMinDistance(float minDistance) { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); - m_library.alSourcef(m_sourceId, AL_REFERENCE_DISTANCE, minDistance); + device.alSourcef(m_sourceId, AL_REFERENCE_DISTANCE, minDistance); } void OpenALSource::SetPitch(float pitch) { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); - m_library.alSourcef(m_sourceId, AL_PITCH, pitch); + device.alSourcef(m_sourceId, AL_PITCH, pitch); } void OpenALSource::SetPlayingOffset(Time offset) { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); #ifdef AL_SOFT_source_latency if (GetDevice().IsExtensionSupported(OpenALExtension::SourceLatency)) // alGetSourcedvSOFT has extra precision thanks to double - m_library.alSourcedSOFT(m_sourceId, AL_SEC_OFFSET, offset.AsSeconds()); + device.alSourcedSOFT(m_sourceId, AL_SEC_OFFSET, offset.AsSeconds()); else #endif - m_library.alSourcef(m_sourceId, AL_SEC_OFFSET, offset.AsSeconds()); + device.alSourcef(m_sourceId, AL_SEC_OFFSET, offset.AsSeconds()); } void OpenALSource::SetPosition(const Vector3f& position) { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); - m_library.alSource3f(m_sourceId, AL_POSITION, position.x, position.y, position.z); + device.alSource3f(m_sourceId, AL_POSITION, position.x, position.y, position.z); } void OpenALSource::SetSampleOffset(UInt32 offset) { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); - m_library.alSourcei(m_sourceId, AL_SAMPLE_OFFSET, offset); + device.alSourcei(m_sourceId, AL_SAMPLE_OFFSET, offset); } void OpenALSource::SetVelocity(const Vector3f& velocity) { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); - m_library.alSource3f(m_sourceId, AL_VELOCITY, velocity.x, velocity.y, velocity.z); + device.alSource3f(m_sourceId, AL_VELOCITY, velocity.x, velocity.y, velocity.z); } void OpenALSource::SetVolume(float volume) { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); - m_library.alSourcef(m_sourceId, AL_GAIN, volume); + device.alSourcef(m_sourceId, AL_GAIN, volume); } void OpenALSource::Stop() { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); - m_library.alSourceStop(m_sourceId); + device.alSourceStop(m_sourceId); } std::shared_ptr OpenALSource::TryUnqueueProcessedBuffer() { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); ALint processedCount = 0; - m_library.alGetSourcei(m_sourceId, AL_BUFFERS_PROCESSED, &processedCount); + device.alGetSourcei(m_sourceId, AL_BUFFERS_PROCESSED, &processedCount); if (processedCount == 0) return {}; ALuint bufferId; - m_library.alSourceUnqueueBuffers(m_sourceId, 1, &bufferId); + device.alSourceUnqueueBuffers(m_sourceId, 1, &bufferId); auto it = std::find_if(m_queuedBuffers.begin(), m_queuedBuffers.end(), [=](const std::shared_ptr& alBuffer) { @@ -337,13 +370,14 @@ namespace Nz void OpenALSource::UnqueueAllBuffers() { - GetDevice().MakeContextCurrent(); + OpenALDevice& device = GetDevice(); + device.MakeContextCurrent(); ALint queuedBufferCount = 0; - m_library.alGetSourcei(m_sourceId, AL_BUFFERS_QUEUED, &queuedBufferCount); + device.alGetSourcei(m_sourceId, AL_BUFFERS_QUEUED, &queuedBufferCount); StackArray buffers = NazaraStackArrayNoInit(ALuint, queuedBufferCount); - m_library.alSourceUnqueueBuffers(m_sourceId, queuedBufferCount, buffers.data()); + device.alSourceUnqueueBuffers(m_sourceId, queuedBufferCount, buffers.data()); m_queuedBuffers.clear(); }