mirror of
https://github.com/mpv-player/mpv
synced 2025-01-11 17:39:38 +00:00
af_lavrresample: fix unintended audio drift when setting playback speed
Small adjustments to the playback speed use swr_set_compensation() to stretch the audio as it is required. But since large adjustments are now handled by actually reinitializing libswresample, the small adjustments get rounded off completely with typical frame sizes. Compensate for this by accounting for the rounding error and keeping track of fractional samples that should have been output to achieve the correct ratio. This fixes display sync mode behavior, which requires these adjustments to be relatively accurate.
This commit is contained in:
parent
da496ae2fe
commit
e0f8d79772
@ -91,6 +91,8 @@ struct af_resample {
|
||||
int out_rate;
|
||||
int out_format;
|
||||
struct mp_chmap out_channels;
|
||||
|
||||
double missing_samples; // fractional samples not yet output
|
||||
};
|
||||
|
||||
#if HAVE_LIBAVRESAMPLE
|
||||
@ -224,6 +226,8 @@ static int configure_lavrr(struct af_instance *af, struct mp_audio *in,
|
||||
s->out_channels= out->channels;
|
||||
s->in_channels = in->channels;
|
||||
|
||||
s->missing_samples = 0;
|
||||
|
||||
av_opt_set_int(s->avrctx, "filter_size", s->opts.filter_size, 0);
|
||||
av_opt_set_int(s->avrctx, "phase_shift", s->opts.phase_shift, 0);
|
||||
av_opt_set_int(s->avrctx, "linear_interp", s->opts.linear, 0);
|
||||
@ -519,10 +523,12 @@ static int filter(struct af_instance *af, struct mp_audio *in)
|
||||
if (!need_reinit && s->avrctx) {
|
||||
double speed_factor = s->playback_speed * s->in_rate_af / s->in_rate;
|
||||
int in_samples = in ? in->samples : 0;
|
||||
int wanted_samples = lrint(in_samples / speed_factor);
|
||||
double wanted_samples = in_samples / speed_factor + s->missing_samples;
|
||||
int wanted_samples_i = lrint(wanted_samples);
|
||||
s->missing_samples = wanted_samples - wanted_samples_i;
|
||||
if (avresample_set_compensation(s->avrctx,
|
||||
(wanted_samples - in_samples) * s->out_rate / s->in_rate,
|
||||
wanted_samples * s->out_rate / s->in_rate) < 0)
|
||||
(wanted_samples_i - in_samples) * s->out_rate / s->in_rate,
|
||||
wanted_samples_i * s->out_rate / s->in_rate) < 0)
|
||||
need_reinit = true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user