Audio update

OpenAL is now loaded dynamically
Added (back) Audio::[Get|Set]ListenerRotation


Former-commit-id: d99ba9f15ec250f3963cd50d6a4a892209235c4a
This commit is contained in:
Lynix
2014-01-08 11:06:40 +01:00
parent 9ac4df3c6c
commit 26a6158f8f
7 changed files with 692 additions and 109 deletions

476
src/Nazara/Audio/OpenAL.cpp Normal file
View File

@@ -0,0 +1,476 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Audio module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Audio/OpenAL.hpp>
#include <Nazara/Core/DynLib.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Log.hpp>
#include <cstring>
#include <sstream>
#include <stdexcept>
#include <Nazara/Audio/Debug.hpp>
namespace
{
NzDynLib s_library;
NzString s_deviceName;
NzString s_rendererName;
NzString s_vendorName;
ALCdevice* s_device = nullptr;
ALCcontext* s_context = nullptr;
unsigned int s_version;
unsigned int ParseDevices(const char* deviceString, std::vector<NzString>& devices)
{
if (!deviceString)
return 0;
unsigned int startSize = devices.size();
unsigned int length;
while ((length = std::strlen(deviceString)) > 0)
{
devices.push_back(NzString(deviceString, length));
deviceString += length + 1;
}
return devices.size() - startSize;
}
}
NzOpenALFunc NzOpenAL::GetEntry(const NzString& entryPoint)
{
return LoadEntry(entryPoint.GetConstBuffer(), false);
}
NzString NzOpenAL::GetRendererName()
{
return s_rendererName;
}
NzString NzOpenAL::GetVendorName()
{
return s_vendorName;
}
unsigned int NzOpenAL::GetVersion()
{
return s_version;
}
bool NzOpenAL::Initialize(bool openDevice)
{
if (s_library.IsLoaded())
return true;
#if defined(NAZARA_PLATFORM_WINDOWS)
// OpenAL Soft est une meilleure implémentation que les redistribuables de Creative
///TODO: Détecter le driver software de Creative et basculer sur OpenAL Soft si possible
const char* libs[] = {
"soft_oal.dll",
"wrap_oal.dll",
"openal32.dll"
};
#elif defined(NAZARA_PLATFORM_LINUX)
const char* libs[] = {
"libopenal.so.1",
"libopenal.so.0",
"libopenal.so"
};
//#elif defined(NAZARA_PLATFORM_MACOSX)
#else
NazaraError("Unknown OS");
return false;
#endif
bool succeeded = false;
for (const char* path : libs)
{
NzString libPath(path);
if (!s_library.Load(libPath, false))
continue;
try
{
// al
alBuffer3f = reinterpret_cast<NzOpenALDetail::LPALBUFFER3F>(LoadEntry("alBuffer3f"));
alBuffer3i = reinterpret_cast<NzOpenALDetail::LPALBUFFER3I>(LoadEntry("alBuffer3i"));
alBufferData = reinterpret_cast<NzOpenALDetail::LPALBUFFERDATA>(LoadEntry("alBufferData"));
alBufferf = reinterpret_cast<NzOpenALDetail::LPALBUFFERF>(LoadEntry("alBufferf"));
alBufferfv = reinterpret_cast<NzOpenALDetail::LPALBUFFERFV>(LoadEntry("alBufferfv"));
alBufferi = reinterpret_cast<NzOpenALDetail::LPALBUFFERI>(LoadEntry("alBufferi"));
alBufferiv = reinterpret_cast<NzOpenALDetail::LPALBUFFERIV>(LoadEntry("alBufferiv"));
alDeleteBuffers = reinterpret_cast<NzOpenALDetail::LPALDELETEBUFFERS>(LoadEntry("alDeleteBuffers"));
alDeleteSources = reinterpret_cast<NzOpenALDetail::LPALDELETESOURCES>(LoadEntry("alDeleteSources"));
alDisable = reinterpret_cast<NzOpenALDetail::LPALDISABLE>(LoadEntry("alDisable"));
alDistanceModel = reinterpret_cast<NzOpenALDetail::LPALDISTANCEMODEL>(LoadEntry("alDistanceModel"));
alDopplerFactor = reinterpret_cast<NzOpenALDetail::LPALDOPPLERFACTOR>(LoadEntry("alDopplerFactor"));
alDopplerVelocity = reinterpret_cast<NzOpenALDetail::LPALDOPPLERVELOCITY>(LoadEntry("alDopplerVelocity"));
alEnable = reinterpret_cast<NzOpenALDetail::LPALENABLE>(LoadEntry("alEnable"));
alGenBuffers = reinterpret_cast<NzOpenALDetail::LPALGENBUFFERS>(LoadEntry("alGenBuffers"));
alGenSources = reinterpret_cast<NzOpenALDetail::LPALGENSOURCES>(LoadEntry("alGenSources"));
alGetBoolean = reinterpret_cast<NzOpenALDetail::LPALGETBOOLEAN>(LoadEntry("alGetBoolean"));
alGetBooleanv = reinterpret_cast<NzOpenALDetail::LPALGETBOOLEANV>(LoadEntry("alGetBooleanv"));
alGetBuffer3f = reinterpret_cast<NzOpenALDetail::LPALGETBUFFER3F>(LoadEntry("alGetBuffer3f"));
alGetBuffer3i = reinterpret_cast<NzOpenALDetail::LPALGETBUFFER3I>(LoadEntry("alGetBuffer3i"));
alGetBufferf = reinterpret_cast<NzOpenALDetail::LPALGETBUFFERF>(LoadEntry("alGetBufferf"));
alGetBufferfv = reinterpret_cast<NzOpenALDetail::LPALGETBUFFERFV>(LoadEntry("alGetBufferfv"));
alGetBufferi = reinterpret_cast<NzOpenALDetail::LPALGETBUFFERI>(LoadEntry("alGetBufferi"));
alGetBufferiv = reinterpret_cast<NzOpenALDetail::LPALGETBUFFERIV>(LoadEntry("alGetBufferiv"));
alGetDouble = reinterpret_cast<NzOpenALDetail::LPALGETDOUBLE>(LoadEntry("alGetDouble"));
alGetDoublev = reinterpret_cast<NzOpenALDetail::LPALGETDOUBLEV>(LoadEntry("alGetDoublev"));
alGetEnumValue = reinterpret_cast<NzOpenALDetail::LPALGETENUMVALUE>(LoadEntry("alGetEnumValue"));
alGetError = reinterpret_cast<NzOpenALDetail::LPALGETERROR>(LoadEntry("alGetError"));
alGetFloat = reinterpret_cast<NzOpenALDetail::LPALGETFLOAT>(LoadEntry("alGetFloat"));
alGetFloatv = reinterpret_cast<NzOpenALDetail::LPALGETFLOATV>(LoadEntry("alGetFloatv"));
alGetInteger = reinterpret_cast<NzOpenALDetail::LPALGETINTEGER>(LoadEntry("alGetInteger"));
alGetIntegerv = reinterpret_cast<NzOpenALDetail::LPALGETINTEGERV>(LoadEntry("alGetIntegerv"));
alGetListener3f = reinterpret_cast<NzOpenALDetail::LPALGETLISTENER3F>(LoadEntry("alGetListener3f"));
alGetListener3i = reinterpret_cast<NzOpenALDetail::LPALGETLISTENER3I>(LoadEntry("alGetListener3i"));
alGetListenerf = reinterpret_cast<NzOpenALDetail::LPALGETLISTENERF>(LoadEntry("alGetListenerf"));
alGetListenerfv = reinterpret_cast<NzOpenALDetail::LPALGETLISTENERFV>(LoadEntry("alGetListenerfv"));
alGetListeneri = reinterpret_cast<NzOpenALDetail::LPALGETLISTENERI>(LoadEntry("alGetListeneri"));
alGetListeneriv = reinterpret_cast<NzOpenALDetail::LPALGETLISTENERIV>(LoadEntry("alGetListeneriv"));
alGetProcAddress = reinterpret_cast<NzOpenALDetail::LPALGETPROCADDRESS>(LoadEntry("alGetProcAddress"));
alGetSource3f = reinterpret_cast<NzOpenALDetail::LPALGETSOURCE3F>(LoadEntry("alGetSource3f"));
alGetSource3i = reinterpret_cast<NzOpenALDetail::LPALGETSOURCE3I>(LoadEntry("alGetSource3i"));
alGetSourcef = reinterpret_cast<NzOpenALDetail::LPALGETSOURCEF>(LoadEntry("alGetSourcef"));
alGetSourcefv = reinterpret_cast<NzOpenALDetail::LPALGETSOURCEFV>(LoadEntry("alGetSourcefv"));
alGetSourcei = reinterpret_cast<NzOpenALDetail::LPALGETSOURCEI>(LoadEntry("alGetSourcei"));
alGetSourceiv = reinterpret_cast<NzOpenALDetail::LPALGETSOURCEIV>(LoadEntry("alGetSourceiv"));
alGetString = reinterpret_cast<NzOpenALDetail::LPALGETSTRING>(LoadEntry("alGetString"));
alIsBuffer = reinterpret_cast<NzOpenALDetail::LPALISBUFFER>(LoadEntry("alIsBuffer"));
alIsEnabled = reinterpret_cast<NzOpenALDetail::LPALISENABLED>(LoadEntry("alIsEnabled"));
alIsExtensionPresent = reinterpret_cast<NzOpenALDetail::LPALISEXTENSIONPRESENT>(LoadEntry("alIsExtensionPresent"));
alIsSource = reinterpret_cast<NzOpenALDetail::LPALISSOURCE>(LoadEntry("alIsSource"));
alListener3f = reinterpret_cast<NzOpenALDetail::LPALLISTENER3F>(LoadEntry("alListener3f"));
alListener3i = reinterpret_cast<NzOpenALDetail::LPALLISTENER3I>(LoadEntry("alListener3i"));
alListenerf = reinterpret_cast<NzOpenALDetail::LPALLISTENERF>(LoadEntry("alListenerf"));
alListenerfv = reinterpret_cast<NzOpenALDetail::LPALLISTENERFV>(LoadEntry("alListenerfv"));
alListeneri = reinterpret_cast<NzOpenALDetail::LPALLISTENERI>(LoadEntry("alListeneri"));
alListeneriv = reinterpret_cast<NzOpenALDetail::LPALLISTENERIV>(LoadEntry("alListeneriv"));
alSource3f = reinterpret_cast<NzOpenALDetail::LPALSOURCE3F>(LoadEntry("alSource3f"));
alSource3i = reinterpret_cast<NzOpenALDetail::LPALSOURCE3I>(LoadEntry("alSource3i"));
alSourcef = reinterpret_cast<NzOpenALDetail::LPALSOURCEF>(LoadEntry("alSourcef"));
alSourcefv = reinterpret_cast<NzOpenALDetail::LPALSOURCEFV>(LoadEntry("alSourcefv"));
alSourcei = reinterpret_cast<NzOpenALDetail::LPALSOURCEI>(LoadEntry("alSourcei"));
alSourceiv = reinterpret_cast<NzOpenALDetail::LPALSOURCEIV>(LoadEntry("alSourceiv"));
alSourcePause = reinterpret_cast<NzOpenALDetail::LPALSOURCEPAUSE>(LoadEntry("alSourcePause"));
alSourcePausev = reinterpret_cast<NzOpenALDetail::LPALSOURCEPAUSEV>(LoadEntry("alSourcePausev"));
alSourcePlay = reinterpret_cast<NzOpenALDetail::LPALSOURCEPLAY>(LoadEntry("alSourcePlay"));
alSourcePlayv = reinterpret_cast<NzOpenALDetail::LPALSOURCEPLAYV>(LoadEntry("alSourcePlayv"));
alSourceQueueBuffers = reinterpret_cast<NzOpenALDetail::LPALSOURCEQUEUEBUFFERS>(LoadEntry("alSourceQueueBuffers"));
alSourceRewind = reinterpret_cast<NzOpenALDetail::LPALSOURCEREWIND>(LoadEntry("alSourceRewind"));
alSourceRewindv = reinterpret_cast<NzOpenALDetail::LPALSOURCEREWINDV>(LoadEntry("alSourceRewindv"));
alSourceStop = reinterpret_cast<NzOpenALDetail::LPALSOURCESTOP>(LoadEntry("alSourceStop"));
alSourceStopv = reinterpret_cast<NzOpenALDetail::LPALSOURCESTOPV>(LoadEntry("alSourceStopv"));
alSourceUnqueueBuffers = reinterpret_cast<NzOpenALDetail::LPALSOURCEUNQUEUEBUFFERS>(LoadEntry("alSourceUnqueueBuffers"));
alSpeedOfSound = reinterpret_cast<NzOpenALDetail::LPALSPEEDOFSOUND>(LoadEntry("alSpeedOfSound"));
// alc
alcCaptureCloseDevice = reinterpret_cast<NzOpenALDetail::LPALCCAPTURECLOSEDEVICE>(LoadEntry("alcCaptureCloseDevice"));
alcCaptureOpenDevice = reinterpret_cast<NzOpenALDetail::LPALCCAPTUREOPENDEVICE>(LoadEntry("alcCaptureOpenDevice"));
alcCaptureSamples = reinterpret_cast<NzOpenALDetail::LPALCCAPTURESAMPLES>(LoadEntry("alcCaptureSamples"));
alcCaptureStart = reinterpret_cast<NzOpenALDetail::LPALCCAPTURESTART>(LoadEntry("alcCaptureStart"));
alcCaptureStop = reinterpret_cast<NzOpenALDetail::LPALCCAPTURESTOP>(LoadEntry("alcCaptureStop"));
alcCloseDevice = reinterpret_cast<NzOpenALDetail::LPALCCLOSEDEVICE>(LoadEntry("alcCloseDevice"));
alcCreateContext = reinterpret_cast<NzOpenALDetail::LPALCCREATECONTEXT>(LoadEntry("alcCreateContext"));
alcDestroyContext = reinterpret_cast<NzOpenALDetail::LPALCDESTROYCONTEXT>(LoadEntry("alcDestroyContext"));
alcGetContextsDevice = reinterpret_cast<NzOpenALDetail::LPALCGETCONTEXTSDEVICE>(LoadEntry("alcGetContextsDevice"));
alcGetCurrentContext = reinterpret_cast<NzOpenALDetail::LPALCGETCURRENTCONTEXT>(LoadEntry("alcGetCurrentContext"));
alcGetEnumValue = reinterpret_cast<NzOpenALDetail::LPALCGETENUMVALUE>(LoadEntry("alcGetEnumValue"));
alcGetError = reinterpret_cast<NzOpenALDetail::LPALCGETERROR>(LoadEntry("alcGetError"));
alcGetIntegerv = reinterpret_cast<NzOpenALDetail::LPALCGETINTEGERV>(LoadEntry("alcGetIntegerv"));
alcGetProcAddress = reinterpret_cast<NzOpenALDetail::LPALCGETPROCADDRESS>(LoadEntry("alcGetProcAddress"));
alcGetString = reinterpret_cast<NzOpenALDetail::LPALCGETSTRING>(LoadEntry("alcGetString"));
alcIsExtensionPresent = reinterpret_cast<NzOpenALDetail::LPALCISEXTENSIONPRESENT>(LoadEntry("alcIsExtensionPresent"));
alcMakeContextCurrent = reinterpret_cast<NzOpenALDetail::LPALCMAKECONTEXTCURRENT>(LoadEntry("alcMakeContextCurrent"));
alcOpenDevice = reinterpret_cast<NzOpenALDetail::LPALCOPENDEVICE>(LoadEntry("alcOpenDevice"));
alcProcessContext = reinterpret_cast<NzOpenALDetail::LPALCPROCESSCONTEXT>(LoadEntry("alcProcessContext"));
alcSuspendContext = reinterpret_cast<NzOpenALDetail::LPALCSUSPENDCONTEXT>(LoadEntry("alcSuspendContext"));
succeeded = true;
break;
}
catch (const std::exception& e)
{
NazaraWarning(libPath + " loading failed: " + NzString(e.what()));
continue;
}
}
if (!succeeded)
{
NazaraError("Failed to load OpenAL");
Uninitialize();
return false;
}
// On complète le tableau de formats
// The presence of an enum value does not guarantee the applicability of an extension to the current context.
if (alIsExtensionPresent("AL_EXT_MCFORMATS"))
{
AudioFormat[nzAudioFormat_Quad] = alGetEnumValue("AL_FORMAT_QUAD16");
AudioFormat[nzAudioFormat_5_1] = alGetEnumValue("AL_FORMAT_51CHN16");
AudioFormat[nzAudioFormat_6_1] = alGetEnumValue("AL_FORMAT_61CHN16");
AudioFormat[nzAudioFormat_7_1] = alGetEnumValue("AL_FORMAT_71CHN16");
}
else if (alIsExtensionPresent("AL_LOKI_quadriphonic"))
AudioFormat[nzAudioFormat_Quad] = alGetEnumValue("AL_FORMAT_QUAD16_LOKI");
if (openDevice)
OpenDevice();
return true;
}
bool NzOpenAL::IsInitialized()
{
return s_library.IsLoaded();
}
unsigned int NzOpenAL::QueryInputDevices(std::vector<NzString>& devices)
{
const char* deviceString = reinterpret_cast<const char*>(alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER));
if (!deviceString)
return 0;
return ParseDevices(deviceString, devices);
}
unsigned int NzOpenAL::QueryOutputDevices(std::vector<NzString>& devices)
{
const char* deviceString = reinterpret_cast<const char*>(alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER));
if (!deviceString)
return 0;
return ParseDevices(deviceString, devices);
}
bool NzOpenAL::SetDevice(const NzString& deviceName)
{
s_deviceName = deviceName;
if (IsInitialized())
{
CloseDevice();
return OpenDevice();
}
else
return true;
}
void NzOpenAL::Uninitialize()
{
CloseDevice();
s_rendererName.Clear(false);
s_vendorName.Clear(false);
s_library.Unload();
}
ALenum NzOpenAL::AudioFormat[nzAudioFormat_Max+1] =
{
AL_FORMAT_MONO16, // nzAudioFormat_Mono
AL_FORMAT_STEREO16, // nzAudioFormat_Stereo
// Les valeurs suivantes sont récupérées à l'initialisation car faisant partie d'une extension
0, // nzAudioFormat_Quad
0, // nzAudioFormat_5_1
0, // nzAudioFormat_6_1
0 // nzAudioFormat_7_1
};
static_assert(sizeof(NzOpenAL::AudioFormat)/sizeof(ALenum) == nzAudioFormat_Max+1, "Audio format array is incomplete");
void NzOpenAL::CloseDevice()
{
if (s_device)
{
if (s_context)
{
alcMakeContextCurrent(nullptr);
alcDestroyContext(s_context);
s_context = nullptr;
}
if (!alcCloseDevice(s_device))
// Nous n'avons pas pu fermer le device, ce qui signifie qu'il est en cours d'utilisation
NazaraWarning("Failed to close device");
s_device = nullptr;
}
}
bool NzOpenAL::OpenDevice()
{
// Initialisation du module
s_device = alcOpenDevice(s_deviceName.IsEmpty() ? nullptr : s_deviceName.GetConstBuffer()); // On choisit le device par défaut
if (!s_device)
{
NazaraError("Failed to open default device");
return false;
}
// Un seul contexte nous suffira
s_context = alcCreateContext(s_device, nullptr);
if (!s_context)
{
NazaraError("Failed to create context");
return false;
}
if (!alcMakeContextCurrent(s_context))
{
NazaraError("Failed to activate context");
return false;
}
s_rendererName = reinterpret_cast<const char*>(alGetString(AL_RENDERER));
s_vendorName = reinterpret_cast<const char*>(alGetString(AL_VENDOR));
const ALchar* version = alGetString(AL_VERSION);
if (version)
{
unsigned int major = version[0] - '0';
unsigned int minor = version[2] - '0';
if (major != 0 && major <= 9)
{
if (minor > 9)
{
NazaraWarning("Unable to retrieve OpenAL minor version (using 0)");
minor = 0;
}
s_version = major*100 + minor*10;
NazaraDebug("OpenAL version: " + NzString::Number(major) + '.' + NzString::Number(minor));
}
else
{
NazaraDebug("Unable to retrieve OpenAL major version");
s_version = 0;
}
}
else
{
NazaraDebug("Unable to retrieve OpenAL version");
s_version = 0;
}
return true;
}
NzOpenALFunc NzOpenAL::LoadEntry(const char* name, bool throwException)
{
NzOpenALFunc entry = reinterpret_cast<NzOpenALFunc>(s_library.GetSymbol(name));
if (!entry && throwException)
{
std::ostringstream oss;
oss << "failed to load \"" << name << '"';
throw std::runtime_error(oss.str());
}
return entry;
}
// al
NzOpenALDetail::LPALBUFFER3F alBuffer3f = nullptr;
NzOpenALDetail::LPALBUFFER3I alBuffer3i = nullptr;
NzOpenALDetail::LPALBUFFERDATA alBufferData = nullptr;
NzOpenALDetail::LPALBUFFERF alBufferf = nullptr;
NzOpenALDetail::LPALBUFFERFV alBufferfv = nullptr;
NzOpenALDetail::LPALBUFFERI alBufferi = nullptr;
NzOpenALDetail::LPALBUFFERIV alBufferiv = nullptr;
NzOpenALDetail::LPALDELETEBUFFERS alDeleteBuffers = nullptr;
NzOpenALDetail::LPALDELETESOURCES alDeleteSources = nullptr;
NzOpenALDetail::LPALDISABLE alDisable = nullptr;
NzOpenALDetail::LPALDISTANCEMODEL alDistanceModel = nullptr;
NzOpenALDetail::LPALDOPPLERFACTOR alDopplerFactor = nullptr;
NzOpenALDetail::LPALDOPPLERVELOCITY alDopplerVelocity = nullptr;
NzOpenALDetail::LPALENABLE alEnable = nullptr;
NzOpenALDetail::LPALGENBUFFERS alGenBuffers = nullptr;
NzOpenALDetail::LPALGENSOURCES alGenSources = nullptr;
NzOpenALDetail::LPALGETBOOLEAN alGetBoolean = nullptr;
NzOpenALDetail::LPALGETBOOLEANV alGetBooleanv = nullptr;
NzOpenALDetail::LPALGETBUFFER3F alGetBuffer3f = nullptr;
NzOpenALDetail::LPALGETBUFFER3I alGetBuffer3i = nullptr;
NzOpenALDetail::LPALGETBUFFERF alGetBufferf = nullptr;
NzOpenALDetail::LPALGETBUFFERFV alGetBufferfv = nullptr;
NzOpenALDetail::LPALGETBUFFERI alGetBufferi = nullptr;
NzOpenALDetail::LPALGETBUFFERIV alGetBufferiv = nullptr;
NzOpenALDetail::LPALGETDOUBLE alGetDouble = nullptr;
NzOpenALDetail::LPALGETDOUBLEV alGetDoublev = nullptr;
NzOpenALDetail::LPALGETENUMVALUE alGetEnumValue = nullptr;
NzOpenALDetail::LPALGETERROR alGetError = nullptr;
NzOpenALDetail::LPALGETFLOAT alGetFloat = nullptr;
NzOpenALDetail::LPALGETFLOATV alGetFloatv = nullptr;
NzOpenALDetail::LPALGETINTEGER alGetInteger = nullptr;
NzOpenALDetail::LPALGETINTEGERV alGetIntegerv = nullptr;
NzOpenALDetail::LPALGETLISTENER3F alGetListener3f = nullptr;
NzOpenALDetail::LPALGETLISTENER3I alGetListener3i = nullptr;
NzOpenALDetail::LPALGETLISTENERF alGetListenerf = nullptr;
NzOpenALDetail::LPALGETLISTENERFV alGetListenerfv = nullptr;
NzOpenALDetail::LPALGETLISTENERI alGetListeneri = nullptr;
NzOpenALDetail::LPALGETLISTENERIV alGetListeneriv = nullptr;
NzOpenALDetail::LPALGETPROCADDRESS alGetProcAddress = nullptr;
NzOpenALDetail::LPALGETSOURCE3F alGetSource3f = nullptr;
NzOpenALDetail::LPALGETSOURCE3I alGetSource3i = nullptr;
NzOpenALDetail::LPALGETSOURCEF alGetSourcef = nullptr;
NzOpenALDetail::LPALGETSOURCEFV alGetSourcefv = nullptr;
NzOpenALDetail::LPALGETSOURCEI alGetSourcei = nullptr;
NzOpenALDetail::LPALGETSOURCEIV alGetSourceiv = nullptr;
NzOpenALDetail::LPALGETSTRING alGetString = nullptr;
NzOpenALDetail::LPALISBUFFER alIsBuffer = nullptr;
NzOpenALDetail::LPALISENABLED alIsEnabled = nullptr;
NzOpenALDetail::LPALISEXTENSIONPRESENT alIsExtensionPresent = nullptr;
NzOpenALDetail::LPALISSOURCE alIsSource = nullptr;
NzOpenALDetail::LPALLISTENER3F alListener3f = nullptr;
NzOpenALDetail::LPALLISTENER3I alListener3i = nullptr;
NzOpenALDetail::LPALLISTENERF alListenerf = nullptr;
NzOpenALDetail::LPALLISTENERFV alListenerfv = nullptr;
NzOpenALDetail::LPALLISTENERI alListeneri = nullptr;
NzOpenALDetail::LPALLISTENERIV alListeneriv = nullptr;
NzOpenALDetail::LPALSOURCE3F alSource3f = nullptr;
NzOpenALDetail::LPALSOURCE3I alSource3i = nullptr;
NzOpenALDetail::LPALSOURCEF alSourcef = nullptr;
NzOpenALDetail::LPALSOURCEFV alSourcefv = nullptr;
NzOpenALDetail::LPALSOURCEI alSourcei = nullptr;
NzOpenALDetail::LPALSOURCEIV alSourceiv = nullptr;
NzOpenALDetail::LPALSOURCEPAUSE alSourcePause = nullptr;
NzOpenALDetail::LPALSOURCEPAUSEV alSourcePausev = nullptr;
NzOpenALDetail::LPALSOURCEPLAY alSourcePlay = nullptr;
NzOpenALDetail::LPALSOURCEPLAYV alSourcePlayv = nullptr;
NzOpenALDetail::LPALSOURCEQUEUEBUFFERS alSourceQueueBuffers = nullptr;
NzOpenALDetail::LPALSOURCEREWIND alSourceRewind = nullptr;
NzOpenALDetail::LPALSOURCEREWINDV alSourceRewindv = nullptr;
NzOpenALDetail::LPALSOURCESTOP alSourceStop = nullptr;
NzOpenALDetail::LPALSOURCESTOPV alSourceStopv = nullptr;
NzOpenALDetail::LPALSOURCEUNQUEUEBUFFERS alSourceUnqueueBuffers = nullptr;
NzOpenALDetail::LPALSPEEDOFSOUND alSpeedOfSound = nullptr;
// alc
NzOpenALDetail::LPALCCAPTURECLOSEDEVICE alcCaptureCloseDevice = nullptr;
NzOpenALDetail::LPALCCAPTUREOPENDEVICE alcCaptureOpenDevice = nullptr;
NzOpenALDetail::LPALCCAPTURESAMPLES alcCaptureSamples = nullptr;
NzOpenALDetail::LPALCCAPTURESTART alcCaptureStart = nullptr;
NzOpenALDetail::LPALCCAPTURESTOP alcCaptureStop = nullptr;
NzOpenALDetail::LPALCCLOSEDEVICE alcCloseDevice = nullptr;
NzOpenALDetail::LPALCCREATECONTEXT alcCreateContext = nullptr;
NzOpenALDetail::LPALCDESTROYCONTEXT alcDestroyContext = nullptr;
NzOpenALDetail::LPALCGETCONTEXTSDEVICE alcGetContextsDevice = nullptr;
NzOpenALDetail::LPALCGETCURRENTCONTEXT alcGetCurrentContext = nullptr;
NzOpenALDetail::LPALCGETENUMVALUE alcGetEnumValue = nullptr;
NzOpenALDetail::LPALCGETERROR alcGetError = nullptr;
NzOpenALDetail::LPALCGETINTEGERV alcGetIntegerv = nullptr;
NzOpenALDetail::LPALCGETPROCADDRESS alcGetProcAddress = nullptr;
NzOpenALDetail::LPALCGETSTRING alcGetString = nullptr;
NzOpenALDetail::LPALCISEXTENSIONPRESENT alcIsExtensionPresent = nullptr;
NzOpenALDetail::LPALCMAKECONTEXTCURRENT alcMakeContextCurrent = nullptr;
NzOpenALDetail::LPALCOPENDEVICE alcOpenDevice = nullptr;
NzOpenALDetail::LPALCPROCESSCONTEXT alcProcessContext = nullptr;
NzOpenALDetail::LPALCSUSPENDCONTEXT alcSuspendContext = nullptr;