]> git.alsa-project.org Git - alsa-lib.git/commitdiff
pcm: plugin - fix avail_min calculation on rate plugin
authorAndreas Pape <apape@de.adit-jv.com>
Tue, 22 Mar 2022 11:45:37 +0000 (12:45 +0100)
committerJaroslav Kysela <perex@perex.cz>
Fri, 20 May 2022 08:35:45 +0000 (10:35 +0200)
commit 88e4ae27ff1f669d 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>
src/pcm/pcm_local.h
src/pcm/pcm_plugin.c
src/pcm/pcm_rate.c

index 8d25971f6e094e4021aada1fc53e9482cd9097c4..d5393bc9a755487122c5123d9ac3119c25d632fb 100644 (file)
@@ -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)
index 24c9941dcbb8452d1b8e54ee84c135a8eff63a98..7f934e8a0b8f1ee0dccfef210244975150b4b557 100644 (file)
@@ -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);
index ba5364c0c03aaaa26f9d110463a88314a1a99515..9ba36eedee5d91fe823e9d743a0c9e964b78adcd 100644 (file)
@@ -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)