19 Commits

Author SHA1 Message Date
David Reid ea205fb7b0 Version 0.11.16 2023-05-15 09:36:42 +10:00
David Reid 26c11a7771 Process jobs on the calling thread when WAIT_INIT is used.
Since the calling thread is waiting anyway, it's better to just do the
processing on the calling thread rather than posting it to the job
queue and waiting. This ensures the calling thread stays busy which
will improve performance, but it also makes it so the calling thread
doesn't get stalled while already-queued jobs are getting processed.
2023-05-12 09:11:29 +10:00
David Reid 870ac8a22c Don't link to advapi32.dll for the GDK build. 2023-05-06 08:59:13 +10:00
David Reid a1ea4438ee Fix ma_dlopen() on the GDK build. 2023-05-06 08:50:55 +10:00
David Reid 902c19d6ab WASAPI: Another fix for the GDK build. 2023-05-06 08:41:08 +10:00
David Reid 64f14070a7 WASAPI: Revert an experimental change and try fixing GDK build. 2023-05-06 08:31:32 +10:00
David Reid 6d20ccb701 WASAPI: Experimental change for rerouting. 2023-05-05 10:26:39 +10:00
David Reid 96ac03f184 WASAPI: Log error codes when a device fails to start. 2023-05-05 09:34:31 +10:00
David Reid e913a6d1aa Silence a warning. 2023-05-05 09:24:46 +10:00
David Reid de706d44b8 Experimental fix for better handling of AUDCLNT_E_DEVICE_INVALIDATED. 2023-05-05 09:18:18 +10:00
David Reid 2bf7e03777 WASAPI: Relax validation checks when doing device reroutes. 2023-05-05 08:55:23 +10:00
David Reid ae25dbcdac Fix a memory leak in ma_sound_init_copy().
Public issue https://github.com/mackron/miniaudio/issues/667
2023-05-03 08:02:42 +10:00
David Reid 4326fad97a Update links in readme. 2023-04-30 12:15:38 +10:00
David Reid 937cd9c16c Another update to the readme to make it less wordy. 2023-04-30 12:03:26 +10:00
David Reid d1f3715a08 Playing around with a restructure to the readme. 2023-04-30 11:20:53 +10:00
David Reid 9fe0970e20 Remove the previous experimental change to the readme. Doesn't work. 2023-04-30 08:56:43 +10:00
David Reid a74c2c78d9 Try fixing some HTML formatting. 2023-04-30 08:54:26 +10:00
David Reid 189beb67fa Experiment with a change to the readme. 2023-04-30 08:53:14 +10:00
David Reid 7384bde372 Update change history. 2023-04-30 08:39:53 +10:00
5 changed files with 249 additions and 221 deletions
+10 -2
View File
@@ -1,8 +1,16 @@
v0.11.15 - TBD
==============
v0.11.16 - 2023-05-15
=====================
* Fix a memory leak with `ma_sound_init_copy()`.
* Improve performance of `ma_sound_init_*()` when using the `ASYNC | DECODE` flag combination.
v0.11.15 - 2023-04-30
=====================
* Fix a bug where initialization of a duplex device fails on some backends.
* Fix a bug in ma_gainer where smoothing isn't applied correctly thus resulting in glitching.
* Add support for volume smoothing to sounds when changing the volume with `ma_sound_set_volume()`. To use this, you must configure it via the `volumeSmoothTimeInPCMFrames` member of ma_sound_config and use `ma_sound_init_ex()` to initialize your sound. Smoothing is disabled by default.
* WASAPI: Fix a possible buffer overrun when initializing a device.
* WASAPI: Make device initialization more robust by improving the handling of the querying of the internal data format.
v0.11.14 - 2023-03-29
+70 -94
View File
@@ -3,7 +3,7 @@
<br>
</h1>
<h4 align="center">A single file library for audio playback and capture.</h4>
<h4 align="center">An audio playback and capture library in a single source file.</h4>
<p align="center">
<a href="https://discord.gg/9vpqbjU"><img src="https://img.shields.io/discord/712952679415939085?label=discord&logo=discord&style=flat-square" alt="discord"></a>
@@ -12,14 +12,39 @@
</p>
<p align="center">
<a href="#features">Features</a> -
<a href="#examples">Examples</a> -
<a href="#building">Building</a> -
<a href="#documentation">Documentation</a> -
<a href="#supported-platforms">Supported Platforms</a> -
<a href="#backends">Backends</a> -
<a href="#major-features">Major Features</a> -
<a href="#building">Building</a>
<a href="#license">License</a>
</p>
miniaudio is written in C with no dependencies except the standard library and should compile clean on all major
compilers without the need to install any additional development packages. All major desktop and mobile platforms
are supported.
Features
========
- Simple build system with no external dependencies.
- Simple and flexible API.
- Low-level API for direct access to raw audio data.
- High-level API for sound management, mixing, effects and optional 3D spatialization.
- Flexible node graph system for advanced mixing and effect processing.
- Resource management for loading sound files.
- Decoding, with built-in support for WAV, FLAC and MP3, in addition to being able to plug in custom decoders.
- Encoding (WAV only).
- Data conversion.
- Resampling, including custom resamplers.
- Channel mapping.
- Basic generation of waveforms and noise.
- Basic effects and filters.
Refer to the [Programming Manual](https://miniaud.io/docs/manual/) for a more complete description of
available features in miniaudio.
Examples
========
@@ -27,27 +52,21 @@ This example shows one way to play a sound using the high level API.
```c
#define MINIAUDIO_IMPLEMENTATION
#include "../miniaudio.h"
#include "miniaudio.h"
#include <stdio.h>
int main(int argc, char** argv)
int main()
{
ma_result result;
ma_engine engine;
if (argc < 2) {
printf("No input file.");
return -1;
}
result = ma_engine_init(NULL, &engine);
if (result != MA_SUCCESS) {
printf("Failed to initialize audio engine.");
return -1;
}
ma_engine_play_sound(&engine, argv[1], NULL);
ma_engine_play_sound(&engine, "sound.wav", NULL);
printf("Press Enter to quit...");
getchar();
@@ -62,7 +81,7 @@ This example shows how to decode and play a sound using the low level API.
```c
#define MINIAUDIO_IMPLEMENTATION
#include "../miniaudio.h"
#include "miniaudio.h"
#include <stdio.h>
@@ -128,6 +147,34 @@ int main(int argc, char** argv)
More examples can be found in the [examples](examples) folder or online here: https://miniaud.io/docs/examples/
Building
========
Do the following in one source file:
```c
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
```
Then just compile. There's no need to install any dependencies. On Windows and macOS there's no need to link
to anything. On Linux just link to `-lpthread`, `-lm` and `-ldl`. On BSD just link to `-lpthread` and `-lm`.
On iOS you need to compile as Objective-C.
If you get errors about undefined references to `__sync_val_compare_and_swap_8`, `__atomic_load_8`, etc. you
need to link with `-latomic`.
If you prefer separate .h and .c files, you can find a split version of miniaudio in the extras/miniaudio_split
folder. From here you can use miniaudio as a traditional .c and .h library - just add miniaudio.c to your source
tree like any other source file and include miniaudio.h like a normal header. If you prefer compiling as a
single translation unit (AKA unity builds), you can just #include the .c file in your main source file:
```c
#include "miniaudio.c"
```
Note that the split version is auto-generated using a tool and is based on the main file in the root directory.
If you want to contribute, please make the change in the main file.
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.
Documentation
=============
Online documentation can be found here: https://miniaud.io/docs/
@@ -139,17 +186,20 @@ documentation is generated from this in-code documentation.
Supported Platforms
===================
- Windows, UWP
- Windows
- macOS, iOS
- Linux
- BSD
- FreeBSD / OpenBSD / NetBSD
- Android
- Raspberry Pi
- Emscripten / HTML5
miniaudio should compile clean on other platforms, but it will not include any support for playback or capture
by default. To support that, you would need to implement a custom backend. You can do this without needing to
modify the miniaudio source code. See the [custom_backend](examples/custom_backend.c) example.
Backends
========
--------
- WASAPI
- DirectSound
- WinMM
@@ -167,80 +217,6 @@ Backends
- Custom
Major Features
==============
- Your choice of either public domain or [MIT No Attribution](https://github.com/aws/mit-0).
- Entirely contained within a single file for easy integration into your source tree.
- No external dependencies except for the C standard library and backend libraries.
- Written in C and compilable as C++, enabling miniaudio to work on almost all compilers.
- Supports all major desktop and mobile platforms, with multiple backends for maximum compatibility.
- A low level API with direct access to the raw audio data.
- A high level API with sound management and effects, including 3D spatialization.
- Supports playback, capture, full-duplex and loopback (WASAPI only).
- Device enumeration for connecting to specific devices, not just defaults.
- Connect to multiple devices at once.
- Shared and exclusive mode on supported backends.
- Resource management for loading and streaming sounds.
- A node graph system for advanced mixing and effect processing.
- Data conversion (sample format conversion, channel conversion and resampling).
- Filters.
- Biquads
- Low-pass (first, second and high order)
- High-pass (first, second and high order)
- Band-pass (second and high order)
- Effects.
- Delay/Echo
- Spatializer
- Stereo Pan
- Waveform generation (sine, square, triangle, sawtooth).
- Noise generation (white, pink, Brownian).
- Decoding
- WAV
- FLAC
- MP3
- Vorbis via stb_vorbis (not built in - must be included separately).
- Custom
- Encoding
- WAV
Refer to the [Programming Manual](https://miniaud.io/docs/manual/) for a more complete description of
available features in miniaudio.
Building
========
Do the following in one source file:
```c
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
```
Then just compile. There's no need to install any dependencies. On Windows and macOS there's no need to link
to anything. On Linux just link to -lpthread, -lm and -ldl. On BSD just link to -lpthread and -lm. On iOS you
need to compile as Objective-C.
If you prefer separate .h and .c files, you can find a split version of miniaudio in the extras/miniaudio_split
folder. From here you can use miniaudio as a traditional .c and .h library - just add miniaudio.c to your source
tree like any other source file and include miniaudio.h like a normal header. If you prefer compiling as a
single translation unit (AKA unity builds), you can just #include the .c file in your main source file:
```c
#include "miniaudio.c"
```
Note that the split version is auto-generated using a tool and is based on the main file in the root directory.
If you want to contribute, please make the change in the main file.
Vorbis Decoding
---------------
Vorbis decoding is enabled via stb_vorbis. To use it, you need to include the header section of stb_vorbis
before the implementation of miniaudio. You can enable Vorbis by doing the following:
```c
#define STB_VORBIS_HEADER_ONLY
#include "extras/stb_vorbis.c" /* Enables Vorbis decoding. */
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
/* stb_vorbis implementation must come after the implementation of miniaudio. */
#undef STB_VORBIS_HEADER_ONLY
#include "extras/stb_vorbis.c"
```
License
=======
Your choice of either public domain or [MIT No Attribution](https://github.com/aws/mit-0).
+57 -35
View File
@@ -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.11.15 - 2023-04-30
miniaudio - v0.11.16 - 2023-05-15
David Reid - mackron@gmail.com
@@ -7101,9 +7101,9 @@ MA_API ma_handle ma_dlopen(ma_context* pContext, const char* filename)
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "Loading library: %s\n", filename);
#ifdef _WIN32
#ifdef MA_WIN32
/* From MSDN: Desktop applications cannot use LoadPackagedLibrary; if a desktop application calls this function it fails with APPMODEL_ERROR_NO_PACKAGE.*/
#if !defined(WINAPI_FAMILY) || (defined(WINAPI_FAMILY) && (defined(WINAPI_FAMILY_DESKTOP_APP) && WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
#if !defined(MA_WIN32_UWP)
handle = (ma_handle)LoadLibraryA(filename);
#else
/* *sigh* It appears there is no ANSI version of LoadPackagedLibrary()... */
@@ -7139,7 +7139,7 @@ MA_API ma_handle ma_dlopen(ma_context* pContext, const char* filename)
MA_API void ma_dlclose(ma_context* pContext, ma_handle handle)
{
#ifndef MA_NO_RUNTIME_LINKING
#ifdef _WIN32
#ifdef MA_WIN32
FreeLibrary((HMODULE)handle);
#else
dlclose((void*)handle);
@@ -8466,7 +8466,7 @@ WIN32 COMMON
*******************************************************************************/
#if defined(MA_WIN32)
#if defined(MA_WIN32_DESKTOP)
#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK)
#define ma_CoInitializeEx(pContext, pvReserved, dwCoInit) ((pContext->win32.CoInitializeEx) ? ((MA_PFN_CoInitializeEx)pContext->win32.CoInitializeEx)(pvReserved, dwCoInit) : ((MA_PFN_CoInitialize)pContext->win32.CoInitialize)(pvReserved))
#define ma_CoUninitialize(pContext) ((MA_PFN_CoUninitialize)pContext->win32.CoUninitialize)()
#define ma_CoCreateInstance(pContext, rclsid, pUnkOuter, dwClsContext, riid, ppv) ((MA_PFN_CoCreateInstance)pContext->win32.CoCreateInstance)(rclsid, pUnkOuter, dwClsContext, riid, ppv)
@@ -9526,13 +9526,9 @@ static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDefaultDeviceChanged
/*ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "IMMNotificationClient_OnDefaultDeviceChanged(dataFlow=%d, role=%d, pDefaultDeviceID=%S)\n", dataFlow, role, (pDefaultDeviceID != NULL) ? pDefaultDeviceID : L"(NULL)");*/
#endif
/* We only ever use the eConsole role in miniaudio. */
if (role != ma_eConsole) {
ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Stream rerouting: role != eConsole\n");
return S_OK;
}
(void)role;
/* We only care about devices with the same data flow and role as the current device. */
/* We only care about devices with the same data flow as the current device. */
if ((pThis->pDevice->type == ma_device_type_playback && dataFlow != ma_eRender) ||
(pThis->pDevice->type == ma_device_type_capture && dataFlow != ma_eCapture) ||
(pThis->pDevice->type == ma_device_type_loopback && dataFlow != ma_eRender)) {
@@ -11577,7 +11573,7 @@ static ma_result ma_device_start__wasapi_nolock(ma_device* pDevice)
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
if (FAILED(hr)) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal capture device.");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal capture device. HRESULT = %d.", (int)hr);
return ma_result_from_HRESULT(hr);
}
@@ -11587,7 +11583,7 @@ static ma_result ma_device_start__wasapi_nolock(ma_device* pDevice)
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
if (FAILED(hr)) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal playback device.");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal playback device. HRESULT = %d.", (int)hr);
return ma_result_from_HRESULT(hr);
}
@@ -29618,11 +29614,15 @@ static ma_bool32 ma_device__is_initialized(ma_device* pDevice)
static ma_result ma_context_uninit_backend_apis__win32(ma_context* pContext)
{
/* For some reason UWP complains when CoUninitialize() is called. I'm just not going to call it on UWP. */
#ifdef MA_WIN32_DESKTOP
#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK)
ma_CoUninitialize(pContext);
#if defined(MA_WIN32_DESKTOP)
ma_dlclose(pContext, pContext->win32.hUser32DLL);
ma_dlclose(pContext, pContext->win32.hOle32DLL);
ma_dlclose(pContext, pContext->win32.hAdvapi32DLL);
#endif
ma_dlclose(pContext, pContext->win32.hOle32DLL);
#else
(void)pContext;
#endif
@@ -29632,22 +29632,8 @@ static ma_result ma_context_uninit_backend_apis__win32(ma_context* pContext)
static ma_result ma_context_init_backend_apis__win32(ma_context* pContext)
{
#ifdef MA_WIN32_DESKTOP
/* Ole32.dll */
pContext->win32.hOle32DLL = ma_dlopen(pContext, "ole32.dll");
if (pContext->win32.hOle32DLL == NULL) {
return MA_FAILED_TO_INIT_BACKEND;
}
pContext->win32.CoInitialize = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoInitialize");
pContext->win32.CoInitializeEx = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoInitializeEx");
pContext->win32.CoUninitialize = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoUninitialize");
pContext->win32.CoCreateInstance = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoCreateInstance");
pContext->win32.CoTaskMemFree = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoTaskMemFree");
pContext->win32.PropVariantClear = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "PropVariantClear");
pContext->win32.StringFromGUID2 = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "StringFromGUID2");
#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK)
#if defined(MA_WIN32_DESKTOP)
/* User32.dll */
pContext->win32.hUser32DLL = ma_dlopen(pContext, "user32.dll");
if (pContext->win32.hUser32DLL == NULL) {
@@ -29667,6 +29653,21 @@ static ma_result ma_context_init_backend_apis__win32(ma_context* pContext)
pContext->win32.RegOpenKeyExA = (ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL, "RegOpenKeyExA");
pContext->win32.RegCloseKey = (ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL, "RegCloseKey");
pContext->win32.RegQueryValueExA = (ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL, "RegQueryValueExA");
#endif
/* Ole32.dll */
pContext->win32.hOle32DLL = ma_dlopen(pContext, "ole32.dll");
if (pContext->win32.hOle32DLL == NULL) {
return MA_FAILED_TO_INIT_BACKEND;
}
pContext->win32.CoInitialize = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoInitialize");
pContext->win32.CoInitializeEx = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoInitializeEx");
pContext->win32.CoUninitialize = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoUninitialize");
pContext->win32.CoCreateInstance = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoCreateInstance");
pContext->win32.CoTaskMemFree = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoTaskMemFree");
pContext->win32.PropVariantClear = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "PropVariantClear");
pContext->win32.StringFromGUID2 = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "StringFromGUID2");
#else
(void)pContext; /* Unused. */
#endif
@@ -56583,7 +56584,12 @@ static ma_result ma_resource_manager_data_buffer_node_acquire_critical_section(m
job.data.resourceManager.loadDataBufferNode.pInitFence = pInitFence;
job.data.resourceManager.loadDataBufferNode.pDoneFence = pDoneFence;
if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) {
result = ma_job_process(&job);
} else {
result = ma_resource_manager_post_job(pResourceManager, &job);
}
if (result != MA_SUCCESS) {
/* Failed to post job. Probably ran out of memory. */
ma_log_postf(ma_resource_manager_get_log(pResourceManager), MA_LOG_LEVEL_ERROR, "Failed to post MA_JOB_TYPE_RESOURCE_MANAGER_LOAD_DATA_BUFFER_NODE job. %s.\n", ma_result_description(result));
@@ -56596,11 +56602,12 @@ static ma_result ma_resource_manager_data_buffer_node_acquire_critical_section(m
if (pDoneFence != NULL) { ma_fence_release(pDoneFence); }
if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) {
ma_resource_manager_inline_notification_init(pResourceManager, pInitNotification);
}
ma_resource_manager_inline_notification_uninit(pInitNotification);
} else {
/* These will have been freed by the job thread, but with WAIT_INIT they will already have happend sinced the job has already been handled. */
ma_free(pFilePathCopy, &pResourceManager->config.allocationCallbacks);
ma_free(pFilePathWCopy, &pResourceManager->config.allocationCallbacks);
}
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBufferNode);
ma_free(pDataBufferNode, &pResourceManager->config.allocationCallbacks);
@@ -57040,7 +57047,13 @@ static ma_result ma_resource_manager_data_buffer_init_ex_internal(ma_resource_ma
job.data.resourceManager.loadDataBuffer.loopPointEndInPCMFrames = pConfig->loopPointEndInPCMFrames;
job.data.resourceManager.loadDataBuffer.isLooping = pConfig->isLooping;
/* If we need to wait for initialization to complete we can just process the job in place. */
if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) {
result = ma_job_process(&job);
} else {
result = ma_resource_manager_post_job(pResourceManager, &job);
}
if (result != MA_SUCCESS) {
/* We failed to post the job. Most likely there isn't enough room in the queue's buffer. */
ma_log_postf(ma_resource_manager_get_log(pResourceManager), MA_LOG_LEVEL_ERROR, "Failed to post MA_JOB_TYPE_RESOURCE_MANAGER_LOAD_DATA_BUFFER job. %s.\n", ma_result_description(result));
@@ -58739,6 +58752,12 @@ done:
/* Increment the node's execution pointer so that the next jobs can be processed. This is how we keep decoding of pages in-order. */
c89atomic_fetch_add_32(&pDataBufferNode->executionPointer, 1);
/* A busy result should be considered successful from the point of view of the job system. */
if (result == MA_BUSY) {
result = MA_SUCCESS;
}
return result;
}
@@ -64090,7 +64109,7 @@ MA_API ma_result ma_sound_init_copy(ma_engine* pEngine, const ma_sound* pExistin
/*
We need to make a clone of the data source. If the data source is not a data buffer (i.e. a stream)
the this will fail.
this will fail.
*/
pSound->pResourceManagerDataSource = (ma_resource_manager_data_source*)ma_malloc(sizeof(*pSound->pResourceManagerDataSource), &pEngine->allocationCallbacks);
if (pSound->pResourceManagerDataSource == NULL) {
@@ -64118,6 +64137,9 @@ MA_API ma_result ma_sound_init_copy(ma_engine* pEngine, const ma_sound* pExistin
return result;
}
/* Make sure the sound is marked as the owner of the data source or else it will never get uninitialized. */
pSound->ownsDataSource = MA_TRUE;
return MA_SUCCESS;
}
#endif
+2 -2
View File
@@ -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.11.15 - 2023-04-30
miniaudio - v0.11.16 - 2023-05-15
David Reid - mackron@gmail.com
@@ -20,7 +20,7 @@ extern "C" {
#define MA_VERSION_MAJOR 0
#define MA_VERSION_MINOR 11
#define MA_VERSION_REVISION 15
#define MA_VERSION_REVISION 16
#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__)
+58 -36
View File
@@ -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.11.15 - 2023-04-30
miniaudio - v0.11.16 - 2023-05-15
David Reid - mackron@gmail.com
@@ -3722,7 +3722,7 @@ extern "C" {
#define MA_VERSION_MAJOR 0
#define MA_VERSION_MINOR 11
#define MA_VERSION_REVISION 15
#define MA_VERSION_REVISION 16
#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__)
@@ -18455,9 +18455,9 @@ MA_API ma_handle ma_dlopen(ma_context* pContext, const char* filename)
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "Loading library: %s\n", filename);
#ifdef _WIN32
#ifdef MA_WIN32
/* From MSDN: Desktop applications cannot use LoadPackagedLibrary; if a desktop application calls this function it fails with APPMODEL_ERROR_NO_PACKAGE.*/
#if !defined(WINAPI_FAMILY) || (defined(WINAPI_FAMILY) && (defined(WINAPI_FAMILY_DESKTOP_APP) && WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
#if !defined(MA_WIN32_UWP)
handle = (ma_handle)LoadLibraryA(filename);
#else
/* *sigh* It appears there is no ANSI version of LoadPackagedLibrary()... */
@@ -18493,7 +18493,7 @@ MA_API ma_handle ma_dlopen(ma_context* pContext, const char* filename)
MA_API void ma_dlclose(ma_context* pContext, ma_handle handle)
{
#ifndef MA_NO_RUNTIME_LINKING
#ifdef _WIN32
#ifdef MA_WIN32
FreeLibrary((HMODULE)handle);
#else
dlclose((void*)handle);
@@ -19820,7 +19820,7 @@ WIN32 COMMON
*******************************************************************************/
#if defined(MA_WIN32)
#if defined(MA_WIN32_DESKTOP)
#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK)
#define ma_CoInitializeEx(pContext, pvReserved, dwCoInit) ((pContext->win32.CoInitializeEx) ? ((MA_PFN_CoInitializeEx)pContext->win32.CoInitializeEx)(pvReserved, dwCoInit) : ((MA_PFN_CoInitialize)pContext->win32.CoInitialize)(pvReserved))
#define ma_CoUninitialize(pContext) ((MA_PFN_CoUninitialize)pContext->win32.CoUninitialize)()
#define ma_CoCreateInstance(pContext, rclsid, pUnkOuter, dwClsContext, riid, ppv) ((MA_PFN_CoCreateInstance)pContext->win32.CoCreateInstance)(rclsid, pUnkOuter, dwClsContext, riid, ppv)
@@ -20880,13 +20880,9 @@ static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDefaultDeviceChanged
/*ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "IMMNotificationClient_OnDefaultDeviceChanged(dataFlow=%d, role=%d, pDefaultDeviceID=%S)\n", dataFlow, role, (pDefaultDeviceID != NULL) ? pDefaultDeviceID : L"(NULL)");*/
#endif
/* We only ever use the eConsole role in miniaudio. */
if (role != ma_eConsole) {
ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Stream rerouting: role != eConsole\n");
return S_OK;
}
(void)role;
/* We only care about devices with the same data flow and role as the current device. */
/* We only care about devices with the same data flow as the current device. */
if ((pThis->pDevice->type == ma_device_type_playback && dataFlow != ma_eRender) ||
(pThis->pDevice->type == ma_device_type_capture && dataFlow != ma_eCapture) ||
(pThis->pDevice->type == ma_device_type_loopback && dataFlow != ma_eRender)) {
@@ -22931,7 +22927,7 @@ static ma_result ma_device_start__wasapi_nolock(ma_device* pDevice)
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
if (FAILED(hr)) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal capture device.");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal capture device. HRESULT = %d.", (int)hr);
return ma_result_from_HRESULT(hr);
}
@@ -22941,7 +22937,7 @@ static ma_result ma_device_start__wasapi_nolock(ma_device* pDevice)
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
if (FAILED(hr)) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal playback device.");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal playback device. HRESULT = %d.", (int)hr);
return ma_result_from_HRESULT(hr);
}
@@ -40972,11 +40968,15 @@ static ma_bool32 ma_device__is_initialized(ma_device* pDevice)
static ma_result ma_context_uninit_backend_apis__win32(ma_context* pContext)
{
/* For some reason UWP complains when CoUninitialize() is called. I'm just not going to call it on UWP. */
#ifdef MA_WIN32_DESKTOP
#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK)
ma_CoUninitialize(pContext);
#if defined(MA_WIN32_DESKTOP)
ma_dlclose(pContext, pContext->win32.hUser32DLL);
ma_dlclose(pContext, pContext->win32.hOle32DLL);
ma_dlclose(pContext, pContext->win32.hAdvapi32DLL);
#endif
ma_dlclose(pContext, pContext->win32.hOle32DLL);
#else
(void)pContext;
#endif
@@ -40986,22 +40986,8 @@ static ma_result ma_context_uninit_backend_apis__win32(ma_context* pContext)
static ma_result ma_context_init_backend_apis__win32(ma_context* pContext)
{
#ifdef MA_WIN32_DESKTOP
/* Ole32.dll */
pContext->win32.hOle32DLL = ma_dlopen(pContext, "ole32.dll");
if (pContext->win32.hOle32DLL == NULL) {
return MA_FAILED_TO_INIT_BACKEND;
}
pContext->win32.CoInitialize = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoInitialize");
pContext->win32.CoInitializeEx = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoInitializeEx");
pContext->win32.CoUninitialize = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoUninitialize");
pContext->win32.CoCreateInstance = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoCreateInstance");
pContext->win32.CoTaskMemFree = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoTaskMemFree");
pContext->win32.PropVariantClear = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "PropVariantClear");
pContext->win32.StringFromGUID2 = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "StringFromGUID2");
#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK)
#if defined(MA_WIN32_DESKTOP)
/* User32.dll */
pContext->win32.hUser32DLL = ma_dlopen(pContext, "user32.dll");
if (pContext->win32.hUser32DLL == NULL) {
@@ -41021,6 +41007,21 @@ static ma_result ma_context_init_backend_apis__win32(ma_context* pContext)
pContext->win32.RegOpenKeyExA = (ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL, "RegOpenKeyExA");
pContext->win32.RegCloseKey = (ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL, "RegCloseKey");
pContext->win32.RegQueryValueExA = (ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL, "RegQueryValueExA");
#endif
/* Ole32.dll */
pContext->win32.hOle32DLL = ma_dlopen(pContext, "ole32.dll");
if (pContext->win32.hOle32DLL == NULL) {
return MA_FAILED_TO_INIT_BACKEND;
}
pContext->win32.CoInitialize = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoInitialize");
pContext->win32.CoInitializeEx = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoInitializeEx");
pContext->win32.CoUninitialize = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoUninitialize");
pContext->win32.CoCreateInstance = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoCreateInstance");
pContext->win32.CoTaskMemFree = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoTaskMemFree");
pContext->win32.PropVariantClear = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "PropVariantClear");
pContext->win32.StringFromGUID2 = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "StringFromGUID2");
#else
(void)pContext; /* Unused. */
#endif
@@ -67937,7 +67938,12 @@ static ma_result ma_resource_manager_data_buffer_node_acquire_critical_section(m
job.data.resourceManager.loadDataBufferNode.pInitFence = pInitFence;
job.data.resourceManager.loadDataBufferNode.pDoneFence = pDoneFence;
if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) {
result = ma_job_process(&job);
} else {
result = ma_resource_manager_post_job(pResourceManager, &job);
}
if (result != MA_SUCCESS) {
/* Failed to post job. Probably ran out of memory. */
ma_log_postf(ma_resource_manager_get_log(pResourceManager), MA_LOG_LEVEL_ERROR, "Failed to post MA_JOB_TYPE_RESOURCE_MANAGER_LOAD_DATA_BUFFER_NODE job. %s.\n", ma_result_description(result));
@@ -67950,11 +67956,12 @@ static ma_result ma_resource_manager_data_buffer_node_acquire_critical_section(m
if (pDoneFence != NULL) { ma_fence_release(pDoneFence); }
if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) {
ma_resource_manager_inline_notification_init(pResourceManager, pInitNotification);
}
ma_resource_manager_inline_notification_uninit(pInitNotification);
} else {
/* These will have been freed by the job thread, but with WAIT_INIT they will already have happend sinced the job has already been handled. */
ma_free(pFilePathCopy, &pResourceManager->config.allocationCallbacks);
ma_free(pFilePathWCopy, &pResourceManager->config.allocationCallbacks);
}
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBufferNode);
ma_free(pDataBufferNode, &pResourceManager->config.allocationCallbacks);
@@ -68394,7 +68401,13 @@ static ma_result ma_resource_manager_data_buffer_init_ex_internal(ma_resource_ma
job.data.resourceManager.loadDataBuffer.loopPointEndInPCMFrames = pConfig->loopPointEndInPCMFrames;
job.data.resourceManager.loadDataBuffer.isLooping = pConfig->isLooping;
/* If we need to wait for initialization to complete we can just process the job in place. */
if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) {
result = ma_job_process(&job);
} else {
result = ma_resource_manager_post_job(pResourceManager, &job);
}
if (result != MA_SUCCESS) {
/* We failed to post the job. Most likely there isn't enough room in the queue's buffer. */
ma_log_postf(ma_resource_manager_get_log(pResourceManager), MA_LOG_LEVEL_ERROR, "Failed to post MA_JOB_TYPE_RESOURCE_MANAGER_LOAD_DATA_BUFFER job. %s.\n", ma_result_description(result));
@@ -70093,6 +70106,12 @@ done:
/* Increment the node's execution pointer so that the next jobs can be processed. This is how we keep decoding of pages in-order. */
c89atomic_fetch_add_32(&pDataBufferNode->executionPointer, 1);
/* A busy result should be considered successful from the point of view of the job system. */
if (result == MA_BUSY) {
result = MA_SUCCESS;
}
return result;
}
@@ -75444,7 +75463,7 @@ MA_API ma_result ma_sound_init_copy(ma_engine* pEngine, const ma_sound* pExistin
/*
We need to make a clone of the data source. If the data source is not a data buffer (i.e. a stream)
the this will fail.
this will fail.
*/
pSound->pResourceManagerDataSource = (ma_resource_manager_data_source*)ma_malloc(sizeof(*pSound->pResourceManagerDataSource), &pEngine->allocationCallbacks);
if (pSound->pResourceManagerDataSource == NULL) {
@@ -75472,6 +75491,9 @@ MA_API ma_result ma_sound_init_copy(ma_engine* pEngine, const ma_sound* pExistin
return result;
}
/* Make sure the sound is marked as the owner of the data source or else it will never get uninitialized. */
pSound->ownsDataSource = MA_TRUE;
return MA_SUCCESS;
}
#endif