From: Andreas Pape Date: Tue, 22 Mar 2022 11:45:37 +0000 (+0100) Subject: pcm: plugin - fix avail_min calculation on rate plugin X-Git-Tag: v1.2.7~9 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=d21e0e01c66c627c38496027ba6757ea13e65999;p=alsa-lib.git pcm: plugin - fix avail_min calculation on rate plugin commit 88e4ae27, ff1f669d introduced a dynamic recalculation of the slave's avail_min value. The calculated avail_min setting did not take into account, that the avail_min value depends on the used sampling rate and must be adapted accordingly if the slave is using a different sampling rate. That leads to too large/too small calculated avail_min settings and inaccurate period wake-up events if a rate converter plugin is used. This patch is adapting the avail_min calculation to consider a different sampling rate between actual pcm and it's slave. Fixes: https://github.com/alsa-project/alsa-lib/pull/218 Signed-off-by: Andreas Pape Signed-off-by: Jaroslav Kysela --- diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index 8d25971f..d5393bc9 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -286,6 +286,8 @@ struct _snd_pcm { snd1_pcm_wait_nocheck #define snd_pcm_rate_get_default_converter \ snd1_pcm_rate_get_default_converter +#define snd_pcm_rate_slave_frames \ + snd1_pcm_rate_slave_frames #define snd_pcm_set_hw_ptr \ snd1_pcm_set_hw_ptr #define snd_pcm_set_appl_ptr \ @@ -1009,6 +1011,8 @@ int snd_pcm_wait_nocheck(snd_pcm_t *pcm, int timeout); const snd_config_t *snd_pcm_rate_get_default_converter(snd_config_t *root); +snd_pcm_uframes_t snd_pcm_rate_slave_frames(snd_pcm_t *pcm, snd_pcm_uframes_t frames); + #define SND_PCM_HW_PARBIT_ACCESS (1U << SND_PCM_HW_PARAM_ACCESS) #define SND_PCM_HW_PARBIT_FORMAT (1U << SND_PCM_HW_PARAM_FORMAT) #define SND_PCM_HW_PARBIT_SUBFORMAT (1U << SND_PCM_HW_PARAM_SUBFORMAT) diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c index 24c9941d..7f934e8a 100644 --- a/src/pcm/pcm_plugin.c +++ b/src/pcm/pcm_plugin.c @@ -614,6 +614,14 @@ int snd_pcm_plugin_may_wait_for_avail_min(snd_pcm_t *pcm, return 0; needed_slave_avail_min = pcm->avail_min - available; + + /* proportional adaption if rate converter is in place.. + * Can happen only on built-in rate plugin. + * This code is also used by extplug, but extplug does not allow to alter the sampling rate. + */ + if (snd_pcm_type(pcm) == SND_PCM_TYPE_RATE) + needed_slave_avail_min = snd_pcm_rate_slave_frames(pcm, needed_slave_avail_min); + if (slave->avail_min != needed_slave_avail_min) { snd_pcm_sw_params_t *swparams; snd_pcm_sw_params_alloca(&swparams); diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index ba5364c0..9ba36eed 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -1343,6 +1343,25 @@ const snd_config_t *snd_pcm_rate_get_default_converter(snd_config_t *root) return NULL; } +/** + * \brief Convert rate pcm frames to corresponding rate slave pcm frames + * \param pcm PCM handle + * \param frames Frames to be converted to slave frames + * \retval Corresponding slave frames +*/ +snd_pcm_uframes_t snd_pcm_rate_slave_frames(snd_pcm_t *pcm, snd_pcm_uframes_t frames) +{ + snd_pcm_uframes_t sframes; + snd_pcm_rate_t *rate = pcm->private_data; + + if (pcm->stream == SND_PCM_STREAM_PLAYBACK) + sframes = rate->ops.output_frames(rate->obj, frames); + else + sframes = rate->ops.input_frames(rate->obj, frames); + + return sframes; +} + static void rate_initial_setup(snd_pcm_rate_t *rate) { if (rate->plugin_version == SND_PCM_RATE_PLUGIN_VERSION)