From bfb19f2938a37715d5b34d34e0b55c44907fcc19 Mon Sep 17 00:00:00 2001 From: David Reid Date: Mon, 26 Aug 2019 19:51:39 +1000 Subject: [PATCH] Experimental improvements for the ALSA backend. --- miniaudio.h | 19 +++++-------------- tests/ma_duplex.c | 12 +++++++++--- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/miniaudio.h b/miniaudio.h index ec6bc8ab..045a7ae5 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -13538,20 +13538,11 @@ ma_result ma_device_init_by_type__alsa(ma_context* pContext, const ma_device_con return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to initialize software parameters. snd_pcm_sw_params_current() failed.", MA_FAILED_TO_CONFIGURE_BACKEND_DEVICE); } - if (deviceType == ma_device_type_capture) { - if (((ma_snd_pcm_sw_params_set_avail_min_proc)pContext->alsa.snd_pcm_sw_params_set_avail_min)(pPCM, pSWParams, 1) != 0) { - ma_free(pSWParams); - ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM); - return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] snd_pcm_sw_params_set_avail_min() failed.", MA_FORMAT_NOT_SUPPORTED); - } - } else { - if (((ma_snd_pcm_sw_params_set_avail_min_proc)pContext->alsa.snd_pcm_sw_params_set_avail_min)(pPCM, pSWParams, 1) != 0) { - ma_free(pSWParams); - ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM); - return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] snd_pcm_sw_params_set_avail_min() failed.", MA_FORMAT_NOT_SUPPORTED); - } + if (((ma_snd_pcm_sw_params_set_avail_min_proc)pContext->alsa.snd_pcm_sw_params_set_avail_min)(pPCM, pSWParams, ma_prev_power_of_2(internalBufferSizeInFrames/internalPeriods)) != 0) { + ma_free(pSWParams); + ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM); + return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] snd_pcm_sw_params_set_avail_min() failed.", MA_FORMAT_NOT_SUPPORTED); } - if (((ma_snd_pcm_sw_params_get_boundary_proc)pContext->alsa.snd_pcm_sw_params_get_boundary)(pSWParams, &bufferBoundary) < 0) { bufferBoundary = internalBufferSizeInFrames; @@ -13564,7 +13555,7 @@ ma_result ma_device_init_by_type__alsa(ma_context* pContext, const ma_device_con Subtle detail here with the start threshold. When in playback-only mode (no full-duplex) we can set the start threshold to the size of a period. But for full-duplex we need to set it such that it is at least two periods. */ - if (((ma_snd_pcm_sw_params_set_start_threshold_proc)pContext->alsa.snd_pcm_sw_params_set_start_threshold)(pPCM, pSWParams, internalBufferSizeInFrames) != 0) { + if (((ma_snd_pcm_sw_params_set_start_threshold_proc)pContext->alsa.snd_pcm_sw_params_set_start_threshold)(pPCM, pSWParams, (internalBufferSizeInFrames/internalPeriods)*2) != 0) { ma_free(pSWParams); ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM); return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to set start threshold for playback device. snd_pcm_sw_params_set_start_threshold() failed.", MA_FAILED_TO_CONFIGURE_BACKEND_DEVICE); diff --git a/tests/ma_duplex.c b/tests/ma_duplex.c index ae559e3e..deadb157 100644 --- a/tests/ma_duplex.c +++ b/tests/ma_duplex.c @@ -7,7 +7,7 @@ #define DR_WAV_IMPLEMENTATION #include "../extras/dr_wav.h" -#define OUTPUT_WAV 1 +#define OUTPUT_WAV 0 #ifdef __EMSCRIPTEN__ void main_loop__em() @@ -63,11 +63,12 @@ int main(int argc, char** argv) #endif - ma_backend backend = ma_backend_winmm; + ma_backend backend = ma_backend_alsa; ma_context_config contextConfig = ma_context_config_init(); contextConfig.logCallback = log_callback; contextConfig.alsa.useVerboseDeviceEnumeration = MA_TRUE; + contextConfig.threadPriority = ma_thread_priority_realtime; ma_context context; result = ma_context_init(&backend, 1, &contextConfig, &context); @@ -107,13 +108,15 @@ int main(int argc, char** argv) deviceConfig.playback.format = ma_format_s16; deviceConfig.playback.channels = 2; deviceConfig.playback.shareMode = ma_share_mode_shared; - deviceConfig.sampleRate = 50000; + deviceConfig.sampleRate = 0; //deviceConfig.bufferSizeInMilliseconds = 60; deviceConfig.bufferSizeInFrames = 4096; //deviceConfig.periods = 3; deviceConfig.dataCallback = data_callback; deviceConfig.stopCallback = stop_callback; +#if defined(OUTPUT_WAV) && OUTPUT_WAV==1 deviceConfig.pUserData = &wav; +#endif ma_device device; result = ma_device_init(&context, &deviceConfig, &device); @@ -135,7 +138,10 @@ int main(int argc, char** argv) #endif ma_device_uninit(&device); + +#if defined(OUTPUT_WAV) && OUTPUT_WAV==1 drwav_uninit(&wav); +#endif (void)argc; (void)argv;