1
1
Fork 0
mirror of https://github.com/QB64-Phoenix-Edition/QB64pe.git synced 2024-07-04 04:50:22 +00:00

Merge pull request #422 from a740g/miniaudio-upgrade

Upgrade miniaudio to v0.11.21
This commit is contained in:
Samuel Gomes 2024-01-03 16:33:02 +05:30 committed by GitHub
commit fcac614f67
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

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.18 - 2023-08-07
miniaudio - v0.11.21 - 2023-11-15
David Reid - mackron@gmail.com
@ -87,7 +87,7 @@ device on the stack, but you could allocate it on the heap if that suits your si
// Do something here. Probably your program's main loop.
ma_device_uninit(&device); // This will stop the device so no need to do that manually.
ma_device_uninit(&device);
return 0;
}
```
@ -1675,7 +1675,7 @@ an example for initializing a data source:
// ...
ma_resource_manager_data_source_uninit(pResourceManager, &dataSource);
ma_resource_manager_data_source_uninit(&dataSource);
```
The `flags` parameter specifies how you want to perform loading of the sound file. It can be a
@ -1912,10 +1912,10 @@ once after the other:
```c
ma_resource_manager_data_source_init(pResourceManager, "my_file", ..., &myDataBuffer0); // Refcount = 1. Initial load.
ma_resource_manager_data_source_uninit(pResourceManager, &myDataBuffer0); // Refcount = 0. Unloaded.
ma_resource_manager_data_source_uninit(&myDataBuffer0); // Refcount = 0. Unloaded.
ma_resource_manager_data_source_init(pResourceManager, "my_file", ..., &myDataBuffer1); // Refcount = 1. Reloaded because previous uninit() unloaded it.
ma_resource_manager_data_source_uninit(pResourceManager, &myDataBuffer1); // Refcount = 0. Unloaded.
ma_resource_manager_data_source_uninit(&myDataBuffer1); // Refcount = 0. Unloaded.
```
A binary search tree (BST) is used for storing data buffers as it has good balance between
@ -2675,9 +2675,16 @@ outputting any audio data. To output audio data, use `ma_encoder_write_pcm_frame
example below:
```c
framesWritten = ma_encoder_write_pcm_frames(&encoder, pPCMFramesToWrite, framesToWrite);
ma_uint64 framesWritten;
result = ma_encoder_write_pcm_frames(&encoder, pPCMFramesToWrite, framesToWrite, &framesWritten);
if (result != MA_SUCCESS) {
... handle error ...
}
```
The `framesWritten` variable will contain the number of PCM frames that were actually written. This
is optionally and you can pass in `NULL` if you need this.
Encoders must be uninitialized with `ma_encoder_uninit()`.
@ -3409,7 +3416,7 @@ miniaudio supports reading from a buffer of raw audio data via the `ma_audio_buf
read from memory that's managed by the application, but can also handle the memory management for
you internally. Memory management is flexible and should support most use cases.
Audio buffers are initialised using the standard configuration system used everywhere in miniaudio:
Audio buffers are initialized using the standard configuration system used everywhere in miniaudio:
```c
ma_audio_buffer_config config = ma_audio_buffer_config_init(
@ -3716,7 +3723,7 @@ extern "C" {
#define MA_VERSION_MAJOR 0
#define MA_VERSION_MINOR 11
#define MA_VERSION_REVISION 18
#define MA_VERSION_REVISION 21
#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__)
@ -4267,7 +4274,7 @@ typedef enum
ma_standard_sample_rate_192000 = 192000,
ma_standard_sample_rate_16000 = 16000, /* Extreme lows */
ma_standard_sample_rate_11025 = 11250,
ma_standard_sample_rate_11025 = 11025,
ma_standard_sample_rate_8000 = 8000,
ma_standard_sample_rate_352800 = 352800, /* Extreme highs */
@ -5390,7 +5397,7 @@ MA_API void ma_resampler_uninit(ma_resampler* pResampler, const ma_allocation_ca
/*
Converts the given input data.
Both the input and output frames must be in the format specified in the config when the resampler was initilized.
Both the input and output frames must be in the format specified in the config when the resampler was initialized.
On input, [pFrameCountOut] contains the number of output frames to process. On output it contains the number of output frames that
were actually processed, which may be less than the requested amount which will happen if there's not enough input data. You can use
@ -6709,7 +6716,8 @@ typedef enum
ma_device_notification_type_stopped,
ma_device_notification_type_rerouted,
ma_device_notification_type_interruption_began,
ma_device_notification_type_interruption_ended
ma_device_notification_type_interruption_ended,
ma_device_notification_type_unlocked
} ma_device_notification_type;
typedef struct
@ -7035,7 +7043,7 @@ struct ma_device_config
ma_uint32 periods;
ma_performance_profile performanceProfile;
ma_bool8 noPreSilencedOutputBuffer; /* When set to true, the contents of the output buffer passed into the data callback will be left undefined rather than initialized to silence. */
ma_bool8 noClip; /* When set to true, the contents of the output buffer passed into the data callback will be clipped after returning. Only applies when the playback sample format is f32. */
ma_bool8 noClip; /* When set to true, the contents of the output buffer passed into the data callback will not be clipped after returning. Only applies when the playback sample format is f32. */
ma_bool8 noDisableDenormals; /* Do not disable denormals when firing the data callback. */
ma_bool8 noFixedSizedCallback; /* Disables strict fixed-sized data callbacks. Setting this to true will result in the period size being treated only as a hint to the backend. This is an optimization for those who don't need fixed sized callbacks. */
ma_device_data_proc dataCallback;
@ -8619,8 +8627,8 @@ then be set directly on the structure. Below are the members of the `ma_device_c
callback will write to every sample in the output buffer, or if you are doing your own clearing.
noClip
When set to true, the contents of the output buffer passed into the data callback will be clipped after returning. When set to false (default), the
contents of the output buffer are left alone after returning and it will be left up to the backend itself to decide whether or not the clip. This only
When set to true, the contents of the output buffer are left alone after returning and it will be left up to the backend itself to decide whether or
not to clip. When set to false (default), the contents of the output buffer passed into the data callback will be clipped after returning. This only
applies when the playback sample format is f32.
noDisableDenormals
@ -9133,8 +9141,6 @@ speakers or received from the microphone which can in turn result in de-syncs.
Do not call this in any callback.
This will be called implicitly by `ma_device_uninit()`.
See Also
--------
@ -10171,7 +10177,7 @@ MA_API ma_noise_config ma_noise_config_init(ma_format format, ma_uint32 channels
typedef struct
{
ma_data_source_vtable ds;
ma_data_source_base ds;
ma_noise_config config;
ma_lcg lcg;
union
@ -10569,7 +10575,7 @@ typedef struct
/*
Extended processing callback. This callback is used for effects that process input and output
at different rates (i.e. they perform resampling). This is similar to the simple version, only
they take two seperate frame counts: one for input, and one for output.
they take two separate frame counts: one for input, and one for output.
On input, `pFrameCountOut` is equal to the capacity of the output buffer for each bus, whereas
`pFrameCountIn` will be equal to the number of PCM frames in each of the buffers in `ppFramesIn`.
@ -12238,7 +12244,7 @@ static MA_INLINE void ma_zero_memory_default(void* p, size_t sz)
#define ma_abs(x) (((x) > 0) ? (x) : -(x))
#define ma_clamp(x, lo, hi) (ma_max(lo, ma_min(x, hi)))
#define ma_offset_ptr(p, offset) (((ma_uint8*)(p)) + (offset))
#define ma_align(x, a) ((x + (a-1)) & ~(a-1))
#define ma_align(x, a) (((x) + ((a)-1)) & ~((a)-1))
#define ma_align_64(x) ma_align(x, 8)
#define ma_buffer_frame_capacity(buffer, channels, format) (sizeof(buffer) / ma_get_bytes_per_sample(format) / (channels))
@ -13639,7 +13645,7 @@ MA_API ma_result ma_log_postv(ma_log* pLog, ma_uint32 level, const char* pFormat
/* First try formatting into our fixed sized stack allocated buffer. If this is too small we'll fallback to a heap allocation. */
length = vsnprintf(pFormattedMessageStack, sizeof(pFormattedMessageStack), pFormat, args);
if (length < 0) {
return MA_INVALID_OPERATION; /* An error occured when trying to convert the buffer. */
return MA_INVALID_OPERATION; /* An error occurred when trying to convert the buffer. */
}
if ((size_t)length < sizeof(pFormattedMessageStack)) {
@ -16180,7 +16186,15 @@ static void ma_thread_wait__posix(ma_thread* pThread)
static ma_result ma_mutex_init__posix(ma_mutex* pMutex)
{
int result = pthread_mutex_init((pthread_mutex_t*)pMutex, NULL);
int result;
if (pMutex == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pMutex);
result = pthread_mutex_init((pthread_mutex_t*)pMutex, NULL);
if (result != 0) {
return ma_result_from_errno(result);
}
@ -17807,7 +17821,7 @@ MA_API ma_handle ma_dlopen(ma_log* pLog, const char* filename)
#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(MA_WIN32_UWP)
#if !defined(MA_WIN32_UWP) || !(defined(WINAPI_FAMILY) && ((defined(WINAPI_FAMILY_PHONE_APP) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)))
handle = (ma_handle)LoadLibraryA(filename);
#else
/* *sigh* It appears there is no ANSI version of LoadPackagedLibrary()... */
@ -18452,7 +18466,7 @@ Timing
*******************************************************************************/
#if defined(MA_WIN32) && !defined(MA_POSIX)
static LARGE_INTEGER g_ma_TimerFrequency; /* <-- Initialized to zero since it's static. */
void ma_timer_init(ma_timer* pTimer)
static void ma_timer_init(ma_timer* pTimer)
{
LARGE_INTEGER counter;
@ -18464,7 +18478,7 @@ Timing
pTimer->counter = counter.QuadPart;
}
double ma_timer_get_time_in_seconds(ma_timer* pTimer)
static double ma_timer_get_time_in_seconds(ma_timer* pTimer)
{
LARGE_INTEGER counter;
if (!QueryPerformanceCounter(&counter)) {
@ -18637,30 +18651,31 @@ static void ma_device__on_notification(ma_device_notification notification)
}
}
void ma_device__on_notification_started(ma_device* pDevice)
static void ma_device__on_notification_started(ma_device* pDevice)
{
ma_device__on_notification(ma_device_notification_init(pDevice, ma_device_notification_type_started));
}
void ma_device__on_notification_stopped(ma_device* pDevice)
static void ma_device__on_notification_stopped(ma_device* pDevice)
{
ma_device__on_notification(ma_device_notification_init(pDevice, ma_device_notification_type_stopped));
}
void ma_device__on_notification_rerouted(ma_device* pDevice)
/* Not all platforms support reroute notifications. */
#if !defined(MA_EMSCRIPTEN)
static void ma_device__on_notification_rerouted(ma_device* pDevice)
{
ma_device__on_notification(ma_device_notification_init(pDevice, ma_device_notification_type_rerouted));
}
#endif
void ma_device__on_notification_interruption_began(ma_device* pDevice)
#if defined(MA_EMSCRIPTEN)
EMSCRIPTEN_KEEPALIVE
void ma_device__on_notification_unlocked(ma_device* pDevice)
{
ma_device__on_notification(ma_device_notification_init(pDevice, ma_device_notification_type_interruption_began));
}
void ma_device__on_notification_interruption_ended(ma_device* pDevice)
{
ma_device__on_notification(ma_device_notification_init(pDevice, ma_device_notification_type_interruption_ended));
ma_device__on_notification(ma_device_notification_init(pDevice, ma_device_notification_type_unlocked));
}
#endif
static void ma_device__on_data_inner(ma_device* pDevice, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount)
@ -19115,10 +19130,10 @@ static MA_INLINE void ma_device__set_state(ma_device* pDevice, ma_device_state n
#if defined(MA_WIN32)
GUID MA_GUID_KSDATAFORMAT_SUBTYPE_PCM = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
GUID MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
/*GUID MA_GUID_KSDATAFORMAT_SUBTYPE_ALAW = {0x00000006, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/
/*GUID MA_GUID_KSDATAFORMAT_SUBTYPE_MULAW = {0x00000007, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/
static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_PCM = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
/*static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_ALAW = {0x00000006, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/
/*static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_MULAW = {0x00000007, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/
#endif
@ -23270,7 +23285,7 @@ static ma_result ma_device_read__wasapi(ma_device* pDevice, void* pFrames, ma_ui
/* At this point we should be able to loop back to the start of the loop and try retrieving a data buffer again. */
} else {
/* An error occured and we need to abort. */
/* An error occurred and we need to abort. */
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve internal buffer from capture device in preparation for reading from the device. HRESULT = %d. Stopping device.\n", (int)hr);
result = ma_result_from_HRESULT(hr);
break;
@ -23492,6 +23507,39 @@ static ma_result ma_context_init__wasapi(ma_context* pContext, const ma_context_
MA_ZERO_OBJECT(&pContext->wasapi);
#if defined(MA_WIN32_UWP)
{
/* Link to mmdevapi so we can get access to ActivateAudioInterfaceAsync(). */
pContext->wasapi.hMMDevapi = ma_dlopen(ma_context_get_log(pContext), "mmdevapi.dll");
if (pContext->wasapi.hMMDevapi) {
pContext->wasapi.ActivateAudioInterfaceAsync = ma_dlsym(ma_context_get_log(pContext), pContext->wasapi.hMMDevapi, "ActivateAudioInterfaceAsync");
if (pContext->wasapi.ActivateAudioInterfaceAsync == NULL) {
ma_dlclose(ma_context_get_log(pContext), pContext->wasapi.hMMDevapi);
return MA_NO_BACKEND; /* ActivateAudioInterfaceAsync() could not be loaded. */
}
} else {
return MA_NO_BACKEND; /* Failed to load mmdevapi.dll which is required for ActivateAudioInterfaceAsync() */
}
}
#endif
/* Optionally use the Avrt API to specify the audio thread's latency sensitivity requirements */
pContext->wasapi.hAvrt = ma_dlopen(ma_context_get_log(pContext), "avrt.dll");
if (pContext->wasapi.hAvrt) {
pContext->wasapi.AvSetMmThreadCharacteristicsA = ma_dlsym(ma_context_get_log(pContext), pContext->wasapi.hAvrt, "AvSetMmThreadCharacteristicsA");
pContext->wasapi.AvRevertMmThreadcharacteristics = ma_dlsym(ma_context_get_log(pContext), pContext->wasapi.hAvrt, "AvRevertMmThreadCharacteristics");
/* If either function could not be found, disable use of avrt entirely. */
if (!pContext->wasapi.AvSetMmThreadCharacteristicsA || !pContext->wasapi.AvRevertMmThreadcharacteristics) {
pContext->wasapi.AvSetMmThreadCharacteristicsA = NULL;
pContext->wasapi.AvRevertMmThreadcharacteristics = NULL;
ma_dlclose(ma_context_get_log(pContext), pContext->wasapi.hAvrt);
pContext->wasapi.hAvrt = NULL;
}
}
/*
Annoyingly, WASAPI does not allow you to release an IAudioClient object from a different thread
than the one that retrieved it with GetService(). This can result in a deadlock in two
@ -23535,41 +23583,6 @@ static ma_result ma_context_init__wasapi(ma_context* pContext, const ma_context_
ma_mutex_uninit(&pContext->wasapi.commandLock);
return result;
}
#if defined(MA_WIN32_UWP)
{
/* Link to mmdevapi so we can get access to ActivateAudioInterfaceAsync(). */
pContext->wasapi.hMMDevapi = ma_dlopen(ma_context_get_log(pContext), "mmdevapi.dll");
if (pContext->wasapi.hMMDevapi) {
pContext->wasapi.ActivateAudioInterfaceAsync = ma_dlsym(ma_context_get_log(pContext), pContext->wasapi.hMMDevapi, "ActivateAudioInterfaceAsync");
if (pContext->wasapi.ActivateAudioInterfaceAsync == NULL) {
ma_semaphore_uninit(&pContext->wasapi.commandSem);
ma_mutex_uninit(&pContext->wasapi.commandLock);
ma_dlclose(ma_context_get_log(pContext), pContext->wasapi.hMMDevapi);
return MA_NO_BACKEND; /* ActivateAudioInterfaceAsync() could not be loaded. */
}
} else {
ma_semaphore_uninit(&pContext->wasapi.commandSem);
ma_mutex_uninit(&pContext->wasapi.commandLock);
return MA_NO_BACKEND; /* Failed to load mmdevapi.dll which is required for ActivateAudioInterfaceAsync() */
}
}
#endif
/* Optionally use the Avrt API to specify the audio thread's latency sensitivity requirements */
pContext->wasapi.hAvrt = ma_dlopen(ma_context_get_log(pContext), "avrt.dll");
if (pContext->wasapi.hAvrt) {
pContext->wasapi.AvSetMmThreadCharacteristicsA = ma_dlsym(ma_context_get_log(pContext), pContext->wasapi.hAvrt, "AvSetMmThreadCharacteristicsA");
pContext->wasapi.AvRevertMmThreadcharacteristics = ma_dlsym(ma_context_get_log(pContext), pContext->wasapi.hAvrt, "AvRevertMmThreadCharacteristics");
/* If either function could not be found, disable use of avrt entirely. */
if (!pContext->wasapi.AvSetMmThreadCharacteristicsA || !pContext->wasapi.AvRevertMmThreadcharacteristics) {
pContext->wasapi.AvSetMmThreadCharacteristicsA = NULL;
pContext->wasapi.AvRevertMmThreadcharacteristics = NULL;
ma_dlclose(ma_context_get_log(pContext), pContext->wasapi.hAvrt);
pContext->wasapi.hAvrt = NULL;
}
}
}
@ -31865,6 +31878,18 @@ size, allocate a block of memory of that size and then call AudioObjectGetProper
AudioDeviceID's so just do "dataSize/sizeof(AudioDeviceID)" to know the device count.
*/
#if defined(MA_APPLE_MOBILE)
static void ma_device__on_notification_interruption_began(ma_device* pDevice)
{
ma_device__on_notification(ma_device_notification_init(pDevice, ma_device_notification_type_interruption_began));
}
static void ma_device__on_notification_interruption_ended(ma_device* pDevice)
{
ma_device__on_notification(ma_device_notification_init(pDevice, ma_device_notification_type_interruption_ended));
}
#endif
static ma_result ma_result_from_OSStatus(OSStatus status)
{
switch (status)
@ -32781,9 +32806,9 @@ static ma_result ma_find_best_format__coreaudio(ma_context* pContext, AudioObjec
hasSupportedFormat = MA_FALSE;
for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) {
ma_format format;
ma_result formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &format);
if (formatResult == MA_SUCCESS && format != ma_format_unknown) {
ma_format formatFromDescription;
ma_result formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &formatFromDescription);
if (formatResult == MA_SUCCESS && formatFromDescription != ma_format_unknown) {
hasSupportedFormat = MA_TRUE;
bestDeviceFormatSoFar = pDeviceFormatDescriptions[iFormat].mFormat;
break;
@ -34834,7 +34859,7 @@ static ma_result ma_context_init__coreaudio(ma_context* pContext, const ma_conte
#endif
#if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
pContext->coreaudio.hCoreFoundation = ma_dlopen(ma_context_get_log(pContext), "CoreFoundation.framework/CoreFoundation");
pContext->coreaudio.hCoreFoundation = ma_dlopen(ma_context_get_log(pContext), "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation");
if (pContext->coreaudio.hCoreFoundation == NULL) {
return MA_API_NOT_FOUND;
}
@ -34843,7 +34868,7 @@ static ma_result ma_context_init__coreaudio(ma_context* pContext, const ma_conte
pContext->coreaudio.CFRelease = ma_dlsym(ma_context_get_log(pContext), pContext->coreaudio.hCoreFoundation, "CFRelease");
pContext->coreaudio.hCoreAudio = ma_dlopen(ma_context_get_log(pContext), "CoreAudio.framework/CoreAudio");
pContext->coreaudio.hCoreAudio = ma_dlopen(ma_context_get_log(pContext), "/System/Library/Frameworks/CoreAudio.framework/CoreAudio");
if (pContext->coreaudio.hCoreAudio == NULL) {
ma_dlclose(ma_context_get_log(pContext), pContext->coreaudio.hCoreFoundation);
return MA_API_NOT_FOUND;
@ -34861,7 +34886,7 @@ static ma_result ma_context_init__coreaudio(ma_context* pContext, const ma_conte
The way it'll work is that it'll first try AudioUnit, and if the required symbols are not present there we'll fall back to
AudioToolbox.
*/
pContext->coreaudio.hAudioUnit = ma_dlopen(ma_context_get_log(pContext), "AudioUnit.framework/AudioUnit");
pContext->coreaudio.hAudioUnit = ma_dlopen(ma_context_get_log(pContext), "/System/Library/Frameworks/AudioUnit.framework/AudioUnit");
if (pContext->coreaudio.hAudioUnit == NULL) {
ma_dlclose(ma_context_get_log(pContext), pContext->coreaudio.hCoreAudio);
ma_dlclose(ma_context_get_log(pContext), pContext->coreaudio.hCoreFoundation);
@ -34871,7 +34896,7 @@ static ma_result ma_context_init__coreaudio(ma_context* pContext, const ma_conte
if (ma_dlsym(ma_context_get_log(pContext), pContext->coreaudio.hAudioUnit, "AudioComponentFindNext") == NULL) {
/* Couldn't find the required symbols in AudioUnit, so fall back to AudioToolbox. */
ma_dlclose(ma_context_get_log(pContext), pContext->coreaudio.hAudioUnit);
pContext->coreaudio.hAudioUnit = ma_dlopen(ma_context_get_log(pContext), "AudioToolbox.framework/AudioToolbox");
pContext->coreaudio.hAudioUnit = ma_dlopen(ma_context_get_log(pContext), "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox");
if (pContext->coreaudio.hAudioUnit == NULL) {
ma_dlclose(ma_context_get_log(pContext), pContext->coreaudio.hCoreAudio);
ma_dlclose(ma_context_get_log(pContext), pContext->coreaudio.hCoreFoundation);
@ -39784,6 +39809,7 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice)
*/
device.webaudio.close();
device.webaudio = undefined;
device.pDevice = undefined;
}, pDevice->webaudio.deviceIndex);
}
#endif
@ -39807,6 +39833,10 @@ static ma_uint32 ma_calculate_period_size_in_frames_from_descriptor__webaudio(co
*/
ma_uint32 periodSizeInFrames;
if (nativeSampleRate == 0) {
nativeSampleRate = MA_DEFAULT_SAMPLE_RATE;
}
if (pDescriptor->periodSizeInFrames == 0) {
if (pDescriptor->periodSizeInMilliseconds == 0) {
if (performanceProfile == ma_performance_profile_low_latency) {
@ -39956,7 +39986,7 @@ static void ma_audio_worklet_processor_created__webaudio(EMSCRIPTEN_WEBAUDIO_T a
/* With the audio worklet initialized we can now attach it to the graph. */
if (pParameters->pConfig->deviceType == ma_device_type_capture || pParameters->pConfig->deviceType == ma_device_type_duplex) {
ma_result attachmentResult = EM_ASM_INT({
ma_result attachmentResult = (ma_result)EM_ASM_INT({
var getUserMediaResult = 0;
var audioWorklet = emscriptenGetAudioObject($0);
var audioContext = emscriptenGetAudioObject($1);
@ -39987,7 +40017,7 @@ static void ma_audio_worklet_processor_created__webaudio(EMSCRIPTEN_WEBAUDIO_T a
/* If it's playback only we can now attach the worklet node to the graph. This has already been done for the duplex case. */
if (pParameters->pConfig->deviceType == ma_device_type_playback) {
ma_result attachmentResult = EM_ASM_INT({
ma_result attachmentResult = (ma_result)EM_ASM_INT({
var audioWorklet = emscriptenGetAudioObject($0);
var audioContext = emscriptenGetAudioObject($1);
audioWorklet.connect(audioContext.destination);
@ -40202,7 +40232,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
/* First thing we need is an AudioContext. */
var audioContextOptions = {};
if (deviceType == window.miniaudio.device_type.playback) {
if (deviceType == window.miniaudio.device_type.playback && sampleRate != 0) {
audioContextOptions.sampleRate = sampleRate;
}
@ -40279,6 +40309,8 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
device.scriptNode.connect(device.webaudio.destination);
}
device.pDevice = pDevice;
return miniaudio.track_device(device);
}, pConfig->deviceType, channels, sampleRate, periodSizeInFrames, pDevice->webaudio.pIntermediaryBuffer, pDevice);
@ -40445,14 +40477,21 @@ static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_contex
};
miniaudio.unlock_event_types = (function(){
return ['touchstart', 'touchend', 'click'];
return ['touchend', 'click'];
})();
miniaudio.unlock = function() {
for(var i = 0; i < miniaudio.devices.length; ++i) {
var device = miniaudio.devices[i];
if (device != null && device.webaudio != null && device.state === 2 /* ma_device_state_started */) {
device.webaudio.resume();
if (device != null &&
device.webaudio != null &&
device.state === window.miniaudio.device_state.started) {
device.webaudio.resume().then(() => {
Module._ma_device__on_notification_unlocked(device.pDevice);
},
(error) => {console.error("Failed to resume audiocontext", error);
});
}
}
miniaudio.unlock_event_types.map(function(event_type) {
@ -40890,6 +40929,11 @@ static ma_thread_result MA_THREADCALL ma_worker_thread(void* pData)
ma_device__on_notification_stopped(pDevice);
}
/* If we stopped because the device has been uninitialized, abort now. */
if (ma_device_get_state(pDevice) == ma_device_state_uninitialized) {
break;
}
/* A function somewhere is waiting for the device to have stopped for real so we need to signal an event to allow it to continue. */
ma_device__set_state(pDevice, ma_device_state_stopped);
ma_event_signal(&pDevice->stopEvent);
@ -42100,10 +42144,23 @@ MA_API void ma_device_uninit(ma_device* pDevice)
return;
}
/* Make sure the device is stopped first. The backends will probably handle this naturally, but I like to do it explicitly for my own sanity. */
if (ma_device_is_started(pDevice)) {
ma_device_stop(pDevice);
/*
It's possible for the miniaudio side of the device and the backend to not be in sync due to
system-level situations such as the computer being put into sleep mode and the backend not
notifying miniaudio of the fact the device has stopped. It's possible for this to result in a
deadlock due to miniaudio thinking the device is in a running state, when in fact it's not
running at all. For this reason I am no longer explicitly stopping the device. I don't think
this should affect anyone in practice since uninitializing the backend will naturally stop the
device anyway.
*/
#if 0
{
/* Make sure the device is stopped first. The backends will probably handle this naturally, but I like to do it explicitly for my own sanity. */
if (ma_device_is_started(pDevice)) {
ma_device_stop(pDevice);
}
}
#endif
/* Putting the device into an uninitialized state will make the worker thread return. */
ma_device__set_state(pDevice, ma_device_state_uninitialized);
@ -52835,7 +52892,7 @@ static ma_result ma_channel_map_apply_mono_in_f32(float* MA_RESTRICT pFramesOut,
for (iFrame = 0; iFrame < unrolledFrameCount; iFrame += 1) {
__m128 in0 = _mm_set1_ps(pFramesIn[iFrame*2 + 0]);
__m128 in1 = _mm_set1_ps(pFramesIn[iFrame*2 + 1]);
_mm_storeu_ps(&pFramesOut[iFrame*4 + 0], _mm_shuffle_ps(in1, in0, _MM_SHUFFLE(0, 0, 0, 0)));
_mm_storeu_ps(&pFramesOut[iFrame*4 + 0], _mm_shuffle_ps(in0, in1, _MM_SHUFFLE(0, 0, 0, 0)));
}
/* Tail. */
@ -52861,7 +52918,7 @@ static ma_result ma_channel_map_apply_mono_in_f32(float* MA_RESTRICT pFramesOut,
__m128 in1 = _mm_set1_ps(pFramesIn[iFrame*2 + 1]);
_mm_storeu_ps(&pFramesOut[iFrame*12 + 0], in0);
_mm_storeu_ps(&pFramesOut[iFrame*12 + 4], _mm_shuffle_ps(in1, in0, _MM_SHUFFLE(0, 0, 0, 0)));
_mm_storeu_ps(&pFramesOut[iFrame*12 + 4], _mm_shuffle_ps(in0, in1, _MM_SHUFFLE(0, 0, 0, 0)));
_mm_storeu_ps(&pFramesOut[iFrame*12 + 8], in1);
}
@ -59701,7 +59758,7 @@ extern "C" {
#define MA_DR_WAV_XSTRINGIFY(x) MA_DR_WAV_STRINGIFY(x)
#define MA_DR_WAV_VERSION_MAJOR 0
#define MA_DR_WAV_VERSION_MINOR 13
#define MA_DR_WAV_VERSION_REVISION 12
#define MA_DR_WAV_VERSION_REVISION 13
#define MA_DR_WAV_VERSION_STRING MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MAJOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MINOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_REVISION)
#include <stddef.h>
#define MA_DR_WAVE_FORMAT_PCM 0x1
@ -60121,7 +60178,7 @@ extern "C" {
#define MA_DR_FLAC_XSTRINGIFY(x) MA_DR_FLAC_STRINGIFY(x)
#define MA_DR_FLAC_VERSION_MAJOR 0
#define MA_DR_FLAC_VERSION_MINOR 12
#define MA_DR_FLAC_VERSION_REVISION 41
#define MA_DR_FLAC_VERSION_REVISION 42
#define MA_DR_FLAC_VERSION_STRING MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_MAJOR) "." MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_MINOR) "." MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_REVISION)
#include <stddef.h>
#if defined(_MSC_VER) && _MSC_VER >= 1700
@ -60408,7 +60465,7 @@ extern "C" {
#define MA_DR_MP3_XSTRINGIFY(x) MA_DR_MP3_STRINGIFY(x)
#define MA_DR_MP3_VERSION_MAJOR 0
#define MA_DR_MP3_VERSION_MINOR 6
#define MA_DR_MP3_VERSION_REVISION 37
#define MA_DR_MP3_VERSION_REVISION 38
#define MA_DR_MP3_VERSION_STRING MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_MAJOR) "." MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_MINOR) "." MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_REVISION)
#include <stddef.h>
#define MA_DR_MP3_MAX_PCM_FRAMES_PER_MP3_FRAME 1152
@ -64826,7 +64883,7 @@ MA_API ma_result ma_decoder_init_file(const char* pFilePath, const ma_decoder_co
/* Probably no implementation for loading from a file path. Use miniaudio's file IO instead. */
result = ma_decoder_init_vfs(NULL, pFilePath, pConfig, pDecoder);
if (result != MA_SUCCESS) {
return MA_SUCCESS;
return result;
}
}
@ -64976,7 +65033,7 @@ MA_API ma_result ma_decoder_init_file_w(const wchar_t* pFilePath, const ma_decod
/* Probably no implementation for loading from a file path. Use miniaudio's file IO instead. */
result = ma_decoder_init_vfs_w(NULL, pFilePath, pConfig, pDecoder);
if (result != MA_SUCCESS) {
return MA_SUCCESS;
return result;
}
}
@ -68744,7 +68801,7 @@ static ma_result ma_resource_manager_data_buffer_init_ex_internal(ma_resource_ma
async = (flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC) != 0;
/*
Fences need to be acquired before doing anything. These must be aquired and released outside of
Fences need to be acquired before doing anything. These must be acquired and released outside of
the node to ensure there's no holes where ma_fence_wait() could prematurely return before the
data buffer has completed initialization.
@ -72016,7 +72073,7 @@ MA_API ma_result ma_node_init_preallocated(ma_node_graph* pNodeGraph, const ma_n
}
if (heapLayout.outputBusOffset != MA_SIZE_MAX) {
pNodeBase->pOutputBuses = (ma_node_output_bus*)ma_offset_ptr(pHeap, heapLayout.inputBusOffset);
pNodeBase->pOutputBuses = (ma_node_output_bus*)ma_offset_ptr(pHeap, heapLayout.outputBusOffset);
} else {
pNodeBase->pOutputBuses = pNodeBase->_outputBuses;
}
@ -72507,11 +72564,11 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde
/*
At this point we know that we are inside our start/stop times. However, we may need to adjust
our frame count and output pointer to accomodate since we could be straddling the time period
our frame count and output pointer to accommodate since we could be straddling the time period
that this function is getting called for.
It's possible (and likely) that the start time does not line up with the output buffer. We
therefore need to offset it by a number of frames to accomodate. The same thing applies for
therefore need to offset it by a number of frames to accommodate. The same thing applies for
the stop time.
*/
timeOffsetBeg = (globalTimeBeg < startTime) ? (ma_uint32)(globalTimeEnd - startTime) : 0;
@ -74097,7 +74154,7 @@ static void ma_engine_node_process_pcm_frames__general(ma_engine_node* pEngineNo
if (fadeStartOffsetInFrames == (ma_int64)(~(ma_uint64)0)) {
fadeStartOffsetInFrames = 0;
} else {
fadeStartOffsetInFrames -= ma_engine_get_time(pEngineNode->pEngine);
fadeStartOffsetInFrames -= ma_engine_get_time_in_pcm_frames(pEngineNode->pEngine);
}
ma_fader_set_fade_ex(&pEngineNode->fader, fadeVolumeBeg, fadeVolumeEnd, fadeLengthInFrames, fadeStartOffsetInFrames);
@ -75534,6 +75591,10 @@ MA_API void ma_engine_listener_get_cone(const ma_engine* pEngine, ma_uint32 list
*pOuterGain = 0;
}
if (pEngine == NULL || listenerIndex >= pEngine->listenerCount) {
return;
}
ma_spatializer_listener_get_cone(&pEngine->listeners[listenerIndex], pInnerAngleInRadians, pOuterAngleInRadians, pOuterGain);
}
@ -76103,7 +76164,7 @@ MA_API ma_result ma_sound_stop_with_fade_in_pcm_frames(ma_sound* pSound, ma_uint
}
/* Stopping with a fade out requires us to schedule the stop into the future by the fade length. */
ma_sound_set_stop_time_with_fade_in_pcm_frames(pSound, ma_engine_get_time(ma_sound_get_engine(pSound)) + fadeLengthInFrames, fadeLengthInFrames);
ma_sound_set_stop_time_with_fade_in_pcm_frames(pSound, ma_engine_get_time_in_pcm_frames(ma_sound_get_engine(pSound)) + fadeLengthInFrames, fadeLengthInFrames);
return MA_SUCCESS;
}
@ -76476,6 +76537,10 @@ MA_API void ma_sound_get_cone(const ma_sound* pSound, float* pInnerAngleInRadian
*pOuterGain = 0;
}
if (pSound == NULL) {
return;
}
ma_spatializer_get_cone(&pSound->engineNode.spatializer, pInnerAngleInRadians, pOuterAngleInRadians, pOuterGain);
}
@ -76757,6 +76822,8 @@ MA_API ma_result ma_sound_get_data_format(ma_sound* pSound, ma_format* pFormat,
MA_API ma_result ma_sound_get_cursor_in_pcm_frames(ma_sound* pSound, ma_uint64* pCursor)
{
ma_uint64 seekTarget;
if (pSound == NULL) {
return MA_INVALID_ARGS;
}
@ -76766,7 +76833,13 @@ MA_API ma_result ma_sound_get_cursor_in_pcm_frames(ma_sound* pSound, ma_uint64*
return MA_INVALID_OPERATION;
}
return ma_data_source_get_cursor_in_pcm_frames(pSound->pDataSource, pCursor);
seekTarget = ma_atomic_load_64(&pSound->seekTarget);
if (seekTarget != MA_SEEK_TARGET_NONE) {
*pCursor = seekTarget;
return MA_SUCCESS;
} else {
return ma_data_source_get_cursor_in_pcm_frames(pSound->pDataSource, pCursor);
}
}
MA_API ma_result ma_sound_get_length_in_pcm_frames(ma_sound* pSound, ma_uint64* pLength)
@ -76785,16 +76858,28 @@ MA_API ma_result ma_sound_get_length_in_pcm_frames(ma_sound* pSound, ma_uint64*
MA_API ma_result ma_sound_get_cursor_in_seconds(ma_sound* pSound, float* pCursor)
{
if (pSound == NULL) {
return MA_INVALID_ARGS;
ma_result result;
ma_uint64 cursorInPCMFrames;
ma_uint32 sampleRate;
if (pCursor != NULL) {
*pCursor = 0;
}
/* The notion of a cursor is only valid for sounds that are backed by a data source. */
if (pSound->pDataSource == NULL) {
return MA_INVALID_OPERATION;
result = ma_sound_get_cursor_in_pcm_frames(pSound, &cursorInPCMFrames);
if (result != MA_SUCCESS) {
return result;
}
return ma_data_source_get_cursor_in_seconds(pSound->pDataSource, pCursor);
result = ma_sound_get_data_format(pSound, NULL, NULL, &sampleRate, NULL, 0);
if (result != MA_SUCCESS) {
return result;
}
/* VC6 does not support division of unsigned 64-bit integers with floating point numbers. Need to use a signed number. This shouldn't effect anything in practice. */
*pCursor = (ma_int64)cursorInPCMFrames / (float)sampleRate;
return MA_SUCCESS;
}
MA_API ma_result ma_sound_get_length_in_seconds(ma_sound* pSound, float* pLength)
@ -77193,8 +77278,8 @@ code below please report the bug to the respective repository for the relevant p
#define ma_dr_wav_clamp(x, lo, hi) (ma_dr_wav_max((lo), ma_dr_wav_min((hi), (x))))
#define ma_dr_wav_offset_ptr(p, offset) (((ma_uint8*)(p)) + (offset))
#define MA_DR_WAV_MAX_SIMD_VECTOR_SIZE 32
#define MA_DR_WAV_INT64_MIN ((ma_int64)0x80000000 << 32)
#define MA_DR_WAV_INT64_MAX ((((ma_int64)0x7FFFFFFF) << 32) | 0xFFFFFFFF)
#define MA_DR_WAV_INT64_MIN ((ma_int64) ((ma_uint64)0x80000000 << 32))
#define MA_DR_WAV_INT64_MAX ((ma_int64)(((ma_uint64)0x7FFFFFFF << 32) | 0xFFFFFFFF))
#if defined(_MSC_VER) && _MSC_VER >= 1400
#define MA_DR_WAV_HAS_BYTESWAP16_INTRINSIC
#define MA_DR_WAV_HAS_BYTESWAP32_INTRINSIC
@ -82322,7 +82407,7 @@ static MA_INLINE ma_uint32 ma_dr_flac__swap_endian_uint32(ma_uint32 n)
#if defined(_MSC_VER) && !defined(__clang__)
return _byteswap_ulong(n);
#elif defined(__GNUC__) || defined(__clang__)
#if defined(MA_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 6) && !defined(MA_64BIT)
#if defined(MA_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 6) && !defined(__ARM_ARCH_6M__) && !defined(MA_64BIT)
ma_uint32 r;
__asm__ __volatile__ (
#if defined(MA_64BIT)
@ -83063,7 +83148,7 @@ static MA_INLINE ma_uint32 ma_dr_flac__clz_lzcnt(ma_dr_flac_cache_t x)
);
return r;
}
#elif defined(MA_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(MA_64BIT)
#elif defined(MA_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(__ARM_ARCH_6M__) && !defined(MA_64BIT)
{
unsigned int r;
__asm__ __volatile__ (
@ -85804,7 +85889,7 @@ static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRea
for (;;) {
ma_dr_flac_metadata metadata;
ma_uint8 isLastBlock = 0;
ma_uint8 blockType;
ma_uint8 blockType = 0;
ma_uint32 blockSize;
if (ma_dr_flac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == MA_FALSE) {
return MA_FALSE;
@ -89884,7 +89969,7 @@ static int ma_dr_mp3_have_simd(void)
#else
#define MA_DR_MP3_HAVE_SIMD 0
#endif
#if defined(__ARM_ARCH) && (__ARM_ARCH >= 6) && !defined(__aarch64__) && !defined(_M_ARM64)
#if defined(__ARM_ARCH) && (__ARM_ARCH >= 6) && !defined(__aarch64__) && !defined(_M_ARM64) && !defined(__ARM_ARCH_6M__)
#define MA_DR_MP3_HAVE_ARMV6 1
static __inline__ __attribute__((always_inline)) ma_int32 ma_dr_mp3_clip_int16_arm(ma_int32 a)
{