diff --git a/extras/miniaudio_split/miniaudio.c b/extras/miniaudio_split/miniaudio.c index d5fba855..5354e517 100644 --- a/extras/miniaudio_split/miniaudio.c +++ b/extras/miniaudio_split/miniaudio.c @@ -1,6 +1,6 @@ /* Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file. -miniaudio - v0.10.10 - 26-06-2020 +miniaudio - v0.10.11 - 28-06-2020 David Reid - davidreidsoftware@gmail.com @@ -26,8 +26,10 @@ GitHub: https://github.com/dr-soft/miniaudio #ifdef MA_WIN32 #include #else -#include /* For malloc(), free(), wcstombs(). */ -#include /* For memset() */ +#include /* For malloc(), free(), wcstombs(). */ +#include /* For memset() */ +#include +#include /* select() (used for ma_sleep()). */ #endif #include /* For fstat(), etc. */ @@ -464,6 +466,75 @@ static MA_INLINE ma_uint32 ma_swap_endian_uint32(ma_uint32 n) } +#if !defined(MA_EMSCRIPTEN) +#ifdef MA_WIN32 +static void ma_sleep__win32(ma_uint32 milliseconds) +{ + Sleep((DWORD)milliseconds); +} +#endif +#ifdef MA_POSIX +static void ma_sleep__posix(ma_uint32 milliseconds) +{ +#ifdef MA_EMSCRIPTEN + (void)milliseconds; + MA_ASSERT(MA_FALSE); /* The Emscripten build should never sleep. */ +#else + #if _POSIX_C_SOURCE >= 199309L + struct timespec ts; + ts.tv_sec = milliseconds / 1000; + ts.tv_nsec = milliseconds % 1000 * 1000000; + nanosleep(&ts, NULL); + #else + struct timeval tv; + tv.tv_sec = milliseconds / 1000; + tv.tv_usec = milliseconds % 1000 * 1000; + select(0, NULL, NULL, NULL, &tv); + #endif +#endif +} +#endif + +static void ma_sleep(ma_uint32 milliseconds) +{ +#ifdef MA_WIN32 + ma_sleep__win32(milliseconds); +#endif +#ifdef MA_POSIX + ma_sleep__posix(milliseconds); +#endif +} +#endif + +#if !defined(MA_EMSCRIPTEN) +static MA_INLINE void ma_yield() +{ +#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) + /* x86/x64 */ + #if defined(_MSC_VER) && !defined(__clang__) + #if _MSC_VER >= 1400 + _mm_pause(); + #else + __asm pause; + #endif + #else + __asm__ __volatile__ ("pause"); + #endif +#elif (defined(__arm__) && defined(__ARM_ARCH) && __ARM_ARCH >= 6) || (defined(_M_ARM) && _M_ARM >= 6) + /* ARM */ + #if defined(_MSC_VER) + /* Apparently there is a __yield() intrinsic that's compatible with ARM, but I cannot find documentation for it nor can I find where it's declared. */ + __yield(); + #else + __asm__ __volatile__ ("yield"); + #endif +#else + /* Unknown or unsupported architecture. No-op. */ +#endif +} +#endif + + #ifndef MA_COINIT_VALUE #define MA_COINIT_VALUE 0 /* 0 = COINIT_MULTITHREADED */ @@ -2599,6 +2670,51 @@ c89atomic_bool c89atomic_compare_exchange_strong_explicit_64(volatile c89atomic_ /* c89atomic.h end */ +typedef unsigned char ma_spinlock; + +static MA_INLINE ma_result ma_spinlock_lock_ex(ma_spinlock* pSpinlock, ma_bool32 yield) +{ + if (pSpinlock == NULL) { + return MA_INVALID_ARGS; + } + + for (;;) { + if (c89atomic_flag_test_and_set_explicit(pSpinlock, c89atomic_memory_order_acquire) == 0) { + break; + } + + while (c89atomic_load_explicit_8(pSpinlock, c89atomic_memory_order_relaxed) == 1) { + if (yield) { + ma_yield(); + } + } + } + + return MA_SUCCESS; +} + +static ma_result ma_spinlock_lock(ma_spinlock* pSpinlock) +{ + return ma_spinlock_lock_ex(pSpinlock, MA_TRUE); +} + +static ma_result ma_spinlock_lock_noyield(ma_spinlock* pSpinlock) +{ + return ma_spinlock_lock_ex(pSpinlock, MA_FALSE); +} + +static ma_result ma_spinlock_unlock(ma_spinlock* pSpinlock) +{ + if (pSpinlock == NULL) { + return MA_INVALID_ARGS; + } + + c89atomic_flag_clear_explicit(pSpinlock, c89atomic_memory_order_release); + return MA_SUCCESS; +} + + + static void* ma__malloc_default(size_t sz, void* pUserData) { (void)pUserData; @@ -2823,11 +2939,6 @@ static void ma_thread_wait__win32(ma_thread* pThread) WaitForSingleObject((HANDLE)*pThread, INFINITE); } -static void ma_sleep__win32(ma_uint32 milliseconds) -{ - Sleep((DWORD)milliseconds); -} - static ma_result ma_mutex_init__win32(ma_mutex* pMutex) { @@ -2937,9 +3048,6 @@ static ma_result ma_semaphore_release__win32(ma_semaphore* pSemaphore) #ifdef MA_POSIX -#include -#include - static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority priority, size_t stackSize, ma_thread_entry_proc entryProc, void* pData) { int result; @@ -3016,28 +3124,6 @@ static void ma_thread_wait__posix(ma_thread* pThread) pthread_join(*pThread, NULL); } -#if !defined(MA_EMSCRIPTEN) -static void ma_sleep__posix(ma_uint32 milliseconds) -{ -#ifdef MA_EMSCRIPTEN - (void)milliseconds; - MA_ASSERT(MA_FALSE); /* The Emscripten build should never sleep. */ -#else - #if _POSIX_C_SOURCE >= 199309L - struct timespec ts; - ts.tv_sec = milliseconds / 1000; - ts.tv_nsec = milliseconds % 1000 * 1000000; - nanosleep(&ts, NULL); - #else - struct timeval tv; - tv.tv_sec = milliseconds / 1000; - tv.tv_usec = milliseconds % 1000 * 1000; - select(0, NULL, NULL, NULL, &tv); - #endif -#endif -} -#endif /* MA_EMSCRIPTEN */ - static ma_result ma_mutex_init__posix(ma_mutex* pMutex) { @@ -3216,46 +3302,6 @@ static void ma_thread_wait(ma_thread* pThread) #endif } -#if !defined(MA_EMSCRIPTEN) -static void ma_sleep(ma_uint32 milliseconds) -{ -#ifdef MA_WIN32 - ma_sleep__win32(milliseconds); -#endif -#ifdef MA_POSIX - ma_sleep__posix(milliseconds); -#endif -} -#endif - -#if !defined(MA_EMSCRIPTEN) -static MA_INLINE void ma_yield() -{ -#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) - /* x86/x64 */ - #if defined(_MSC_VER) && !defined(__clang__) - #if _MSC_VER >= 1400 - _mm_pause(); - #else - __asm pause; - #endif - #else - __asm__ __volatile__ ("pause"); - #endif -#elif (defined(__arm__) && defined(__ARM_ARCH) && __ARM_ARCH >= 6) || (defined(_M_ARM) && _M_ARM >= 6) - /* ARM */ - #if defined(_MSC_VER) - /* Apparently there is a __yield() intrinsic that's compatible with ARM, but I cannot find documentation for it nor can I find where it's declared. */ - __yield(); - #else - __asm__ __volatile__ ("yield"); - #endif -#else - /* Unknown or unsupported architecture. No-op. */ -#endif -} -#endif - MA_API ma_result ma_mutex_init(ma_mutex* pMutex) { @@ -18414,6 +18460,7 @@ static void on_start_stop__coreaudio(void* pUserData, AudioUnit audioUnit, Audio } #if defined(MA_APPLE_DESKTOP) +static ma_spinlock g_DeviceTrackingInitLock_CoreAudio = 0; /* A spinlock for mutal exclusion of the init/uninit of the global tracking data. Initialization to 0 is what we need. */ static ma_uint32 g_DeviceTrackingInitCounter_CoreAudio = 0; static ma_mutex g_DeviceTrackingMutex_CoreAudio; static ma_device** g_ppTrackedDevices_CoreAudio = NULL; @@ -18497,7 +18544,8 @@ static ma_result ma_context__init_device_tracking__coreaudio(ma_context* pContex { MA_ASSERT(pContext != NULL); - if (c89atomic_fetch_add_32(&g_DeviceTrackingInitCounter_CoreAudio, 1) == 0) { + ma_spinlock_lock(&g_DeviceTrackingInitLock_CoreAudio); + { AudioObjectPropertyAddress propAddress; propAddress.mScope = kAudioObjectPropertyScopeGlobal; propAddress.mElement = kAudioObjectPropertyElementMaster; @@ -18510,7 +18558,8 @@ static ma_result ma_context__init_device_tracking__coreaudio(ma_context* pContex propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice; ((ma_AudioObjectAddPropertyListener_proc)pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL); } - + ma_spinlock_unlock(&g_DeviceTrackingInitLock_CoreAudio); + return MA_SUCCESS; } @@ -18518,7 +18567,8 @@ static ma_result ma_context__uninit_device_tracking__coreaudio(ma_context* pCont { MA_ASSERT(pContext != NULL); - if (c89atomic_fetch_sub_32(&g_DeviceTrackingInitCounter_CoreAudio, 1) == 1) { + ma_spinlock_lock(&g_DeviceTrackingInitLock_CoreAudio); + { AudioObjectPropertyAddress propAddress; propAddress.mScope = kAudioObjectPropertyScopeGlobal; propAddress.mElement = kAudioObjectPropertyElementMaster; @@ -18535,21 +18585,15 @@ static ma_result ma_context__uninit_device_tracking__coreaudio(ma_context* pCont ma_mutex_uninit(&g_DeviceTrackingMutex_CoreAudio); } + ma_spinlock_unlock(&g_DeviceTrackingInitLock_CoreAudio); return MA_SUCCESS; } static ma_result ma_device__track__coreaudio(ma_device* pDevice) { - ma_result result; - MA_ASSERT(pDevice != NULL); - result = ma_context__init_device_tracking__coreaudio(pDevice->pContext); - if (result != MA_SUCCESS) { - return result; - } - ma_mutex_lock(&g_DeviceTrackingMutex_CoreAudio); { /* Allocate memory if required. */ @@ -18584,8 +18628,6 @@ static ma_result ma_device__track__coreaudio(ma_device* pDevice) static ma_result ma_device__untrack__coreaudio(ma_device* pDevice) { - ma_result result; - MA_ASSERT(pDevice != NULL); ma_mutex_lock(&g_DeviceTrackingMutex_CoreAudio); @@ -18614,11 +18656,6 @@ static ma_result ma_device__untrack__coreaudio(ma_device* pDevice) } ma_mutex_unlock(&g_DeviceTrackingMutex_CoreAudio); - result = ma_context__uninit_device_tracking__coreaudio(pDevice->pContext); - if (result != MA_SUCCESS) { - return result; - } - return MA_SUCCESS; } #endif @@ -19461,6 +19498,8 @@ static ma_result ma_context_uninit__coreaudio(ma_context* pContext) ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation); #endif + ma_context__init_device_tracking__coreaudio(pContext); + (void)pContext; return MA_SUCCESS; } @@ -19488,6 +19527,8 @@ static AVAudioSessionCategory ma_to_AVAudioSessionCategory(ma_ios_session_catego static ma_result ma_context_init__coreaudio(const ma_context_config* pConfig, ma_context* pContext) { + ma_result result; + MA_ASSERT(pConfig != NULL); MA_ASSERT(pContext != NULL); @@ -19642,6 +19683,16 @@ static ma_result ma_context_init__coreaudio(const ma_context_config* pConfig, ma return MA_FAILED_TO_INIT_BACKEND; } } + + result = ma_context__init_device_tracking__coreaudio(pContext); + if (result != MA_SUCCESS) { +#if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE) + ma_dlclose(pContext, pContext->coreaudio.hAudioUnit); + ma_dlclose(pContext, pContext->coreaudio.hCoreAudio); + ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation); +#endif + return result; + } return MA_SUCCESS; } diff --git a/extras/miniaudio_split/miniaudio.h b/extras/miniaudio_split/miniaudio.h index 480d3e82..90122120 100644 --- a/extras/miniaudio_split/miniaudio.h +++ b/extras/miniaudio_split/miniaudio.h @@ -1,6 +1,6 @@ /* Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file. -miniaudio - v0.10.10 - 26-06-2020 +miniaudio - v0.10.11 - 28-06-2020 David Reid - davidreidsoftware@gmail.com @@ -19,7 +19,7 @@ extern "C" { #define MA_VERSION_MAJOR 0 #define MA_VERSION_MINOR 10 -#define MA_VERSION_REVISION 10 +#define MA_VERSION_REVISION 11 #define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION) #if defined(_MSC_VER) && !defined(__clang__) diff --git a/miniaudio.h b/miniaudio.h index 68be2aa8..fe78e9e7 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -25267,11 +25267,11 @@ static ma_result ma_context_init__coreaudio(const ma_context_config* pConfig, ma pContext->coreaudio.component = ((ma_AudioComponentFindNext_proc)pContext->coreaudio.AudioComponentFindNext)(NULL, &desc); if (pContext->coreaudio.component == NULL) { - #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE) + #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE) ma_dlclose(pContext, pContext->coreaudio.hAudioUnit); ma_dlclose(pContext, pContext->coreaudio.hCoreAudio); ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation); - #endif + #endif return MA_FAILED_TO_INIT_BACKEND; } } @@ -25279,9 +25279,9 @@ static ma_result ma_context_init__coreaudio(const ma_context_config* pConfig, ma result = ma_context__init_device_tracking__coreaudio(pContext); if (result != MA_SUCCESS) { #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE) - ma_dlclose(pContext, pContext->coreaudio.hAudioUnit); - ma_dlclose(pContext, pContext->coreaudio.hCoreAudio); - ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation); + ma_dlclose(pContext, pContext->coreaudio.hAudioUnit); + ma_dlclose(pContext, pContext->coreaudio.hCoreAudio); + ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation); #endif return result; }