Commit 4afeda4b authored by David Reid's avatar David Reid

Remove the OpenAL backend.

parent 2e6c6e66
...@@ -174,10 +174,6 @@ Web Audio / Emscripten ...@@ -174,10 +174,6 @@ Web Audio / Emscripten
of user input. See here for details: https://developers.google.com/web/updates/2017/09/autoplay-policy-changes. Starting of user input. See here for details: https://developers.google.com/web/updates/2017/09/autoplay-policy-changes. Starting
the device may fail if you try to start playback without first handling some kind of user input. the device may fail if you try to start playback without first handling some kind of user input.
OpenAL
------
- Capture is not supported on iOS with OpenAL. Use the Core Audio backend instead.
OPTIONS OPTIONS
======= =======
...@@ -222,9 +218,6 @@ OPTIONS ...@@ -222,9 +218,6 @@ OPTIONS
#define MAL_NO_WEBAUDIO #define MAL_NO_WEBAUDIO
Disables the Web Audio backend. Disables the Web Audio backend.
#define MAL_NO_OPENAL
Disables the OpenAL backend.
#define MAL_NO_NULL #define MAL_NO_NULL
Disables the null backend. Disables the null backend.
...@@ -1233,9 +1226,8 @@ void mal_interleave_pcm_frames(mal_format format, mal_uint32 channels, mal_uint6 ...@@ -1233,9 +1226,8 @@ void mal_interleave_pcm_frames(mal_format format, mal_uint32 channels, mal_uint6
#define MAL_SUPPORT_WEBAUDIO #define MAL_SUPPORT_WEBAUDIO
#endif #endif
// Explicitly disable OpenAL and Null backends for Emscripten because they both use a background thread which is not properly supported right now. // Explicitly disable the Null backend for Emscripten because it uses a background thread which is not properly supported right now.
#if !defined(MAL_EMSCRIPTEN) #if !defined(MAL_EMSCRIPTEN)
#define MAL_SUPPORT_OPENAL
#define MAL_SUPPORT_NULL #define MAL_SUPPORT_NULL
#endif #endif
...@@ -1279,9 +1271,6 @@ void mal_interleave_pcm_frames(mal_format format, mal_uint32 channels, mal_uint6 ...@@ -1279,9 +1271,6 @@ void mal_interleave_pcm_frames(mal_format format, mal_uint32 channels, mal_uint6
#if !defined(MAL_NO_WEBAUDIO) && defined(MAL_SUPPORT_WEBAUDIO) #if !defined(MAL_NO_WEBAUDIO) && defined(MAL_SUPPORT_WEBAUDIO)
#define MAL_ENABLE_WEBAUDIO #define MAL_ENABLE_WEBAUDIO
#endif #endif
#if !defined(MAL_NO_OPENAL) && defined(MAL_SUPPORT_OPENAL)
#define MAL_ENABLE_OPENAL
#endif
#if !defined(MAL_NO_NULL) && defined(MAL_SUPPORT_NULL) #if !defined(MAL_NO_NULL) && defined(MAL_SUPPORT_NULL)
#define MAL_ENABLE_NULL #define MAL_ENABLE_NULL
#endif #endif
...@@ -1312,7 +1301,6 @@ typedef enum ...@@ -1312,7 +1301,6 @@ typedef enum
mal_backend_aaudio, mal_backend_aaudio,
mal_backend_opensl, mal_backend_opensl,
mal_backend_webaudio, mal_backend_webaudio,
mal_backend_openal,
mal_backend_null /* <-- Must always be the last item. Lowest priority, and used as the terminator for backend enumeration. */ mal_backend_null /* <-- Must always be the last item. Lowest priority, and used as the terminator for backend enumeration. */
} mal_backend; } mal_backend;
...@@ -1399,7 +1387,6 @@ typedef struct ...@@ -1399,7 +1387,6 @@ typedef struct
#define MAL_MAX_PERIODS_DSOUND 4 #define MAL_MAX_PERIODS_DSOUND 4
#define MAL_MAX_PERIODS_OPENAL 4
typedef void (* mal_log_proc) (mal_context* pContext, mal_device* pDevice, mal_uint32 logLevel, const char* message); typedef void (* mal_log_proc) (mal_context* pContext, mal_device* pDevice, mal_uint32 logLevel, const char* message);
typedef void (* mal_recv_proc)(mal_device* pDevice, mal_uint32 frameCount, const void* pSamples); typedef void (* mal_recv_proc)(mal_device* pDevice, mal_uint32 frameCount, const void* pSamples);
...@@ -1459,9 +1446,6 @@ typedef union ...@@ -1459,9 +1446,6 @@ typedef union
#ifdef MAL_SUPPORT_WEBAUDIO #ifdef MAL_SUPPORT_WEBAUDIO
char webaudio[32]; // Web Audio always uses default devices for now, but if this changes it'll be a GUID. char webaudio[32]; // Web Audio always uses default devices for now, but if this changes it'll be a GUID.
#endif #endif
#ifdef MAL_SUPPORT_OPENAL
char openal[256]; // OpenAL seems to use human-readable device names as the ID.
#endif
#ifdef MAL_SUPPORT_NULL #ifdef MAL_SUPPORT_NULL
int nullbackend; // The null backend uses an integer for device IDs. int nullbackend; // The null backend uses an integer for device IDs.
#endif #endif
...@@ -1841,93 +1825,6 @@ struct mal_context ...@@ -1841,93 +1825,6 @@ struct mal_context
int _unused; int _unused;
} webaudio; } webaudio;
#endif #endif
#ifdef MAL_SUPPORT_OPENAL
struct
{
/*HMODULE*/ mal_handle hOpenAL; // OpenAL32.dll, etc.
mal_proc alcCreateContext;
mal_proc alcMakeContextCurrent;
mal_proc alcProcessContext;
mal_proc alcSuspendContext;
mal_proc alcDestroyContext;
mal_proc alcGetCurrentContext;
mal_proc alcGetContextsDevice;
mal_proc alcOpenDevice;
mal_proc alcCloseDevice;
mal_proc alcGetError;
mal_proc alcIsExtensionPresent;
mal_proc alcGetProcAddress;
mal_proc alcGetEnumValue;
mal_proc alcGetString;
mal_proc alcGetIntegerv;
mal_proc alcCaptureOpenDevice;
mal_proc alcCaptureCloseDevice;
mal_proc alcCaptureStart;
mal_proc alcCaptureStop;
mal_proc alcCaptureSamples;
mal_proc alEnable;
mal_proc alDisable;
mal_proc alIsEnabled;
mal_proc alGetString;
mal_proc alGetBooleanv;
mal_proc alGetIntegerv;
mal_proc alGetFloatv;
mal_proc alGetDoublev;
mal_proc alGetBoolean;
mal_proc alGetInteger;
mal_proc alGetFloat;
mal_proc alGetDouble;
mal_proc alGetError;
mal_proc alIsExtensionPresent;
mal_proc alGetProcAddress;
mal_proc alGetEnumValue;
mal_proc alGenSources;
mal_proc alDeleteSources;
mal_proc alIsSource;
mal_proc alSourcef;
mal_proc alSource3f;
mal_proc alSourcefv;
mal_proc alSourcei;
mal_proc alSource3i;
mal_proc alSourceiv;
mal_proc alGetSourcef;
mal_proc alGetSource3f;
mal_proc alGetSourcefv;
mal_proc alGetSourcei;
mal_proc alGetSource3i;
mal_proc alGetSourceiv;
mal_proc alSourcePlayv;
mal_proc alSourceStopv;
mal_proc alSourceRewindv;
mal_proc alSourcePausev;
mal_proc alSourcePlay;
mal_proc alSourceStop;
mal_proc alSourceRewind;
mal_proc alSourcePause;
mal_proc alSourceQueueBuffers;
mal_proc alSourceUnqueueBuffers;
mal_proc alGenBuffers;
mal_proc alDeleteBuffers;
mal_proc alIsBuffer;
mal_proc alBufferData;
mal_proc alBufferf;
mal_proc alBuffer3f;
mal_proc alBufferfv;
mal_proc alBufferi;
mal_proc alBuffer3i;
mal_proc alBufferiv;
mal_proc alGetBufferf;
mal_proc alGetBuffer3f;
mal_proc alGetBufferfv;
mal_proc alGetBufferi;
mal_proc alGetBuffer3i;
mal_proc alGetBufferiv;
mal_bool32 isEnumerationSupported : 1;
mal_bool32 isFloat32Supported : 1;
mal_bool32 isMCFormatsSupported : 1;
} openal;
#endif
#ifdef MAL_SUPPORT_NULL #ifdef MAL_SUPPORT_NULL
struct struct
{ {
...@@ -2164,20 +2061,6 @@ MAL_ALIGNED_STRUCT(MAL_SIMD_ALIGNMENT) mal_device ...@@ -2164,20 +2061,6 @@ MAL_ALIGNED_STRUCT(MAL_SIMD_ALIGNMENT) mal_device
int index; /* We use a factory on the JavaScript side to manage devices and use an index for JS/C interop. */ int index; /* We use a factory on the JavaScript side to manage devices and use an index for JS/C interop. */
} webaudio; } webaudio;
#endif #endif
#ifdef MAL_SUPPORT_OPENAL
struct
{
/*ALCcontext**/ mal_ptr pContextALC;
/*ALCdevice**/ mal_ptr pDeviceALC;
/*ALuint*/ mal_uint32 sourceAL;
/*ALuint*/ mal_uint32 buffersAL[MAL_MAX_PERIODS_OPENAL];
/*ALenum*/ mal_uint32 formatAL;
mal_uint32 subBufferSizeInFrames; // This is the size of each of the OpenAL buffers (buffersAL).
mal_uint8* pIntermediaryBuffer; // This is malloc()'d and is used as the destination for reading from the client. Typed as mal_uint8 for easy offsetting.
mal_uint32 iNextBuffer; // The next buffer to unenqueue and then re-enqueue as new data is read.
mal_bool32 breakFromMainLoop;
} openal;
#endif
#ifdef MAL_SUPPORT_NULL #ifdef MAL_SUPPORT_NULL
struct struct
{ {
...@@ -3787,16 +3670,6 @@ mal_uint32 mal_get_standard_sample_rate_priority_index(mal_uint32 sampleRate) ...@@ -3787,16 +3670,6 @@ mal_uint32 mal_get_standard_sample_rate_priority_index(mal_uint32 sampleRate)
#ifdef MAL_ENABLE_WEBAUDIO #ifdef MAL_ENABLE_WEBAUDIO
#define MAL_HAS_WEBAUDIO #define MAL_HAS_WEBAUDIO
#endif #endif
#ifdef MAL_ENABLE_OPENAL
#define MAL_HAS_OPENAL
#ifdef MAL_NO_RUNTIME_LINKING
#ifdef __has_include
#if !__has_include(<AL/al.h>)
#undef MAL_HAS_OPENAL
#endif
#endif
#endif
#endif
#ifdef MAL_ENABLE_NULL #ifdef MAL_ENABLE_NULL
#define MAL_HAS_NULL // Everything supports the null backend. #define MAL_HAS_NULL // Everything supports the null backend.
#endif #endif
...@@ -3818,7 +3691,6 @@ const char* mal_get_backend_name(mal_backend backend) ...@@ -3818,7 +3691,6 @@ const char* mal_get_backend_name(mal_backend backend)
case mal_backend_aaudio: return "AAudio"; case mal_backend_aaudio: return "AAudio";
case mal_backend_opensl: return "OpenSL|ES"; case mal_backend_opensl: return "OpenSL|ES";
case mal_backend_webaudio: return "Web Audio"; case mal_backend_webaudio: return "Web Audio";
case mal_backend_openal: return "OpenAL";
case mal_backend_null: return "Null"; case mal_backend_null: return "Null";
default: return "Unknown"; default: return "Unknown";
} }
...@@ -19627,981 +19499,6 @@ mal_result mal_context_init__webaudio(mal_context* pContext) ...@@ -19627,981 +19499,6 @@ mal_result mal_context_init__webaudio(mal_context* pContext)
#endif // Web Audio #endif // Web Audio
///////////////////////////////////////////////////////////////////////////////
//
// OpenAL Backend
//
///////////////////////////////////////////////////////////////////////////////
#ifdef MAL_HAS_OPENAL
#ifdef MAL_WIN32
#define MAL_AL_APIENTRY __cdecl
#else
#define MAL_AL_APIENTRY
#endif
#ifdef MAL_NO_RUNTIME_LINKING
#if defined(MAL_APPLE)
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#else
#include <AL/al.h>
#include <AL/alc.h>
#endif
#endif
typedef struct mal_ALCdevice_struct mal_ALCdevice;
typedef struct mal_ALCcontext_struct mal_ALCcontext;
typedef char mal_ALCboolean;
typedef char mal_ALCchar;
typedef signed char mal_ALCbyte;
typedef unsigned char mal_ALCubyte;
typedef short mal_ALCshort;
typedef unsigned short mal_ALCushort;
typedef int mal_ALCint;
typedef unsigned int mal_ALCuint;
typedef int mal_ALCsizei;
typedef int mal_ALCenum;
typedef float mal_ALCfloat;
typedef double mal_ALCdouble;
typedef void mal_ALCvoid;
typedef mal_ALCboolean mal_ALboolean;
typedef mal_ALCchar mal_ALchar;
typedef mal_ALCbyte mal_ALbyte;
typedef mal_ALCubyte mal_ALubyte;
typedef mal_ALCshort mal_ALshort;
typedef mal_ALCushort mal_ALushort;
typedef mal_ALCint mal_ALint;
typedef mal_ALCuint mal_ALuint;
typedef mal_ALCsizei mal_ALsizei;
typedef mal_ALCenum mal_ALenum;
typedef mal_ALCfloat mal_ALfloat;
typedef mal_ALCdouble mal_ALdouble;
typedef mal_ALCvoid mal_ALvoid;
#define MAL_ALC_DEVICE_SPECIFIER 0x1005
#define MAL_ALC_CAPTURE_DEVICE_SPECIFIER 0x310
#define MAL_ALC_CAPTURE_SAMPLES 0x312
#define MAL_AL_SOURCE_STATE 0x1010
#define MAL_AL_INITIAL 0x1011
#define MAL_AL_PLAYING 0x1012
#define MAL_AL_PAUSED 0x1013
#define MAL_AL_STOPPED 0x1014
#define MAL_AL_BUFFERS_PROCESSED 0x1016
#define MAL_AL_FORMAT_MONO8 0x1100
#define MAL_AL_FORMAT_MONO16 0x1101
#define MAL_AL_FORMAT_STEREO8 0x1102
#define MAL_AL_FORMAT_STEREO16 0x1103
#define MAL_AL_FORMAT_MONO_FLOAT32 0x10010
#define MAL_AL_FORMAT_STEREO_FLOAT32 0x10011
#define MAL_AL_FORMAT_51CHN16 0x120B
#define MAL_AL_FORMAT_51CHN32 0x120C
#define MAL_AL_FORMAT_51CHN8 0x120A
#define MAL_AL_FORMAT_61CHN16 0x120E
#define MAL_AL_FORMAT_61CHN32 0x120F
#define MAL_AL_FORMAT_61CHN8 0x120D
#define MAL_AL_FORMAT_71CHN16 0x1211
#define MAL_AL_FORMAT_71CHN32 0x1212
#define MAL_AL_FORMAT_71CHN8 0x1210
#define MAL_AL_FORMAT_QUAD16 0x1205
#define MAL_AL_FORMAT_QUAD32 0x1206
#define MAL_AL_FORMAT_QUAD8 0x1204
#define MAL_AL_FORMAT_REAR16 0x1208
#define MAL_AL_FORMAT_REAR32 0x1209
#define MAL_AL_FORMAT_REAR8 0x1207
typedef mal_ALCcontext* (MAL_AL_APIENTRY * MAL_LPALCCREATECONTEXT) (mal_ALCdevice *device, const mal_ALCint *attrlist);
typedef mal_ALCboolean (MAL_AL_APIENTRY * MAL_LPALCMAKECONTEXTCURRENT) (mal_ALCcontext *context);
typedef void (MAL_AL_APIENTRY * MAL_LPALCPROCESSCONTEXT) (mal_ALCcontext *context);
typedef void (MAL_AL_APIENTRY * MAL_LPALCSUSPENDCONTEXT) (mal_ALCcontext *context);
typedef void (MAL_AL_APIENTRY * MAL_LPALCDESTROYCONTEXT) (mal_ALCcontext *context);
typedef mal_ALCcontext* (MAL_AL_APIENTRY * MAL_LPALCGETCURRENTCONTEXT) (void);
typedef mal_ALCdevice* (MAL_AL_APIENTRY * MAL_LPALCGETCONTEXTSDEVICE) (mal_ALCcontext *context);
typedef mal_ALCdevice* (MAL_AL_APIENTRY * MAL_LPALCOPENDEVICE) (const mal_ALCchar *devicename);
typedef mal_ALCboolean (MAL_AL_APIENTRY * MAL_LPALCCLOSEDEVICE) (mal_ALCdevice *device);
typedef mal_ALCenum (MAL_AL_APIENTRY * MAL_LPALCGETERROR) (mal_ALCdevice *device);
typedef mal_ALCboolean (MAL_AL_APIENTRY * MAL_LPALCISEXTENSIONPRESENT) (mal_ALCdevice *device, const mal_ALCchar *extname);
typedef void* (MAL_AL_APIENTRY * MAL_LPALCGETPROCADDRESS) (mal_ALCdevice *device, const mal_ALCchar *funcname);
typedef mal_ALCenum (MAL_AL_APIENTRY * MAL_LPALCGETENUMVALUE) (mal_ALCdevice *device, const mal_ALCchar *enumname);
typedef const mal_ALCchar* (MAL_AL_APIENTRY * MAL_LPALCGETSTRING) (mal_ALCdevice *device, mal_ALCenum param);
typedef void (MAL_AL_APIENTRY * MAL_LPALCGETINTEGERV) (mal_ALCdevice *device, mal_ALCenum param, mal_ALCsizei size, mal_ALCint *values);
typedef mal_ALCdevice* (MAL_AL_APIENTRY * MAL_LPALCCAPTUREOPENDEVICE) (const mal_ALCchar *devicename, mal_ALCuint frequency, mal_ALCenum format, mal_ALCsizei buffersize);
typedef mal_ALCboolean (MAL_AL_APIENTRY * MAL_LPALCCAPTURECLOSEDEVICE) (mal_ALCdevice *device);
typedef void (MAL_AL_APIENTRY * MAL_LPALCCAPTURESTART) (mal_ALCdevice *device);
typedef void (MAL_AL_APIENTRY * MAL_LPALCCAPTURESTOP) (mal_ALCdevice *device);
typedef void (MAL_AL_APIENTRY * MAL_LPALCCAPTURESAMPLES) (mal_ALCdevice *device, mal_ALCvoid *buffer, mal_ALCsizei samples);
typedef void (MAL_AL_APIENTRY * MAL_LPALENABLE) (mal_ALenum capability);
typedef void (MAL_AL_APIENTRY * MAL_LPALDISABLE) (mal_ALenum capability);
typedef mal_ALboolean (MAL_AL_APIENTRY * MAL_LPALISENABLED) (mal_ALenum capability);
typedef const mal_ALchar* (MAL_AL_APIENTRY * MAL_LPALGETSTRING) (mal_ALenum param);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETBOOLEANV) (mal_ALenum param, mal_ALboolean *values);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETINTEGERV) (mal_ALenum param, mal_ALint *values);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETFLOATV) (mal_ALenum param, mal_ALfloat *values);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETDOUBLEV) (mal_ALenum param, mal_ALdouble *values);
typedef mal_ALboolean (MAL_AL_APIENTRY * MAL_LPALGETBOOLEAN) (mal_ALenum param);
typedef mal_ALint (MAL_AL_APIENTRY * MAL_LPALGETINTEGER) (mal_ALenum param);
typedef mal_ALfloat (MAL_AL_APIENTRY * MAL_LPALGETFLOAT) (mal_ALenum param);
typedef mal_ALdouble (MAL_AL_APIENTRY * MAL_LPALGETDOUBLE) (mal_ALenum param);
typedef mal_ALenum (MAL_AL_APIENTRY * MAL_LPALGETERROR) (void);
typedef mal_ALboolean (MAL_AL_APIENTRY * MAL_LPALISEXTENSIONPRESENT) (const mal_ALchar *extname);
typedef void* (MAL_AL_APIENTRY * MAL_LPALGETPROCADDRESS) (const mal_ALchar *fname);
typedef mal_ALenum (MAL_AL_APIENTRY * MAL_LPALGETENUMVALUE) (const mal_ALchar *ename);
typedef void (MAL_AL_APIENTRY * MAL_LPALGENSOURCES) (mal_ALsizei n, mal_ALuint *sources);
typedef void (MAL_AL_APIENTRY * MAL_LPALDELETESOURCES) (mal_ALsizei n, const mal_ALuint *sources);
typedef mal_ALboolean (MAL_AL_APIENTRY * MAL_LPALISSOURCE) (mal_ALuint source);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCEF) (mal_ALuint source, mal_ALenum param, mal_ALfloat value);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCE3F) (mal_ALuint source, mal_ALenum param, mal_ALfloat value1, mal_ALfloat value2, mal_ALfloat value3);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCEFV) (mal_ALuint source, mal_ALenum param, const mal_ALfloat *values);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCEI) (mal_ALuint source, mal_ALenum param, mal_ALint value);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCE3I) (mal_ALuint source, mal_ALenum param, mal_ALint value1, mal_ALint value2, mal_ALint value3);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCEIV) (mal_ALuint source, mal_ALenum param, const mal_ALint *values);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETSOURCEF) (mal_ALuint source, mal_ALenum param, mal_ALfloat *value);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETSOURCE3F) (mal_ALuint source, mal_ALenum param, mal_ALfloat *value1, mal_ALfloat *value2, mal_ALfloat *value3);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETSOURCEFV) (mal_ALuint source, mal_ALenum param, mal_ALfloat *values);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETSOURCEI) (mal_ALuint source, mal_ALenum param, mal_ALint *value);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETSOURCE3I) (mal_ALuint source, mal_ALenum param, mal_ALint *value1, mal_ALint *value2, mal_ALint *value3);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETSOURCEIV) (mal_ALuint source, mal_ALenum param, mal_ALint *values);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCEPLAYV) (mal_ALsizei n, const mal_ALuint *sources);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCESTOPV) (mal_ALsizei n, const mal_ALuint *sources);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCEREWINDV) (mal_ALsizei n, const mal_ALuint *sources);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCEPAUSEV) (mal_ALsizei n, const mal_ALuint *sources);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCEPLAY) (mal_ALuint source);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCESTOP) (mal_ALuint source);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCEREWIND) (mal_ALuint source);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCEPAUSE) (mal_ALuint source);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCEQUEUEBUFFERS) (mal_ALuint source, mal_ALsizei nb, const mal_ALuint *buffers);
typedef void (MAL_AL_APIENTRY * MAL_LPALSOURCEUNQUEUEBUFFERS)(mal_ALuint source, mal_ALsizei nb, mal_ALuint *buffers);
typedef void (MAL_AL_APIENTRY * MAL_LPALGENBUFFERS) (mal_ALsizei n, mal_ALuint *buffers);
typedef void (MAL_AL_APIENTRY * MAL_LPALDELETEBUFFERS) (mal_ALsizei n, const mal_ALuint *buffers);
typedef mal_ALboolean (MAL_AL_APIENTRY * MAL_LPALISBUFFER) (mal_ALuint buffer);
typedef void (MAL_AL_APIENTRY * MAL_LPALBUFFERDATA) (mal_ALuint buffer, mal_ALenum format, const mal_ALvoid *data, mal_ALsizei size, mal_ALsizei freq);
typedef void (MAL_AL_APIENTRY * MAL_LPALBUFFERF) (mal_ALuint buffer, mal_ALenum param, mal_ALfloat value);
typedef void (MAL_AL_APIENTRY * MAL_LPALBUFFER3F) (mal_ALuint buffer, mal_ALenum param, mal_ALfloat value1, mal_ALfloat value2, mal_ALfloat value3);
typedef void (MAL_AL_APIENTRY * MAL_LPALBUFFERFV) (mal_ALuint buffer, mal_ALenum param, const mal_ALfloat *values);
typedef void (MAL_AL_APIENTRY * MAL_LPALBUFFERI) (mal_ALuint buffer, mal_ALenum param, mal_ALint value);
typedef void (MAL_AL_APIENTRY * MAL_LPALBUFFER3I) (mal_ALuint buffer, mal_ALenum param, mal_ALint value1, mal_ALint value2, mal_ALint value3);
typedef void (MAL_AL_APIENTRY * MAL_LPALBUFFERIV) (mal_ALuint buffer, mal_ALenum param, const mal_ALint *values);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETBUFFERF) (mal_ALuint buffer, mal_ALenum param, mal_ALfloat *value);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETBUFFER3F) (mal_ALuint buffer, mal_ALenum param, mal_ALfloat *value1, mal_ALfloat *value2, mal_ALfloat *value3);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETBUFFERFV) (mal_ALuint buffer, mal_ALenum param, mal_ALfloat *values);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETBUFFERI) (mal_ALuint buffer, mal_ALenum param, mal_ALint *value);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETBUFFER3I) (mal_ALuint buffer, mal_ALenum param, mal_ALint *value1, mal_ALint *value2, mal_ALint *value3);
typedef void (MAL_AL_APIENTRY * MAL_LPALGETBUFFERIV) (mal_ALuint buffer, mal_ALenum param, mal_ALint *values);
mal_bool32 mal_context_is_device_id_equal__openal(mal_context* pContext, const mal_device_id* pID0, const mal_device_id* pID1)
{
mal_assert(pContext != NULL);
mal_assert(pID0 != NULL);
mal_assert(pID1 != NULL);
(void)pContext;
return mal_strcmp(pID0->openal, pID1->openal) == 0;
}
mal_result mal_context_enumerate_devices__openal(mal_context* pContext, mal_enum_devices_callback_proc callback, void* pUserData)
{
mal_assert(pContext != NULL);
mal_assert(callback != NULL);
if (pContext->openal.isEnumerationSupported) {
mal_bool32 isTerminated = MAL_FALSE;
// Playback
if (!isTerminated) {
const mal_ALCchar* pPlaybackDeviceNames = ((MAL_LPALCGETSTRING)pContext->openal.alcGetString)(NULL, MAL_ALC_DEVICE_SPECIFIER);
if (pPlaybackDeviceNames == NULL) {
return MAL_NO_DEVICE;
}
// Each device is stored in pDeviceNames, separated by a null-terminator. The string itself is double-null-terminated.
const mal_ALCchar* pNextPlaybackDeviceName = pPlaybackDeviceNames;
while (pNextPlaybackDeviceName[0] != '\0') {
mal_device_info deviceInfo;
mal_zero_object(&deviceInfo);
mal_strncpy_s(deviceInfo.id.openal, sizeof(deviceInfo.id.openal), (const char*)pNextPlaybackDeviceName, (size_t)-1);
mal_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), (const char*)pNextPlaybackDeviceName, (size_t)-1);
mal_bool32 cbResult = callback(pContext, mal_device_type_playback, &deviceInfo, pUserData);
if (cbResult == MAL_FALSE) {
isTerminated = MAL_TRUE;
break;
}
// Move to the next device name.
while (*pNextPlaybackDeviceName != '\0') {
pNextPlaybackDeviceName += 1;
}
// Skip past the null terminator.
pNextPlaybackDeviceName += 1;
};
}
// Capture
if (!isTerminated) {
const mal_ALCchar* pCaptureDeviceNames = ((MAL_LPALCGETSTRING)pContext->openal.alcGetString)(NULL, MAL_ALC_CAPTURE_DEVICE_SPECIFIER);
if (pCaptureDeviceNames == NULL) {
return MAL_NO_DEVICE;
}
const mal_ALCchar* pNextCaptureDeviceName = pCaptureDeviceNames;
while (pNextCaptureDeviceName[0] != '\0') {
mal_device_info deviceInfo;
mal_zero_object(&deviceInfo);
mal_strncpy_s(deviceInfo.id.openal, sizeof(deviceInfo.id.openal), (const char*)pNextCaptureDeviceName, (size_t)-1);
mal_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), (const char*)pNextCaptureDeviceName, (size_t)-1);
mal_bool32 cbResult = callback(pContext, mal_device_type_capture, &deviceInfo, pUserData);
if (cbResult == MAL_FALSE) {
isTerminated = MAL_TRUE;
break;
}
// Move to the next device name.
while (*pNextCaptureDeviceName != '\0') {
pNextCaptureDeviceName += 1;
}
// Skip past the null terminator.
pNextCaptureDeviceName += 1;
};
}
} else {
// Enumeration is not supported. Use default devices.
mal_bool32 cbResult = MAL_TRUE;
// Playback.
if (cbResult) {
mal_device_info deviceInfo;
mal_zero_object(&deviceInfo);
mal_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MAL_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
cbResult = callback(pContext, mal_device_type_playback, &deviceInfo, pUserData);
}
// Capture.
if (cbResult) {
mal_device_info deviceInfo;
mal_zero_object(&deviceInfo);
mal_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MAL_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
cbResult = callback(pContext, mal_device_type_capture, &deviceInfo, pUserData);
}
}
return MAL_SUCCESS;
}
typedef struct
{
mal_device_type deviceType;
const mal_device_id* pDeviceID;
mal_share_mode shareMode;
mal_device_info* pDeviceInfo;
mal_bool32 foundDevice;
} mal_context_get_device_info_enum_callback_data__openal;
mal_bool32 mal_context_get_device_info_enum_callback__openal(mal_context* pContext, mal_device_type deviceType, const mal_device_info* pDeviceInfo, void* pUserData)
{
mal_context_get_device_info_enum_callback_data__openal* pData = (mal_context_get_device_info_enum_callback_data__openal*)pUserData;
mal_assert(pData != NULL);
if (pData->deviceType == deviceType && mal_context_is_device_id_equal__openal(pContext, pData->pDeviceID, &pDeviceInfo->id)) {
mal_strncpy_s(pData->pDeviceInfo->name, sizeof(pData->pDeviceInfo->name), pDeviceInfo->name, (size_t)-1);
pData->foundDevice = MAL_TRUE;
}
// Keep enumerating until we have found the device.
return !pData->foundDevice;
}
mal_result mal_context_get_device_info__openal(mal_context* pContext, mal_device_type deviceType, const mal_device_id* pDeviceID, mal_share_mode shareMode, mal_device_info* pDeviceInfo)
{
mal_assert(pContext != NULL);
(void)shareMode;
// Name / Description
if (pDeviceID == NULL) {
if (deviceType == mal_device_type_playback) {
mal_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MAL_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
} else {
mal_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MAL_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
}
return MAL_SUCCESS;
} else {
mal_context_get_device_info_enum_callback_data__openal data;
data.deviceType = deviceType;
data.pDeviceID = pDeviceID;
data.shareMode = shareMode;
data.pDeviceInfo = pDeviceInfo;
data.foundDevice = MAL_FALSE;
mal_result result = mal_context_enumerate_devices__openal(pContext, mal_context_get_device_info_enum_callback__openal, &data);
if (result != MAL_SUCCESS) {
return result;
}
if (!data.foundDevice) {
return MAL_NO_DEVICE;
}
}
// mini_al's OpenAL backend only supports:
// - mono and stereo
// - u8, s16 and f32
// - All standard sample rates
pDeviceInfo->minChannels = 1;
pDeviceInfo->maxChannels = 2;
pDeviceInfo->minSampleRate = MAL_MIN_SAMPLE_RATE;
pDeviceInfo->maxSampleRate = MAL_MAX_SAMPLE_RATE;
pDeviceInfo->formatCount = 2;
pDeviceInfo->formats[0] = mal_format_u8;
pDeviceInfo->formats[1] = mal_format_s16;
if (pContext->openal.isFloat32Supported) {
pDeviceInfo->formats[pDeviceInfo->formatCount] = mal_format_f32;
pDeviceInfo->formatCount += 1;
}
return MAL_SUCCESS;
}
void mal_device_uninit__openal(mal_device* pDevice)
{
mal_assert(pDevice != NULL);
// Delete buffers and source first.
((MAL_LPALCMAKECONTEXTCURRENT)pDevice->pContext->openal.alcMakeContextCurrent)((mal_ALCcontext*)pDevice->openal.pContextALC);
if (pDevice->openal.sourceAL != 0) {
((MAL_LPALDELETESOURCES)pDevice->pContext->openal.alDeleteSources)(1, (const mal_ALuint*)&pDevice->openal.sourceAL);
}
if (pDevice->periods > 0 && pDevice->openal.buffersAL[0] != 0) {
((MAL_LPALDELETEBUFFERS)pDevice->pContext->openal.alDeleteBuffers)(pDevice->periods, (const mal_ALuint*)pDevice->openal.buffersAL);
}
// Now that resources have been deleted we can destroy the OpenAL context and close the device.
((MAL_LPALCMAKECONTEXTCURRENT)pDevice->pContext->openal.alcMakeContextCurrent)(NULL);
((MAL_LPALCDESTROYCONTEXT)pDevice->pContext->openal.alcDestroyContext)((mal_ALCcontext*)pDevice->openal.pContextALC);
if (pDevice->type == mal_device_type_playback) {
((MAL_LPALCCLOSEDEVICE)pDevice->pContext->openal.alcCloseDevice)((mal_ALCdevice*)pDevice->openal.pDeviceALC);
} else {
((MAL_LPALCCAPTURECLOSEDEVICE)pDevice->pContext->openal.alcCaptureCloseDevice)((mal_ALCdevice*)pDevice->openal.pDeviceALC);
}
mal_free(pDevice->openal.pIntermediaryBuffer);
}
mal_result mal_device_init__openal(mal_context* pContext, mal_device_type type, const mal_device_id* pDeviceID, const mal_device_config* pConfig, mal_device* pDevice)
{
if (pDevice->periods > MAL_MAX_PERIODS_OPENAL) {
pDevice->periods = MAL_MAX_PERIODS_OPENAL;
}
// Try calculating an appropriate default buffer size.
if (pDevice->bufferSizeInFrames == 0) {
pDevice->bufferSizeInFrames = mal_calculate_buffer_size_in_frames_from_milliseconds(pDevice->bufferSizeInMilliseconds, pDevice->sampleRate);
if (pDevice->usingDefaultBufferSize) {
float bufferSizeScaleFactor = 3;
pDevice->bufferSizeInFrames = mal_scale_buffer_size(pDevice->bufferSizeInFrames, bufferSizeScaleFactor);
}
}
mal_ALCsizei bufferSizeInSamplesAL = pDevice->bufferSizeInFrames;
mal_ALCuint frequencyAL = pConfig->sampleRate;
mal_uint32 channelsAL = 0;
// OpenAL currently only supports only mono and stereo. TODO: Check for the AL_EXT_MCFORMATS extension and use one of those formats for quad, 5.1, etc.
mal_ALCenum formatAL = 0;
if (pConfig->channels == 1) {
// Mono.
channelsAL = 1;
if (pConfig->format == mal_format_f32) {
if (pContext->openal.isFloat32Supported) {
formatAL = MAL_AL_FORMAT_MONO_FLOAT32;
} else {
formatAL = MAL_AL_FORMAT_MONO16;
}
} else if (pConfig->format == mal_format_s32) {
formatAL = MAL_AL_FORMAT_MONO16;
} else if (pConfig->format == mal_format_s24) {
formatAL = MAL_AL_FORMAT_MONO16;
} else if (pConfig->format == mal_format_s16) {
formatAL = MAL_AL_FORMAT_MONO16;
} else if (pConfig->format == mal_format_u8) {
formatAL = MAL_AL_FORMAT_MONO8;
}
} else {
// Stereo.
channelsAL = 2;
if (pConfig->format == mal_format_f32) {
if (pContext->openal.isFloat32Supported) {
formatAL = MAL_AL_FORMAT_STEREO_FLOAT32;
} else {
formatAL = MAL_AL_FORMAT_STEREO16;
}
} else if (pConfig->format == mal_format_s32) {
formatAL = MAL_AL_FORMAT_STEREO16;
} else if (pConfig->format == mal_format_s24) {
formatAL = MAL_AL_FORMAT_STEREO16;
} else if (pConfig->format == mal_format_s16) {
formatAL = MAL_AL_FORMAT_STEREO16;
} else if (pConfig->format == mal_format_u8) {
formatAL = MAL_AL_FORMAT_STEREO8;
}
}
if (formatAL == 0) {
return mal_context_post_error(pContext, NULL, MAL_LOG_LEVEL_ERROR, "[OpenAL] Format not supported.", MAL_FORMAT_NOT_SUPPORTED);
}
bufferSizeInSamplesAL *= channelsAL;
// OpenAL feels a bit unintuitive to me... The global object is a device, and it would appear that each device can have
// many context's...
mal_ALCdevice* pDeviceALC = NULL;
if (type == mal_device_type_playback) {
pDeviceALC = ((MAL_LPALCOPENDEVICE)pContext->openal.alcOpenDevice)((pDeviceID == NULL) ? NULL : pDeviceID->openal);
} else {
pDeviceALC = ((MAL_LPALCCAPTUREOPENDEVICE)pContext->openal.alcCaptureOpenDevice)((pDeviceID == NULL) ? NULL : pDeviceID->openal, frequencyAL, formatAL, bufferSizeInSamplesAL);
}
if (pDeviceALC == NULL) {
return mal_context_post_error(pContext, NULL, MAL_LOG_LEVEL_ERROR, "[OpenAL] Failed to open device.", MAL_FAILED_TO_INIT_BACKEND);
}
// A context is only required for playback.
mal_ALCcontext* pContextALC = NULL;
if (pDevice->type == mal_device_type_playback) {
pContextALC = ((MAL_LPALCCREATECONTEXT)pContext->openal.alcCreateContext)(pDeviceALC, NULL);
if (pContextALC == NULL) {
((MAL_LPALCCLOSEDEVICE)pDevice->pContext->openal.alcCloseDevice)(pDeviceALC);
return mal_context_post_error(pContext, NULL, MAL_LOG_LEVEL_ERROR, "[OpenAL] Failed to open OpenAL context.", MAL_FAILED_TO_INIT_BACKEND);
}
((MAL_LPALCMAKECONTEXTCURRENT)pDevice->pContext->openal.alcMakeContextCurrent)(pContextALC);
mal_ALuint sourceAL;
((MAL_LPALGENSOURCES)pDevice->pContext->openal.alGenSources)(1, &sourceAL);
pDevice->openal.sourceAL = sourceAL;
// We create the buffers, but only fill and queue them when the device is started.
mal_ALuint buffersAL[MAL_MAX_PERIODS_OPENAL];
((MAL_LPALGENBUFFERS)pDevice->pContext->openal.alGenBuffers)(pDevice->periods, buffersAL);
for (mal_uint32 i = 0; i < pDevice->periods; ++i) {
pDevice->openal.buffersAL[i] = buffersAL[i];
}
}
pDevice->internalChannels = channelsAL;
pDevice->internalSampleRate = frequencyAL;
switch (formatAL)
{
case MAL_AL_FORMAT_MONO8:
case MAL_AL_FORMAT_STEREO8:
case MAL_AL_FORMAT_REAR8:
case MAL_AL_FORMAT_QUAD8:
case MAL_AL_FORMAT_51CHN8:
case MAL_AL_FORMAT_61CHN8:
case MAL_AL_FORMAT_71CHN8:
{
pDevice->internalFormat = mal_format_u8;
} break;
case MAL_AL_FORMAT_MONO16:
case MAL_AL_FORMAT_STEREO16:
case MAL_AL_FORMAT_REAR16:
case MAL_AL_FORMAT_QUAD16:
case MAL_AL_FORMAT_51CHN16:
case MAL_AL_FORMAT_61CHN16:
case MAL_AL_FORMAT_71CHN16:
{
pDevice->internalFormat = mal_format_s16;
} break;
case MAL_AL_FORMAT_REAR32:
case MAL_AL_FORMAT_QUAD32:
case MAL_AL_FORMAT_51CHN32:
case MAL_AL_FORMAT_61CHN32:
case MAL_AL_FORMAT_71CHN32:
{
pDevice->internalFormat = mal_format_s32;
} break;
case MAL_AL_FORMAT_MONO_FLOAT32:
case MAL_AL_FORMAT_STEREO_FLOAT32:
{
pDevice->internalFormat = mal_format_f32;
} break;
}
// From what I can tell, the ordering of channels is fixed for OpenAL.
switch (formatAL)
{
case MAL_AL_FORMAT_MONO8:
case MAL_AL_FORMAT_MONO16:
case MAL_AL_FORMAT_MONO_FLOAT32:
{
pDevice->internalChannelMap[0] = MAL_CHANNEL_FRONT_CENTER;
} break;
case MAL_AL_FORMAT_STEREO8:
case MAL_AL_FORMAT_STEREO16:
case MAL_AL_FORMAT_STEREO_FLOAT32:
{
pDevice->internalChannelMap[0] = MAL_CHANNEL_FRONT_LEFT;
pDevice->internalChannelMap[1] = MAL_CHANNEL_FRONT_RIGHT;
} break;
case MAL_AL_FORMAT_REAR8:
case MAL_AL_FORMAT_REAR16:
case MAL_AL_FORMAT_REAR32:
{
pDevice->internalChannelMap[0] = MAL_CHANNEL_BACK_LEFT;
pDevice->internalChannelMap[1] = MAL_CHANNEL_BACK_RIGHT;
} break;
case MAL_AL_FORMAT_QUAD8:
case MAL_AL_FORMAT_QUAD16:
case MAL_AL_FORMAT_QUAD32:
{
pDevice->internalChannelMap[0] = MAL_CHANNEL_FRONT_LEFT;
pDevice->internalChannelMap[1] = MAL_CHANNEL_FRONT_RIGHT;
pDevice->internalChannelMap[2] = MAL_CHANNEL_BACK_LEFT;
pDevice->internalChannelMap[3] = MAL_CHANNEL_BACK_RIGHT;
} break;
case MAL_AL_FORMAT_51CHN8:
case MAL_AL_FORMAT_51CHN16:
case MAL_AL_FORMAT_51CHN32:
{
pDevice->internalChannelMap[0] = MAL_CHANNEL_FRONT_LEFT;
pDevice->internalChannelMap[1] = MAL_CHANNEL_FRONT_RIGHT;
pDevice->internalChannelMap[2] = MAL_CHANNEL_FRONT_CENTER;
pDevice->internalChannelMap[3] = MAL_CHANNEL_LFE;
pDevice->internalChannelMap[4] = MAL_CHANNEL_BACK_LEFT;
pDevice->internalChannelMap[5] = MAL_CHANNEL_BACK_RIGHT;
} break;
case MAL_AL_FORMAT_61CHN8:
case MAL_AL_FORMAT_61CHN16:
case MAL_AL_FORMAT_61CHN32:
{
pDevice->internalChannelMap[0] = MAL_CHANNEL_FRONT_LEFT;
pDevice->internalChannelMap[1] = MAL_CHANNEL_FRONT_RIGHT;
pDevice->internalChannelMap[2] = MAL_CHANNEL_FRONT_CENTER;
pDevice->internalChannelMap[3] = MAL_CHANNEL_LFE;
pDevice->internalChannelMap[4] = MAL_CHANNEL_BACK_CENTER;
pDevice->internalChannelMap[5] = MAL_CHANNEL_SIDE_LEFT;
pDevice->internalChannelMap[6] = MAL_CHANNEL_SIDE_RIGHT;
} break;
case MAL_AL_FORMAT_71CHN8:
case MAL_AL_FORMAT_71CHN16:
case MAL_AL_FORMAT_71CHN32:
{
pDevice->internalChannelMap[0] = MAL_CHANNEL_FRONT_LEFT;
pDevice->internalChannelMap[1] = MAL_CHANNEL_FRONT_RIGHT;
pDevice->internalChannelMap[2] = MAL_CHANNEL_FRONT_CENTER;
pDevice->internalChannelMap[3] = MAL_CHANNEL_LFE;
pDevice->internalChannelMap[4] = MAL_CHANNEL_BACK_LEFT;
pDevice->internalChannelMap[5] = MAL_CHANNEL_BACK_RIGHT;
pDevice->internalChannelMap[6] = MAL_CHANNEL_SIDE_LEFT;
pDevice->internalChannelMap[7] = MAL_CHANNEL_SIDE_RIGHT;
} break;
default: break;
}
pDevice->openal.pDeviceALC = pDeviceALC;
pDevice->openal.pContextALC = pContextALC;
pDevice->openal.formatAL = formatAL;
pDevice->openal.subBufferSizeInFrames = pDevice->bufferSizeInFrames / pDevice->periods;
pDevice->openal.pIntermediaryBuffer = (mal_uint8*)mal_malloc(pDevice->openal.subBufferSizeInFrames * channelsAL * mal_get_bytes_per_sample(pDevice->internalFormat));
if (pDevice->openal.pIntermediaryBuffer == NULL) {
mal_device_uninit__openal(pDevice);
return mal_context_post_error(pContext, NULL, MAL_LOG_LEVEL_ERROR, "[OpenAL] Failed to allocate memory for intermediary buffer.", MAL_OUT_OF_MEMORY);
}
return MAL_SUCCESS;
}
mal_result mal_device_start__openal(mal_device* pDevice)
{
mal_assert(pDevice != NULL);
if (pDevice->type == mal_device_type_playback) {
// Playback.
//
// When starting playback we want to ensure each buffer is filled and queued before playing the source.
pDevice->openal.iNextBuffer = 0;
((MAL_LPALCMAKECONTEXTCURRENT)pDevice->pContext->openal.alcMakeContextCurrent)((mal_ALCcontext*)pDevice->openal.pContextALC);
for (mal_uint32 i = 0; i < pDevice->periods; ++i) {
mal_device__read_frames_from_client(pDevice, pDevice->openal.subBufferSizeInFrames, pDevice->openal.pIntermediaryBuffer);
mal_ALuint bufferAL = pDevice->openal.buffersAL[i];
((MAL_LPALBUFFERDATA)pDevice->pContext->openal.alBufferData)(bufferAL, pDevice->openal.formatAL, pDevice->openal.pIntermediaryBuffer, pDevice->openal.subBufferSizeInFrames * pDevice->internalChannels * mal_get_bytes_per_sample(pDevice->internalFormat), pDevice->internalSampleRate);
((MAL_LPALSOURCEQUEUEBUFFERS)pDevice->pContext->openal.alSourceQueueBuffers)(pDevice->openal.sourceAL, 1, &bufferAL);
}
// Start the source only after filling and queueing each buffer.
((MAL_LPALSOURCEPLAY)pDevice->pContext->openal.alSourcePlay)(pDevice->openal.sourceAL);
} else {
// Capture.
((MAL_LPALCCAPTURESTART)pDevice->pContext->openal.alcCaptureStart)((mal_ALCdevice*)pDevice->openal.pDeviceALC);
}
return MAL_SUCCESS;
}
mal_result mal_device_stop__openal(mal_device* pDevice)
{
mal_assert(pDevice != NULL);
if (pDevice->type == mal_device_type_playback) {
((MAL_LPALCMAKECONTEXTCURRENT)pDevice->pContext->openal.alcMakeContextCurrent)((mal_ALCcontext*)pDevice->openal.pContextALC);
((MAL_LPALSOURCESTOP)pDevice->pContext->openal.alSourceStop)(pDevice->openal.sourceAL);
} else {
((MAL_LPALCCAPTURESTOP)pDevice->pContext->openal.alcCaptureStop)((mal_ALCdevice*)pDevice->openal.pDeviceALC);
}
return MAL_SUCCESS;
}
mal_result mal_device_break_main_loop__openal(mal_device* pDevice)
{
mal_assert(pDevice != NULL);
pDevice->openal.breakFromMainLoop = MAL_TRUE;
return MAL_SUCCESS;
}
mal_uint32 mal_device__get_available_frames__openal(mal_device* pDevice)
{
mal_assert(pDevice != NULL);
if (pDevice->type == mal_device_type_playback) {
((MAL_LPALCMAKECONTEXTCURRENT)pDevice->pContext->openal.alcMakeContextCurrent)((mal_ALCcontext*)pDevice->openal.pContextALC);
mal_ALint processedBufferCount = 0;
((MAL_LPALGETSOURCEI)pDevice->pContext->openal.alGetSourcei)(pDevice->openal.sourceAL, MAL_AL_BUFFERS_PROCESSED, &processedBufferCount);
return processedBufferCount * pDevice->openal.subBufferSizeInFrames;
} else {
mal_ALint samplesAvailable = 0;
((MAL_LPALCGETINTEGERV)pDevice->pContext->openal.alcGetIntegerv)((mal_ALCdevice*)pDevice->openal.pDeviceALC, MAL_ALC_CAPTURE_SAMPLES, 1, &samplesAvailable);
return samplesAvailable / pDevice->channels;
}
}
mal_uint32 mal_device__wait_for_frames__openal(mal_device* pDevice)
{
mal_assert(pDevice != NULL);
while (!pDevice->openal.breakFromMainLoop) {
mal_uint32 framesAvailable = mal_device__get_available_frames__openal(pDevice);
if (framesAvailable > 0) {
return framesAvailable;
}
mal_sleep(1);
}
// We'll get here if the loop was terminated. When capturing we want to return whatever is available. For playback we just drop it.
if (pDevice->type == mal_device_type_playback) {
return 0;
} else {
return mal_device__get_available_frames__openal(pDevice);
}
}
mal_result mal_device_main_loop__openal(mal_device* pDevice)
{
mal_assert(pDevice != NULL);
pDevice->openal.breakFromMainLoop = MAL_FALSE;
while (!pDevice->openal.breakFromMainLoop) {
mal_uint32 framesAvailable = mal_device__wait_for_frames__openal(pDevice);
if (framesAvailable == 0) {
continue;
}
// If it's a playback device, don't bother grabbing more data if the device is being stopped.
if (pDevice->openal.breakFromMainLoop && pDevice->type == mal_device_type_playback) {
return MAL_FALSE;
}
if (pDevice->type == mal_device_type_playback) {
while (framesAvailable > 0) {
mal_uint32 framesToRead = (framesAvailable > pDevice->openal.subBufferSizeInFrames) ? pDevice->openal.subBufferSizeInFrames : framesAvailable;
mal_ALuint bufferAL = pDevice->openal.buffersAL[pDevice->openal.iNextBuffer];
pDevice->openal.iNextBuffer = (pDevice->openal.iNextBuffer + 1) % pDevice->periods;
mal_device__read_frames_from_client(pDevice, framesToRead, pDevice->openal.pIntermediaryBuffer);
((MAL_LPALCMAKECONTEXTCURRENT)pDevice->pContext->openal.alcMakeContextCurrent)((mal_ALCcontext*)pDevice->openal.pContextALC);
((MAL_LPALSOURCEUNQUEUEBUFFERS)pDevice->pContext->openal.alSourceUnqueueBuffers)(pDevice->openal.sourceAL, 1, &bufferAL);
((MAL_LPALBUFFERDATA)pDevice->pContext->openal.alBufferData)(bufferAL, pDevice->openal.formatAL, pDevice->openal.pIntermediaryBuffer, pDevice->openal.subBufferSizeInFrames * pDevice->internalChannels * mal_get_bytes_per_sample(pDevice->internalFormat), pDevice->internalSampleRate);
((MAL_LPALSOURCEQUEUEBUFFERS)pDevice->pContext->openal.alSourceQueueBuffers)(pDevice->openal.sourceAL, 1, &bufferAL);
framesAvailable -= framesToRead;
}
// There's a chance the source has stopped playing due to there not being any buffer's queue. Make sure it's restarted.
mal_ALenum state;
((MAL_LPALGETSOURCEI)pDevice->pContext->openal.alGetSourcei)(pDevice->openal.sourceAL, MAL_AL_SOURCE_STATE, &state);
if (state != MAL_AL_PLAYING) {
((MAL_LPALSOURCEPLAY)pDevice->pContext->openal.alSourcePlay)(pDevice->openal.sourceAL);
}
} else {
while (framesAvailable > 0) {
mal_uint32 framesToSend = (framesAvailable > pDevice->openal.subBufferSizeInFrames) ? pDevice->openal.subBufferSizeInFrames : framesAvailable;
((MAL_LPALCCAPTURESAMPLES)pDevice->pContext->openal.alcCaptureSamples)((mal_ALCdevice*)pDevice->openal.pDeviceALC, pDevice->openal.pIntermediaryBuffer, framesToSend);
mal_device__send_frames_to_client(pDevice, framesToSend, pDevice->openal.pIntermediaryBuffer);
framesAvailable -= framesToSend;
}
}
}
return MAL_SUCCESS;
}
mal_result mal_context_uninit__openal(mal_context* pContext)
{
mal_assert(pContext != NULL);
mal_assert(pContext->backend == mal_backend_openal);
#ifndef MAL_NO_RUNTIME_LINKING
mal_dlclose(pContext->openal.hOpenAL);
#endif
return MAL_SUCCESS;
}
mal_result mal_context_init__openal(mal_context* pContext)
{
mal_assert(pContext != NULL);
#ifndef MAL_NO_RUNTIME_LINKING
const char* libNames[] = {
#if defined(MAL_WIN32)
"OpenAL32.dll",
"soft_oal.dll"
#endif
#if defined(MAL_UNIX) && !defined(MAL_APPLE)
"libopenal.so",
"libopenal.so.1"
#endif
#if defined(MAL_APPLE)
"OpenAL.framework/OpenAL"
#endif
};
for (size_t i = 0; i < mal_countof(libNames); ++i) {
pContext->openal.hOpenAL = mal_dlopen(libNames[i]);
if (pContext->openal.hOpenAL != NULL) {
break;
}
}
if (pContext->openal.hOpenAL == NULL) {
return MAL_FAILED_TO_INIT_BACKEND;
}
pContext->openal.alcCreateContext = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcCreateContext");
pContext->openal.alcMakeContextCurrent = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcMakeContextCurrent");
pContext->openal.alcProcessContext = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcProcessContext");
pContext->openal.alcSuspendContext = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcSuspendContext");
pContext->openal.alcDestroyContext = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcDestroyContext");
pContext->openal.alcGetCurrentContext = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcGetCurrentContext");
pContext->openal.alcGetContextsDevice = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcGetContextsDevice");
pContext->openal.alcOpenDevice = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcOpenDevice");
pContext->openal.alcCloseDevice = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcCloseDevice");
pContext->openal.alcGetError = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcGetError");
pContext->openal.alcIsExtensionPresent = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcIsExtensionPresent");
pContext->openal.alcGetProcAddress = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcGetProcAddress");
pContext->openal.alcGetEnumValue = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcGetEnumValue");
pContext->openal.alcGetString = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcGetString");
pContext->openal.alcGetIntegerv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcGetIntegerv");
pContext->openal.alcCaptureOpenDevice = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcCaptureOpenDevice");
pContext->openal.alcCaptureCloseDevice = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcCaptureCloseDevice");
pContext->openal.alcCaptureStart = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcCaptureStart");
pContext->openal.alcCaptureStop = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcCaptureStop");
pContext->openal.alcCaptureSamples = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alcCaptureSamples");
pContext->openal.alEnable = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alEnable");
pContext->openal.alDisable = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alDisable");
pContext->openal.alIsEnabled = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alIsEnabled");
pContext->openal.alGetString = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetString");
pContext->openal.alGetBooleanv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetBooleanv");
pContext->openal.alGetIntegerv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetIntegerv");
pContext->openal.alGetFloatv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetFloatv");
pContext->openal.alGetDoublev = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetDoublev");
pContext->openal.alGetBoolean = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetBoolean");
pContext->openal.alGetInteger = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetInteger");
pContext->openal.alGetFloat = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetFloat");
pContext->openal.alGetDouble = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetDouble");
pContext->openal.alGetError = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetError");
pContext->openal.alIsExtensionPresent = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alIsExtensionPresent");
pContext->openal.alGetProcAddress = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetProcAddress");
pContext->openal.alGetEnumValue = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetEnumValue");
pContext->openal.alGenSources = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGenSources");
pContext->openal.alDeleteSources = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alDeleteSources");
pContext->openal.alIsSource = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alIsSource");
pContext->openal.alSourcef = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSourcef");
pContext->openal.alSource3f = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSource3f");
pContext->openal.alSourcefv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSourcefv");
pContext->openal.alSourcei = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSourcei");
pContext->openal.alSource3i = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSource3i");
pContext->openal.alSourceiv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSourceiv");
pContext->openal.alGetSourcef = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetSourcef");
pContext->openal.alGetSource3f = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetSource3f");
pContext->openal.alGetSourcefv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetSourcefv");
pContext->openal.alGetSourcei = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetSourcei");
pContext->openal.alGetSource3i = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetSource3i");
pContext->openal.alGetSourceiv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetSourceiv");
pContext->openal.alSourcePlayv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSourcePlayv");
pContext->openal.alSourceStopv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSourceStopv");
pContext->openal.alSourceRewindv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSourceRewindv");
pContext->openal.alSourcePausev = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSourcePausev");
pContext->openal.alSourcePlay = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSourcePlay");
pContext->openal.alSourceStop = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSourceStop");
pContext->openal.alSourceRewind = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSourceRewind");
pContext->openal.alSourcePause = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSourcePause");
pContext->openal.alSourceQueueBuffers = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSourceQueueBuffers");
pContext->openal.alSourceUnqueueBuffers = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alSourceUnqueueBuffers");
pContext->openal.alGenBuffers = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGenBuffers");
pContext->openal.alDeleteBuffers = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alDeleteBuffers");
pContext->openal.alIsBuffer = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alIsBuffer");
pContext->openal.alBufferData = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alBufferData");
pContext->openal.alBufferf = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alBufferf");
pContext->openal.alBuffer3f = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alBuffer3f");
pContext->openal.alBufferfv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alBufferfv");
pContext->openal.alBufferi = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alBufferi");
pContext->openal.alBuffer3i = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alBuffer3i");
pContext->openal.alBufferiv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alBufferiv");
pContext->openal.alGetBufferf = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetBufferf");
pContext->openal.alGetBuffer3f = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetBuffer3f");
pContext->openal.alGetBufferfv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetBufferfv");
pContext->openal.alGetBufferi = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetBufferi");
pContext->openal.alGetBuffer3i = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetBuffer3i");
pContext->openal.alGetBufferiv = (mal_proc)mal_dlsym(pContext->openal.hOpenAL, "alGetBufferiv");
#else
pContext->openal.alcCreateContext = (mal_proc)alcCreateContext;
pContext->openal.alcMakeContextCurrent = (mal_proc)alcMakeContextCurrent;
pContext->openal.alcProcessContext = (mal_proc)alcProcessContext;
pContext->openal.alcSuspendContext = (mal_proc)alcSuspendContext;
pContext->openal.alcDestroyContext = (mal_proc)alcDestroyContext;
pContext->openal.alcGetCurrentContext = (mal_proc)alcGetCurrentContext;
pContext->openal.alcGetContextsDevice = (mal_proc)alcGetContextsDevice;
pContext->openal.alcOpenDevice = (mal_proc)alcOpenDevice;
pContext->openal.alcCloseDevice = (mal_proc)alcCloseDevice;
pContext->openal.alcGetError = (mal_proc)alcGetError;
pContext->openal.alcIsExtensionPresent = (mal_proc)alcIsExtensionPresent;
pContext->openal.alcGetProcAddress = (mal_proc)alcGetProcAddress;
pContext->openal.alcGetEnumValue = (mal_proc)alcGetEnumValue;
pContext->openal.alcGetString = (mal_proc)alcGetString;
pContext->openal.alcGetIntegerv = (mal_proc)alcGetIntegerv;
pContext->openal.alcCaptureOpenDevice = (mal_proc)alcCaptureOpenDevice;
pContext->openal.alcCaptureCloseDevice = (mal_proc)alcCaptureCloseDevice;
pContext->openal.alcCaptureStart = (mal_proc)alcCaptureStart;
pContext->openal.alcCaptureStop = (mal_proc)alcCaptureStop;
pContext->openal.alcCaptureSamples = (mal_proc)alcCaptureSamples;
pContext->openal.alEnable = (mal_proc)alEnable;
pContext->openal.alDisable = (mal_proc)alDisable;
pContext->openal.alIsEnabled = (mal_proc)alIsEnabled;
pContext->openal.alGetString = (mal_proc)alGetString;
pContext->openal.alGetBooleanv = (mal_proc)alGetBooleanv;
pContext->openal.alGetIntegerv = (mal_proc)alGetIntegerv;
pContext->openal.alGetFloatv = (mal_proc)alGetFloatv;
pContext->openal.alGetDoublev = (mal_proc)alGetDoublev;
pContext->openal.alGetBoolean = (mal_proc)alGetBoolean;
pContext->openal.alGetInteger = (mal_proc)alGetInteger;
pContext->openal.alGetFloat = (mal_proc)alGetFloat;
pContext->openal.alGetDouble = (mal_proc)alGetDouble;
pContext->openal.alGetError = (mal_proc)alGetError;
pContext->openal.alIsExtensionPresent = (mal_proc)alIsExtensionPresent;
pContext->openal.alGetProcAddress = (mal_proc)alGetProcAddress;
pContext->openal.alGetEnumValue = (mal_proc)alGetEnumValue;
pContext->openal.alGenSources = (mal_proc)alGenSources;
pContext->openal.alDeleteSources = (mal_proc)alDeleteSources;
pContext->openal.alIsSource = (mal_proc)alIsSource;
pContext->openal.alSourcef = (mal_proc)alSourcef;
pContext->openal.alSource3f = (mal_proc)alSource3f;
pContext->openal.alSourcefv = (mal_proc)alSourcefv;
pContext->openal.alSourcei = (mal_proc)alSourcei;
pContext->openal.alSource3i = (mal_proc)alSource3i;
pContext->openal.alSourceiv = (mal_proc)alSourceiv;
pContext->openal.alGetSourcef = (mal_proc)alGetSourcef;
pContext->openal.alGetSource3f = (mal_proc)alGetSource3f;
pContext->openal.alGetSourcefv = (mal_proc)alGetSourcefv;
pContext->openal.alGetSourcei = (mal_proc)alGetSourcei;
pContext->openal.alGetSource3i = (mal_proc)alGetSource3i;
pContext->openal.alGetSourceiv = (mal_proc)alGetSourceiv;
pContext->openal.alSourcePlayv = (mal_proc)alSourcePlayv;
pContext->openal.alSourceStopv = (mal_proc)alSourceStopv;
pContext->openal.alSourceRewindv = (mal_proc)alSourceRewindv;
pContext->openal.alSourcePausev = (mal_proc)alSourcePausev;
pContext->openal.alSourcePlay = (mal_proc)alSourcePlay;
pContext->openal.alSourceStop = (mal_proc)alSourceStop;
pContext->openal.alSourceRewind = (mal_proc)alSourceRewind;
pContext->openal.alSourcePause = (mal_proc)alSourcePause;
pContext->openal.alSourceQueueBuffers = (mal_proc)alSourceQueueBuffers;
pContext->openal.alSourceUnqueueBuffers = (mal_proc)alSourceUnqueueBuffers;
pContext->openal.alGenBuffers = (mal_proc)alGenBuffers;
pContext->openal.alDeleteBuffers = (mal_proc)alDeleteBuffers;
pContext->openal.alIsBuffer = (mal_proc)alIsBuffer;
pContext->openal.alBufferData = (mal_proc)alBufferData;
pContext->openal.alBufferf = (mal_proc)alBufferf;
pContext->openal.alBuffer3f = (mal_proc)alBuffer3f;
pContext->openal.alBufferfv = (mal_proc)alBufferfv;
pContext->openal.alBufferi = (mal_proc)alBufferi;
pContext->openal.alBuffer3i = (mal_proc)alBuffer3i;
pContext->openal.alBufferiv = (mal_proc)alBufferiv;
pContext->openal.alGetBufferf = (mal_proc)alGetBufferf;
pContext->openal.alGetBuffer3f = (mal_proc)alGetBuffer3f;
pContext->openal.alGetBufferfv = (mal_proc)alGetBufferfv;
pContext->openal.alGetBufferi = (mal_proc)alGetBufferi;
pContext->openal.alGetBuffer3i = (mal_proc)alGetBuffer3i;
pContext->openal.alGetBufferiv = (mal_proc)alGetBufferiv;
#endif
// We depend on the ALC_ENUMERATION_EXT extension for enumeration. If this is not supported we fall back to default devices.
pContext->openal.isEnumerationSupported = ((MAL_LPALCISEXTENSIONPRESENT)pContext->openal.alcIsExtensionPresent)(NULL, "ALC_ENUMERATION_EXT");
pContext->openal.isFloat32Supported = ((MAL_LPALISEXTENSIONPRESENT)pContext->openal.alIsExtensionPresent)("AL_EXT_float32");
pContext->openal.isMCFormatsSupported = ((MAL_LPALISEXTENSIONPRESENT)pContext->openal.alIsExtensionPresent)("AL_EXT_MCFORMATS");
pContext->onUninit = mal_context_uninit__openal;
pContext->onDeviceIDEqual = mal_context_is_device_id_equal__openal;
pContext->onEnumDevices = mal_context_enumerate_devices__openal;
pContext->onGetDeviceInfo = mal_context_get_device_info__openal;
pContext->onDeviceInit = mal_device_init__openal;
pContext->onDeviceUninit = mal_device_uninit__openal;
pContext->onDeviceStart = mal_device_start__openal;
pContext->onDeviceStop = mal_device_stop__openal;
pContext->onDeviceBreakMainLoop = mal_device_break_main_loop__openal;
pContext->onDeviceMainLoop = mal_device_main_loop__openal;
return MAL_SUCCESS;
}
#endif // OpenAL
mal_bool32 mal__is_channel_map_valid(const mal_channel* channelMap, mal_uint32 channels) mal_bool32 mal__is_channel_map_valid(const mal_channel* channelMap, mal_uint32 channels)
{ {
...@@ -21075,12 +19972,6 @@ mal_result mal_context_init(const mal_backend backends[], mal_uint32 backendCoun ...@@ -21075,12 +19972,6 @@ mal_result mal_context_init(const mal_backend backends[], mal_uint32 backendCoun
result = mal_context_init__webaudio(pContext); result = mal_context_init__webaudio(pContext);
} break; } break;
#endif #endif
#ifdef MAL_HAS_OPENAL
case mal_backend_openal:
{
result = mal_context_init__openal(pContext);
} break;
#endif
#ifdef MAL_HAS_NULL #ifdef MAL_HAS_NULL
case mal_backend_null: case mal_backend_null:
{ {
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment