diff --git a/mini_al.h b/mini_al.h index 6f40d209..383136e0 100644 --- a/mini_al.h +++ b/mini_al.h @@ -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 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 ======= @@ -222,9 +218,6 @@ OPTIONS #define MAL_NO_WEBAUDIO Disables the Web Audio backend. -#define MAL_NO_OPENAL - Disables the OpenAL backend. - #define MAL_NO_NULL Disables the null backend. @@ -1233,9 +1226,8 @@ void mal_interleave_pcm_frames(mal_format format, mal_uint32 channels, mal_uint6 #define MAL_SUPPORT_WEBAUDIO #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) -#define MAL_SUPPORT_OPENAL #define MAL_SUPPORT_NULL #endif @@ -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) #define MAL_ENABLE_WEBAUDIO #endif -#if !defined(MAL_NO_OPENAL) && defined(MAL_SUPPORT_OPENAL) - #define MAL_ENABLE_OPENAL -#endif #if !defined(MAL_NO_NULL) && defined(MAL_SUPPORT_NULL) #define MAL_ENABLE_NULL #endif @@ -1312,7 +1301,6 @@ typedef enum mal_backend_aaudio, mal_backend_opensl, 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; @@ -1398,8 +1386,7 @@ typedef struct } mal_event; -#define MAL_MAX_PERIODS_DSOUND 4 -#define MAL_MAX_PERIODS_OPENAL 4 +#define MAL_MAX_PERIODS_DSOUND 4 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); @@ -1459,9 +1446,6 @@ typedef union #ifdef MAL_SUPPORT_WEBAUDIO char webaudio[32]; // Web Audio always uses default devices for now, but if this changes it'll be a GUID. #endif -#ifdef MAL_SUPPORT_OPENAL - char openal[256]; // OpenAL seems to use human-readable device names as the ID. -#endif #ifdef MAL_SUPPORT_NULL int nullbackend; // The null backend uses an integer for device IDs. #endif @@ -1841,93 +1825,6 @@ struct mal_context int _unused; } webaudio; #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 struct { @@ -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. */ } webaudio; #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 struct { @@ -3787,16 +3670,6 @@ mal_uint32 mal_get_standard_sample_rate_priority_index(mal_uint32 sampleRate) #ifdef MAL_ENABLE_WEBAUDIO #define MAL_HAS_WEBAUDIO #endif -#ifdef MAL_ENABLE_OPENAL - #define MAL_HAS_OPENAL - #ifdef MAL_NO_RUNTIME_LINKING - #ifdef __has_include - #if !__has_include() - #undef MAL_HAS_OPENAL - #endif - #endif - #endif -#endif #ifdef MAL_ENABLE_NULL #define MAL_HAS_NULL // Everything supports the null backend. #endif @@ -3818,7 +3691,6 @@ const char* mal_get_backend_name(mal_backend backend) case mal_backend_aaudio: return "AAudio"; case mal_backend_opensl: return "OpenSL|ES"; case mal_backend_webaudio: return "Web Audio"; - case mal_backend_openal: return "OpenAL"; case mal_backend_null: return "Null"; default: return "Unknown"; } @@ -19627,981 +19499,6 @@ mal_result mal_context_init__webaudio(mal_context* pContext) #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 - #include - #else - #include - #include - #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) { @@ -21075,12 +19972,6 @@ mal_result mal_context_init(const mal_backend backends[], mal_uint32 backendCoun result = mal_context_init__webaudio(pContext); } break; #endif - #ifdef MAL_HAS_OPENAL - case mal_backend_openal: - { - result = mal_context_init__openal(pContext); - } break; - #endif #ifdef MAL_HAS_NULL case mal_backend_null: {