af_lavrresample: reinit resampler on large speed changes

swr/avresample_set_compensation() was made for small speed adjustments.
Non-documentation says it should be used for changes not larger than 1%,
so reinitialize the sampler if the change is larger than that.
This commit is contained in:
wm4 2015-10-12 21:12:05 +02:00
parent bddd1e9e3b
commit 3804376ccc
1 changed files with 18 additions and 14 deletions

View File

@ -513,22 +513,26 @@ static int filter(struct af_instance *af, struct mp_audio *in)
{ {
struct af_resample *s = af->priv; struct af_resample *s = af->priv;
int in_samples = in ? in->samples : 0; int new_rate = rate_from_speed(s->in_rate_af, s->playback_speed);
int wanted_samples = lrint(in_samples / s->playback_speed); bool need_reinit = fabs(new_rate / (double)s->in_rate - 1) > 0.01;
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);
if (avresample_set_compensation(s->avrctx, if (avresample_set_compensation(s->avrctx,
(wanted_samples - in_samples) * s->out_rate / s->in_rate, (wanted_samples - in_samples) * s->out_rate / s->in_rate,
wanted_samples * s->out_rate / s->in_rate) < 0) wanted_samples * s->out_rate / s->in_rate) < 0)
{ need_reinit = true;
int new_rate = rate_from_speed(s->in_rate_af, s->playback_speed); }
if (new_rate != s->in_rate && s->avrctx && af->fmt_out.format) {
if (need_reinit && new_rate != s->in_rate) {
// Before reconfiguring, drain the audio that is still buffered // Before reconfiguring, drain the audio that is still buffered
// in the resampler. // in the resampler.
filter_resample(af, NULL); filter_resample(af, NULL);
// Reinitialize resampler. // Reinitialize resampler.
configure_lavrr(af, &af->fmt_in, &af->fmt_out, false); configure_lavrr(af, &af->fmt_in, &af->fmt_out, false);
} }
}
return filter_resample(af, in); return filter_resample(af, in);
} }