Commit c26544ba authored by David Reid's avatar David Reid

Fix some full duplex issues for asynchronous backends.

parent 39edf6d8
...@@ -17005,7 +17005,7 @@ ma_result ma_device_init__jack(ma_context* pContext, const ma_device_config* pCo ...@@ -17005,7 +17005,7 @@ ma_result ma_device_init__jack(ma_context* pContext, const ma_device_config* pCo
/* The buffer size in frames can change. */ /* The buffer size in frames can change. */
periods = 2; periods = pConfig->periods;
bufferSizeInFrames = ((ma_jack_get_buffer_size_proc)pContext->jack.jack_get_buffer_size)((ma_jack_client_t*)pDevice->jack.pClient) * periods; bufferSizeInFrames = ((ma_jack_get_buffer_size_proc)pContext->jack.jack_get_buffer_size)((ma_jack_client_t*)pDevice->jack.pClient) * periods;
if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) { if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
...@@ -17095,6 +17095,17 @@ ma_result ma_device_init__jack(ma_context* pContext, const ma_device_config* pCo ...@@ -17095,6 +17095,17 @@ ma_result ma_device_init__jack(ma_context* pContext, const ma_device_config* pCo
ma_device_uninit__jack(pDevice); ma_device_uninit__jack(pDevice);
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to initialize ring buffer.", result); return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to initialize ring buffer.", result);
} }
/* We need a period to act as a buffer for cases where the playback and capture device's end up desyncing. */
{
ma_uint32 marginSizeInFrames = rbSizeInFrames / pDevice->capture.internalPeriods;
void* pMarginData;
ma_pcm_rb_acquire_write(&pDevice->jack.duplexRB, &marginSizeInFrames, &pMarginData);
{
ma_zero_memory(pMarginData, marginSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels));
}
ma_pcm_rb_commit_write(&pDevice->jack.duplexRB, marginSizeInFrames, pMarginData);
}
} }
return MA_SUCCESS; return MA_SUCCESS;
...@@ -22914,6 +22925,7 @@ ma_result ma_open_stream__aaudio(ma_context* pContext, ma_device_type deviceType ...@@ -22914,6 +22925,7 @@ ma_result ma_open_stream__aaudio(ma_context* pContext, ma_device_type deviceType
if (bufferCapacityInFrames == 0) { if (bufferCapacityInFrames == 0) {
bufferCapacityInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pConfig->bufferSizeInMilliseconds, pConfig->sampleRate); bufferCapacityInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pConfig->bufferSizeInMilliseconds, pConfig->sampleRate);
} }
bufferCapacityInFrames = (bufferCapacityInFrames / pConfig->periods) * pConfig->periods; /* <-- Make sure the buffer capacity is an even multiple of a period. */
((MA_PFN_AAudioStreamBuilder_setBufferCapacityInFrames)pContext->aaudio.AAudioStreamBuilder_setBufferCapacityInFrames)(pBuilder, bufferCapacityInFrames); ((MA_PFN_AAudioStreamBuilder_setBufferCapacityInFrames)pContext->aaudio.AAudioStreamBuilder_setBufferCapacityInFrames)(pBuilder, bufferCapacityInFrames);
((MA_PFN_AAudioStreamBuilder_setFramesPerDataCallback)pContext->aaudio.AAudioStreamBuilder_setFramesPerDataCallback)(pBuilder, bufferCapacityInFrames / pConfig->periods); ((MA_PFN_AAudioStreamBuilder_setFramesPerDataCallback)pContext->aaudio.AAudioStreamBuilder_setFramesPerDataCallback)(pBuilder, bufferCapacityInFrames / pConfig->periods);
...@@ -23120,15 +23132,11 @@ ma_result ma_device_init__aaudio(ma_context* pContext, const ma_device_config* p ...@@ -23120,15 +23132,11 @@ ma_result ma_device_init__aaudio(ma_context* pContext, const ma_device_config* p
ma_get_standard_channel_map(ma_standard_channel_map_default, pDevice->capture.internalChannels, pDevice->capture.internalChannelMap); /* <-- Cannot find info on channel order, so assuming a default. */ ma_get_standard_channel_map(ma_standard_channel_map_default, pDevice->capture.internalChannels, pDevice->capture.internalChannelMap); /* <-- Cannot find info on channel order, so assuming a default. */
pDevice->capture.internalBufferSizeInFrames = ((MA_PFN_AAudioStream_getBufferCapacityInFrames)pContext->aaudio.AAudioStream_getBufferCapacityInFrames)((ma_AAudioStream*)pDevice->aaudio.pStreamCapture); pDevice->capture.internalBufferSizeInFrames = ((MA_PFN_AAudioStream_getBufferCapacityInFrames)pContext->aaudio.AAudioStream_getBufferCapacityInFrames)((ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
/*
TODO: When synchronous reading and writing is supported, use AAudioStream_getFramesPerBurst() instead of AAudioStream_getFramesPerDataCallback(). Keep
using AAudioStream_getFramesPerDataCallback() for asynchronous mode, though.
*/
framesPerPeriod = ((MA_PFN_AAudioStream_getFramesPerDataCallback)pContext->aaudio.AAudioStream_getFramesPerDataCallback)((ma_AAudioStream*)pDevice->aaudio.pStreamCapture); framesPerPeriod = ((MA_PFN_AAudioStream_getFramesPerDataCallback)pContext->aaudio.AAudioStream_getFramesPerDataCallback)((ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
if (framesPerPeriod > 0) { if (framesPerPeriod > 0) {
pDevice->capture.internalPeriods = 1;
} else {
pDevice->capture.internalPeriods = pDevice->capture.internalBufferSizeInFrames / framesPerPeriod; pDevice->capture.internalPeriods = pDevice->capture.internalBufferSizeInFrames / framesPerPeriod;
} else {
pDevice->capture.internalPeriods = 1;
} }
} }
...@@ -23148,9 +23156,9 @@ ma_result ma_device_init__aaudio(ma_context* pContext, const ma_device_config* p ...@@ -23148,9 +23156,9 @@ ma_result ma_device_init__aaudio(ma_context* pContext, const ma_device_config* p
framesPerPeriod = ((MA_PFN_AAudioStream_getFramesPerDataCallback)pContext->aaudio.AAudioStream_getFramesPerDataCallback)((ma_AAudioStream*)pDevice->aaudio.pStreamPlayback); framesPerPeriod = ((MA_PFN_AAudioStream_getFramesPerDataCallback)pContext->aaudio.AAudioStream_getFramesPerDataCallback)((ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
if (framesPerPeriod > 0) { if (framesPerPeriod > 0) {
pDevice->playback.internalPeriods = 1;
} else {
pDevice->playback.internalPeriods = pDevice->playback.internalBufferSizeInFrames / framesPerPeriod; pDevice->playback.internalPeriods = pDevice->playback.internalBufferSizeInFrames / framesPerPeriod;
} else {
pDevice->playback.internalPeriods = 1;
} }
} }
...@@ -23166,6 +23174,17 @@ ma_result ma_device_init__aaudio(ma_context* pContext, const ma_device_config* p ...@@ -23166,6 +23174,17 @@ ma_result ma_device_init__aaudio(ma_context* pContext, const ma_device_config* p
} }
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[AAudio] Failed to initialize ring buffer.", result); return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[AAudio] Failed to initialize ring buffer.", result);
} }
/* We need a period to act as a buffer for cases where the playback and capture device's end up desyncing. */
{
ma_uint32 marginSizeInFrames = rbSizeInFrames / pDevice->capture.internalPeriods;
void* pMarginData;
ma_pcm_rb_acquire_write(&pDevice->aaudio.duplexRB, &marginSizeInFrames, &pMarginData);
{
ma_zero_memory(pMarginData, marginSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels));
}
ma_pcm_rb_commit_write(&pDevice->aaudio.duplexRB, marginSizeInFrames, pMarginData);
}
} }
return MA_SUCCESS; return MA_SUCCESS;
...@@ -24163,6 +24182,17 @@ ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_config* p ...@@ -24163,6 +24182,17 @@ ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_config* p
ma_device_uninit__opensl(pDevice); ma_device_uninit__opensl(pDevice);
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to initialize ring buffer.", result); return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to initialize ring buffer.", result);
} }
/* We need a period to act as a buffer for cases where the playback and capture device's end up desyncing. */
{
ma_uint32 marginSizeInFrames = rbSizeInFrames / pDevice->capture.internalPeriods;
void* pMarginData;
ma_pcm_rb_acquire_write(&pDevice->opensl.duplexRB, &marginSizeInFrames, &pMarginData);
{
ma_zero_memory(pMarginData, marginSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels));
}
ma_pcm_rb_commit_write(&pDevice->opensl.duplexRB, marginSizeInFrames, pMarginData);
}
} }
return MA_SUCCESS; return MA_SUCCESS;
...@@ -24768,6 +24798,17 @@ ma_result ma_device_init__webaudio(ma_context* pContext, const ma_device_config* ...@@ -24768,6 +24798,17 @@ ma_result ma_device_init__webaudio(ma_context* pContext, const ma_device_config*
} }
return result; return result;
} }
/* We need a period to act as a buffer for cases where the playback and capture device's end up desyncing. */
{
ma_uint32 marginSizeInFrames = rbSizeInFrames / 3; /* <-- Dividing by 3 because internalPeriods is always set to 1 for WebAudio. */
void* pMarginData;
ma_pcm_rb_acquire_write(&pDevice->webaudio.duplexRB, &marginSizeInFrames, &pMarginData);
{
ma_zero_memory(pMarginData, marginSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels));
}
ma_pcm_rb_commit_write(&pDevice->webaudio.duplexRB, marginSizeInFrames, pMarginData);
}
} }
return MA_SUCCESS; return MA_SUCCESS;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment