From 8fcf6889aa7b6dd6d1ffd600f1d17dfa5a842998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Labb=C3=A9?= Date: Fri, 10 Nov 2023 21:18:05 -0800 Subject: [PATCH] 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. --- extras/miniaudio_split/miniaudio.c | 22 ++++++++++++++++++++-- extras/miniaudio_split/miniaudio.h | 3 ++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/extras/miniaudio_split/miniaudio.c b/extras/miniaudio_split/miniaudio.c index 3e185c79..8154519a 100644 --- a/extras/miniaudio_split/miniaudio.c +++ b/extras/miniaudio_split/miniaudio.c @@ -7245,6 +7245,14 @@ static void ma_device__on_notification_rerouted(ma_device* pDevice) } #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) { @@ -28377,6 +28385,7 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice) */ device.webaudio.close(); device.webaudio = undefined; + device.pDevice = undefined; }, pDevice->webaudio.deviceIndex); } #endif @@ -28872,6 +28881,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); @@ -29044,8 +29055,15 @@ static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_contex 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) { diff --git a/extras/miniaudio_split/miniaudio.h b/extras/miniaudio_split/miniaudio.h index a019ecd8..b148db5f 100644 --- a/extras/miniaudio_split/miniaudio.h +++ b/extras/miniaudio_split/miniaudio.h @@ -3013,7 +3013,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