mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-24 09:14:04 +02:00
Work on full-duplex for JACK.
This commit is contained in:
@@ -2263,6 +2263,7 @@ MAL_ALIGNED_STRUCT(MAL_SIMD_ALIGNMENT) mal_device
|
|||||||
/*jack_port_t**/ mal_ptr pPortsCapture[MAL_MAX_CHANNELS];
|
/*jack_port_t**/ mal_ptr pPortsCapture[MAL_MAX_CHANNELS];
|
||||||
float* pIntermediaryBufferPlayback; // Typed as a float because JACK is always floating point.
|
float* pIntermediaryBufferPlayback; // Typed as a float because JACK is always floating point.
|
||||||
float* pIntermediaryBufferCapture;
|
float* pIntermediaryBufferCapture;
|
||||||
|
mal_pcm_rb duplexRB;
|
||||||
} jack;
|
} jack;
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_SUPPORT_COREAUDIO
|
#ifdef MAL_SUPPORT_COREAUDIO
|
||||||
@@ -2278,6 +2279,7 @@ MAL_ALIGNED_STRUCT(MAL_SIMD_ALIGNMENT) mal_device
|
|||||||
mal_bool32 isDefaultCaptureDevice;
|
mal_bool32 isDefaultCaptureDevice;
|
||||||
mal_bool32 isSwitchingPlaybackDevice; /* <-- Set to true when the default device has changed and mini_al is in the process of switching. */
|
mal_bool32 isSwitchingPlaybackDevice; /* <-- Set to true when the default device has changed and mini_al is in the process of switching. */
|
||||||
mal_bool32 isSwitchingCaptureDevice; /* <-- Set to true when the default device has changed and mini_al is in the process of switching. */
|
mal_bool32 isSwitchingCaptureDevice; /* <-- Set to true when the default device has changed and mini_al is in the process of switching. */
|
||||||
|
mal_pcm_rb duplexRB;
|
||||||
} coreaudio;
|
} coreaudio;
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_SUPPORT_SNDIO
|
#ifdef MAL_SUPPORT_SNDIO
|
||||||
@@ -14595,6 +14597,18 @@ void mal_device_uninit__jack(mal_device* pDevice)
|
|||||||
if (pDevice->jack.pClient != NULL) {
|
if (pDevice->jack.pClient != NULL) {
|
||||||
((mal_jack_client_close_proc)pContext->jack.jack_client_close)((mal_jack_client_t*)pDevice->jack.pClient);
|
((mal_jack_client_close_proc)pContext->jack.jack_client_close)((mal_jack_client_t*)pDevice->jack.pClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pDevice->type == mal_device_type_capture || pDevice->type == mal_device_type_duplex) {
|
||||||
|
mal_free(pDevice->jack.pIntermediaryBufferCapture);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pDevice->type == mal_device_type_playback || pDevice->type == mal_device_type_duplex) {
|
||||||
|
mal_free(pDevice->jack.pIntermediaryBufferPlayback);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pDevice->type == mal_device_type_duplex) {
|
||||||
|
mal_pcm_rb_uninit(&pDevice->jack.duplexRB);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_device__jack_shutdown_callback(void* pUserData)
|
void mal_device__jack_shutdown_callback(void* pUserData)
|
||||||
@@ -14642,41 +14656,47 @@ int mal_device__jack_process_callback(mal_jack_nframes_t frameCount, void* pUser
|
|||||||
mal_context* pContext = pDevice->pContext;
|
mal_context* pContext = pDevice->pContext;
|
||||||
mal_assert(pContext != NULL);
|
mal_assert(pContext != NULL);
|
||||||
|
|
||||||
if (pDevice->type == mal_device_type_duplex) {
|
if (pDevice->type == mal_device_type_capture || pDevice->type == mal_device_type_duplex) {
|
||||||
// TODO: Implement me.
|
// Channels need to be interleaved.
|
||||||
} else {
|
for (mal_uint32 iChannel = 0; iChannel < pDevice->capture.internalChannels; ++iChannel) {
|
||||||
if (pDevice->type == mal_device_type_playback) {
|
const float* pSrc = (const float*)((mal_jack_port_get_buffer_proc)pContext->jack.jack_port_get_buffer)((mal_jack_port_t*)pDevice->jack.pPortsCapture[iChannel], frameCount);
|
||||||
mal_device__read_frames_from_client(pDevice, frameCount, pDevice->jack.pIntermediaryBufferPlayback);
|
if (pSrc != NULL) {
|
||||||
|
float* pDst = pDevice->jack.pIntermediaryBufferCapture + iChannel;
|
||||||
|
for (mal_jack_nframes_t iFrame = 0; iFrame < frameCount; ++iFrame) {
|
||||||
|
*pDst = *pSrc;
|
||||||
|
|
||||||
// Channels need to be deinterleaved.
|
pDst += pDevice->capture.internalChannels;
|
||||||
for (mal_uint32 iChannel = 0; iChannel < pDevice->playback.internalChannels; ++iChannel) {
|
pSrc += 1;
|
||||||
float* pDst = (float*)((mal_jack_port_get_buffer_proc)pContext->jack.jack_port_get_buffer)((mal_jack_port_t*)pDevice->jack.pPortsPlayback[iChannel], frameCount);
|
|
||||||
if (pDst != NULL) {
|
|
||||||
const float* pSrc = pDevice->jack.pIntermediaryBufferPlayback + iChannel;
|
|
||||||
for (mal_jack_nframes_t iFrame = 0; iFrame < frameCount; ++iFrame) {
|
|
||||||
*pDst = *pSrc;
|
|
||||||
|
|
||||||
pDst += 1;
|
|
||||||
pSrc += pDevice->playback.internalChannels;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pDevice->type == mal_device_type_duplex) {
|
||||||
|
mal_device__handle_duplex_callback_capture(pDevice, frameCount, pDevice->jack.pIntermediaryBufferCapture, &pDevice->jack.duplexRB);
|
||||||
} else {
|
} else {
|
||||||
// Channels need to be interleaved.
|
mal_device__send_frames_to_client(pDevice, frameCount, pDevice->jack.pIntermediaryBufferCapture);
|
||||||
for (mal_uint32 iChannel = 0; iChannel < pDevice->capture.internalChannels; ++iChannel) {
|
}
|
||||||
const float* pSrc = (const float*)((mal_jack_port_get_buffer_proc)pContext->jack.jack_port_get_buffer)((mal_jack_port_t*)pDevice->jack.pPortsCapture[iChannel], frameCount);
|
}
|
||||||
if (pSrc != NULL) {
|
|
||||||
float* pDst = pDevice->jack.pIntermediaryBufferCapture + iChannel;
|
|
||||||
for (mal_jack_nframes_t iFrame = 0; iFrame < frameCount; ++iFrame) {
|
|
||||||
*pDst = *pSrc;
|
|
||||||
|
|
||||||
pDst += pDevice->capture.internalChannels;
|
if (pDevice->type == mal_device_type_playback || pDevice->type == mal_device_type_duplex) {
|
||||||
pSrc += 1;
|
if (pDevice->type == mal_device_type_duplex) {
|
||||||
}
|
mal_device__handle_duplex_callback_playback(pDevice, frameCount, pDevice->jack.pIntermediaryBufferPlayback, &pDevice->jack.duplexRB);
|
||||||
|
} else {
|
||||||
|
mal_device__read_frames_from_client(pDevice, frameCount, pDevice->jack.pIntermediaryBufferPlayback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Channels need to be deinterleaved.
|
||||||
|
for (mal_uint32 iChannel = 0; iChannel < pDevice->playback.internalChannels; ++iChannel) {
|
||||||
|
float* pDst = (float*)((mal_jack_port_get_buffer_proc)pContext->jack.jack_port_get_buffer)((mal_jack_port_t*)pDevice->jack.pPortsPlayback[iChannel], frameCount);
|
||||||
|
if (pDst != NULL) {
|
||||||
|
const float* pSrc = pDevice->jack.pIntermediaryBufferPlayback + iChannel;
|
||||||
|
for (mal_jack_nframes_t iFrame = 0; iFrame < frameCount; ++iFrame) {
|
||||||
|
*pDst = *pSrc;
|
||||||
|
|
||||||
|
pDst += 1;
|
||||||
|
pSrc += pDevice->playback.internalChannels;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_device__send_frames_to_client(pDevice, frameCount, pDevice->jack.pIntermediaryBufferCapture);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14804,6 +14824,15 @@ mal_result mal_device_init__jack(mal_context* pContext, const mal_device_config*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pDevice->type == mal_device_type_duplex) {
|
||||||
|
mal_uint32 rbSizeInFrames = (mal_uint32)mal_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames);
|
||||||
|
result = mal_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames, NULL, &pDevice->jack.duplexRB);
|
||||||
|
if (result != MAL_SUCCESS) {
|
||||||
|
mal_device_uninit__jack(pDevice);
|
||||||
|
return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[AAudio] Failed to initialize ring buffer.", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return MAL_SUCCESS;
|
return MAL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19838,7 +19867,7 @@ mal_result mal_device_init__aaudio(mal_context* pContext, const mal_device_confi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pConfig->deviceType == mal_device_type_duplex) {
|
if (pConfig->deviceType == mal_device_type_duplex) {
|
||||||
mal_uint32 rbSizeInFrames = mal_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames);
|
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->aaudio.duplexRB);
|
mal_result result = mal_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames, NULL, &pDevice->aaudio.duplexRB);
|
||||||
if (result != MAL_SUCCESS) {
|
if (result != MAL_SUCCESS) {
|
||||||
if (pDevice->type == mal_device_type_capture || pDevice->type == mal_device_type_duplex) {
|
if (pDevice->type == mal_device_type_capture || pDevice->type == mal_device_type_duplex) {
|
||||||
@@ -20810,7 +20839,7 @@ mal_result mal_device_init__opensl(mal_context* pContext, const mal_device_confi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pConfig->deviceType == mal_device_type_duplex) {
|
if (pConfig->deviceType == mal_device_type_duplex) {
|
||||||
mal_uint32 rbSizeInFrames = mal_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames);
|
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->opensl.duplexRB);
|
mal_result result = mal_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames, NULL, &pDevice->opensl.duplexRB);
|
||||||
if (result != MAL_SUCCESS) {
|
if (result != MAL_SUCCESS) {
|
||||||
mal_device_uninit__opensl(pDevice);
|
mal_device_uninit__opensl(pDevice);
|
||||||
@@ -21396,7 +21425,7 @@ mal_result mal_device_init__webaudio(mal_context* pContext, const mal_device_con
|
|||||||
the external sample rate.
|
the external sample rate.
|
||||||
*/
|
*/
|
||||||
if (pConfig->deviceType == mal_device_type_duplex) {
|
if (pConfig->deviceType == mal_device_type_duplex) {
|
||||||
mal_uint32 rbSizeInFrames = mal_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames);
|
mal_uint32 rbSizeInFrames = (mal_uint32)mal_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames);
|
||||||
result = mal_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames, NULL, &pDevice->webaudio.duplexRB);
|
result = mal_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames, NULL, &pDevice->webaudio.duplexRB);
|
||||||
if (result != MAL_SUCCESS) {
|
if (result != MAL_SUCCESS) {
|
||||||
if (pDevice->type == mal_device_type_capture || pDevice->type == mal_device_type_duplex) {
|
if (pDevice->type == mal_device_type_capture || pDevice->type == mal_device_type_duplex) {
|
||||||
|
|||||||
Reference in New Issue
Block a user