mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-24 09:14:04 +02:00
Work on full-duplex with Core Audio.
This commit is contained in:
@@ -14829,7 +14829,7 @@ mal_result mal_device_init__jack(mal_context* pContext, const mal_device_config*
|
|||||||
result = mal_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames, NULL, &pDevice->jack.duplexRB);
|
result = mal_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames, NULL, &pDevice->jack.duplexRB);
|
||||||
if (result != MAL_SUCCESS) {
|
if (result != MAL_SUCCESS) {
|
||||||
mal_device_uninit__jack(pDevice);
|
mal_device_uninit__jack(pDevice);
|
||||||
return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[AAudio] Failed to initialize ring buffer.", result);
|
return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[JACK] Failed to initialize ring buffer.", result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16359,6 +16359,10 @@ void mal_device_uninit__coreaudio(mal_device* pDevice)
|
|||||||
if (pDevice->coreaudio.pAudioBufferList) {
|
if (pDevice->coreaudio.pAudioBufferList) {
|
||||||
mal_free(pDevice->coreaudio.pAudioBufferList);
|
mal_free(pDevice->coreaudio.pAudioBufferList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pDevice->type == mal_device_type_duplex) {
|
||||||
|
mal_pcm_rb_uninit(&pDevice->coreaudio.duplexRB);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -16388,7 +16392,11 @@ OSStatus mal_on_output__coreaudio(void* pUserData, AudioUnitRenderActionFlags* p
|
|||||||
if (pBufferList->mBuffers[iBuffer].mNumberChannels == pDevice->internalChannels) {
|
if (pBufferList->mBuffers[iBuffer].mNumberChannels == pDevice->internalChannels) {
|
||||||
mal_uint32 frameCountForThisBuffer = pBufferList->mBuffers[iBuffer].mDataByteSize / mal_get_bytes_per_frame(pDevice->internalFormat, pDevice->internalChannels);
|
mal_uint32 frameCountForThisBuffer = pBufferList->mBuffers[iBuffer].mDataByteSize / mal_get_bytes_per_frame(pDevice->internalFormat, pDevice->internalChannels);
|
||||||
if (frameCountForThisBuffer > 0) {
|
if (frameCountForThisBuffer > 0) {
|
||||||
mal_device__read_frames_from_client(pDevice, frameCountForThisBuffer, pBufferList->mBuffers[iBuffer].mData);
|
if (pDevice->type == mal_device_type_duplex) {
|
||||||
|
mal_device__handle_duplex_callback_playback(pDevice, frameCountForThisBuffer, pBufferList->mBuffers[iBuffer].mData, &pDevice->coreaudio.duplexRB);
|
||||||
|
} else {
|
||||||
|
mal_device__read_frames_from_client(pDevice, frameCountForThisBuffer, pBufferList->mBuffers[iBuffer].mData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MAL_DEBUG_OUTPUT)
|
#if defined(MAL_DEBUG_OUTPUT)
|
||||||
@@ -16419,7 +16427,11 @@ OSStatus mal_on_output__coreaudio(void* pUserData, AudioUnitRenderActionFlags* p
|
|||||||
framesToRead = framesRemaining;
|
framesToRead = framesRemaining;
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_device__read_frames_from_client(pDevice, framesToRead, tempBuffer);
|
if (pDevice->type == mal_device_type_duplex) {
|
||||||
|
mal_device__handle_duplex_callback_playback(pDevice, framesToRead, tempBuffer, &pDevice->coreaudio.duplexRB);
|
||||||
|
} else {
|
||||||
|
mal_device__read_frames_from_client(pDevice, framesToRead, tempBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
void* ppDeinterleavedBuffers[MAL_MAX_CHANNELS];
|
void* ppDeinterleavedBuffers[MAL_MAX_CHANNELS];
|
||||||
for (mal_uint32 iChannel = 0; iChannel < pDevice->internalChannels; ++iChannel) {
|
for (mal_uint32 iChannel = 0; iChannel < pDevice->internalChannels; ++iChannel) {
|
||||||
@@ -16472,7 +16484,11 @@ OSStatus mal_on_input__coreaudio(void* pUserData, AudioUnitRenderActionFlags* pA
|
|||||||
if (layout == mal_stream_layout_interleaved) {
|
if (layout == mal_stream_layout_interleaved) {
|
||||||
for (UInt32 iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; ++iBuffer) {
|
for (UInt32 iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; ++iBuffer) {
|
||||||
if (pRenderedBufferList->mBuffers[iBuffer].mNumberChannels == pDevice->internalChannels) {
|
if (pRenderedBufferList->mBuffers[iBuffer].mNumberChannels == pDevice->internalChannels) {
|
||||||
mal_device__send_frames_to_client(pDevice, frameCount, pRenderedBufferList->mBuffers[iBuffer].mData);
|
if (pDevice->type == mal_device_type_duplex) {
|
||||||
|
mal_device__handle_duplex_callback_capture(pDevice, frameCount, pRenderedBufferList->mBuffers[iBuffer].mData, &pDevice->coreaudio.duplexRB);
|
||||||
|
} else {
|
||||||
|
mal_device__send_frames_to_client(pDevice, frameCount, pRenderedBufferList->mBuffers[iBuffer].mData);
|
||||||
|
}
|
||||||
#if defined(MAL_DEBUG_OUTPUT)
|
#if defined(MAL_DEBUG_OUTPUT)
|
||||||
printf(" mDataByteSize=%d\n", pRenderedBufferList->mBuffers[iBuffer].mDataByteSize);
|
printf(" mDataByteSize=%d\n", pRenderedBufferList->mBuffers[iBuffer].mDataByteSize);
|
||||||
#endif
|
#endif
|
||||||
@@ -16517,7 +16533,12 @@ OSStatus mal_on_input__coreaudio(void* pUserData, AudioUnitRenderActionFlags* pA
|
|||||||
}
|
}
|
||||||
|
|
||||||
mal_interleave_pcm_frames(pDevice->internalFormat, pDevice->internalChannels, framesToSend, (const void**)ppDeinterleavedBuffers, tempBuffer);
|
mal_interleave_pcm_frames(pDevice->internalFormat, pDevice->internalChannels, framesToSend, (const void**)ppDeinterleavedBuffers, tempBuffer);
|
||||||
mal_device__send_frames_to_client(pDevice, framesToSend, tempBuffer);
|
|
||||||
|
if (pDevice->type == mal_device_type_duplex) {
|
||||||
|
mal_device__handle_duplex_callback_capture(pDevice, framesToSend, tempBuffer, &pDevice->coreaudio.duplexRB);
|
||||||
|
} else {
|
||||||
|
mal_device__send_frames_to_client(pDevice, framesToSend, tempBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
framesRemaining -= framesToSend;
|
framesRemaining -= framesToSend;
|
||||||
}
|
}
|
||||||
@@ -17064,23 +17085,6 @@ mal_result mal_device_reinit_internal__coreaudio(mal_device* pDevice, mal_device
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEMP. BACKWARDS COMPATIBILITY.
|
|
||||||
if (pDevice->type == mal_device_type_capture || pDevice->type == mal_device_type_duplex) {
|
|
||||||
pDevice->internalFormat = pDevice->capture.internalFormat;
|
|
||||||
pDevice->internalChannels = pDevice->capture.internalChannels;
|
|
||||||
pDevice->internalSampleRate = pDevice->capture.internalSampleRate;
|
|
||||||
mal_copy_memory(pDevice->internalChannelMap, pDevice->capture.channelMap, sizeof(pDevice->capture.channelMap));
|
|
||||||
pDevice->bufferSizeInFrames = pDevice->capture.internalBufferSizeInFrames;
|
|
||||||
pDevice->periods = pDevice->capture.internalPeriods;
|
|
||||||
} else {
|
|
||||||
pDevice->internalFormat = pDevice->playback.internalFormat;
|
|
||||||
pDevice->internalChannels = pDevice->playback.internalChannels;
|
|
||||||
pDevice->internalSampleRate = pDevice->playback.internalSampleRate;
|
|
||||||
mal_copy_memory(pDevice->internalChannelMap, pDevice->playback.channelMap, sizeof(pDevice->playback.channelMap));
|
|
||||||
pDevice->bufferSizeInFrames = pDevice->playback.internalBufferSizeInFrames;
|
|
||||||
pDevice->periods = pDevice->playback.internalPeriods;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MAL_SUCCESS;
|
return MAL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17208,28 +17212,21 @@ mal_result mal_device_init__coreaudio(mal_context* pContext, const mal_device_co
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pDevice->type == mal_device_type_capture || pDevice->type == mal_device_type_duplex) {
|
|
||||||
pDevice->internalFormat = pDevice->capture.internalFormat;
|
|
||||||
pDevice->internalChannels = pDevice->capture.internalChannels;
|
|
||||||
pDevice->internalSampleRate = pDevice->capture.internalSampleRate;
|
|
||||||
mal_copy_memory(pDevice->internalChannelMap, pDevice->capture.channelMap, sizeof(pDevice->capture.channelMap));
|
|
||||||
pDevice->bufferSizeInFrames = pDevice->capture.internalBufferSizeInFrames;
|
|
||||||
pDevice->periods = pDevice->capture.internalPeriods;
|
|
||||||
} else {
|
|
||||||
pDevice->internalFormat = pDevice->playback.internalFormat;
|
|
||||||
pDevice->internalChannels = pDevice->playback.internalChannels;
|
|
||||||
pDevice->internalSampleRate = pDevice->playback.internalSampleRate;
|
|
||||||
mal_copy_memory(pDevice->internalChannelMap, pDevice->playback.channelMap, sizeof(pDevice->playback.channelMap));
|
|
||||||
pDevice->bufferSizeInFrames = pDevice->playback.internalBufferSizeInFrames;
|
|
||||||
pDevice->periods = pDevice->playback.internalPeriods;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
When stopping the device, a callback is called on another thread. We need to wait for this callback
|
When stopping the device, a callback is called on another thread. We need to wait for this callback
|
||||||
before returning from mal_device_stop(). This event is used for this.
|
before returning from mal_device_stop(). This event is used for this.
|
||||||
*/
|
*/
|
||||||
mal_event_init(pContext, &pDevice->coreaudio.stopEvent);
|
mal_event_init(pContext, &pDevice->coreaudio.stopEvent);
|
||||||
|
|
||||||
|
/* Need a ring buffer for duplex mode. */
|
||||||
|
if (pConfig->deviceType == mal_device_type_duplex) {
|
||||||
|
mal_uint32 rbSizeInFrames = (mal_uint32)mal_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames);
|
||||||
|
mal_result result = mal_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames, NULL, &pDevice->coreaudio.duplexRB);
|
||||||
|
if (result != MAL_SUCCESS) {
|
||||||
|
return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[Core Audio] Failed to initialize ring buffer.", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return MAL_SUCCESS;
|
return MAL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user