Audio: Fix loading of OpenAL extensions (pointers are context-local)
This commit is contained in:
parent
6059f608c0
commit
f75a00efe2
|
|
@ -80,8 +80,6 @@ jobs:
|
||||||
- name: Run unit tests
|
- name: Run unit tests
|
||||||
if: matrix.confs.mode != 'releasedbg'
|
if: matrix.confs.mode != 'releasedbg'
|
||||||
run: xmake run UnitTests
|
run: xmake run UnitTests
|
||||||
env:
|
|
||||||
NAZARA_NO_AUDIO: 1
|
|
||||||
|
|
||||||
# Setup installation configuration
|
# Setup installation configuration
|
||||||
- name: Configure xmake for installation
|
- name: Configure xmake for installation
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ namespace Nz
|
||||||
class NAZARA_AUDIO_API OpenALBuffer final : public AudioBuffer
|
class NAZARA_AUDIO_API OpenALBuffer final : public AudioBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline OpenALBuffer(std::shared_ptr<AudioDevice> device, OpenALLibrary& library, ALuint bufferId);
|
inline OpenALBuffer(std::shared_ptr<AudioDevice> device, ALuint bufferId);
|
||||||
OpenALBuffer(const OpenALBuffer&) = delete;
|
OpenALBuffer(const OpenALBuffer&) = delete;
|
||||||
OpenALBuffer(OpenALBuffer&&) = delete;
|
OpenALBuffer(OpenALBuffer&&) = delete;
|
||||||
~OpenALBuffer();
|
~OpenALBuffer();
|
||||||
|
|
@ -44,7 +44,6 @@ namespace Nz
|
||||||
const OpenALDevice& GetDevice() const;
|
const OpenALDevice& GetDevice() const;
|
||||||
|
|
||||||
ALuint m_bufferId;
|
ALuint m_bufferId;
|
||||||
OpenALLibrary& m_library;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,9 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
inline OpenALBuffer::OpenALBuffer(std::shared_ptr<AudioDevice> device, OpenALLibrary& library, ALuint bufferId) :
|
inline OpenALBuffer::OpenALBuffer(std::shared_ptr<AudioDevice> device, ALuint bufferId) :
|
||||||
AudioBuffer(std::move(device)),
|
AudioBuffer(std::move(device)),
|
||||||
m_bufferId(bufferId),
|
m_bufferId(bufferId)
|
||||||
m_library(library)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,13 @@ namespace Nz
|
||||||
Max = SourceLatency
|
Max = SourceLatency
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using ALFunction = void(*)(void);
|
||||||
|
|
||||||
class NAZARA_AUDIO_API OpenALDevice : public AudioDevice
|
class NAZARA_AUDIO_API OpenALDevice : public AudioDevice
|
||||||
{
|
{
|
||||||
friend OpenALLibrary;
|
friend OpenALLibrary;
|
||||||
|
struct SymbolLoader;
|
||||||
|
friend SymbolLoader;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OpenALDevice(OpenALLibrary& library, ALCdevice* device);
|
OpenALDevice(OpenALLibrary& library, ALCdevice* device);
|
||||||
|
|
@ -41,11 +45,18 @@ namespace Nz
|
||||||
OpenALDevice(OpenALDevice&&) = delete;
|
OpenALDevice(OpenALDevice&&) = delete;
|
||||||
~OpenALDevice();
|
~OpenALDevice();
|
||||||
|
|
||||||
|
bool ClearErrorFlag() const;
|
||||||
|
|
||||||
std::shared_ptr<AudioBuffer> CreateBuffer() override;
|
std::shared_ptr<AudioBuffer> CreateBuffer() override;
|
||||||
std::shared_ptr<AudioSource> CreateSource() override;
|
std::shared_ptr<AudioSource> CreateSource() override;
|
||||||
|
|
||||||
|
inline bool DidLastCallSucceed() const;
|
||||||
|
|
||||||
float GetDopplerFactor() const override;
|
float GetDopplerFactor() const override;
|
||||||
|
inline ALFunction GetFunctionByIndex(std::size_t funcIndex) const;
|
||||||
float GetGlobalVolume() const override;
|
float GetGlobalVolume() const override;
|
||||||
|
inline OpenALLibrary& GetLibrary();
|
||||||
|
inline const OpenALLibrary& GetLibrary() const;
|
||||||
Vector3f GetListenerDirection(Vector3f* up = nullptr) const override;
|
Vector3f GetListenerDirection(Vector3f* up = nullptr) const override;
|
||||||
Vector3f GetListenerPosition() const override;
|
Vector3f GetListenerPosition() const override;
|
||||||
Quaternionf GetListenerRotation() const override;
|
Quaternionf GetListenerRotation() const override;
|
||||||
|
|
@ -58,6 +69,9 @@ namespace Nz
|
||||||
|
|
||||||
void MakeContextCurrent() const;
|
void MakeContextCurrent() const;
|
||||||
|
|
||||||
|
template<typename... Args> void PrintFunctionCall(std::size_t funcIndex, Args... args) const;
|
||||||
|
bool ProcessErrorFlag() const;
|
||||||
|
|
||||||
void SetDopplerFactor(float dopplerFactor) override;
|
void SetDopplerFactor(float dopplerFactor) override;
|
||||||
void SetGlobalVolume(float volume) override;
|
void SetGlobalVolume(float volume) override;
|
||||||
void SetListenerDirection(const Vector3f& direction, const Vector3f& up = Vector3f::Up()) 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=(const OpenALDevice&) = delete;
|
||||||
OpenALDevice& operator=(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 <Nazara/Audio/OpenALFunctions.hpp>
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EnumArray<AudioFormat, ALenum> m_audioFormatValues;
|
enum class FunctionIndex
|
||||||
EnumArray<OpenALExtension, ALenum> m_extensionStatus;
|
{
|
||||||
|
#define NAZARA_AUDIO_AL_ALC_FUNCTION(name) name,
|
||||||
|
#include <Nazara/Audio/OpenALFunctions.hpp>
|
||||||
|
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
|
std::array<ALFunction, UnderlyingCast(FunctionIndex::Count)> m_originalFunctionPointer;
|
||||||
std::string m_renderer;
|
std::string m_renderer;
|
||||||
std::string m_vendor;
|
std::string m_vendor;
|
||||||
|
EnumArray<AudioFormat, ALenum> m_audioFormatValues;
|
||||||
|
EnumArray<OpenALExtension, ALenum> m_extensionStatus;
|
||||||
OpenALLibrary& m_library;
|
OpenALLibrary& m_library;
|
||||||
MovablePtr<ALCcontext> m_context;
|
MovablePtr<ALCcontext> m_context;
|
||||||
MovablePtr<ALCdevice> m_device;
|
MovablePtr<ALCdevice> m_device;
|
||||||
|
mutable bool m_didCollectErrors;
|
||||||
|
mutable bool m_hadAnyError;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,30 @@
|
||||||
|
|
||||||
namespace Nz
|
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
|
inline bool OpenALDevice::IsExtensionSupported(OpenALExtension extension) const
|
||||||
{
|
{
|
||||||
return m_extensionStatus[extension];
|
return m_extensionStatus[extension];
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ namespace Nz
|
||||||
OpenALLibrary& operator=(OpenALLibrary&&) = delete;
|
OpenALLibrary& operator=(OpenALLibrary&&) = delete;
|
||||||
|
|
||||||
#define NAZARA_AUDIO_AL_ALC_FUNCTION(name) decltype(&::name) name;
|
#define NAZARA_AUDIO_AL_ALC_FUNCTION(name) decltype(&::name) name;
|
||||||
|
#define NAZARA_AUDIO_AL_EXT_FUNCTION(name)
|
||||||
#include <Nazara/Audio/OpenALFunctions.hpp>
|
#include <Nazara/Audio/OpenALFunctions.hpp>
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Nz
|
||||||
class NAZARA_AUDIO_API OpenALSource final : public AudioSource
|
class NAZARA_AUDIO_API OpenALSource final : public AudioSource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline OpenALSource(std::shared_ptr<AudioDevice> device, OpenALLibrary& library, ALuint sourceId);
|
inline OpenALSource(std::shared_ptr<AudioDevice> device, ALuint sourceId);
|
||||||
OpenALSource(const OpenALSource&) = delete;
|
OpenALSource(const OpenALSource&) = delete;
|
||||||
OpenALSource(OpenALSource&&) = delete;
|
OpenALSource(OpenALSource&&) = delete;
|
||||||
~OpenALSource();
|
~OpenALSource();
|
||||||
|
|
@ -76,7 +76,6 @@ namespace Nz
|
||||||
std::shared_ptr<OpenALBuffer> m_currentBuffer;
|
std::shared_ptr<OpenALBuffer> m_currentBuffer;
|
||||||
std::vector<std::shared_ptr<OpenALBuffer>> m_queuedBuffers;
|
std::vector<std::shared_ptr<OpenALBuffer>> m_queuedBuffers;
|
||||||
ALuint m_sourceId;
|
ALuint m_sourceId;
|
||||||
OpenALLibrary& m_library;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,9 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
inline OpenALSource::OpenALSource(std::shared_ptr<AudioDevice> device, OpenALLibrary& library, ALuint sourceId) :
|
inline OpenALSource::OpenALSource(std::shared_ptr<AudioDevice> device, ALuint sourceId) :
|
||||||
AudioSource(std::move(device)),
|
AudioSource(std::move(device)),
|
||||||
m_sourceId(sourceId),
|
m_sourceId(sourceId)
|
||||||
m_library(library)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,20 @@ namespace Nz
|
||||||
{
|
{
|
||||||
OpenALBuffer::~OpenALBuffer()
|
OpenALBuffer::~OpenALBuffer()
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
m_library.alDeleteBuffers(1, &m_bufferId);
|
device.alDeleteBuffers(1, &m_bufferId);
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt64 OpenALBuffer::GetSampleCount() const
|
UInt64 OpenALBuffer::GetSampleCount() const
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
ALint bits, size;
|
ALint bits, size;
|
||||||
m_library.alGetBufferi(m_bufferId, AL_BITS, &bits);
|
device.alGetBufferi(m_bufferId, AL_BITS, &bits);
|
||||||
m_library.alGetBufferi(m_bufferId, AL_SIZE, &size);
|
device.alGetBufferi(m_bufferId, AL_SIZE, &size);
|
||||||
|
|
||||||
UInt64 sampleCount = 0;
|
UInt64 sampleCount = 0;
|
||||||
if (bits != 0)
|
if (bits != 0)
|
||||||
|
|
@ -34,20 +36,22 @@ namespace Nz
|
||||||
|
|
||||||
UInt64 OpenALBuffer::GetSize() const
|
UInt64 OpenALBuffer::GetSize() const
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
ALint size;
|
ALint size;
|
||||||
m_library.alGetBufferi(m_bufferId, AL_SIZE, &size);
|
device.alGetBufferi(m_bufferId, AL_SIZE, &size);
|
||||||
|
|
||||||
return SafeCast<UInt64>(size);
|
return SafeCast<UInt64>(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 OpenALBuffer::GetSampleRate() const
|
UInt32 OpenALBuffer::GetSampleRate() const
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
ALint sampleRate;
|
ALint sampleRate;
|
||||||
m_library.alGetBufferi(m_bufferId, AL_FREQUENCY, &sampleRate);
|
device.alGetBufferi(m_bufferId, AL_FREQUENCY, &sampleRate);
|
||||||
|
|
||||||
return SafeCast<UInt32>(sampleRate);
|
return SafeCast<UInt32>(sampleRate);
|
||||||
}
|
}
|
||||||
|
|
@ -55,7 +59,7 @@ namespace Nz
|
||||||
bool OpenALBuffer::IsCompatibleWith(const AudioDevice& device) const
|
bool OpenALBuffer::IsCompatibleWith(const AudioDevice& device) const
|
||||||
{
|
{
|
||||||
// OpenAL buffers are shared among contexts and thus devices
|
// 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)
|
bool OpenALBuffer::Reset(AudioFormat format, UInt64 sampleCount, UInt32 sampleRate, const void* samples)
|
||||||
|
|
@ -72,11 +76,11 @@ namespace Nz
|
||||||
device.MakeContextCurrent();
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
// We empty the error stack
|
// 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<ALsizei>(sampleCount * sizeof(Int16)), SafeCast<ALsizei>(sampleRate));
|
device.alBufferData(m_bufferId, alFormat, samples, SafeCast<ALsizei>(sampleCount * sizeof(Int16)), SafeCast<ALsizei>(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));
|
NazaraErrorFmt("failed to reset OpenAL buffer: {0}", std::to_string(lastError));
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -7,29 +7,134 @@
|
||||||
#include <Nazara/Audio/OpenALLibrary.hpp>
|
#include <Nazara/Audio/OpenALLibrary.hpp>
|
||||||
#include <Nazara/Audio/OpenALSource.hpp>
|
#include <Nazara/Audio/OpenALSource.hpp>
|
||||||
#include <Nazara/Audio/OpenALUtils.hpp>
|
#include <Nazara/Audio/OpenALUtils.hpp>
|
||||||
|
#include <Nazara/Core/Log.hpp>
|
||||||
|
#include <NazaraUtils/Algorithm.hpp>
|
||||||
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <Nazara/Audio/Debug.hpp>
|
#include <Nazara/Audio/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
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 <Nazara/Audio/OpenALFunctions.hpp>
|
||||||
|
};
|
||||||
|
|
||||||
|
thread_local const OpenALDevice* s_currentALDevice;
|
||||||
|
|
||||||
|
template<typename FuncType, std::size_t FuncIndex, typename>
|
||||||
|
struct ALWrapper;
|
||||||
|
|
||||||
|
template<typename FuncType, std::size_t FuncIndex, typename Ret, typename... Args>
|
||||||
|
struct ALWrapper<FuncType, FuncIndex, Ret(AL_APIENTRY*)(Args...)>
|
||||||
|
{
|
||||||
|
static auto WrapErrorHandling()
|
||||||
|
{
|
||||||
|
return [](Args... args) -> Ret
|
||||||
|
{
|
||||||
|
const OpenALDevice* device = s_currentALDevice; //< pay TLS cost once
|
||||||
|
assert(device);
|
||||||
|
|
||||||
|
FuncType funcPtr = reinterpret_cast<FuncType>(device->GetFunctionByIndex(FuncIndex));
|
||||||
|
|
||||||
|
if constexpr (std::is_same_v<Ret, void>)
|
||||||
|
{
|
||||||
|
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<typename FuncType, std::size_t FuncIndex, bool ContextFunction, typename Func>
|
||||||
|
bool Load(Func& func, const char* funcName, FuncType libraryPtr)
|
||||||
|
{
|
||||||
|
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||||
|
|
||||||
|
ALFunction originalFuncPtr;
|
||||||
|
if constexpr (ContextFunction)
|
||||||
|
originalFuncPtr = BitCast<ALFunction>(device.m_library.alcGetProcAddress(device.m_device, funcName));
|
||||||
|
else
|
||||||
|
originalFuncPtr = BitCast<ALFunction>(device.m_library.alGetProcAddress(funcName));
|
||||||
|
|
||||||
|
// Fallback in case of faulty OpenAL implementations not returning core functions through alGetProcAddress/alcGetProcAddress
|
||||||
|
if (!originalFuncPtr)
|
||||||
|
originalFuncPtr = reinterpret_cast<ALFunction>(libraryPtr);
|
||||||
|
|
||||||
|
func = reinterpret_cast<FuncType>(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<FuncType, FuncIndex, FuncType>;
|
||||||
|
func = Wrapper::WrapErrorHandling();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
device.m_originalFunctionPointer[FuncIndex] = originalFuncPtr;
|
||||||
|
|
||||||
|
return func != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenALDevice& device;
|
||||||
|
bool wrapErrorHandling = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
OpenALDevice::OpenALDevice(OpenALLibrary& library, ALCdevice* device) :
|
OpenALDevice::OpenALDevice(OpenALLibrary& library, ALCdevice* device) :
|
||||||
m_library(library),
|
m_library(library),
|
||||||
m_device(device)
|
m_device(device)
|
||||||
{
|
{
|
||||||
|
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||||
|
|
||||||
m_context = m_library.alcCreateContext(device, nullptr);
|
m_context = m_library.alcCreateContext(device, nullptr);
|
||||||
if (!m_context)
|
if (!m_context)
|
||||||
throw std::runtime_error("failed to create OpenAL 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<const char*>(m_library.alGetString(AL_RENDERER));
|
s_currentALDevice = this;
|
||||||
m_vendor = reinterpret_cast<const char*>(m_library.alGetString(AL_VENDOR));
|
|
||||||
|
SymbolLoader loader(*this);
|
||||||
|
#ifdef NAZARA_DEBUG
|
||||||
|
loader.wrapErrorHandling = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NAZARA_AUDIO_AL_FUNCTION(name) loader.Load<decltype(&::name), UnderlyingCast(FunctionIndex:: name), false>(name, #name, library.name);
|
||||||
|
#define NAZARA_AUDIO_ALC_FUNCTION(name) loader.Load<decltype(&::name), UnderlyingCast(FunctionIndex:: name), true>(name, #name, library.name);
|
||||||
|
#define NAZARA_AUDIO_AL_EXT_FUNCTION(name) loader.Load<decltype(&::name), UnderlyingCast(FunctionIndex:: name), false>(name, #name, nullptr);
|
||||||
|
#include <Nazara/Audio/OpenALFunctions.hpp>
|
||||||
|
|
||||||
|
m_renderer = reinterpret_cast<const char*>(alGetString(AL_RENDERER));
|
||||||
|
m_vendor = reinterpret_cast<const char*>(alGetString(AL_VENDOR));
|
||||||
|
|
||||||
// We complete the formats table
|
// We complete the formats table
|
||||||
m_audioFormatValues.fill(0);
|
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."
|
// "The presence of an enum value does not guarantee the applicability of an extension to the current context."
|
||||||
if (library.alIsExtensionPresent("AL_EXT_MCFORMATS"))
|
if (library.alIsExtensionPresent("AL_EXT_MCFORMATS"))
|
||||||
{
|
{
|
||||||
m_audioFormatValues[AudioFormat::I16_Quad] = m_library.alGetEnumValue("AL_FORMAT_QUAD16");
|
m_audioFormatValues[AudioFormat::I16_Quad] = alGetEnumValue("AL_FORMAT_QUAD16");
|
||||||
m_audioFormatValues[AudioFormat::I16_5_1] = m_library.alGetEnumValue("AL_FORMAT_51CHN16");
|
m_audioFormatValues[AudioFormat::I16_5_1] = alGetEnumValue("AL_FORMAT_51CHN16");
|
||||||
m_audioFormatValues[AudioFormat::I16_6_1] = m_library.alGetEnumValue("AL_FORMAT_61CHN16");
|
m_audioFormatValues[AudioFormat::I16_6_1] = alGetEnumValue("AL_FORMAT_61CHN16");
|
||||||
m_audioFormatValues[AudioFormat::I16_7_1] = m_library.alGetEnumValue("AL_FORMAT_71CHN16");
|
m_audioFormatValues[AudioFormat::I16_7_1] = alGetEnumValue("AL_FORMAT_71CHN16");
|
||||||
}
|
}
|
||||||
else if (library.alIsExtensionPresent("AL_LOKI_quadriphonic"))
|
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);
|
m_extensionStatus.fill(false);
|
||||||
if (library.alIsExtensionPresent("AL_SOFT_source_latency"))
|
if (library.alIsExtensionPresent("AL_SOFT_source_latency"))
|
||||||
|
|
@ -57,49 +162,65 @@ namespace Nz
|
||||||
|
|
||||||
OpenALDevice::~OpenALDevice()
|
OpenALDevice::~OpenALDevice()
|
||||||
{
|
{
|
||||||
|
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||||
|
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
m_library.alcDestroyContext(m_context);
|
alcDestroyContext(m_context);
|
||||||
m_library.alcCloseDevice(m_device);
|
alcCloseDevice(m_device);
|
||||||
|
|
||||||
if (s_currentContext == m_context)
|
if (s_currentALDevice == this)
|
||||||
s_currentContext = nullptr;
|
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<AudioBuffer> OpenALDevice::CreateBuffer()
|
std::shared_ptr<AudioBuffer> OpenALDevice::CreateBuffer()
|
||||||
{
|
{
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
m_library.alGetError(); // Clear error flags
|
ClearErrorFlag();
|
||||||
|
|
||||||
ALuint bufferId = 0;
|
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 {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<OpenALBuffer>(shared_from_this(), m_library, bufferId);
|
return std::make_shared<OpenALBuffer>(shared_from_this(), bufferId);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<AudioSource> OpenALDevice::CreateSource()
|
std::shared_ptr<AudioSource> OpenALDevice::CreateSource()
|
||||||
{
|
{
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
m_library.alGetError(); // Clear error flags
|
ClearErrorFlag();
|
||||||
|
|
||||||
ALuint sourceId = 0;
|
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 {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<OpenALSource>(shared_from_this(), m_library, sourceId);
|
return std::make_shared<OpenALSource>(shared_from_this(), sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -110,7 +231,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
return m_library.alGetFloat(AL_DOPPLER_FACTOR);
|
return alGetFloat(AL_DOPPLER_FACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -122,7 +243,7 @@ namespace Nz
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
ALfloat gain = 0.f;
|
ALfloat gain = 0.f;
|
||||||
m_library.alGetListenerf(AL_GAIN, &gain);
|
alGetListenerf(AL_GAIN, &gain);
|
||||||
|
|
||||||
return gain;
|
return gain;
|
||||||
}
|
}
|
||||||
|
|
@ -140,7 +261,7 @@ namespace Nz
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
ALfloat orientation[6];
|
ALfloat orientation[6];
|
||||||
m_library.alGetListenerfv(AL_ORIENTATION, orientation);
|
alGetListenerfv(AL_ORIENTATION, orientation);
|
||||||
|
|
||||||
if (up)
|
if (up)
|
||||||
(*up) = Vector3f(orientation[3], orientation[4], orientation[5]);
|
(*up) = Vector3f(orientation[3], orientation[4], orientation[5]);
|
||||||
|
|
@ -159,7 +280,7 @@ namespace Nz
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
Vector3f position;
|
Vector3f position;
|
||||||
m_library.alGetListenerfv(AL_POSITION, &position.x);
|
alGetListenerfv(AL_POSITION, &position.x);
|
||||||
|
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
@ -177,7 +298,7 @@ namespace Nz
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
ALfloat orientation[6];
|
ALfloat orientation[6];
|
||||||
m_library.alGetListenerfv(AL_ORIENTATION, orientation);
|
alGetListenerfv(AL_ORIENTATION, orientation);
|
||||||
|
|
||||||
Vector3f forward(orientation[0], orientation[1], orientation[2]);
|
Vector3f forward(orientation[0], orientation[1], orientation[2]);
|
||||||
Vector3f up(orientation[3], orientation[4], orientation[5]);
|
Vector3f up(orientation[3], orientation[4], orientation[5]);
|
||||||
|
|
@ -196,20 +317,68 @@ namespace Nz
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
Vector3f velocity;
|
Vector3f velocity;
|
||||||
m_library.alGetListenerfv(AL_VELOCITY, &velocity.x);
|
alGetListenerfv(AL_VELOCITY, &velocity.x);
|
||||||
|
|
||||||
return velocity;
|
return velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALDevice::MakeContextCurrent() const
|
void OpenALDevice::MakeContextCurrent() const
|
||||||
{
|
{
|
||||||
if (s_currentContext != m_context)
|
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||||
|
|
||||||
|
if (s_currentALDevice != this)
|
||||||
{
|
{
|
||||||
m_library.alcMakeContextCurrent(m_context);
|
m_library.alcMakeContextCurrent(m_context);
|
||||||
s_currentContext = m_context;
|
s_currentALDevice = this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
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
|
* \brief Gets the speed of sound
|
||||||
* \return Speed of sound
|
* \return Speed of sound
|
||||||
|
|
@ -218,7 +387,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
return m_library.alGetFloat(AL_SPEED_OF_SOUND);
|
return alGetFloat(AL_SPEED_OF_SOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
const void* OpenALDevice::GetSubSystemIdentifier() const
|
const void* OpenALDevice::GetSubSystemIdentifier() const
|
||||||
|
|
@ -249,7 +418,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
m_library.alDopplerFactor(dopplerFactor);
|
alDopplerFactor(dopplerFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -261,7 +430,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
m_library.alListenerf(AL_GAIN, volume);
|
alListenerf(AL_GAIN, volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -282,7 +451,7 @@ namespace Nz
|
||||||
up.x, up.y, up.z
|
up.x, up.y, up.z
|
||||||
};
|
};
|
||||||
|
|
||||||
m_library.alListenerfv(AL_ORIENTATION, orientation);
|
alListenerfv(AL_ORIENTATION, orientation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -296,7 +465,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
m_library.alListenerfv(AL_POSITION, &position.x);
|
alListenerfv(AL_POSITION, &position.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -310,7 +479,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
m_library.alListenerfv(AL_VELOCITY, &velocity.x);
|
alListenerfv(AL_VELOCITY, &velocity.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -322,6 +491,6 @@ namespace Nz
|
||||||
{
|
{
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
m_library.alSpeedOfSound(speed);
|
alSpeedOfSound(speed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,6 @@ namespace Nz
|
||||||
|
|
||||||
auto PostLoad = [&]
|
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<decltype(&::name)>(alGetProcAddress(#name));
|
|
||||||
#include <Nazara/Audio/OpenALFunctions.hpp>
|
|
||||||
|
|
||||||
m_hasCaptureSupport = alcIsExtensionPresent(nullptr, "ALC_EXT_CAPTURE");
|
m_hasCaptureSupport = alcIsExtensionPresent(nullptr, "ALC_EXT_CAPTURE");
|
||||||
m_isLoaded = true;
|
m_isLoaded = true;
|
||||||
|
|
||||||
|
|
@ -79,8 +72,6 @@ namespace Nz
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#define NAZARA_AUDIO_AL_ALC_FUNCTION(name) name = reinterpret_cast<decltype(&::name)>(LoadSymbol(#name, false));
|
#define NAZARA_AUDIO_AL_ALC_FUNCTION(name) name = reinterpret_cast<decltype(&::name)>(LoadSymbol(#name, false));
|
||||||
#define NAZARA_AUDIO_AL_EXT_BEGIN(name)
|
|
||||||
#define NAZARA_AUDIO_AL_EXT_END(name)
|
|
||||||
#define NAZARA_AUDIO_AL_EXT_FUNCTION(name)
|
#define NAZARA_AUDIO_AL_EXT_FUNCTION(name)
|
||||||
#include <Nazara/Audio/OpenALFunctions.hpp>
|
#include <Nazara/Audio/OpenALFunctions.hpp>
|
||||||
}
|
}
|
||||||
|
|
@ -104,8 +95,6 @@ namespace Nz
|
||||||
|
|
||||||
// Load core
|
// Load core
|
||||||
#define NAZARA_AUDIO_AL_ALC_FUNCTION(name) name = &::name;
|
#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)
|
#define NAZARA_AUDIO_AL_EXT_FUNCTION(name)
|
||||||
#include <Nazara/Audio/OpenALFunctions.hpp>
|
#include <Nazara/Audio/OpenALFunctions.hpp>
|
||||||
|
|
||||||
|
|
@ -142,6 +131,7 @@ namespace Nz
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#define NAZARA_AUDIO_AL_ALC_FUNCTION(name) name = nullptr;
|
#define NAZARA_AUDIO_AL_ALC_FUNCTION(name) name = nullptr;
|
||||||
|
#define NAZARA_AUDIO_AL_EXT_FUNCTION(name)
|
||||||
#include <Nazara/Audio/OpenALFunctions.hpp>
|
#include <Nazara/Audio/OpenALFunctions.hpp>
|
||||||
|
|
||||||
m_library.Unload();
|
m_library.Unload();
|
||||||
|
|
|
||||||
|
|
@ -15,63 +15,72 @@ namespace Nz
|
||||||
{
|
{
|
||||||
OpenALSource::~OpenALSource()
|
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)
|
void OpenALSource::EnableLooping(bool loop)
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
OpenALDevice& device = GetDevice();
|
||||||
m_library.alSourcei(m_sourceId, AL_LOOPING, loop);
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
|
device.alSourcei(m_sourceId, AL_LOOPING, loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALSource::EnableSpatialization(bool spatialization)
|
void OpenALSource::EnableSpatialization(bool spatialization)
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
OpenALDevice& device = GetDevice();
|
||||||
m_library.alSourcei(m_sourceId, AL_SOURCE_RELATIVE, !spatialization);
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
|
device.alSourcei(m_sourceId, AL_SOURCE_RELATIVE, !spatialization);
|
||||||
}
|
}
|
||||||
|
|
||||||
float OpenALSource::GetAttenuation() const
|
float OpenALSource::GetAttenuation() const
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
ALfloat attenuation;
|
ALfloat attenuation;
|
||||||
m_library.alGetSourcefv(m_sourceId, AL_ROLLOFF_FACTOR, &attenuation);
|
device.alGetSourcefv(m_sourceId, AL_ROLLOFF_FACTOR, &attenuation);
|
||||||
|
|
||||||
return attenuation;
|
return attenuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
float OpenALSource::GetMinDistance() const
|
float OpenALSource::GetMinDistance() const
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
ALfloat minDistance;
|
ALfloat minDistance;
|
||||||
m_library.alGetSourcefv(m_sourceId, AL_REFERENCE_DISTANCE, &minDistance);
|
device.alGetSourcefv(m_sourceId, AL_REFERENCE_DISTANCE, &minDistance);
|
||||||
|
|
||||||
return minDistance;
|
return minDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
float OpenALSource::GetPitch() const
|
float OpenALSource::GetPitch() const
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
ALfloat pitch;
|
ALfloat pitch;
|
||||||
m_library.alGetSourcefv(m_sourceId, AL_PITCH, &pitch);
|
device.alGetSourcefv(m_sourceId, AL_PITCH, &pitch);
|
||||||
|
|
||||||
return pitch;
|
return pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
Time OpenALSource::GetPlayingOffset() const
|
Time OpenALSource::GetPlayingOffset() const
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
#ifdef AL_SOFT_source_latency
|
#ifdef AL_SOFT_source_latency
|
||||||
if (GetDevice().IsExtensionSupported(OpenALExtension::SourceLatency))
|
if (GetDevice().IsExtensionSupported(OpenALExtension::SourceLatency))
|
||||||
{
|
{
|
||||||
// alGetSourcedvSOFT has extra precision thanks to double
|
// alGetSourcedvSOFT has extra precision thanks to double
|
||||||
ALdouble playingOffset;
|
ALdouble playingOffset;
|
||||||
m_library.alGetSourcedvSOFT(m_sourceId, AL_SEC_OFFSET, &playingOffset);
|
device.alGetSourcedvSOFT(m_sourceId, AL_SEC_OFFSET, &playingOffset);
|
||||||
|
|
||||||
return Time::Seconds(playingOffset);
|
return Time::Seconds(playingOffset);
|
||||||
}
|
}
|
||||||
|
|
@ -79,7 +88,7 @@ namespace Nz
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
ALfloat playingOffset;
|
ALfloat playingOffset;
|
||||||
m_library.alGetSourcefv(m_sourceId, AL_SEC_OFFSET, &playingOffset);
|
device.alGetSourcefv(m_sourceId, AL_SEC_OFFSET, &playingOffset);
|
||||||
|
|
||||||
return Time::Seconds(playingOffset);
|
return Time::Seconds(playingOffset);
|
||||||
}
|
}
|
||||||
|
|
@ -87,20 +96,23 @@ namespace Nz
|
||||||
|
|
||||||
Vector3f OpenALSource::GetPosition() const
|
Vector3f OpenALSource::GetPosition() const
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
Vector3f position;
|
Vector3f position;
|
||||||
m_library.alGetSourcefv(m_sourceId, AL_POSITION, &position.x);
|
device.alGetSourcefv(m_sourceId, AL_POSITION, &position.x);
|
||||||
|
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 OpenALSource::GetSampleOffset() const
|
UInt32 OpenALSource::GetSampleOffset() const
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
|
|
||||||
ALint samples = 0;
|
ALint samples = 0;
|
||||||
m_library.alGetSourcei(m_sourceId, AL_SAMPLE_OFFSET, &samples);
|
device.alGetSourcei(m_sourceId, AL_SAMPLE_OFFSET, &samples);
|
||||||
|
|
||||||
return SafeCast<UInt32>(samples);
|
return SafeCast<UInt32>(samples);
|
||||||
}
|
}
|
||||||
|
|
@ -111,10 +123,11 @@ namespace Nz
|
||||||
#ifdef AL_SOFT_source_latency
|
#ifdef AL_SOFT_source_latency
|
||||||
if (GetDevice().IsExtensionSupported(OpenALExtension::SourceLatency))
|
if (GetDevice().IsExtensionSupported(OpenALExtension::SourceLatency))
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
std::array<ALint64SOFT, 2> values;
|
std::array<ALint64SOFT, 2> 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.sampleOffset = ((values[0] & 0xFFFFFFFF00000000) >> 32) * 1'000;
|
||||||
offsetWithLatency.sourceLatency = Time::Nanoseconds(values[1] / 1'000);
|
offsetWithLatency.sourceLatency = Time::Nanoseconds(values[1] / 1'000);
|
||||||
|
|
@ -132,20 +145,22 @@ namespace Nz
|
||||||
|
|
||||||
Vector3f OpenALSource::GetVelocity() const
|
Vector3f OpenALSource::GetVelocity() const
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
Vector3f velocity;
|
Vector3f velocity;
|
||||||
m_library.alGetSourcefv(m_sourceId, AL_VELOCITY, &velocity.x);
|
device.alGetSourcefv(m_sourceId, AL_VELOCITY, &velocity.x);
|
||||||
|
|
||||||
return velocity;
|
return velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundStatus OpenALSource::GetStatus() const
|
SoundStatus OpenALSource::GetStatus() const
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
ALint state;
|
ALint state;
|
||||||
m_library.alGetSourcei(m_sourceId, AL_SOURCE_STATE, &state);
|
device.alGetSourcei(m_sourceId, AL_SOURCE_STATE, &state);
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
|
|
@ -168,30 +183,33 @@ namespace Nz
|
||||||
|
|
||||||
float OpenALSource::GetVolume() const
|
float OpenALSource::GetVolume() const
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
ALfloat volume;
|
ALfloat volume;
|
||||||
m_library.alGetSourcefv(m_sourceId, AL_GAIN, &volume);
|
device.alGetSourcefv(m_sourceId, AL_GAIN, &volume);
|
||||||
|
|
||||||
return volume;
|
return volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenALSource::IsLooping() const
|
bool OpenALSource::IsLooping() const
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
ALint looping;
|
ALint looping;
|
||||||
m_library.alGetSourcei(m_sourceId, AL_LOOPING, &looping);
|
device.alGetSourcei(m_sourceId, AL_LOOPING, &looping);
|
||||||
|
|
||||||
return looping == AL_TRUE;
|
return looping == AL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenALSource::IsSpatializationEnabled() const
|
bool OpenALSource::IsSpatializationEnabled() const
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
const OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
ALint relative;
|
ALint relative;
|
||||||
m_library.alGetSourcei(m_sourceId, AL_SOURCE_RELATIVE, &relative);
|
device.alGetSourcei(m_sourceId, AL_SOURCE_RELATIVE, &relative);
|
||||||
|
|
||||||
return relative == AL_FALSE;
|
return relative == AL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
@ -203,33 +221,38 @@ namespace Nz
|
||||||
|
|
||||||
std::shared_ptr<OpenALBuffer> newBuffer = std::static_pointer_cast<OpenALBuffer>(std::move(audioBuffer));
|
std::shared_ptr<OpenALBuffer> newBuffer = std::static_pointer_cast<OpenALBuffer>(std::move(audioBuffer));
|
||||||
|
|
||||||
GetDevice().MakeContextCurrent();
|
OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
|
|
||||||
ALuint bufferId = newBuffer->GetBufferId();
|
ALuint bufferId = newBuffer->GetBufferId();
|
||||||
m_library.alSourceQueueBuffers(m_sourceId, 1, &bufferId);
|
device.alSourceQueueBuffers(m_sourceId, 1, &bufferId);
|
||||||
|
|
||||||
m_queuedBuffers.emplace_back(std::move(newBuffer));
|
m_queuedBuffers.emplace_back(std::move(newBuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALSource::Pause()
|
void OpenALSource::Pause()
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
m_library.alSourcePause(m_sourceId);
|
device.alSourcePause(m_sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALSource::Play()
|
void OpenALSource::Play()
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
m_library.alSourcePlay(m_sourceId);
|
device.alSourcePlay(m_sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALSource::SetAttenuation(float attenuation)
|
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> audioBuffer)
|
void OpenALSource::SetBuffer(std::shared_ptr<AudioBuffer> audioBuffer)
|
||||||
|
|
@ -238,90 +261,100 @@ namespace Nz
|
||||||
|
|
||||||
std::shared_ptr<OpenALBuffer> newBuffer = std::static_pointer_cast<OpenALBuffer>(std::move(audioBuffer));
|
std::shared_ptr<OpenALBuffer> newBuffer = std::static_pointer_cast<OpenALBuffer>(std::move(audioBuffer));
|
||||||
|
|
||||||
GetDevice().MakeContextCurrent();
|
OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
if (newBuffer)
|
if (newBuffer)
|
||||||
m_library.alSourcei(m_sourceId, AL_BUFFER, newBuffer->GetBufferId());
|
device.alSourcei(m_sourceId, AL_BUFFER, newBuffer->GetBufferId());
|
||||||
else
|
else
|
||||||
m_library.alSourcei(m_sourceId, AL_BUFFER, AL_NONE);
|
device.alSourcei(m_sourceId, AL_BUFFER, AL_NONE);
|
||||||
|
|
||||||
m_currentBuffer = std::move(newBuffer);
|
m_currentBuffer = std::move(newBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALSource::SetMinDistance(float minDistance)
|
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)
|
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)
|
void OpenALSource::SetPlayingOffset(Time offset)
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
#ifdef AL_SOFT_source_latency
|
#ifdef AL_SOFT_source_latency
|
||||||
if (GetDevice().IsExtensionSupported(OpenALExtension::SourceLatency))
|
if (GetDevice().IsExtensionSupported(OpenALExtension::SourceLatency))
|
||||||
// alGetSourcedvSOFT has extra precision thanks to double
|
// alGetSourcedvSOFT has extra precision thanks to double
|
||||||
m_library.alSourcedSOFT(m_sourceId, AL_SEC_OFFSET, offset.AsSeconds<ALdouble>());
|
device.alSourcedSOFT(m_sourceId, AL_SEC_OFFSET, offset.AsSeconds<ALdouble>());
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
m_library.alSourcef(m_sourceId, AL_SEC_OFFSET, offset.AsSeconds<ALfloat>());
|
device.alSourcef(m_sourceId, AL_SEC_OFFSET, offset.AsSeconds<ALfloat>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALSource::SetPosition(const Vector3f& position)
|
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)
|
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)
|
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)
|
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()
|
void OpenALSource::Stop()
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
m_library.alSourceStop(m_sourceId);
|
device.alSourceStop(m_sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<AudioBuffer> OpenALSource::TryUnqueueProcessedBuffer()
|
std::shared_ptr<AudioBuffer> OpenALSource::TryUnqueueProcessedBuffer()
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
ALint processedCount = 0;
|
ALint processedCount = 0;
|
||||||
m_library.alGetSourcei(m_sourceId, AL_BUFFERS_PROCESSED, &processedCount);
|
device.alGetSourcei(m_sourceId, AL_BUFFERS_PROCESSED, &processedCount);
|
||||||
|
|
||||||
if (processedCount == 0)
|
if (processedCount == 0)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
ALuint bufferId;
|
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<OpenALBuffer>& alBuffer)
|
auto it = std::find_if(m_queuedBuffers.begin(), m_queuedBuffers.end(), [=](const std::shared_ptr<OpenALBuffer>& alBuffer)
|
||||||
{
|
{
|
||||||
|
|
@ -337,13 +370,14 @@ namespace Nz
|
||||||
|
|
||||||
void OpenALSource::UnqueueAllBuffers()
|
void OpenALSource::UnqueueAllBuffers()
|
||||||
{
|
{
|
||||||
GetDevice().MakeContextCurrent();
|
OpenALDevice& device = GetDevice();
|
||||||
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
ALint queuedBufferCount = 0;
|
ALint queuedBufferCount = 0;
|
||||||
m_library.alGetSourcei(m_sourceId, AL_BUFFERS_QUEUED, &queuedBufferCount);
|
device.alGetSourcei(m_sourceId, AL_BUFFERS_QUEUED, &queuedBufferCount);
|
||||||
|
|
||||||
StackArray<ALuint> buffers = NazaraStackArrayNoInit(ALuint, queuedBufferCount);
|
StackArray<ALuint> buffers = NazaraStackArrayNoInit(ALuint, queuedBufferCount);
|
||||||
m_library.alSourceUnqueueBuffers(m_sourceId, queuedBufferCount, buffers.data());
|
device.alSourceUnqueueBuffers(m_sourceId, queuedBufferCount, buffers.data());
|
||||||
|
|
||||||
m_queuedBuffers.clear();
|
m_queuedBuffers.clear();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue