Merge branch 'dev' into dev-0.12

This commit is contained in:
David Reid
2023-11-30 09:39:38 +10:00
4 changed files with 174 additions and 77 deletions
+14
View File
@@ -1,3 +1,17 @@
v0.11.22 - TBD
=====================
* ALSA: Fix some warnings relating to unhandled return value of `read()`.
* DirectSound: Add support for specifying an explicit window handle for SetCooperativeLevel().
* Web: Fix ScriptProcessorNode path when compiling with `--closure=1`. Note that the Audio Worklets path is not currently working due to the callback specified in `emscripten_create_wasm_audio_worklet_processor_async` never getting fired.
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
=====================
* Fix a compilation error with iOS.
+69 -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.20 - 2023-11-10
miniaudio - v0.11.22 - TBD
David Reid - mackron@gmail.com
@@ -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)
{
@@ -12592,9 +12600,12 @@ static ma_result ma_context_create_IDirectSound__dsound(ma_context* pContext, ma
}
/* The cooperative level must be set before doing anything else. */
hWnd = ((MA_PFN_GetForegroundWindow)pContext->win32.GetForegroundWindow)();
hWnd = (HWND)pContext->dsound.hWnd;
if (hWnd == 0) {
hWnd = ((MA_PFN_GetDesktopWindow)pContext->win32.GetDesktopWindow)();
hWnd = ((MA_PFN_GetForegroundWindow)pContext->win32.GetForegroundWindow)();
if (hWnd == 0) {
hWnd = ((MA_PFN_GetDesktopWindow)pContext->win32.GetDesktopWindow)();
}
}
hr = ma_IDirectSound_SetCooperativeLevel(pDirectSound, hWnd, (shareMode == ma_share_mode_exclusive) ? MA_DSSCL_EXCLUSIVE : MA_DSSCL_PRIORITY);
@@ -13911,6 +13922,8 @@ static ma_result ma_context_init__dsound(ma_context* pContext, const ma_context_
return MA_API_NOT_FOUND;
}
pContext->dsound.hWnd = pConfig->dsound.hWnd;
pCallbacks->onContextInit = ma_context_init__dsound;
pCallbacks->onContextUninit = ma_context_uninit__dsound;
pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__dsound;
@@ -16631,6 +16644,7 @@ static ma_result ma_device_stop__alsa(ma_device* pDevice)
a small chance that our wakeupfd has not been cleared. We'll clear that out now if applicable.
*/
int resultPoll;
int resultRead;
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Dropping capture device...\n");
@@ -16645,12 +16659,15 @@ static ma_result ma_device_stop__alsa(ma_device* pDevice)
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Preparing capture device successful.\n");
}
/* Clear the wakeupfd. */
resultPoll = poll((struct pollfd*)pDevice->alsa.pPollDescriptorsCapture, 1, 0);
if (resultPoll > 0) {
ma_uint64 t;
read(((struct pollfd*)pDevice->alsa.pPollDescriptorsCapture)[0].fd, &t, sizeof(t));
}
/* Clear the wakeupfd. */
resultPoll = poll((struct pollfd*)pDevice->alsa.pPollDescriptorsCapture, 1, 0);
if (resultPoll > 0) {
ma_uint64 t;
resultRead = read(((struct pollfd*)pDevice->alsa.pPollDescriptorsCapture)[0].fd, &t, sizeof(t));
if (resultRead != sizeof(t)) {
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Failed to read from capture wakeupfd. read() = %d\n", resultRead);
}
}
}
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
@@ -16667,11 +16684,14 @@ static ma_result ma_device_stop__alsa(ma_device* pDevice)
}
/* Clear the wakeupfd. */
resultPoll = poll((struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback, 1, 0);
if (resultPoll > 0) {
ma_uint64 t;
read(((struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback)[0].fd, &t, sizeof(t));
}
resultPoll = poll((struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback, 1, 0);
if (resultPoll > 0) {
ma_uint64 t;
resultRead = read(((struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback)[0].fd, &t, sizeof(t));
if (resultRead != sizeof(t)) {
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Failed to read from playback wakeupfd. read() = %d\n", resultRead);
}
}
}
@@ -21374,9 +21394,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;
@@ -28342,7 +28362,7 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice)
#if defined(MA_USE_AUDIO_WORKLETS)
{
EM_ASM({
var device = miniaudio.get_device_by_index($0);
var device = window.miniaudio.get_device_by_index($0);
if (device.streamNode !== undefined) {
device.streamNode.disconnect();
@@ -28357,7 +28377,7 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice)
#else
{
EM_ASM({
var device = miniaudio.get_device_by_index($0);
var device = window.miniaudio.get_device_by_index($0);
/* Make sure all nodes are disconnected and marked for collection. */
if (device.scriptNode !== undefined) {
@@ -28377,13 +28397,14 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice)
*/
device.webaudio.close();
device.webaudio = undefined;
device.pDevice = undefined;
}, pDevice->webaudio.deviceIndex);
}
#endif
/* Clean up the device on the JS side. */
EM_ASM({
miniaudio.untrack_device_by_index($0);
window.miniaudio.untrack_device_by_index($0);
}, pDevice->webaudio.deviceIndex);
ma_free(pDevice->webaudio.pIntermediaryBuffer, &pDevice->pContext->allocationCallbacks);
@@ -28400,6 +28421,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) {
@@ -28544,7 +28569,6 @@ static void ma_audio_worklet_processor_created__webaudio(EMSCRIPTEN_WEBAUDIO_T a
return;
}
pParameters->pDevice->webaudio.audioWorklet = emscripten_create_wasm_audio_worklet_node(audioContext, "miniaudio", &audioWorkletOptions, &ma_audio_worklet_process_callback__webaudio, pParameters->pDevice);
/* With the audio worklet initialized we can now attach it to the graph. */
@@ -28684,7 +28708,6 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
/* It's not clear if this can return an error. None of the tests in the Emscripten repository check for this, so neither am I for now. */
pDevice->webaudio.audioContext = emscripten_create_audio_context(&audioContextAttributes);
/*
With the context created we can now create the worklet. We can only have a single worklet per audio
context which means we'll need to craft this appropriately to handle duplex devices correctly.
@@ -28733,7 +28756,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
/* We need to add an entry to the miniaudio.devices list on the JS side so we can do some JS/C interop. */
pDevice->webaudio.deviceIndex = EM_ASM_INT({
return miniaudio.track_device({
return window.miniaudio.track_device({
webaudio: emscriptenGetAudioObject($0),
state: 1 /* 1 = ma_device_state_stopped */
});
@@ -28818,11 +28841,11 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
/* The node processing callback. */
device.scriptNode.onaudioprocess = function(e) {
if (device.intermediaryBufferView == null || device.intermediaryBufferView.length == 0) {
device.intermediaryBufferView = new Float32Array(Module.HEAPF32.buffer, pIntermediaryBuffer, bufferSize * channels);
device.intermediaryBufferView = new Float32Array(HEAPF32.buffer, pIntermediaryBuffer, bufferSize * channels);
}
/* Do the capture side first. */
if (deviceType == miniaudio.device_type.capture || deviceType == miniaudio.device_type.duplex) {
if (deviceType == window.miniaudio.device_type.capture || deviceType == window.miniaudio.device_type.duplex) {
/* The data must be interleaved before being processed miniaudio. */
for (var iChannel = 0; iChannel < channels; iChannel += 1) {
var inputBuffer = e.inputBuffer.getChannelData(iChannel);
@@ -28836,7 +28859,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
_ma_device_process_pcm_frames_capture__webaudio(pDevice, bufferSize, pIntermediaryBuffer);
}
if (deviceType == miniaudio.device_type.playback || deviceType == miniaudio.device_type.duplex) {
if (deviceType == window.miniaudio.device_type.playback || deviceType == window.miniaudio.device_type.duplex) {
_ma_device_process_pcm_frames_playback__webaudio(pDevice, bufferSize, pIntermediaryBuffer);
for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) {
@@ -28856,7 +28879,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
};
/* Now we need to connect our node to the graph. */
if (deviceType == miniaudio.device_type.capture || deviceType == miniaudio.device_type.duplex) {
if (deviceType == window.miniaudio.device_type.capture || deviceType == window.miniaudio.device_type.duplex) {
navigator.mediaDevices.getUserMedia({audio:true, video:false})
.then(function(stream) {
device.streamNode = device.webaudio.createMediaStreamSource(stream);
@@ -28868,11 +28891,13 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
});
}
if (deviceType == miniaudio.device_type.playback) {
if (deviceType == window.miniaudio.device_type.playback) {
device.scriptNode.connect(device.webaudio.destination);
}
return miniaudio.track_device(device);
device.pDevice = pDevice;
return window.miniaudio.track_device(device);
}, pConfig->deviceType, channels, sampleRate, periodSizeInFrames, pDevice->webaudio.pIntermediaryBuffer, pDevice);
if (deviceIndex < 0) {
@@ -28882,7 +28907,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
pDevice->webaudio.deviceIndex = deviceIndex;
/* Grab the sample rate from the audio context directly. */
sampleRate = (ma_uint32)EM_ASM_INT({ return miniaudio.get_device_by_index($0).webaudio.sampleRate; }, deviceIndex);
sampleRate = (ma_uint32)EM_ASM_INT({ return window.miniaudio.get_device_by_index($0).webaudio.sampleRate; }, deviceIndex);
if (pDescriptorCapture != NULL) {
pDescriptorCapture->format = ma_format_f32;
@@ -28912,9 +28937,9 @@ static ma_result ma_device_start__webaudio(ma_device* pDevice)
MA_ASSERT(pDevice != NULL);
EM_ASM({
var device = miniaudio.get_device_by_index($0);
var device = window.miniaudio.get_device_by_index($0);
device.webaudio.resume();
device.state = miniaudio.device_state.started;
device.state = window.miniaudio.device_state.started;
}, pDevice->webaudio.deviceIndex);
return MA_SUCCESS;
@@ -28934,9 +28959,9 @@ static ma_result ma_device_stop__webaudio(ma_device* pDevice)
do any kind of explicit draining.
*/
EM_ASM({
var device = miniaudio.get_device_by_index($0);
var device = window.miniaudio.get_device_by_index($0);
device.webaudio.suspend();
device.state = miniaudio.device_state.stopped;
device.state = window.miniaudio.device_state.stopped;
}, pDevice->webaudio.deviceIndex);
ma_device__on_notification_stopped(pDevice);
@@ -28995,6 +29020,7 @@ static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_contex
window.miniaudio.device_state.started = $4;
/* Device cache for mapping devices to indexes for JavaScript/C interop. */
let miniaudio = window.miniaudio;
miniaudio.devices = [];
miniaudio.track_device = function(device) {
@@ -29044,8 +29070,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 === miniaudio.device_state.started) {
device.webaudio.resume().then(() => {
_ma_device__on_notification_unlocked(device.pDevice);
},
(error) => {console.error("Failed to resume audiocontext", error);
});
}
}
miniaudio.unlock_event_types.map(function(event_type) {
+9 -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.
miniaudio - v0.11.20 - 2023-11-10
miniaudio - v0.11.22 - TBD
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 20
#define MA_VERSION_REVISION 22
#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__)
@@ -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
@@ -3544,6 +3545,10 @@ struct ma_context_config
void* pUserData;
ma_allocation_callbacks allocationCallbacks;
struct
{
ma_handle hWnd; /* HWND. Optional window handle to pass into SetCooperativeLevel(). Will default to the foreground window, and if that fails, the desktop window. */
} dsound;
struct
{
ma_bool32 useVerboseDeviceEnumeration;
} alsa;
@@ -3632,6 +3637,7 @@ struct ma_context
#ifdef MA_SUPPORT_DSOUND
struct
{
ma_handle hWnd; /* Can be null. */
ma_handle hDSoundDLL;
ma_proc DirectSoundCreate;
ma_proc DirectSoundEnumerateA;
+82 -38
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.20 - 2023-11-10
miniaudio - v0.11.22 - TBD
David Reid - mackron@gmail.com
@@ -3723,7 +3723,7 @@ extern "C" {
#define MA_VERSION_MAJOR 0
#define MA_VERSION_MINOR 11
#define MA_VERSION_REVISION 20
#define MA_VERSION_REVISION 22
#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__)
@@ -6785,7 +6785,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
@@ -7334,6 +7335,10 @@ struct ma_context_config
void* pUserData;
ma_allocation_callbacks allocationCallbacks;
struct
{
ma_handle hWnd; /* HWND. Optional window handle to pass into SetCooperativeLevel(). Will default to the foreground window, and if that fails, the desktop window. */
} dsound;
struct
{
ma_bool32 useVerboseDeviceEnumeration;
} alsa;
@@ -7429,6 +7434,7 @@ struct ma_context
#ifdef MA_SUPPORT_DSOUND
struct
{
ma_handle hWnd; /* Can be null. */
ma_handle hDSoundDLL;
ma_proc DirectSoundCreate;
ma_proc DirectSoundEnumerateA;
@@ -18927,6 +18933,19 @@ static void ma_device__on_notification_rerouted(ma_device* pDevice)
}
#endif
#if defined(MA_EMSCRIPTEN)
#ifdef __cplusplus
extern "C" {
#endif
void EMSCRIPTEN_KEEPALIVE ma_device__on_notification_unlocked(ma_device* pDevice)
{
ma_device__on_notification(ma_device_notification_init(pDevice, ma_device_notification_type_unlocked));
}
#ifdef __cplusplus
}
#endif
#endif
static void ma_device__on_data_inner(ma_device* pDevice, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount)
{
@@ -24272,9 +24291,12 @@ static ma_result ma_context_create_IDirectSound__dsound(ma_context* pContext, ma
}
/* The cooperative level must be set before doing anything else. */
hWnd = ((MA_PFN_GetForegroundWindow)pContext->win32.GetForegroundWindow)();
hWnd = (HWND)pContext->dsound.hWnd;
if (hWnd == 0) {
hWnd = ((MA_PFN_GetDesktopWindow)pContext->win32.GetDesktopWindow)();
hWnd = ((MA_PFN_GetForegroundWindow)pContext->win32.GetForegroundWindow)();
if (hWnd == 0) {
hWnd = ((MA_PFN_GetDesktopWindow)pContext->win32.GetDesktopWindow)();
}
}
hr = ma_IDirectSound_SetCooperativeLevel(pDirectSound, hWnd, (shareMode == ma_share_mode_exclusive) ? MA_DSSCL_EXCLUSIVE : MA_DSSCL_PRIORITY);
@@ -25591,6 +25613,8 @@ static ma_result ma_context_init__dsound(ma_context* pContext, const ma_context_
return MA_API_NOT_FOUND;
}
pContext->dsound.hWnd = pConfig->dsound.hWnd;
pCallbacks->onContextInit = ma_context_init__dsound;
pCallbacks->onContextUninit = ma_context_uninit__dsound;
pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__dsound;
@@ -28311,6 +28335,7 @@ static ma_result ma_device_stop__alsa(ma_device* pDevice)
a small chance that our wakeupfd has not been cleared. We'll clear that out now if applicable.
*/
int resultPoll;
int resultRead;
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Dropping capture device...\n");
@@ -28325,12 +28350,15 @@ static ma_result ma_device_stop__alsa(ma_device* pDevice)
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Preparing capture device successful.\n");
}
/* Clear the wakeupfd. */
resultPoll = poll((struct pollfd*)pDevice->alsa.pPollDescriptorsCapture, 1, 0);
if (resultPoll > 0) {
ma_uint64 t;
read(((struct pollfd*)pDevice->alsa.pPollDescriptorsCapture)[0].fd, &t, sizeof(t));
}
/* Clear the wakeupfd. */
resultPoll = poll((struct pollfd*)pDevice->alsa.pPollDescriptorsCapture, 1, 0);
if (resultPoll > 0) {
ma_uint64 t;
resultRead = read(((struct pollfd*)pDevice->alsa.pPollDescriptorsCapture)[0].fd, &t, sizeof(t));
if (resultRead != sizeof(t)) {
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Failed to read from capture wakeupfd. read() = %d\n", resultRead);
}
}
}
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
@@ -28347,11 +28375,14 @@ static ma_result ma_device_stop__alsa(ma_device* pDevice)
}
/* Clear the wakeupfd. */
resultPoll = poll((struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback, 1, 0);
if (resultPoll > 0) {
ma_uint64 t;
read(((struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback)[0].fd, &t, sizeof(t));
}
resultPoll = poll((struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback, 1, 0);
if (resultPoll > 0) {
ma_uint64 t;
resultRead = read(((struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback)[0].fd, &t, sizeof(t));
if (resultRead != sizeof(t)) {
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Failed to read from playback wakeupfd. read() = %d\n", resultRead);
}
}
}
@@ -33021,9 +33052,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;
@@ -39989,7 +40020,7 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice)
#if defined(MA_USE_AUDIO_WORKLETS)
{
EM_ASM({
var device = miniaudio.get_device_by_index($0);
var device = window.miniaudio.get_device_by_index($0);
if (device.streamNode !== undefined) {
device.streamNode.disconnect();
@@ -40004,7 +40035,7 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice)
#else
{
EM_ASM({
var device = miniaudio.get_device_by_index($0);
var device = window.miniaudio.get_device_by_index($0);
/* Make sure all nodes are disconnected and marked for collection. */
if (device.scriptNode !== undefined) {
@@ -40024,13 +40055,14 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice)
*/
device.webaudio.close();
device.webaudio = undefined;
device.pDevice = undefined;
}, pDevice->webaudio.deviceIndex);
}
#endif
/* Clean up the device on the JS side. */
EM_ASM({
miniaudio.untrack_device_by_index($0);
window.miniaudio.untrack_device_by_index($0);
}, pDevice->webaudio.deviceIndex);
ma_free(pDevice->webaudio.pIntermediaryBuffer, &pDevice->pContext->allocationCallbacks);
@@ -40047,6 +40079,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) {
@@ -40191,7 +40227,6 @@ static void ma_audio_worklet_processor_created__webaudio(EMSCRIPTEN_WEBAUDIO_T a
return;
}
pParameters->pDevice->webaudio.audioWorklet = emscripten_create_wasm_audio_worklet_node(audioContext, "miniaudio", &audioWorkletOptions, &ma_audio_worklet_process_callback__webaudio, pParameters->pDevice);
/* With the audio worklet initialized we can now attach it to the graph. */
@@ -40331,7 +40366,6 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
/* It's not clear if this can return an error. None of the tests in the Emscripten repository check for this, so neither am I for now. */
pDevice->webaudio.audioContext = emscripten_create_audio_context(&audioContextAttributes);
/*
With the context created we can now create the worklet. We can only have a single worklet per audio
context which means we'll need to craft this appropriately to handle duplex devices correctly.
@@ -40380,7 +40414,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
/* We need to add an entry to the miniaudio.devices list on the JS side so we can do some JS/C interop. */
pDevice->webaudio.deviceIndex = EM_ASM_INT({
return miniaudio.track_device({
return window.miniaudio.track_device({
webaudio: emscriptenGetAudioObject($0),
state: 1 /* 1 = ma_device_state_stopped */
});
@@ -40465,11 +40499,11 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
/* The node processing callback. */
device.scriptNode.onaudioprocess = function(e) {
if (device.intermediaryBufferView == null || device.intermediaryBufferView.length == 0) {
device.intermediaryBufferView = new Float32Array(Module.HEAPF32.buffer, pIntermediaryBuffer, bufferSize * channels);
device.intermediaryBufferView = new Float32Array(HEAPF32.buffer, pIntermediaryBuffer, bufferSize * channels);
}
/* Do the capture side first. */
if (deviceType == miniaudio.device_type.capture || deviceType == miniaudio.device_type.duplex) {
if (deviceType == window.miniaudio.device_type.capture || deviceType == window.miniaudio.device_type.duplex) {
/* The data must be interleaved before being processed miniaudio. */
for (var iChannel = 0; iChannel < channels; iChannel += 1) {
var inputBuffer = e.inputBuffer.getChannelData(iChannel);
@@ -40483,7 +40517,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
_ma_device_process_pcm_frames_capture__webaudio(pDevice, bufferSize, pIntermediaryBuffer);
}
if (deviceType == miniaudio.device_type.playback || deviceType == miniaudio.device_type.duplex) {
if (deviceType == window.miniaudio.device_type.playback || deviceType == window.miniaudio.device_type.duplex) {
_ma_device_process_pcm_frames_playback__webaudio(pDevice, bufferSize, pIntermediaryBuffer);
for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) {
@@ -40503,7 +40537,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
};
/* Now we need to connect our node to the graph. */
if (deviceType == miniaudio.device_type.capture || deviceType == miniaudio.device_type.duplex) {
if (deviceType == window.miniaudio.device_type.capture || deviceType == window.miniaudio.device_type.duplex) {
navigator.mediaDevices.getUserMedia({audio:true, video:false})
.then(function(stream) {
device.streamNode = device.webaudio.createMediaStreamSource(stream);
@@ -40515,11 +40549,13 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
});
}
if (deviceType == miniaudio.device_type.playback) {
if (deviceType == window.miniaudio.device_type.playback) {
device.scriptNode.connect(device.webaudio.destination);
}
return miniaudio.track_device(device);
device.pDevice = pDevice;
return window.miniaudio.track_device(device);
}, pConfig->deviceType, channels, sampleRate, periodSizeInFrames, pDevice->webaudio.pIntermediaryBuffer, pDevice);
if (deviceIndex < 0) {
@@ -40529,7 +40565,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co
pDevice->webaudio.deviceIndex = deviceIndex;
/* Grab the sample rate from the audio context directly. */
sampleRate = (ma_uint32)EM_ASM_INT({ return miniaudio.get_device_by_index($0).webaudio.sampleRate; }, deviceIndex);
sampleRate = (ma_uint32)EM_ASM_INT({ return window.miniaudio.get_device_by_index($0).webaudio.sampleRate; }, deviceIndex);
if (pDescriptorCapture != NULL) {
pDescriptorCapture->format = ma_format_f32;
@@ -40559,9 +40595,9 @@ static ma_result ma_device_start__webaudio(ma_device* pDevice)
MA_ASSERT(pDevice != NULL);
EM_ASM({
var device = miniaudio.get_device_by_index($0);
var device = window.miniaudio.get_device_by_index($0);
device.webaudio.resume();
device.state = miniaudio.device_state.started;
device.state = window.miniaudio.device_state.started;
}, pDevice->webaudio.deviceIndex);
return MA_SUCCESS;
@@ -40581,9 +40617,9 @@ static ma_result ma_device_stop__webaudio(ma_device* pDevice)
do any kind of explicit draining.
*/
EM_ASM({
var device = miniaudio.get_device_by_index($0);
var device = window.miniaudio.get_device_by_index($0);
device.webaudio.suspend();
device.state = miniaudio.device_state.stopped;
device.state = window.miniaudio.device_state.stopped;
}, pDevice->webaudio.deviceIndex);
ma_device__on_notification_stopped(pDevice);
@@ -40642,6 +40678,7 @@ static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_contex
window.miniaudio.device_state.started = $4;
/* Device cache for mapping devices to indexes for JavaScript/C interop. */
let miniaudio = window.miniaudio;
miniaudio.devices = [];
miniaudio.track_device = function(device) {
@@ -40691,8 +40728,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 === miniaudio.device_state.started) {
device.webaudio.resume().then(() => {
_ma_device__on_notification_unlocked(device.pDevice);
},
(error) => {console.error("Failed to resume audiocontext", error);
});
}
}
miniaudio.unlock_event_types.map(function(event_type) {