diff --git a/mini_al.h b/mini_al.h index 8b60171a..779a6001 100644 --- a/mini_al.h +++ b/mini_al.h @@ -4820,7 +4820,7 @@ static mal_result mal_device__handle_duplex_callback_capture(mal_device* pDevice mal_assert(pRB != NULL); mal_result result; - + pDevice->capture._dspFrameCount = (mal_uint32)frameCount; pDevice->capture._dspFrames = (const mal_uint8*)pFramesInInternalFormat; @@ -4836,7 +4836,9 @@ static mal_result mal_device__handle_duplex_callback_capture(mal_device* pDevice } if (framesToProcess == 0) { - break; /* Overrun. Not enough room in the ring buffer for input frame. Excess frames are dropped. */ + if (mal_pcm_rb_pointer_disance(pRB) == 0) { + break; /* Overrun. Not enough room in the ring buffer for input frame. Excess frames are dropped. */ + } } /* Convert. */ @@ -4862,7 +4864,7 @@ static mal_result mal_device__handle_duplex_callback_playback(mal_device* pDevic mal_assert(frameCount > 0); mal_assert(pFramesInInternalFormat != NULL); mal_assert(pRB != NULL); - + /* Sitting in the ring buffer should be captured data from the capture callback in external format. If there's not enough data in there for the whole frameCount frames we just use silence instead for the input data. @@ -4875,7 +4877,7 @@ static mal_result mal_device__handle_duplex_callback_playback(mal_device* pDevic /* We need to calculate how many output frames are required to be read from the client to completely fill frameCount internal frames. */ mal_uint32 totalFramesToReadFromClient = (mal_uint32)mal_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->playback.internalSampleRate, frameCount); // mal_pcm_converter_get_required_input_frame_count(&pDevice->playback.converter, (mal_uint32)frameCount); mal_uint32 totalFramesReadFromClient = 0; - while (totalFramesReadFromClient < totalFramesToReadFromClient) { + while (totalFramesReadFromClient < totalFramesToReadFromClient && mal_device_is_started(pDevice)) { mal_uint32 framesRemainingFromClient = (totalFramesToReadFromClient - totalFramesReadFromClient); mal_uint32 framesToProcessFromClient = sizeof(playbackFramesInExternalFormat) / mal_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels); if (framesToProcessFromClient > framesRemainingFromClient) { @@ -4886,10 +4888,12 @@ static mal_result mal_device__handle_duplex_callback_playback(mal_device* pDevic mal_uint32 inputFrameCount = framesToProcessFromClient; void* pInputFrames; result = mal_pcm_rb_acquire_read(pRB, &inputFrameCount, &pInputFrames); - if (result == MAL_SUCCESS && inputFrameCount > 0) { - /* Use actual input frames. */ - pDevice->onData(pDevice, playbackFramesInExternalFormat, pInputFrames, inputFrameCount); - + if (result == MAL_SUCCESS) { + if (inputFrameCount > 0) { + /* Use actual input frames. */ + pDevice->onData(pDevice, playbackFramesInExternalFormat, pInputFrames, inputFrameCount); + } + /* We're done with the captured samples. */ result = mal_pcm_rb_commit_read(pRB, inputFrameCount, pInputFrames); if (result != MAL_SUCCESS) { @@ -16509,7 +16513,12 @@ OSStatus mal_on_input__coreaudio(void* pUserData, AudioUnitRenderActionFlags* pA framesToSend = framesRemaining; } - mal_device__send_frames_to_client(pDevice, framesToSend, silentBuffer); + if (pDevice->type == mal_device_type_duplex) { + mal_device__handle_duplex_callback_capture(pDevice, framesToSend, silentBuffer, &pDevice->coreaudio.duplexRB); + } else { + mal_device__send_frames_to_client(pDevice, framesToSend, silentBuffer); + } + framesRemaining -= framesToSend; } @@ -17121,6 +17130,7 @@ mal_result mal_device_init__coreaudio(mal_context* pContext, const mal_device_co data.shareMode = pConfig->capture.shareMode; data.bufferSizeInFramesIn = pConfig->bufferSizeInFrames; data.bufferSizeInMillisecondsIn = pConfig->bufferSizeInMilliseconds; + data.registerStopEvent = MAL_TRUE; mal_result result = mal_device_init_internal__coreaudio(pDevice->pContext, mal_device_type_capture, pConfig->capture.pDeviceID, &data, (void*)pDevice); if (result != MAL_SUCCESS) { @@ -17172,10 +17182,12 @@ mal_result mal_device_init__coreaudio(mal_context* pContext, const mal_device_co if (pConfig->deviceType == mal_device_type_duplex) { data.bufferSizeInFramesIn = pDevice->capture.internalBufferSizeInFrames; data.periodsIn = pDevice->capture.internalPeriods; + data.registerStopEvent = MAL_FALSE; } else { data.bufferSizeInFramesIn = pConfig->bufferSizeInFrames; data.bufferSizeInMillisecondsIn = pConfig->bufferSizeInMilliseconds; data.periodsIn = pConfig->periods; + data.registerStopEvent = MAL_TRUE; } mal_result result = mal_device_init_internal__coreaudio(pDevice->pContext, mal_device_type_playback, pConfig->playback.pDeviceID, &data, (void*)pDevice); diff --git a/tests/mal_duplex.c b/tests/mal_duplex.c index 0e2c0962..b514d416 100644 --- a/tests/mal_duplex.c +++ b/tests/mal_duplex.c @@ -31,7 +31,7 @@ void data_callback(mal_device* pDevice, void* pOutput, const void* pInput, mal_u /* In this test the format and channel count are the same for both input and output which means we can just memcpy(). */ mal_copy_memory(pOutput, pInput, frameCount * mal_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels)); -#if 0 +#if 1 /* Also write to a wav file for debugging. */ drwav* pWav = (drwav*)pDevice->pUserData; mal_assert(pWav != NULL); @@ -44,7 +44,7 @@ int main(int argc, char** argv) { mal_result result; -#if 0 +#if 1 drwav_data_format wavFormat; wavFormat.container = drwav_container_riff; wavFormat.format = DR_WAVE_FORMAT_PCM; @@ -60,7 +60,7 @@ int main(int argc, char** argv) #endif - mal_backend backend = mal_backend_webaudio; + mal_backend backend = mal_backend_coreaudio; mal_context_config contextConfig = mal_context_config_init(); contextConfig.logCallback = log_callback; @@ -84,7 +84,7 @@ int main(int argc, char** argv) deviceConfig.periods = 2; deviceConfig.dataCallback = data_callback; deviceConfig.stopCallback = stop_callback; - deviceConfig.pUserData = NULL; /*&wav;*/ + deviceConfig.pUserData = &wav; mal_device device; result = mal_device_init(&context, &deviceConfig, &device); @@ -106,9 +106,9 @@ int main(int argc, char** argv) #endif mal_device_uninit(&device); - /*drwav_uninit(&wav);*/ + drwav_uninit(&wav); (void)argc; (void)argv; return 0; -} \ No newline at end of file +}