diff --git a/include/Nazara/Audio/Audio.hpp b/include/Nazara/Audio/Audio.hpp index 1e688640e..0ab4f916a 100644 --- a/include/Nazara/Audio/Audio.hpp +++ b/include/Nazara/Audio/Audio.hpp @@ -15,9 +15,6 @@ class NAZARA_API NzAudio { - friend class NzMusic; - friend class NzSoundBuffer; - public: NzAudio() = delete; ~NzAudio() = delete; @@ -27,7 +24,7 @@ class NAZARA_API NzAudio static float GetGlobalVolume(); static NzVector3f GetListenerDirection(); static NzVector3f GetListenerPosition(); - //static NzQuaternionf GetListenerRotation(); + static NzQuaternionf GetListenerRotation(); static NzVector3f GetListenerVelocity(); static float GetSpeedOfSound(); @@ -42,7 +39,7 @@ class NAZARA_API NzAudio static void SetListenerDirection(float dirX, float dirY, float dirZ); static void SetListenerPosition(const NzVector3f& position); static void SetListenerPosition(float x, float y, float z); - //static void SetListenerRotation(const NzQuaternionf& rotation); + static void SetListenerRotation(const NzQuaternionf& rotation); static void SetListenerVelocity(const NzVector3f& velocity); static void SetListenerVelocity(float velX, float velY, float velZ); static void SetSpeedOfSound(float speed); @@ -50,8 +47,6 @@ class NAZARA_API NzAudio static void Uninitialize(); private: - static unsigned int GetOpenALFormat(nzAudioFormat format); - static unsigned int s_moduleReferenceCounter; }; diff --git a/include/Nazara/Audio/OpenAL.hpp b/include/Nazara/Audio/OpenAL.hpp new file mode 100644 index 000000000..a9d72de90 --- /dev/null +++ b/include/Nazara/Audio/OpenAL.hpp @@ -0,0 +1,187 @@ +// 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 + +#pragma once + +#ifndef NAZARA_OPENAL_HPP +#define NAZARA_OPENAL_HPP + +#ifdef NAZARA_AUDIO_OPENAL + +#include +#include +#include +#include + +// Inclusion des headers OpenAL + +// Étant donné que les headers OpenAL ne nous permettent pas de n'avoir que les signatures sans les pointeurs de fonctions +// Et que je ne souhaite pas les modifier, je suis contraint de les placer dans un espace de nom différent pour ensuite +// remettre dans l'espace global les choses intéressantes (les typedef notamment) +namespace NzOpenALDetail +{ + #include + #include +} + +// Si quelqu'un a une meilleure idée ... +using NzOpenALDetail::ALboolean; +using NzOpenALDetail::ALbyte; +using NzOpenALDetail::ALchar; +using NzOpenALDetail::ALdouble; +using NzOpenALDetail::ALenum; +using NzOpenALDetail::ALfloat; +using NzOpenALDetail::ALint; +using NzOpenALDetail::ALshort; +using NzOpenALDetail::ALsizei; +using NzOpenALDetail::ALubyte; +using NzOpenALDetail::ALuint; +using NzOpenALDetail::ALushort; +using NzOpenALDetail::ALvoid; + +using NzOpenALDetail::ALCboolean; +using NzOpenALDetail::ALCbyte; +using NzOpenALDetail::ALCchar; +using NzOpenALDetail::ALCcontext; +using NzOpenALDetail::ALCdevice; +using NzOpenALDetail::ALCdouble; +using NzOpenALDetail::ALCenum; +using NzOpenALDetail::ALCfloat; +using NzOpenALDetail::ALCint; +using NzOpenALDetail::ALCshort; +using NzOpenALDetail::ALCsizei; +using NzOpenALDetail::ALCubyte; +using NzOpenALDetail::ALCuint; +using NzOpenALDetail::ALCushort; +using NzOpenALDetail::ALCvoid; + +using NzOpenALFunc = void (*)(); + +class NAZARA_API NzOpenAL +{ + public: + static NzOpenALFunc GetEntry(const NzString& entryPoint); + static NzString GetRendererName(); + static NzString GetVendorName(); + static unsigned int GetVersion(); + + static bool Initialize(bool openDevice = true); + + static bool IsInitialized(); + + static unsigned int QueryInputDevices(std::vector& devices); + static unsigned int QueryOutputDevices(std::vector& devices); + + static bool SetDevice(const NzString& deviceName); + + static void Uninitialize(); + + static ALenum AudioFormat[nzAudioFormat_Max+1]; + + private: + static void CloseDevice(); + static bool OpenDevice(); + static NzOpenALFunc LoadEntry(const char* name, bool throwException = false); +}; + +// al +NAZARA_API extern NzOpenALDetail::LPALBUFFER3F alBuffer3f; +NAZARA_API extern NzOpenALDetail::LPALBUFFER3I alBuffer3i; +NAZARA_API extern NzOpenALDetail::LPALBUFFERDATA alBufferData; +NAZARA_API extern NzOpenALDetail::LPALBUFFERF alBufferf; +NAZARA_API extern NzOpenALDetail::LPALBUFFERFV alBufferfv; +NAZARA_API extern NzOpenALDetail::LPALBUFFERI alBufferi; +NAZARA_API extern NzOpenALDetail::LPALBUFFERIV alBufferiv; +NAZARA_API extern NzOpenALDetail::LPALDELETEBUFFERS alDeleteBuffers; +NAZARA_API extern NzOpenALDetail::LPALDELETESOURCES alDeleteSources; +NAZARA_API extern NzOpenALDetail::LPALDISABLE alDisable; +NAZARA_API extern NzOpenALDetail::LPALDISTANCEMODEL alDistanceModel; +NAZARA_API extern NzOpenALDetail::LPALDOPPLERFACTOR alDopplerFactor; +NAZARA_API extern NzOpenALDetail::LPALDOPPLERVELOCITY alDopplerVelocity; +NAZARA_API extern NzOpenALDetail::LPALENABLE alEnable; +NAZARA_API extern NzOpenALDetail::LPALGENBUFFERS alGenBuffers; +NAZARA_API extern NzOpenALDetail::LPALGENSOURCES alGenSources; +NAZARA_API extern NzOpenALDetail::LPALGETBOOLEAN alGetBoolean; +NAZARA_API extern NzOpenALDetail::LPALGETBOOLEANV alGetBooleanv; +NAZARA_API extern NzOpenALDetail::LPALGETBUFFER3F alGetBuffer3f; +NAZARA_API extern NzOpenALDetail::LPALGETBUFFER3I alGetBuffer3i; +NAZARA_API extern NzOpenALDetail::LPALGETBUFFERF alGetBufferf; +NAZARA_API extern NzOpenALDetail::LPALGETBUFFERFV alGetBufferfv; +NAZARA_API extern NzOpenALDetail::LPALGETBUFFERI alGetBufferi; +NAZARA_API extern NzOpenALDetail::LPALGETBUFFERIV alGetBufferiv; +NAZARA_API extern NzOpenALDetail::LPALGETDOUBLE alGetDouble; +NAZARA_API extern NzOpenALDetail::LPALGETDOUBLEV alGetDoublev; +NAZARA_API extern NzOpenALDetail::LPALGETENUMVALUE alGetEnumValue; +NAZARA_API extern NzOpenALDetail::LPALGETERROR alGetError; +NAZARA_API extern NzOpenALDetail::LPALGETFLOAT alGetFloat; +NAZARA_API extern NzOpenALDetail::LPALGETFLOATV alGetFloatv; +NAZARA_API extern NzOpenALDetail::LPALGETINTEGER alGetInteger; +NAZARA_API extern NzOpenALDetail::LPALGETINTEGERV alGetIntegerv; +NAZARA_API extern NzOpenALDetail::LPALGETLISTENER3F alGetListener3f; +NAZARA_API extern NzOpenALDetail::LPALGETLISTENER3I alGetListener3i; +NAZARA_API extern NzOpenALDetail::LPALGETLISTENERF alGetListenerf; +NAZARA_API extern NzOpenALDetail::LPALGETLISTENERFV alGetListenerfv; +NAZARA_API extern NzOpenALDetail::LPALGETLISTENERI alGetListeneri; +NAZARA_API extern NzOpenALDetail::LPALGETLISTENERIV alGetListeneriv; +NAZARA_API extern NzOpenALDetail::LPALGETPROCADDRESS alGetProcAddress; +NAZARA_API extern NzOpenALDetail::LPALGETSOURCE3F alGetSource3f; +NAZARA_API extern NzOpenALDetail::LPALGETSOURCE3I alGetSource3i; +NAZARA_API extern NzOpenALDetail::LPALGETSOURCEF alGetSourcef; +NAZARA_API extern NzOpenALDetail::LPALGETSOURCEFV alGetSourcefv; +NAZARA_API extern NzOpenALDetail::LPALGETSOURCEI alGetSourcei; +NAZARA_API extern NzOpenALDetail::LPALGETSOURCEIV alGetSourceiv; +NAZARA_API extern NzOpenALDetail::LPALGETSTRING alGetString; +NAZARA_API extern NzOpenALDetail::LPALISBUFFER alIsBuffer; +NAZARA_API extern NzOpenALDetail::LPALISENABLED alIsEnabled; +NAZARA_API extern NzOpenALDetail::LPALISEXTENSIONPRESENT alIsExtensionPresent; +NAZARA_API extern NzOpenALDetail::LPALISSOURCE alIsSource; +NAZARA_API extern NzOpenALDetail::LPALLISTENER3F alListener3f; +NAZARA_API extern NzOpenALDetail::LPALLISTENER3I alListener3i; +NAZARA_API extern NzOpenALDetail::LPALLISTENERF alListenerf; +NAZARA_API extern NzOpenALDetail::LPALLISTENERFV alListenerfv; +NAZARA_API extern NzOpenALDetail::LPALLISTENERI alListeneri; +NAZARA_API extern NzOpenALDetail::LPALLISTENERIV alListeneriv; +NAZARA_API extern NzOpenALDetail::LPALSOURCE3F alSource3f; +NAZARA_API extern NzOpenALDetail::LPALSOURCE3I alSource3i; +NAZARA_API extern NzOpenALDetail::LPALSOURCEF alSourcef; +NAZARA_API extern NzOpenALDetail::LPALSOURCEFV alSourcefv; +NAZARA_API extern NzOpenALDetail::LPALSOURCEI alSourcei; +NAZARA_API extern NzOpenALDetail::LPALSOURCEIV alSourceiv; +NAZARA_API extern NzOpenALDetail::LPALSOURCEPAUSE alSourcePause; +NAZARA_API extern NzOpenALDetail::LPALSOURCEPAUSEV alSourcePausev; +NAZARA_API extern NzOpenALDetail::LPALSOURCEPLAY alSourcePlay; +NAZARA_API extern NzOpenALDetail::LPALSOURCEPLAYV alSourcePlayv; +NAZARA_API extern NzOpenALDetail::LPALSOURCEQUEUEBUFFERS alSourceQueueBuffers; +NAZARA_API extern NzOpenALDetail::LPALSOURCEREWIND alSourceRewind; +NAZARA_API extern NzOpenALDetail::LPALSOURCEREWINDV alSourceRewindv; +NAZARA_API extern NzOpenALDetail::LPALSOURCESTOP alSourceStop; +NAZARA_API extern NzOpenALDetail::LPALSOURCESTOPV alSourceStopv; +NAZARA_API extern NzOpenALDetail::LPALSOURCEUNQUEUEBUFFERS alSourceUnqueueBuffers; +NAZARA_API extern NzOpenALDetail::LPALSPEEDOFSOUND alSpeedOfSound; + +// alc +NAZARA_API extern NzOpenALDetail::LPALCCAPTURECLOSEDEVICE alcCaptureCloseDevice; +NAZARA_API extern NzOpenALDetail::LPALCCAPTUREOPENDEVICE alcCaptureOpenDevice; +NAZARA_API extern NzOpenALDetail::LPALCCAPTURESAMPLES alcCaptureSamples; +NAZARA_API extern NzOpenALDetail::LPALCCAPTURESTART alcCaptureStart; +NAZARA_API extern NzOpenALDetail::LPALCCAPTURESTOP alcCaptureStop; +NAZARA_API extern NzOpenALDetail::LPALCCLOSEDEVICE alcCloseDevice; +NAZARA_API extern NzOpenALDetail::LPALCCREATECONTEXT alcCreateContext; +NAZARA_API extern NzOpenALDetail::LPALCDESTROYCONTEXT alcDestroyContext; +NAZARA_API extern NzOpenALDetail::LPALCGETCONTEXTSDEVICE alcGetContextsDevice; +NAZARA_API extern NzOpenALDetail::LPALCGETCURRENTCONTEXT alcGetCurrentContext; +NAZARA_API extern NzOpenALDetail::LPALCGETENUMVALUE alcGetEnumValue; +NAZARA_API extern NzOpenALDetail::LPALCGETERROR alcGetError; +NAZARA_API extern NzOpenALDetail::LPALCGETINTEGERV alcGetIntegerv; +NAZARA_API extern NzOpenALDetail::LPALCGETPROCADDRESS alcGetProcAddress; +NAZARA_API extern NzOpenALDetail::LPALCGETSTRING alcGetString; +NAZARA_API extern NzOpenALDetail::LPALCISEXTENSIONPRESENT alcIsExtensionPresent; +NAZARA_API extern NzOpenALDetail::LPALCMAKECONTEXTCURRENT alcMakeContextCurrent; +NAZARA_API extern NzOpenALDetail::LPALCOPENDEVICE alcOpenDevice; +NAZARA_API extern NzOpenALDetail::LPALCPROCESSCONTEXT alcProcessContext; +NAZARA_API extern NzOpenALDetail::LPALCSUSPENDCONTEXT alcSuspendContext; + +#endif // NAZARA_AUDIO_OPENAL + +#endif // NAZARA_OPENAL_HPP diff --git a/src/Nazara/Audio/Audio.cpp b/src/Nazara/Audio/Audio.cpp index 8277658b2..c8aaf1a75 100644 --- a/src/Nazara/Audio/Audio.cpp +++ b/src/Nazara/Audio/Audio.cpp @@ -3,23 +3,15 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include #include -namespace -{ - ALenum formats[nzAudioFormat_Max+1] = {0}; - ALCdevice* device = nullptr; - ALCcontext* context = nullptr; -} - nzAudioFormat NzAudio::GetAudioFormat(unsigned int channelCount) { switch (channelCount) @@ -66,26 +58,17 @@ NzVector3f NzAudio::GetListenerPosition() return position; } -/* + NzQuaternionf NzAudio::GetListenerRotation() { - // http://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another float orientation[6]; alGetListenerfv(AL_ORIENTATION, orientation); NzVector3f forward(orientation[0], orientation[1], orientation[2]); - NzVector3f up(orientation[3], orientation[4], orientation[5]); - NzQuaternionf rotation; - NzVector3f a = NzVector3f::CrossProduct(forward, up); - rotation.x = a.x; - rotation.y = a.y; - rotation.z = a.z; - rotation.w = std::sqrt(forward.SquaredLength() * up.SquaredLength()) + NzVector3f::DotProduct(forward, up); - - return rotation; + return NzQuaternionf::RotationBetween(NzVector3f::Forward(), forward); } -*/ + NzVector3f NzAudio::GetListenerVelocity() { NzVector3f velocity; @@ -113,54 +96,17 @@ bool NzAudio::Initialize() return false; } - // Initialisation du module - device = alcOpenDevice(nullptr); // On choisit le device par défaut - if (!device) + // Initialisation d'OpenGL + if (!NzOpenAL::Initialize()) { - NazaraError("Failed to open default device"); + NazaraError("Failed to initialize OpenAL"); Uninitialize(); return false; } - // Un seul contexte nous suffira - context = alcCreateContext(device, nullptr); - if (!context) - { - NazaraError("Failed to create context"); - Uninitialize(); - - return false; - } - - if (!alcMakeContextCurrent(context)) - { - NazaraError("Failed to activate context"); - Uninitialize(); - - return false; - } - - // Définition de l'orientation - /*{ - NzVector3f forward = NzVector3f::Forward(); - NzVector3f up = NzVector3f::Up(); - - ALfloat orientation[6] = - { - forward.x, forward.y, forward.z, - up.x, up.y, up.z - }; - - alListenerfv(AL_ORIENTATION, orientation); - }*/ - - formats[nzAudioFormat_Mono] = AL_FORMAT_MONO16; - formats[nzAudioFormat_Stereo] = AL_FORMAT_STEREO16; - formats[nzAudioFormat_Quad] = alGetEnumValue("AL_FORMAT_QUAD16"); - formats[nzAudioFormat_5_1] = alGetEnumValue("AL_FORMAT_51CHN16"); - formats[nzAudioFormat_6_1] = alGetEnumValue("AL_FORMAT_61CHN16"); - formats[nzAudioFormat_7_1] = alGetEnumValue("AL_FORMAT_71CHN16"); + // Définition de l'orientation par défaut + SetListenerDirection(NzVector3f::Forward()); // Loaders NzLoaders_sndfile_Register(); @@ -175,7 +121,7 @@ bool NzAudio::IsFormatSupported(nzAudioFormat format) if (format == nzAudioFormat_Unknown) return false; - return formats[format] != 0; + return NzOpenAL::AudioFormat[format] != 0; } bool NzAudio::IsInitialized() @@ -195,10 +141,12 @@ void NzAudio::SetGlobalVolume(float volume) void NzAudio::SetListenerDirection(const NzVector3f& direction) { + NzVector3f up = NzVector3f::Up(); + ALfloat orientation[6] = { direction.x, direction.y, direction.z, - 0.f, 1.f, 0.f + up.x, up.y, up.z }; alListenerfv(AL_ORIENTATION, orientation); @@ -206,10 +154,12 @@ void NzAudio::SetListenerDirection(const NzVector3f& direction) void NzAudio::SetListenerDirection(float dirX, float dirY, float dirZ) { + NzVector3f up = NzVector3f::Up(); + ALfloat orientation[6] = { dirX, dirY, dirZ, - 0.f, 1.f, 0.f + up.x, up.y, up.z }; alListenerfv(AL_ORIENTATION, orientation); @@ -224,7 +174,7 @@ void NzAudio::SetListenerPosition(float x, float y, float z) { alListener3f(AL_POSITION, x, y, z); } -/* + void NzAudio::SetListenerRotation(const NzQuaternionf& rotation) { NzVector3f forward = rotation * NzVector3f::Forward(); @@ -238,7 +188,7 @@ void NzAudio::SetListenerRotation(const NzQuaternionf& rotation) alListenerfv(AL_ORIENTATION, orientation); } -*/ + void NzAudio::SetListenerVelocity(const NzVector3f& velocity) { alListenerfv(AL_VELOCITY, velocity); @@ -271,19 +221,7 @@ void NzAudio::Uninitialize() // Loaders NzLoaders_sndfile_Unregister(); - // Libération d'OpenAL - if (device) - { - if (context) - { - alcMakeContextCurrent(nullptr); - alcDestroyContext(context); - } - - if (!alcCloseDevice(device)) - // Nous n'avons pas pu fermer le device, ce qui signifie qu'il est en cours d'utilisation - NazaraWarning("Failed to close device"); - } + NzOpenAL::Uninitialize(); NazaraNotice("Uninitialized: Audio module"); @@ -291,17 +229,4 @@ void NzAudio::Uninitialize() NzCore::Uninitialize(); } -unsigned int NzAudio::GetOpenALFormat(nzAudioFormat format) -{ - #ifdef NAZARA_DEBUG - if (format == nzAudioFormat_Unknown) - { - NazaraInternalError("Invalid audio format"); - return 0; - } - #endif - - return formats[format]; -} - unsigned int NzAudio::s_moduleReferenceCounter = 0; diff --git a/src/Nazara/Audio/OpenAL.cpp b/src/Nazara/Audio/OpenAL.cpp new file mode 100644 index 000000000..511017f3e --- /dev/null +++ b/src/Nazara/Audio/OpenAL.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include + +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& 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(LoadEntry("alBuffer3f")); + alBuffer3i = reinterpret_cast(LoadEntry("alBuffer3i")); + alBufferData = reinterpret_cast(LoadEntry("alBufferData")); + alBufferf = reinterpret_cast(LoadEntry("alBufferf")); + alBufferfv = reinterpret_cast(LoadEntry("alBufferfv")); + alBufferi = reinterpret_cast(LoadEntry("alBufferi")); + alBufferiv = reinterpret_cast(LoadEntry("alBufferiv")); + alDeleteBuffers = reinterpret_cast(LoadEntry("alDeleteBuffers")); + alDeleteSources = reinterpret_cast(LoadEntry("alDeleteSources")); + alDisable = reinterpret_cast(LoadEntry("alDisable")); + alDistanceModel = reinterpret_cast(LoadEntry("alDistanceModel")); + alDopplerFactor = reinterpret_cast(LoadEntry("alDopplerFactor")); + alDopplerVelocity = reinterpret_cast(LoadEntry("alDopplerVelocity")); + alEnable = reinterpret_cast(LoadEntry("alEnable")); + alGenBuffers = reinterpret_cast(LoadEntry("alGenBuffers")); + alGenSources = reinterpret_cast(LoadEntry("alGenSources")); + alGetBoolean = reinterpret_cast(LoadEntry("alGetBoolean")); + alGetBooleanv = reinterpret_cast(LoadEntry("alGetBooleanv")); + alGetBuffer3f = reinterpret_cast(LoadEntry("alGetBuffer3f")); + alGetBuffer3i = reinterpret_cast(LoadEntry("alGetBuffer3i")); + alGetBufferf = reinterpret_cast(LoadEntry("alGetBufferf")); + alGetBufferfv = reinterpret_cast(LoadEntry("alGetBufferfv")); + alGetBufferi = reinterpret_cast(LoadEntry("alGetBufferi")); + alGetBufferiv = reinterpret_cast(LoadEntry("alGetBufferiv")); + alGetDouble = reinterpret_cast(LoadEntry("alGetDouble")); + alGetDoublev = reinterpret_cast(LoadEntry("alGetDoublev")); + alGetEnumValue = reinterpret_cast(LoadEntry("alGetEnumValue")); + alGetError = reinterpret_cast(LoadEntry("alGetError")); + alGetFloat = reinterpret_cast(LoadEntry("alGetFloat")); + alGetFloatv = reinterpret_cast(LoadEntry("alGetFloatv")); + alGetInteger = reinterpret_cast(LoadEntry("alGetInteger")); + alGetIntegerv = reinterpret_cast(LoadEntry("alGetIntegerv")); + alGetListener3f = reinterpret_cast(LoadEntry("alGetListener3f")); + alGetListener3i = reinterpret_cast(LoadEntry("alGetListener3i")); + alGetListenerf = reinterpret_cast(LoadEntry("alGetListenerf")); + alGetListenerfv = reinterpret_cast(LoadEntry("alGetListenerfv")); + alGetListeneri = reinterpret_cast(LoadEntry("alGetListeneri")); + alGetListeneriv = reinterpret_cast(LoadEntry("alGetListeneriv")); + alGetProcAddress = reinterpret_cast(LoadEntry("alGetProcAddress")); + alGetSource3f = reinterpret_cast(LoadEntry("alGetSource3f")); + alGetSource3i = reinterpret_cast(LoadEntry("alGetSource3i")); + alGetSourcef = reinterpret_cast(LoadEntry("alGetSourcef")); + alGetSourcefv = reinterpret_cast(LoadEntry("alGetSourcefv")); + alGetSourcei = reinterpret_cast(LoadEntry("alGetSourcei")); + alGetSourceiv = reinterpret_cast(LoadEntry("alGetSourceiv")); + alGetString = reinterpret_cast(LoadEntry("alGetString")); + alIsBuffer = reinterpret_cast(LoadEntry("alIsBuffer")); + alIsEnabled = reinterpret_cast(LoadEntry("alIsEnabled")); + alIsExtensionPresent = reinterpret_cast(LoadEntry("alIsExtensionPresent")); + alIsSource = reinterpret_cast(LoadEntry("alIsSource")); + alListener3f = reinterpret_cast(LoadEntry("alListener3f")); + alListener3i = reinterpret_cast(LoadEntry("alListener3i")); + alListenerf = reinterpret_cast(LoadEntry("alListenerf")); + alListenerfv = reinterpret_cast(LoadEntry("alListenerfv")); + alListeneri = reinterpret_cast(LoadEntry("alListeneri")); + alListeneriv = reinterpret_cast(LoadEntry("alListeneriv")); + alSource3f = reinterpret_cast(LoadEntry("alSource3f")); + alSource3i = reinterpret_cast(LoadEntry("alSource3i")); + alSourcef = reinterpret_cast(LoadEntry("alSourcef")); + alSourcefv = reinterpret_cast(LoadEntry("alSourcefv")); + alSourcei = reinterpret_cast(LoadEntry("alSourcei")); + alSourceiv = reinterpret_cast(LoadEntry("alSourceiv")); + alSourcePause = reinterpret_cast(LoadEntry("alSourcePause")); + alSourcePausev = reinterpret_cast(LoadEntry("alSourcePausev")); + alSourcePlay = reinterpret_cast(LoadEntry("alSourcePlay")); + alSourcePlayv = reinterpret_cast(LoadEntry("alSourcePlayv")); + alSourceQueueBuffers = reinterpret_cast(LoadEntry("alSourceQueueBuffers")); + alSourceRewind = reinterpret_cast(LoadEntry("alSourceRewind")); + alSourceRewindv = reinterpret_cast(LoadEntry("alSourceRewindv")); + alSourceStop = reinterpret_cast(LoadEntry("alSourceStop")); + alSourceStopv = reinterpret_cast(LoadEntry("alSourceStopv")); + alSourceUnqueueBuffers = reinterpret_cast(LoadEntry("alSourceUnqueueBuffers")); + alSpeedOfSound = reinterpret_cast(LoadEntry("alSpeedOfSound")); + + // alc + alcCaptureCloseDevice = reinterpret_cast(LoadEntry("alcCaptureCloseDevice")); + alcCaptureOpenDevice = reinterpret_cast(LoadEntry("alcCaptureOpenDevice")); + alcCaptureSamples = reinterpret_cast(LoadEntry("alcCaptureSamples")); + alcCaptureStart = reinterpret_cast(LoadEntry("alcCaptureStart")); + alcCaptureStop = reinterpret_cast(LoadEntry("alcCaptureStop")); + alcCloseDevice = reinterpret_cast(LoadEntry("alcCloseDevice")); + alcCreateContext = reinterpret_cast(LoadEntry("alcCreateContext")); + alcDestroyContext = reinterpret_cast(LoadEntry("alcDestroyContext")); + alcGetContextsDevice = reinterpret_cast(LoadEntry("alcGetContextsDevice")); + alcGetCurrentContext = reinterpret_cast(LoadEntry("alcGetCurrentContext")); + alcGetEnumValue = reinterpret_cast(LoadEntry("alcGetEnumValue")); + alcGetError = reinterpret_cast(LoadEntry("alcGetError")); + alcGetIntegerv = reinterpret_cast(LoadEntry("alcGetIntegerv")); + alcGetProcAddress = reinterpret_cast(LoadEntry("alcGetProcAddress")); + alcGetString = reinterpret_cast(LoadEntry("alcGetString")); + alcIsExtensionPresent = reinterpret_cast(LoadEntry("alcIsExtensionPresent")); + alcMakeContextCurrent = reinterpret_cast(LoadEntry("alcMakeContextCurrent")); + alcOpenDevice = reinterpret_cast(LoadEntry("alcOpenDevice")); + alcProcessContext = reinterpret_cast(LoadEntry("alcProcessContext")); + alcSuspendContext = reinterpret_cast(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& devices) +{ + const char* deviceString = reinterpret_cast(alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER)); + if (!deviceString) + return 0; + + return ParseDevices(deviceString, devices); +} + +unsigned int NzOpenAL::QueryOutputDevices(std::vector& devices) +{ + const char* deviceString = reinterpret_cast(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(alGetString(AL_RENDERER)); + s_vendorName = reinterpret_cast(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(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; diff --git a/src/Nazara/Audio/Sound.cpp b/src/Nazara/Audio/Sound.cpp index 0ecdb8b0d..3ee44bbc6 100644 --- a/src/Nazara/Audio/Sound.cpp +++ b/src/Nazara/Audio/Sound.cpp @@ -5,11 +5,11 @@ #include #include #include +#include #include #include #include #include -#include #include NzSound::NzSound(const NzSoundBuffer* soundBuffer) diff --git a/src/Nazara/Audio/SoundBuffer.cpp b/src/Nazara/Audio/SoundBuffer.cpp index 007be8a60..3f53e46e1 100644 --- a/src/Nazara/Audio/SoundBuffer.cpp +++ b/src/Nazara/Audio/SoundBuffer.cpp @@ -5,10 +5,10 @@ #include #include #include +#include #include #include #include -#include #include ///FIXME: Adapter la création @@ -88,7 +88,7 @@ bool NzSoundBuffer::Create(nzAudioFormat format, unsigned int sampleCount, unsig return false; } - alBufferData(buffer, NzAudio::GetOpenALFormat(format), samples, sampleCount*sizeof(nzInt16), sampleRate); + alBufferData(buffer, NzOpenAL::AudioFormat[format], samples, sampleCount*sizeof(nzInt16), sampleRate); if (alGetError() != AL_NO_ERROR) { @@ -100,7 +100,7 @@ bool NzSoundBuffer::Create(nzAudioFormat format, unsigned int sampleCount, unsig m_impl = new NzSoundBufferImpl; m_impl->buffer = buffer; - m_impl->duration = 1000 * (sampleCount / (format * sampleRate)); + m_impl->duration = (1000*sampleCount / (format * sampleRate)); m_impl->format = format; m_impl->sampleCount = sampleCount; m_impl->sampleRate = sampleRate; diff --git a/src/Nazara/Audio/SoundEmitter.cpp b/src/Nazara/Audio/SoundEmitter.cpp index a67483133..ca1219db1 100644 --- a/src/Nazara/Audio/SoundEmitter.cpp +++ b/src/Nazara/Audio/SoundEmitter.cpp @@ -5,8 +5,8 @@ // http://connect.creativelabs.com/openal/Documentation/OpenAL_Programmers_Guide.pdf #include +#include #include -#include #include NzSoundEmitter::NzSoundEmitter()