summaryrefslogtreecommitdiffstats
path: root/audio/filter
diff options
context:
space:
mode:
Diffstat (limited to 'audio/filter')
-rw-r--r--audio/filter/af_rubberband.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/audio/filter/af_rubberband.c b/audio/filter/af_rubberband.c
index 27e26c1039..4863c2282d 100644
--- a/audio/filter/af_rubberband.c
+++ b/audio/filter/af_rubberband.c
@@ -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;
}