sink-input: Implement resampler pseudo rewinding

This patch uses the two previous patches to implemnt pseudo-rewinding for the
resamplers by feeding some old data into the resampler after a reset. This is
necessary because PA is using external resamplers that do not implement
rewinding.

To get exactly the same output data from the resampler after a rewind if possible,
the matching period is calculated. This is the number of input samples that produces
an integral number of output samples. After the matching period, the resampler state
repeats. If the matching period is not too large, feeding history into the resampler
will start at a point that is a multiple of the matching period back in time. Then
the resampler will produce exactly the same samples.

The PA_RESAMPLER_MAX_HISTORY value has been replaced by PA_RESAMPLER_MAX_DELAY_USEC
and the required number of history samples is calculated from the sink input sample
rate. The number of history samples can be as large as about 12500.

This fixes glitches during volume changes when the sink runs on a rate different
from the sink input rate.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/120>
This commit is contained in:
Georg Chini 2021-01-01 00:23:10 +01:00 committed by PulseAudio Marge Bot
parent 656179a8fe
commit da539ed336
3 changed files with 159 additions and 19 deletions

View file

@ -73,7 +73,11 @@ typedef enum pa_resample_flags {
PA_RESAMPLER_CONSUME_LFE = 0x0040U,
} pa_resample_flags_t;
#define PA_RESAMPLER_MAX_HISTORY 64
/* Currently, the soxr reampler has the largest delay of all supported resamplers.
* The maximum value below has been obtained empirically and contains a safety
* margin of about 3ms. If the resampler configuration is changed or additional
* resamplers are added, the constant must be re-evaluated. */
#define PA_RESAMPLER_MAX_DELAY_USEC 33000
struct pa_resampler {
pa_resample_method_t method;
@ -113,6 +117,7 @@ struct pa_resampler {
double in_frames;
double out_frames;
unsigned gcd;
pa_lfe_filter_t *lfe_filter;
@ -176,6 +181,12 @@ double pa_resampler_get_delay(pa_resampler *r, bool allow_negative);
/* Get delay of the resampler in usec */
pa_usec_t pa_resampler_get_delay_usec(pa_resampler *r);
/* Get the GCD of input and outpu rate */
unsigned pa_resampler_get_gcd(pa_resampler *r);
/* Get maximum number of history frames */
size_t pa_resampler_get_max_history(pa_resampler *r);
const pa_channel_map* pa_resampler_input_channel_map(pa_resampler *r);
const pa_sample_spec* pa_resampler_input_sample_spec(pa_resampler *r);
const pa_channel_map* pa_resampler_output_channel_map(pa_resampler *r);