summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Pape <apape@de.adit-jv.com>2022-03-22 12:45:37 +0100
committerJaroslav Kysela <perex@perex.cz>2022-05-20 10:35:45 +0200
commitd21e0e01c66c627c38496027ba6757ea13e65999 (patch)
tree90977a5e4dc41d009f4a9e7cc9aaabe921d0a8ea
parentea15c8352518cdfb53d56932218f0d31b7980b87 (diff)
downloadalsa-lib-d21e0e01c66c627c38496027ba6757ea13e65999.tar.gz
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 <apape@de.adit-jv.com> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r--src/pcm/pcm_local.h4
-rw-r--r--src/pcm/pcm_plugin.c8
-rw-r--r--src/pcm/pcm_rate.c19
3 files changed, 31 insertions, 0 deletions
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)