diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 667f0fbb..b212298b 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,10 +9,4 @@ assignees: '' **DELETE ALL OF THIS TEXT BEFORE SUBMITTING** -If you think you've found a bug, it will be helpful to run with `#define MA_DEBUG_OUTPUT` above your miniaudio implementation like the code below and to include the output with this bug report: - - #define MA_DEBUG_OUTPUT - #define MINIAUDIO_IMPLEMENTATION - #include "miniaudio.h" - -If you are having issues with playback, please run the simple_payback_sine example and report whether or not it's consistent with what's happening in your program. +If you think you've found a bug, it will be helpful to compile with `#define MA_DEBUG_OUTPUT`. If you are having issues with playback, please run the simple_payback_sine example and report whether or not it's consistent with what's happening in your program. diff --git a/.github/ISSUE_TEMPLATE/general-issue.md b/.github/ISSUE_TEMPLATE/general-issue.md index e64edc47..d3124b84 100644 --- a/.github/ISSUE_TEMPLATE/general-issue.md +++ b/.github/ISSUE_TEMPLATE/general-issue.md @@ -9,6 +9,6 @@ assignees: '' **DELETE ALL OF THIS TEXT BEFORE SUBMITTING** -If you have a question about how to use the library, please read the documentation at the top of miniaudio.h and take a look at the examples. If that still doesn't answer your question, consider posting in the miniaudio subreddit at [r/miniaudio](https://www.reddit.com/r/miniaudio) or in the Discussions section here on GitHub instead. Otherwise, feel free to post your issue and we'll get to it as soon as possible. +If you have a question about how to use the library, please read the documentation at the top of miniaudio.h and take a look at the examples. If that still doesn't answer your question, consider posting in the Discussions section here on GitHub instead. Otherwise, feel free to post your issue and we'll get to it as soon as possible. -If you have an issue with playback, please run the simple_playback_sine example first and check whether or not that is working. Likewise for capture, please run the simple_capture example. If these examples work, it probably (but not always) means you're doing something wrong and a question in the subreddit or the Discussions section is more appropriate. +If you have an issue with playback, please run the simple_playback_sine example first and check whether or not that is working. Likewise for capture, please run the simple_capture example. If these examples work, it probably (but not always) means you're doing something wrong and a question in the Discussions section is more appropriate. diff --git a/.gitignore b/.gitignore index 46432d32..fac0b7ed 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,10 @@ examples/build/vc6/ examples/build/vc15/ examples/build/vc17/ examples/simple_playback_sine.cpp +external/ogg/ +external/vorbis/ +external/opus/ +external/opusfile/ extras/osaudio/tests/build/bin/ extras/osaudio/tests/build/vc17/ extras/osaudio/tests/build/watcom-dos/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 59931629..cf803778 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,7 +69,7 @@ if(MINIAUDIO_FORCE_CXX AND MINIAUDIO_FORCE_C89) endif() if(MINIAUDIO_FORCE_CXX) - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") message(STATUS "Compiling as C++ (GNU/Clang)") list(APPEND COMPILE_OPTIONS -x c++) elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") @@ -81,7 +81,7 @@ if(MINIAUDIO_FORCE_CXX) endif() if(MINIAUDIO_FORCE_C89) - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") message(STATUS "Compiling as C89") list(APPEND COMPILE_OPTIONS -std=c89) elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") @@ -92,7 +92,7 @@ if(MINIAUDIO_FORCE_C89) endif() # Warnings -if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") list(APPEND COMPILE_OPTIONS -Wall -Wextra -Wpedantic) elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") #list(APPEND COMPILE_OPTIONS /W4) @@ -248,39 +248,128 @@ endif() # External Libraries -if(NOT MINIAUDIO_NO_LIBVORBIS) - find_library(LIBVORBISFILE NAMES vorbisfile) - if(LIBVORBISFILE) - message(STATUS "Found libvorbisfile: ${LIBVORBISFILE}") - set(HAS_LIBVORBIS TRUE) - else() - message(STATUS "libvorbisfile not found. miniaudio_libvorbis will be excluded.") - endif() -endif() - -if(NOT MINIAUDIO_NO_LIBOPUS) - find_library(LIBOPUSFILE NAMES opusfile) - if(LIBOPUSFILE) - message(STATUS "Found libopusfile: ${LIBOPUSFILE}") - - # opusfile is very annoying because they do "#include " in opusfile.h which results - # in an error unless we explicitly add the include path to the opus include directory. - find_path(OPUSFILE_INCLUDE_DIR - NAMES opus/opusfile.h - DOC "Directory containing opusfile.h" - ) - - if(OPUSFILE_INCLUDE_DIR) - message(STATUS "Found opusfile.h in ${OPUSFILE_INCLUDE_DIR}") - set(HAS_LIBOPUS TRUE) +function(add_libogg_subdirectory) + if(NOT TARGET ogg) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/external/ogg/CMakeLists.txt) + message(STATUS "Building libogg from source.") + add_subdirectory(external/ogg) else() - message(STATUS "Could not find opusfile.h. miniaudio_libopus will be excluded.") + message(STATUS "libogg not found.") + endif() + endif() +endfunction() + +function(add_libvorbis_subdirectory) + if(NOT TARGET vorbis) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/external/vorbis/CMakeLists.txt) + add_libogg_subdirectory() + if(TARGET ogg) + message(STATUS "Building libvorbis from source.") + add_subdirectory(external/vorbis) + else() + message(STATUS "libogg not found. miniaudio_libvorbis will be excluded.") + endif() + endif() + endif() +endfunction() + +function(add_libopus_subdirectory) + if(NOT TARGET opus) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/external/opus/CMakeLists.txt) + message(STATUS "Building libopus from source.") + set(OPUS_BUILD_TESTING OFF) + add_subdirectory(external/opus) + else() + message(STATUS "libopus not found. miniaudio_libopus will be excluded.") + endif() + endif() +endfunction() + +function(add_libopusfile_subdirectory) + if(NOT TARGET opusfile) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/external/opusfile/CMakeLists.txt) + add_libogg_subdirectory() + if(TARGET ogg) + add_libopus_subdirectory() + if(TARGET opus) + message(STATUS "Building libopusfile from source.") + set(OP_DISABLE_HTTP TRUE) + set(OP_DISABLE_DOCS TRUE) + set(OP_DISABLE_EXAMPLES TRUE) + add_subdirectory(external/opusfile) + else() + message(STATUS "libopus not found. miniaudio_libopus will be excluded.") + endif() + else() + message(STATUS "libogg not found. miniaudio_libopus will be excluded.") + endif() + endif() + endif() +endfunction() + + +# vorbisfile +# +# The vorbisfile target is required for miniaudio_libvorbis. If the vorbisfile target has already been +# defined we'll just use that. Otherwise we'll try to find_library(). If that fails, as a last resort +# we'll allow building it from source from the external/vorbis directory. +if(NOT MINIAUDIO_NO_LIBVORBIS) + if(NOT TARGET vorbisfile) + find_library(LIBVORBISFILE NAMES vorbisfile) + if(LIBVORBISFILE) + message(STATUS "Found libvorbisfile: ${LIBVORBISFILE}") + set(HAS_LIBVORBIS TRUE) + else() + add_libvorbis_subdirectory() + if(NOT TARGET vorbisfile) + message(STATUS "libvorbisfile not found. miniaudio_libvorbis will be excluded.") + else() + set(HAS_LIBVORBIS TRUE) + endif() endif() else() - message(STATUS "libopusfile not found. miniaudio_libopus will be excluded.") + message(STATUS "libvorbisfile already found.") + set(HAS_LIBVORBIS TRUE) endif() endif() +# opusfile +# +# This is the same as vorbisfile above. +if(NOT MINIAUDIO_NO_LIBOPUS) + if(NOT TARGET opusfile) + find_library(LIBOPUSFILE NAMES opusfile) + if(LIBOPUSFILE) + message(STATUS "Found libopusfile: ${LIBOPUSFILE}") + + # opusfile is very annoying because they do "#include " in opusfile.h which results + # in an error unless we explicitly add the include path to the opus include directory. + find_path(OPUSFILE_INCLUDE_DIR + NAMES opus/opusfile.h + DOC "Directory containing opusfile.h" + ) + + if(OPUSFILE_INCLUDE_DIR) + message(STATUS "Found opusfile.h in ${OPUSFILE_INCLUDE_DIR}") + set(HAS_LIBOPUS TRUE) + else() + message(STATUS "Could not find opusfile.h. miniaudio_libopus will be excluded.") + endif() + else() + add_libopusfile_subdirectory() + if(NOT TARGET opusfile) + message(STATUS "libopusfile not found. miniaudio_libopus will be excluded.") + else() + set(HAS_LIBOPUS TRUE) + endif() + endif() + else() + message(STATUS "libopusfile already found.") + set(HAS_LIBOPUS TRUE) + endif() +endif() + + find_library(SDL2_LIBRARY NAMES SDL2) if(SDL2_LIBRARY) message(STATUS "Found SDL2: ${SDL2_LIBRARY}") @@ -307,9 +396,9 @@ else() endif() endif() -# When searching for SteamAudio, we'll support installing it in the extras/steamaudio directory. +# When searching for SteamAudio, we'll support installing it in the external/steamaudio directory. set(STEAMAUDIO_FIND_LIBRARY_HINTS) -list(APPEND STEAMAUDIO_FIND_LIBRARY_HINTS ${CMAKE_CURRENT_SOURCE_DIR}/extras/steamaudio/lib/${STEAMAUDIO_ARCH}) +list(APPEND STEAMAUDIO_FIND_LIBRARY_HINTS ${CMAKE_CURRENT_SOURCE_DIR}/external/steamaudio/lib/${STEAMAUDIO_ARCH}) if(WIN32) else() @@ -318,7 +407,7 @@ else() endif() set(STEAMAUDIO_FIND_HEADER_HINTS) -list(APPEND STEAMAUDIO_FIND_HEADER_HINTS ${CMAKE_CURRENT_SOURCE_DIR}/extras/steamaudio/include) +list(APPEND STEAMAUDIO_FIND_HEADER_HINTS ${CMAKE_CURRENT_SOURCE_DIR}/external/steamaudio/include) if(WIN32) else() @@ -367,10 +456,21 @@ add_library(miniaudio STATIC miniaudio.h ) +target_include_directories(miniaudio PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + target_compile_options (miniaudio PRIVATE ${COMPILE_OPTIONS}) target_compile_definitions(miniaudio PRIVATE ${COMPILE_DEFINES}) +add_library(libvorbis_interface INTERFACE) +if(HAS_LIBVORBIS) + if(TARGET vorbisfile) + target_link_libraries(libvorbis_interface INTERFACE vorbisfile) + else() + target_link_libraries(libvorbis_interface INTERFACE ${LIBVORBISFILE}) + endif() +endif() + if(HAS_LIBVORBIS) add_library(miniaudio_libvorbis STATIC extras/decoders/libvorbis/miniaudio_libvorbis.c @@ -379,7 +479,18 @@ if(HAS_LIBVORBIS) target_compile_options (miniaudio_libvorbis PRIVATE ${COMPILE_OPTIONS}) target_compile_definitions(miniaudio_libvorbis PRIVATE ${COMPILE_DEFINES}) - target_link_libraries (miniaudio_libvorbis PRIVATE ${LIBVORBISFILE}) + target_link_libraries (miniaudio_libvorbis PRIVATE libvorbis_interface) +endif() + + +add_library(libopus_interface INTERFACE) +if(HAS_LIBOPUS) + if(TARGET opusfile) + target_link_libraries (libopus_interface INTERFACE opusfile) + else() + target_link_libraries (libopus_interface INTERFACE ${LIBOPUSFILE}) + target_include_directories(libopus_interface INTERFACE ${OPUSFILE_INCLUDE_DIR}/opus) + endif() endif() if(HAS_LIBOPUS) @@ -390,8 +501,7 @@ if(HAS_LIBOPUS) target_compile_options (miniaudio_libopus PRIVATE ${COMPILE_OPTIONS}) target_compile_definitions(miniaudio_libopus PRIVATE ${COMPILE_DEFINES}) - target_include_directories(miniaudio_libopus PRIVATE ${OPUSFILE_INCLUDE_DIR}/opus) - target_link_libraries (miniaudio_libopus PRIVATE ${LIBOPUSFILE}) + target_link_libraries (miniaudio_libopus PRIVATE libopus_interface) endif() @@ -410,7 +520,7 @@ if(MINIAUDIO_BUILD_TESTS) set(TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests) - function (add_miniaudio_test name source) + function(add_miniaudio_test name source) add_executable(${name} ${TESTS_DIR}/${source}) target_link_libraries(${name} PRIVATE miniaudio_common_options) endfunction() @@ -437,7 +547,7 @@ endif() if (MINIAUDIO_BUILD_EXAMPLES) set(EXAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/examples) - function (add_miniaudio_example name source) + function(add_miniaudio_example name source) add_executable(${name} ${EXAMPLES_DIR}/${source}) target_link_libraries(${name} PRIVATE miniaudio_common_options) endfunction() @@ -445,21 +555,29 @@ if (MINIAUDIO_BUILD_EXAMPLES) add_miniaudio_example(miniaudio_custom_backend custom_backend.c) add_miniaudio_example(miniaudio_custom_decoder_engine custom_decoder_engine.c) - if(NOT HAS_LIBVORBIS) + if(HAS_LIBVORBIS) + target_link_libraries(miniaudio_custom_decoder_engine PRIVATE libvorbis_interface) + else() target_compile_definitions(miniaudio_custom_decoder_engine PRIVATE MA_NO_LIBVORBIS) message(STATUS "miniaudio_libvorbis is disabled. Vorbis support is disabled in miniaudio_custom_decoder_engine.") endif() - if(NOT HAS_LIBOPUS) + if(HAS_LIBOPUS) + target_link_libraries(miniaudio_custom_decoder_engine PRIVATE libopus_interface) + else() target_compile_definitions(miniaudio_custom_decoder_engine PRIVATE MA_NO_LIBOPUS) message(STATUS "miniaudio_libopus is disabled. Opus support is disabled in miniaudio_custom_decoder_engine.") endif() add_miniaudio_example(miniaudio_custom_decoder custom_decoder.c) - if(NOT HAS_LIBVORBIS) + if(HAS_LIBVORBIS) + target_link_libraries(miniaudio_custom_decoder PRIVATE libvorbis_interface) + else() target_compile_definitions(miniaudio_custom_decoder PRIVATE MA_NO_LIBVORBIS) message(STATUS "miniaudio_libvorbis is disabled. Vorbis support is disabled in miniaudio_custom_decoder.") endif() - if(NOT HAS_LIBOPUS) + if(HAS_LIBOPUS) + target_link_libraries(miniaudio_custom_decoder PRIVATE libopus_interface) + else() target_compile_definitions(miniaudio_custom_decoder PRIVATE MA_NO_LIBOPUS) message(STATUS "miniaudio_libopus is disabled. Opus support is disabled in miniaudio_custom_decoder.") endif() diff --git a/README.md b/README.md index d85c3a9e..2f421f63 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@

discord mastodon - reddit

@@ -17,6 +16,7 @@ Building - Documentation - Supported Platforms - + Security - License

@@ -158,6 +158,8 @@ need to link with `-latomic`. ABI compatibility is not guaranteed between versions so take care if compiling as a DLL/SO. The suggested way to integrate miniaudio is by adding it directly to your source tree. +You can also use CMake if that's your preference. + Documentation ============= @@ -201,6 +203,13 @@ Backends - Custom +Security +======== +I deal with all security related issues publicly and transparently, and it can sometimes take a while before I +get a chance to address it. If this is an issue for you, you need to use another library. Please post any +security related bugs on the public GitHub issue tracker. + + License ======= Your choice of either public domain or [MIT No Attribution](https://github.com/aws/mit-0). diff --git a/data/48000-stereo.ogg b/data/48000-stereo.ogg new file mode 100644 index 00000000..27fd0dca Binary files /dev/null and b/data/48000-stereo.ogg differ diff --git a/data/48000-stereo.opus b/data/48000-stereo.opus new file mode 100644 index 00000000..bba9e9be Binary files /dev/null and b/data/48000-stereo.opus differ diff --git a/examples/simple_spatialization.c b/examples/simple_spatialization.c index a9530ae1..48256eba 100644 --- a/examples/simple_spatialization.c +++ b/examples/simple_spatialization.c @@ -20,6 +20,12 @@ orbiting effect. Terminate the program with Ctrl+C. #include #include /* For sinf() and cosf() */ +/* Silence warning about unreachable code for MSVC. */ +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4702) +#endif + int main(int argc, char** argv) { ma_result result; @@ -74,3 +80,7 @@ int main(int argc, char** argv) return 0; } + +#ifdef _MSC_VER + #pragma warning(pop) +#endif diff --git a/external/fs/fs.c b/external/fs/fs.c index afc88fd4..b10ca8f5 100644 --- a/external/fs/fs.c +++ b/external/fs/fs.c @@ -3306,6 +3306,7 @@ FS_API void fs_file_close(fs_file* pFile) const fs_backend* pBackend = fs_file_get_backend(pFile); FS_ASSERT(pBackend != NULL); + (void)pBackend; if (pFile == NULL) { return; diff --git a/external/fs/fs.h b/external/fs/fs.h index e99686bb..5d08c4cc 100644 --- a/external/fs/fs.h +++ b/external/fs/fs.h @@ -579,11 +579,11 @@ extern "C" { #endif /* FS_USE_STDINT */ #if FS_SIZEOF_PTR == 8 - typedef unsigned long long fs_uintptr; - typedef long long fs_intptr; + typedef fs_uint64 fs_uintptr; + typedef fs_int64 fs_intptr; #else - typedef unsigned int fs_uintptr; - typedef int fs_intptr; + typedef fs_uint32 fs_uintptr; + typedef fs_int32 fs_intptr; #endif typedef unsigned char fs_bool8; diff --git a/extras/decoders/libvorbis/miniaudio_libvorbis.c b/extras/decoders/libvorbis/miniaudio_libvorbis.c index 6d0bdb4c..78135b1f 100644 --- a/extras/decoders/libvorbis/miniaudio_libvorbis.c +++ b/extras/decoders/libvorbis/miniaudio_libvorbis.c @@ -143,15 +143,16 @@ static ma_result ma_libvorbis_init_internal(const ma_decoding_backend_config* pC ma_data_source_uninit(&pVorbis->ds); return MA_OUT_OF_MEMORY; } + + return MA_SUCCESS; } #else { /* libvorbis is disabled. */ + (void)pAllocationCallbacks; return MA_NOT_IMPLEMENTED; } #endif - - return MA_SUCCESS; } MA_API ma_result ma_libvorbis_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_libvorbis* pVorbis) @@ -308,7 +309,7 @@ MA_API ma_result ma_libvorbis_read_pcm_frames(ma_libvorbis* pVorbis, void* pFram } } } else { - libvorbisResult = ov_read((OggVorbis_File*)pVorbis->vf, (char*)ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, format, channels), framesToRead * ma_get_bytes_per_frame(format, channels), 0, 2, 1, NULL); + libvorbisResult = ov_read((OggVorbis_File*)pVorbis->vf, (char*)ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, format, channels), (int)(framesToRead * ma_get_bytes_per_frame(format, channels)), 0, 2, 1, NULL); if (libvorbisResult < 0) { result = MA_ERROR; /* Error while decoding. */ break; diff --git a/miniaudio.h b/miniaudio.h index 761b8c94..c8b98d6f 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -10096,7 +10096,7 @@ typedef struct ma_allocation_callbacks allocationCallbacks; ma_encoding_format encodingFormat; ma_uint32 seekPointCount; /* When set to > 0, specifies the number of seek points to use for the generation of a seek table. Not all decoding backends support this. */ - const ma_decoding_backend_vtable** ppBackendVTables; + const ma_decoding_backend_vtable* const* ppBackendVTables; void** ppBackendUserData; ma_uint32 backendCount; } ma_decoder_config; @@ -10615,7 +10615,7 @@ typedef struct ma_uint32 jobQueueCapacity; /* The maximum number of jobs that can fit in the queue at a time. Defaults to MA_JOB_TYPE_RESOURCE_MANAGER_QUEUE_CAPACITY. Cannot be zero. */ ma_uint32 flags; ma_vfs* pVFS; /* Can be NULL in which case defaults will be used. */ - const ma_decoding_backend_vtable** ppDecodingBackendVTables; + const ma_decoding_backend_vtable* const* ppDecodingBackendVTables; ma_uint32 decodingBackendCount; void** ppDecodingBackendUserData; } ma_resource_manager_config; @@ -18070,12 +18070,12 @@ MA_API ma_proc ma_dlsym(ma_log* pLog, ma_handle handle, const char* symbol) #ifdef _WIN32 proc = (ma_proc)GetProcAddress((HMODULE)handle, symbol); #else -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) +#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" #endif proc = (ma_proc)dlsym((void*)handle, symbol); -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) +#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || defined(__clang__) #pragma GCC diagnostic pop #endif #endif @@ -22372,12 +22372,16 @@ static ma_result ma_device_uninit__wasapi(ma_device* pDevice) { MA_ASSERT(pDevice != NULL); -#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK) - if (pDevice->wasapi.pDeviceEnumerator) { - ((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator)->lpVtbl->UnregisterEndpointNotificationCallback((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator, &pDevice->wasapi.notificationClient); - ma_IMMDeviceEnumerator_Release((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator); + #if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK) + { + if (pDevice->wasapi.pDeviceEnumerator) { + ((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator)->lpVtbl->UnregisterEndpointNotificationCallback((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator, &pDevice->wasapi.notificationClient); + ma_IMMDeviceEnumerator_Release((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator); + } + + ma_mutex_uninit(&pDevice->wasapi.rerouteLock); } -#endif + #endif if (pDevice->wasapi.pRenderClient) { if (pDevice->wasapi.pMappedBufferPlayback != NULL) { @@ -33975,11 +33979,12 @@ static OSStatus ma_on_input__coreaudio(void* pUserData, AudioUnitRenderActionFla */ for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; ++iBuffer) { pRenderedBufferList->mBuffers[iBuffer].mDataByteSize = pDevice->coreaudio.audioBufferCapInFrames * ma_get_bytes_per_sample(pDevice->capture.internalFormat) * pRenderedBufferList->mBuffers[iBuffer].mNumberChannels; + /*printf("DEBUG: nDataByteSize = %d\n", (int)pRenderedBufferList->mBuffers[iBuffer].mDataByteSize);*/ } status = ((ma_AudioUnitRender_proc)pDevice->pContext->coreaudio.AudioUnitRender)((AudioUnit)pDevice->coreaudio.audioUnitCapture, pActionFlags, pTimeStamp, busNumber, frameCount, pRenderedBufferList); if (status != noErr) { - ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " ERROR: AudioUnitRender() failed with %d.\n", (int)status); + ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "ERROR: AudioUnitRender() failed with %d.\n", (int)status); return status; } @@ -34527,7 +34532,7 @@ typedef struct static ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_init_internal_data__coreaudio* pData, void* pDevice_DoNotReference) /* <-- pDevice is typed as void* intentionally so as to avoid accidentally referencing it. */ { - ma_result result; + ma_result result = MA_SUCCESS; OSStatus status; UInt32 enableIOFlag; AudioStreamBasicDescription bestFormat; @@ -34734,15 +34739,28 @@ static ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_dev /* I've had a report that the channel count returned by AudioUnitGetProperty above is inconsistent with AVAudioSession outputNumberOfChannels. I'm going to try using the AVAudioSession values instead. + + UPDATE 20/02/2025: + When testing on the simulator with an iPhone 15 and iOS 17 I get an error when initializing the audio + unit if set the input channels to pAudioSession.inputNumberOfChannels. What is happening is the channel + count returned from AudioUnitGetProperty() above is set to 2, but pAudioSession is reporting a channel + count of 1. When this happens, the call to AudioUnitSetProprty() below just down below will succeed, but + AudioUnitInitialize() further down will fail. The only solution I have come up with is to not set the + channel count to pAudioSession.inputNumberOfChannels. */ if (deviceType == ma_device_type_playback) { bestFormat.mChannelsPerFrame = (UInt32)pAudioSession.outputNumberOfChannels; } + + #if 0 if (deviceType == ma_device_type_capture) { + /*printf("DEBUG: bestFormat.mChannelsPerFrame = %d; pAudioSession.inputNumberOfChannels = %d\n", (int)bestFormat.mChannelsPerFrame, (int)pAudioSession.inputNumberOfChannels);*/ bestFormat.mChannelsPerFrame = (UInt32)pAudioSession.inputNumberOfChannels; } + #endif } + status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, sizeof(bestFormat)); if (status != noErr) { ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit); @@ -67950,7 +67968,7 @@ MA_API ma_result ma_resource_manager_init(const ma_resource_manager_config* pCon vtableUserDataSizeInBytes = 0; /* No vtable user data present. No need for an allocation. */ } - pResourceManager->config.ppDecodingBackendVTables = (const ma_decoding_backend_vtable**)ma_malloc(vtableSizeInBytes + vtableUserDataSizeInBytes, &pResourceManager->config.allocationCallbacks); + pResourceManager->config.ppDecodingBackendVTables = (const ma_decoding_backend_vtable* const*)ma_malloc(vtableSizeInBytes + vtableUserDataSizeInBytes, &pResourceManager->config.allocationCallbacks); if (pResourceManager->config.ppDecodingBackendVTables == NULL) { ma_job_queue_uninit(&pResourceManager->jobQueue, &pResourceManager->config.allocationCallbacks); return MA_OUT_OF_MEMORY;