0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 12:02:23 +02:00

af_rubberband: attempt to fix audio position calculation

The problem here is that librubberband can buffer an arbitrary amount
of data, but at the same time doesn't provide a way to query how much
data is buffered. So we keep track of this manually, assuming that
librubberband tries to reach the requested time ratio for input and
output (which is probably true).

The disadvantage is that rounding errors could accumulate over time.
(Maybe it should try to round towards keeping the time ratio.)
This commit is contained in:
wm4 2015-02-11 15:46:12 +01:00
parent 76501f4f57
commit 6f24a61d84

View File

@ -28,6 +28,9 @@ struct priv {
double speed;
struct mp_audio *pending;
bool needs_reset;
// Estimate how much librubberband has buffered internally.
// I could not find a way to do this with the librubberband API.
double rubber_delay;
};
static void update_speed(struct af_instance *af, double new_speed)
@ -66,6 +69,7 @@ static int control(struct af_instance *af, int cmd, void *arg)
}
update_speed(af, p->speed);
control(af, AF_CONTROL_RESET, NULL);
return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE;
}
@ -78,6 +82,7 @@ static int control(struct af_instance *af, int cmd, void *arg)
rubberband_reset(p->rubber);
talloc_free(p->pending);
p->pending = NULL;
p->rubber_delay = 0;
return AF_OK;
}
return AF_UNKNOWN;
@ -106,8 +111,10 @@ static int filter_out(struct af_instance *af)
break;
// recover from previous EOF
if (p->needs_reset)
if (p->needs_reset) {
rubberband_reset(p->rubber);
p->rubber_delay = 0;
}
p->needs_reset = false;
size_t needs = rubberband_get_samples_required(p->rubber);
@ -120,6 +127,8 @@ static int filter_out(struct af_instance *af)
p->needs_reset = !p->pending; // EOF
rubberband_process(p->rubber, in_data, in_samples, p->needs_reset);
p->rubber_delay += in_samples;
if (!p->pending)
break;
mp_audio_skip_samples(p->pending, in_samples);
@ -133,14 +142,18 @@ static int filter_out(struct af_instance *af)
return -1;
if (p->pending)
mp_audio_copy_config(out, p->pending);
float **out_data = (void *)&out->planes;
out->samples = rubberband_retrieve(p->rubber, out_data, out->samples);
p->rubber_delay -= out->samples * p->speed;
af_add_output_frame(af, out);
}
int delay = rubberband_get_latency(p->rubber);
delay += p->pending ? p->pending->samples : 0;
af->delay = delay / (double)af->data->rate;
int delay_samples = p->rubber_delay;
if (p->pending)
delay_samples += p->pending->samples;
af->delay = delay_samples / (af->data->rate * p->speed);
return 0;
}