mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 08:14:04 +02:00
OpenSL: Drain buffers when stopping the device.
This commit is contained in:
+50
-2
@@ -3238,6 +3238,8 @@ struct ma_device
|
|||||||
/*SLRecordItf*/ ma_ptr pAudioRecorder;
|
/*SLRecordItf*/ ma_ptr pAudioRecorder;
|
||||||
/*SLAndroidSimpleBufferQueueItf*/ ma_ptr pBufferQueuePlayback;
|
/*SLAndroidSimpleBufferQueueItf*/ ma_ptr pBufferQueuePlayback;
|
||||||
/*SLAndroidSimpleBufferQueueItf*/ ma_ptr pBufferQueueCapture;
|
/*SLAndroidSimpleBufferQueueItf*/ ma_ptr pBufferQueueCapture;
|
||||||
|
ma_bool32 isDrainingCapture;
|
||||||
|
ma_bool32 isDrainingPlayback;
|
||||||
ma_uint32 currentBufferIndexPlayback;
|
ma_uint32 currentBufferIndexPlayback;
|
||||||
ma_uint32 currentBufferIndexCapture;
|
ma_uint32 currentBufferIndexCapture;
|
||||||
ma_uint8* pBufferPlayback; /* This is malloc()'d and is used for storing audio data. Typed as ma_uint8 for easy offsetting. */
|
ma_uint8* pBufferPlayback; /* This is malloc()'d and is used for storing audio data. Typed as ma_uint8 for easy offsetting. */
|
||||||
@@ -26371,6 +26373,11 @@ static void ma_buffer_queue_callback_capture__opensl_android(SLAndroidSimpleBuff
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Don't do anything if the device is being drained. */
|
||||||
|
if (pDevice->opensl.isDrainingCapture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
periodSizeInBytes = pDevice->capture.internalPeriodSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
|
periodSizeInBytes = pDevice->capture.internalPeriodSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
|
||||||
pBuffer = pDevice->opensl.pBufferCapture + (pDevice->opensl.currentBufferIndexCapture * periodSizeInBytes);
|
pBuffer = pDevice->opensl.pBufferCapture + (pDevice->opensl.currentBufferIndexCapture * periodSizeInBytes);
|
||||||
|
|
||||||
@@ -26404,6 +26411,11 @@ static void ma_buffer_queue_callback_playback__opensl_android(SLAndroidSimpleBuf
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Don't do anything if the device is being drained. */
|
||||||
|
if (pDevice->opensl.isDrainingPlayback) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
periodSizeInBytes = pDevice->playback.internalPeriodSizeInFrames * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
periodSizeInBytes = pDevice->playback.internalPeriodSizeInFrames * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
||||||
pBuffer = pDevice->opensl.pBufferPlayback + (pDevice->opensl.currentBufferIndexPlayback * periodSizeInBytes);
|
pBuffer = pDevice->opensl.pBufferPlayback + (pDevice->opensl.currentBufferIndexPlayback * periodSizeInBytes);
|
||||||
|
|
||||||
@@ -26846,6 +26858,40 @@ static ma_result ma_device_start__opensl(ma_device* pDevice)
|
|||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ma_result ma_device_drain__opensl(ma_device* pDevice, ma_device_type deviceType)
|
||||||
|
{
|
||||||
|
SLAndroidSimpleBufferQueueItf pBufferQueue;
|
||||||
|
|
||||||
|
MA_ASSERT(deviceType == ma_device_type_capture || deviceType == ma_device_type_playback);
|
||||||
|
|
||||||
|
if (pDevice->type == ma_device_type_capture) {
|
||||||
|
pBufferQueue = (SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture;
|
||||||
|
pDevice->opensl.isDrainingCapture = MA_TRUE;
|
||||||
|
} else {
|
||||||
|
pBufferQueue = (SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback;
|
||||||
|
pDevice->opensl.isDrainingPlayback = MA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
SLAndroidSimpleBufferQueueState state;
|
||||||
|
|
||||||
|
MA_OPENSL_BUFFERQUEUE(pBufferQueue)->GetState(pBufferQueue, &state);
|
||||||
|
if (state.count == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ma_sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pDevice->type == ma_device_type_capture) {
|
||||||
|
pDevice->opensl.isDrainingCapture = MA_FALSE;
|
||||||
|
} else {
|
||||||
|
pDevice->opensl.isDrainingPlayback = MA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static ma_result ma_device_stop__opensl(ma_device* pDevice)
|
static ma_result ma_device_stop__opensl(ma_device* pDevice)
|
||||||
{
|
{
|
||||||
SLresult resultSL;
|
SLresult resultSL;
|
||||||
@@ -26858,9 +26904,9 @@ static ma_result ma_device_stop__opensl(ma_device* pDevice)
|
|||||||
return MA_INVALID_OPERATION;
|
return MA_INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Wait until all buffers have been processed. Hint: Maybe SLAndroidSimpleBufferQueue::GetState() could be used in a loop? */
|
|
||||||
|
|
||||||
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
|
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
|
||||||
|
ma_device_drain__opensl(pDevice, ma_device_type_capture);
|
||||||
|
|
||||||
resultSL = MA_OPENSL_RECORD(pDevice->opensl.pAudioRecorder)->SetRecordState((SLRecordItf)pDevice->opensl.pAudioRecorder, SL_RECORDSTATE_STOPPED);
|
resultSL = MA_OPENSL_RECORD(pDevice->opensl.pAudioRecorder)->SetRecordState((SLRecordItf)pDevice->opensl.pAudioRecorder, SL_RECORDSTATE_STOPPED);
|
||||||
if (resultSL != SL_RESULT_SUCCESS) {
|
if (resultSL != SL_RESULT_SUCCESS) {
|
||||||
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to stop internal capture device.", MA_FAILED_TO_STOP_BACKEND_DEVICE);
|
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to stop internal capture device.", MA_FAILED_TO_STOP_BACKEND_DEVICE);
|
||||||
@@ -26870,6 +26916,8 @@ static ma_result ma_device_stop__opensl(ma_device* pDevice)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
|
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
|
||||||
|
ma_device_drain__opensl(pDevice, ma_device_type_playback);
|
||||||
|
|
||||||
resultSL = MA_OPENSL_PLAY(pDevice->opensl.pAudioPlayer)->SetPlayState((SLPlayItf)pDevice->opensl.pAudioPlayer, SL_PLAYSTATE_STOPPED);
|
resultSL = MA_OPENSL_PLAY(pDevice->opensl.pAudioPlayer)->SetPlayState((SLPlayItf)pDevice->opensl.pAudioPlayer, SL_PLAYSTATE_STOPPED);
|
||||||
if (resultSL != SL_RESULT_SUCCESS) {
|
if (resultSL != SL_RESULT_SUCCESS) {
|
||||||
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to stop internal playback device.", MA_FAILED_TO_STOP_BACKEND_DEVICE);
|
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to stop internal playback device.", MA_FAILED_TO_STOP_BACKEND_DEVICE);
|
||||||
|
|||||||
Reference in New Issue
Block a user