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
|
||||
if: matrix.confs.mode != 'releasedbg'
|
||||
run: xmake run UnitTests
|
||||
env:
|
||||
NAZARA_NO_AUDIO: 1
|
||||
|
||||
# Setup installation configuration
|
||||
- name: Configure xmake for installation
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Nz
|
|||
class NAZARA_AUDIO_API OpenALBuffer final : public AudioBuffer
|
||||
{
|
||||
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(OpenALBuffer&&) = delete;
|
||||
~OpenALBuffer();
|
||||
|
|
@ -44,7 +44,6 @@ namespace Nz
|
|||
const OpenALDevice& GetDevice() const;
|
||||
|
||||
ALuint m_bufferId;
|
||||
OpenALLibrary& m_library;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,9 @@
|
|||
|
||||
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)),
|
||||
m_bufferId(bufferId),
|
||||
m_library(library)
|
||||
m_bufferId(bufferId)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<AudioBuffer> CreateBuffer() override;
|
||||
std::shared_ptr<AudioSource> 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<typename... Args> 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 <Nazara/Audio/OpenALFunctions.hpp>
|
||||
|
||||
private:
|
||||
EnumArray<AudioFormat, ALenum> m_audioFormatValues;
|
||||
EnumArray<OpenALExtension, ALenum> m_extensionStatus;
|
||||
enum class FunctionIndex
|
||||
{
|
||||
#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_vendor;
|
||||
EnumArray<AudioFormat, ALenum> m_audioFormatValues;
|
||||
EnumArray<OpenALExtension, ALenum> m_extensionStatus;
|
||||
OpenALLibrary& m_library;
|
||||
MovablePtr<ALCcontext> m_context;
|
||||
MovablePtr<ALCdevice> m_device;
|
||||
mutable bool m_didCollectErrors;
|
||||
mutable bool m_hadAnyError;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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 <Nazara/Audio/OpenALFunctions.hpp>
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace Nz
|
|||
class NAZARA_AUDIO_API OpenALSource final : public AudioSource
|
||||
{
|
||||
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(OpenALSource&&) = delete;
|
||||
~OpenALSource();
|
||||
|
|
@ -76,7 +76,6 @@ namespace Nz
|
|||
std::shared_ptr<OpenALBuffer> m_currentBuffer;
|
||||
std::vector<std::shared_ptr<OpenALBuffer>> m_queuedBuffers;
|
||||
ALuint m_sourceId;
|
||||
OpenALLibrary& m_library;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,9 @@
|
|||
|
||||
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)),
|
||||
m_sourceId(sourceId),
|
||||
m_library(library)
|
||||
m_sourceId(sourceId)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<UInt64>(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<UInt32>(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<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));
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -7,29 +7,134 @@
|
|||
#include <Nazara/Audio/OpenALLibrary.hpp>
|
||||
#include <Nazara/Audio/OpenALSource.hpp>
|
||||
#include <Nazara/Audio/OpenALUtils.hpp>
|
||||
#include <Nazara/Core/Log.hpp>
|
||||
#include <NazaraUtils/Algorithm.hpp>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Audio/Debug.hpp>
|
||||
|
||||
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) :
|
||||
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<const char*>(m_library.alGetString(AL_RENDERER));
|
||||
m_vendor = reinterpret_cast<const char*>(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<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
|
||||
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<AudioBuffer> 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<OpenALBuffer>(shared_from_this(), m_library, bufferId);
|
||||
return std::make_shared<OpenALBuffer>(shared_from_this(), bufferId);
|
||||
}
|
||||
|
||||
std::shared_ptr<AudioSource> 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<OpenALSource>(shared_from_this(), m_library, sourceId);
|
||||
return std::make_shared<OpenALSource>(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<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
|
||||
* \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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<decltype(&::name)>(alGetProcAddress(#name));
|
||||
#include <Nazara/Audio/OpenALFunctions.hpp>
|
||||
|
||||
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<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)
|
||||
#include <Nazara/Audio/OpenALFunctions.hpp>
|
||||
}
|
||||
|
|
@ -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 <Nazara/Audio/OpenALFunctions.hpp>
|
||||
|
||||
|
|
@ -142,6 +131,7 @@ namespace Nz
|
|||
return;
|
||||
|
||||
#define NAZARA_AUDIO_AL_ALC_FUNCTION(name) name = nullptr;
|
||||
#define NAZARA_AUDIO_AL_EXT_FUNCTION(name)
|
||||
#include <Nazara/Audio/OpenALFunctions.hpp>
|
||||
|
||||
m_library.Unload();
|
||||
|
|
|
|||
|
|
@ -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<UInt32>(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<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.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<OpenALBuffer> newBuffer = std::static_pointer_cast<OpenALBuffer>(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> audioBuffer)
|
||||
|
|
@ -238,90 +261,100 @@ namespace Nz
|
|||
|
||||
std::shared_ptr<OpenALBuffer> newBuffer = std::static_pointer_cast<OpenALBuffer>(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<ALdouble>());
|
||||
device.alSourcedSOFT(m_sourceId, AL_SEC_OFFSET, offset.AsSeconds<ALdouble>());
|
||||
else
|
||||
#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)
|
||||
{
|
||||
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<AudioBuffer> 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<OpenALBuffer>& 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<ALuint> buffers = NazaraStackArrayNoInit(ALuint, queuedBufferCount);
|
||||
m_library.alSourceUnqueueBuffers(m_sourceId, queuedBufferCount, buffers.data());
|
||||
device.alSourceUnqueueBuffers(m_sourceId, queuedBufferCount, buffers.data());
|
||||
|
||||
m_queuedBuffers.clear();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue