4 Commits

Author SHA1 Message Date
David Reid 4a5b74bef0 Version 0.11.21 2023-11-15 11:23:00 +10:00
David Reid c77d40ba00 Core Audio: Fix a -Wshadow warning. 2023-11-15 10:35:34 +10:00
Michael Labbé 8fcf6889aa Add new ma_device_notification_type_unlocked notification
Unlocked notification fires on emscripten upon successful resume of
audio context attached to a device.  This occurs only once per device
and it happens after the browser has received the input event
necessary to begin playing audio on most webpages.  This is due
to autoplay rules.

It is recommended to wait until this event is fired to start a
'main game loop' on the web.
2023-11-15 10:28:02 +10:00
David Reid f9ce46330c Web: Fix an error where the buffer size is incorrectly calculated.
Public issue https://github.com/mackron/miniaudio/issues/773
2023-11-15 10:10:46 +10:00
4 changed files with 70 additions and 17 deletions
+7
View File
@@ -1,3 +1,10 @@
v0.11.21 - 2023-11-15
=====================
* Add new ma_device_notification_type_unlocked notification. This is used on Web and will be fired after the user has performed a gesture and thus unlocked the ability to play audio.
* Web: Fix an error where the buffer size is incorrectly calculated.
* Core Audio: Fix a -Wshadow warning.
v0.11.20 - 2023-11-10 v0.11.20 - 2023-11-10
===================== =====================
* Fix a compilation error with iOS. * Fix a compilation error with iOS.
+28 -6
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. Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file.
miniaudio - v0.11.20 - 2023-11-10 miniaudio - v0.11.21 - 2023-11-15
David Reid - mackron@gmail.com David Reid - mackron@gmail.com
@@ -7245,6 +7245,14 @@ static void ma_device__on_notification_rerouted(ma_device* pDevice)
} }
#endif #endif
#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_unlocked));
}
#endif
static void ma_device__on_data_inner(ma_device* pDevice, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount) static void ma_device__on_data_inner(ma_device* pDevice, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount)
{ {
@@ -21374,9 +21382,9 @@ static ma_result ma_find_best_format__coreaudio(ma_context* pContext, AudioObjec
hasSupportedFormat = MA_FALSE; hasSupportedFormat = MA_FALSE;
for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) { for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) {
ma_format format; ma_format formatFromDescription;
ma_result formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &format); ma_result formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &formatFromDescription);
if (formatResult == MA_SUCCESS && format != ma_format_unknown) { if (formatResult == MA_SUCCESS && formatFromDescription != ma_format_unknown) {
hasSupportedFormat = MA_TRUE; hasSupportedFormat = MA_TRUE;
bestDeviceFormatSoFar = pDeviceFormatDescriptions[iFormat].mFormat; bestDeviceFormatSoFar = pDeviceFormatDescriptions[iFormat].mFormat;
break; break;
@@ -28377,6 +28385,7 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice)
*/ */
device.webaudio.close(); device.webaudio.close();
device.webaudio = undefined; device.webaudio = undefined;
device.pDevice = undefined;
}, pDevice->webaudio.deviceIndex); }, pDevice->webaudio.deviceIndex);
} }
#endif #endif
@@ -28400,6 +28409,10 @@ static ma_uint32 ma_calculate_period_size_in_frames_from_descriptor__webaudio(co
*/ */
ma_uint32 periodSizeInFrames; ma_uint32 periodSizeInFrames;
if (nativeSampleRate == 0) {
nativeSampleRate = MA_DEFAULT_SAMPLE_RATE;
}
if (pDescriptor->periodSizeInFrames == 0) { if (pDescriptor->periodSizeInFrames == 0) {
if (pDescriptor->periodSizeInMilliseconds == 0) { if (pDescriptor->periodSizeInMilliseconds == 0) {
if (performanceProfile == ma_performance_profile_low_latency) { if (performanceProfile == ma_performance_profile_low_latency) {
@@ -28872,6 +28885,8 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
device.scriptNode.connect(device.webaudio.destination); device.scriptNode.connect(device.webaudio.destination);
} }
device.pDevice = pDevice;
return miniaudio.track_device(device); return miniaudio.track_device(device);
}, pConfig->deviceType, channels, sampleRate, periodSizeInFrames, pDevice->webaudio.pIntermediaryBuffer, pDevice); }, pConfig->deviceType, channels, sampleRate, periodSizeInFrames, pDevice->webaudio.pIntermediaryBuffer, pDevice);
@@ -29044,8 +29059,15 @@ static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_contex
miniaudio.unlock = function() { miniaudio.unlock = function() {
for(var i = 0; i < miniaudio.devices.length; ++i) { for(var i = 0; i < miniaudio.devices.length; ++i) {
var device = miniaudio.devices[i]; var device = miniaudio.devices[i];
if (device != null && device.webaudio != null && device.state === 2 /* ma_device_state_started */) { if (device != null &&
device.webaudio.resume(); 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) { miniaudio.unlock_event_types.map(function(event_type) {
+4 -3
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. Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file.
miniaudio - v0.11.20 - 2023-11-10 miniaudio - v0.11.21 - 2023-11-15
David Reid - mackron@gmail.com David Reid - mackron@gmail.com
@@ -20,7 +20,7 @@ extern "C" {
#define MA_VERSION_MAJOR 0 #define MA_VERSION_MAJOR 0
#define MA_VERSION_MINOR 11 #define MA_VERSION_MINOR 11
#define MA_VERSION_REVISION 20 #define MA_VERSION_REVISION 21
#define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION) #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__) #if defined(_MSC_VER) && !defined(__clang__)
@@ -3013,7 +3013,8 @@ typedef enum
ma_device_notification_type_stopped, ma_device_notification_type_stopped,
ma_device_notification_type_rerouted, ma_device_notification_type_rerouted,
ma_device_notification_type_interruption_began, 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; } ma_device_notification_type;
typedef struct typedef struct
+31 -8
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. Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file.
miniaudio - v0.11.20 - 2023-11-10 miniaudio - v0.11.21 - 2023-11-15
David Reid - mackron@gmail.com David Reid - mackron@gmail.com
@@ -3723,7 +3723,7 @@ extern "C" {
#define MA_VERSION_MAJOR 0 #define MA_VERSION_MAJOR 0
#define MA_VERSION_MINOR 11 #define MA_VERSION_MINOR 11
#define MA_VERSION_REVISION 20 #define MA_VERSION_REVISION 21
#define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION) #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__) #if defined(_MSC_VER) && !defined(__clang__)
@@ -6716,7 +6716,8 @@ typedef enum
ma_device_notification_type_stopped, ma_device_notification_type_stopped,
ma_device_notification_type_rerouted, ma_device_notification_type_rerouted,
ma_device_notification_type_interruption_began, 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; } ma_device_notification_type;
typedef struct typedef struct
@@ -18668,6 +18669,14 @@ static void ma_device__on_notification_rerouted(ma_device* pDevice)
} }
#endif #endif
#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_unlocked));
}
#endif
static void ma_device__on_data_inner(ma_device* pDevice, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount) static void ma_device__on_data_inner(ma_device* pDevice, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount)
{ {
@@ -32797,9 +32806,9 @@ static ma_result ma_find_best_format__coreaudio(ma_context* pContext, AudioObjec
hasSupportedFormat = MA_FALSE; hasSupportedFormat = MA_FALSE;
for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) { for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) {
ma_format format; ma_format formatFromDescription;
ma_result formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &format); ma_result formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &formatFromDescription);
if (formatResult == MA_SUCCESS && format != ma_format_unknown) { if (formatResult == MA_SUCCESS && formatFromDescription != ma_format_unknown) {
hasSupportedFormat = MA_TRUE; hasSupportedFormat = MA_TRUE;
bestDeviceFormatSoFar = pDeviceFormatDescriptions[iFormat].mFormat; bestDeviceFormatSoFar = pDeviceFormatDescriptions[iFormat].mFormat;
break; break;
@@ -39800,6 +39809,7 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice)
*/ */
device.webaudio.close(); device.webaudio.close();
device.webaudio = undefined; device.webaudio = undefined;
device.pDevice = undefined;
}, pDevice->webaudio.deviceIndex); }, pDevice->webaudio.deviceIndex);
} }
#endif #endif
@@ -39823,6 +39833,10 @@ static ma_uint32 ma_calculate_period_size_in_frames_from_descriptor__webaudio(co
*/ */
ma_uint32 periodSizeInFrames; ma_uint32 periodSizeInFrames;
if (nativeSampleRate == 0) {
nativeSampleRate = MA_DEFAULT_SAMPLE_RATE;
}
if (pDescriptor->periodSizeInFrames == 0) { if (pDescriptor->periodSizeInFrames == 0) {
if (pDescriptor->periodSizeInMilliseconds == 0) { if (pDescriptor->periodSizeInMilliseconds == 0) {
if (performanceProfile == ma_performance_profile_low_latency) { if (performanceProfile == ma_performance_profile_low_latency) {
@@ -40295,6 +40309,8 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
device.scriptNode.connect(device.webaudio.destination); device.scriptNode.connect(device.webaudio.destination);
} }
device.pDevice = pDevice;
return miniaudio.track_device(device); return miniaudio.track_device(device);
}, pConfig->deviceType, channels, sampleRate, periodSizeInFrames, pDevice->webaudio.pIntermediaryBuffer, pDevice); }, pConfig->deviceType, channels, sampleRate, periodSizeInFrames, pDevice->webaudio.pIntermediaryBuffer, pDevice);
@@ -40467,8 +40483,15 @@ static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_contex
miniaudio.unlock = function() { miniaudio.unlock = function() {
for(var i = 0; i < miniaudio.devices.length; ++i) { for(var i = 0; i < miniaudio.devices.length; ++i) {
var device = miniaudio.devices[i]; var device = miniaudio.devices[i];
if (device != null && device.webaudio != null && device.state === 2 /* ma_device_state_started */) { if (device != null &&
device.webaudio.resume(); 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) { miniaudio.unlock_event_types.map(function(event_type) {