Fix an error with the Web Audio backend.

This commit is contained in:
David Reid
2025-12-30 10:13:44 +10:00
parent cc4db76c26
commit d04c1985d6
+12 -8
View File
@@ -7186,6 +7186,7 @@ typedef struct ma_device_backend_info
{ {
const char* pName; const char* pName;
ma_bool32 isLoopbackSupported; ma_bool32 isLoopbackSupported;
ma_bool32 noAudioThread; /* When set to true, the backend does not create a miniaudio-managed audio thread. Will be used for backends like Web Audio, or those that run on platforms that do not support multithreading. Depending on the backend, this may force single-threaded mode. Single-threaded mode will not be enforced for the Web Audio backend. */
} ma_device_backend_info; } ma_device_backend_info;
@@ -7751,6 +7752,7 @@ struct ma_device
ma_context* pContext; ma_context* pContext;
ma_device_type type; ma_device_type type;
ma_threading_mode threadingMode; ma_threading_mode threadingMode;
ma_bool32 hasAudioThread;
ma_uint32 sampleRate; ma_uint32 sampleRate;
ma_atomic_device_status state; /* The state of the device is variable and can change at any time on any thread. Must be used atomically. */ ma_atomic_device_status state; /* The state of the device is variable and can change at any time on any thread. Must be used atomically. */
ma_device_data_proc onData; /* Set once at initialization time and should not be changed after. */ ma_device_data_proc onData; /* Set once at initialization time and should not be changed after. */
@@ -42444,6 +42446,7 @@ static void ma_backend_info__webaudio(ma_device_backend_info* pBackendInfo)
{ {
MA_ASSERT(pBackendInfo != NULL); MA_ASSERT(pBackendInfo != NULL);
pBackendInfo->pName = "Web Audio"; pBackendInfo->pName = "Web Audio";
pBackendInfo->noAudioThread = MA_TRUE; /* We don't want to be creating a miniaudio-managed audio thread with Web Audio. */
} }
static ma_result ma_context_init__webaudio(ma_context* pContext, const void* pContextBackendConfig, void** ppContextState) static ma_result ma_context_init__webaudio(ma_context* pContext, const void* pContextBackendConfig, void** ppContextState)
@@ -44985,6 +44988,7 @@ static const void* ma_device_config_find_backend_config(const ma_device_config*
MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pConfig, ma_device* pDevice) MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pConfig, ma_device* pDevice)
{ {
ma_result result; ma_result result;
ma_device_backend_info backendInfo;
ma_device_descriptor descriptorPlayback; ma_device_descriptor descriptorPlayback;
ma_device_descriptor descriptorCapture; ma_device_descriptor descriptorCapture;
ma_threading_mode threadingMode; ma_threading_mode threadingMode;
@@ -45014,6 +45018,9 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
} }
#endif #endif
/* We'll need the backend info to determine whether or not an audio thread can be created. */
ma_context_get_backend_info(pContext, &backendInfo);
/* Check that we have our callbacks defined. */ /* Check that we have our callbacks defined. */
if (pContext->pVTable->onDeviceInit == NULL) { if (pContext->pVTable->onDeviceInit == NULL) {
return MA_INVALID_OPERATION; return MA_INVALID_OPERATION;
@@ -45042,6 +45049,7 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
pDevice->pContext = pContext; pDevice->pContext = pContext;
pDevice->threadingMode = threadingMode; pDevice->threadingMode = threadingMode;
pDevice->hasAudioThread = !(threadingMode == MA_THREADING_MODE_SINGLE_THREADED || backendInfo.noAudioThread);
pDevice->pUserData = pConfig->pUserData; pDevice->pUserData = pConfig->pUserData;
pDevice->onData = pConfig->dataCallback; pDevice->onData = pConfig->dataCallback;
pDevice->onNotification = pConfig->notificationCallback; pDevice->onNotification = pConfig->notificationCallback;
@@ -45119,7 +45127,6 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
descriptorCapture.periodCount = MA_DEFAULT_PERIODS; descriptorCapture.periodCount = MA_DEFAULT_PERIODS;
} }
/* Starting and stopping must be mutually exclusive. We just use a mutex for this. */ /* Starting and stopping must be mutually exclusive. We just use a mutex for this. */
#ifndef MA_NO_THREADING #ifndef MA_NO_THREADING
{ {
@@ -45130,7 +45137,6 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
} }
#endif #endif
initParams.init.pDeviceBackendConfig = ma_device_config_find_backend_config(pConfig, pContext->pVTable); initParams.init.pDeviceBackendConfig = ma_device_config_find_backend_config(pConfig, pContext->pVTable);
initParams.init.pDescriptorPlayback = &descriptorPlayback; initParams.init.pDescriptorPlayback = &descriptorPlayback;
initParams.init.pDescriptorCapture = &descriptorCapture; initParams.init.pDescriptorCapture = &descriptorCapture;
@@ -45140,7 +45146,7 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
be initialized. It won't be doing anything at first because no operation will be put onto the queue. be initialized. It won't be doing anything at first because no operation will be put onto the queue.
*/ */
#ifndef MA_NO_THREADING #ifndef MA_NO_THREADING
if (threadingMode == MA_THREADING_MODE_MULTITHREADED) { if (pDevice->hasAudioThread) {
/* We need an operation queue before starting the audio thread. */ /* We need an operation queue before starting the audio thread. */
result = ma_device_op_queue_init(&pDevice->opQueue); result = ma_device_op_queue_init(&pDevice->opQueue);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
@@ -45188,9 +45194,7 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
} else } else
#endif #endif
{ {
/* Getting here means we're running in single-threaded mode. We want to run the init operation immediately. */ /* Getting here means we're running in single-threaded mode or we weren't allowed to create an audio thread. We want to run the init operation immediately. */
MA_ASSERT(threadingMode == MA_THREADING_MODE_SINGLE_THREADED);
result = ma_device_op_do_init(pDevice, initParams, NULL); result = ma_device_op_do_init(pDevice, initParams, NULL);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; /* Failed to initialize backend. */ return result; /* Failed to initialize backend. */
@@ -45686,7 +45690,7 @@ MA_API ma_result ma_device_start(ma_device* pDevice)
ma_device_set_status(pDevice, ma_device_status_starting); ma_device_set_status(pDevice, ma_device_status_starting);
#ifndef MA_NO_THREADING #ifndef MA_NO_THREADING
if (ma_device_get_threading_mode(pDevice) == MA_THREADING_MODE_MULTITHREADED) { if (pDevice->hasAudioThread) {
result = ma_device_op_queue_push(&pDevice->opQueue, MA_DEVICE_OP_START, NULL, &pDevice->opCompletionEvent); result = ma_device_op_queue_push(&pDevice->opQueue, MA_DEVICE_OP_START, NULL, &pDevice->opCompletionEvent);
if (result == MA_SUCCESS) { if (result == MA_SUCCESS) {
result = ma_device_op_completion_event_result(&pDevice->opCompletionEvent); /* <-- This will wait for the operation to complete. */ result = ma_device_op_completion_event_result(&pDevice->opCompletionEvent); /* <-- This will wait for the operation to complete. */
@@ -45738,7 +45742,7 @@ MA_API ma_result ma_device_stop(ma_device* pDevice)
ma_device_set_status(pDevice, ma_device_status_stopping); ma_device_set_status(pDevice, ma_device_status_stopping);
#ifndef MA_NO_THREADING #ifndef MA_NO_THREADING
if (ma_device_get_threading_mode(pDevice) == MA_THREADING_MODE_MULTITHREADED) { if (pDevice->hasAudioThread) {
result = ma_device_op_queue_push(&pDevice->opQueue, MA_DEVICE_OP_STOP, NULL, &pDevice->opCompletionEvent); result = ma_device_op_queue_push(&pDevice->opQueue, MA_DEVICE_OP_STOP, NULL, &pDevice->opCompletionEvent);
if (result == MA_SUCCESS) { if (result == MA_SUCCESS) {
/* /*