From d5bc4ee79864404423ddf2786d8e8089fc46eeca Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 18 Nov 2013 14:18:37 +0100 Subject: audio: drop buffered filter data when seeking This could lead to (barely) audible artifacts with --af=scaletempo and modified playback speed. --- audio/filter/af.c | 7 +++++++ audio/filter/af.h | 2 ++ audio/filter/af_lavrresample.c | 11 +++++++++++ audio/filter/af_scaletempo.c | 5 +++++ 4 files changed, 25 insertions(+) (limited to 'audio') diff --git a/audio/filter/af.c b/audio/filter/af.c index 6f0241ec2b..2cc6389841 100644 --- a/audio/filter/af.c +++ b/audio/filter/af.c @@ -746,3 +746,10 @@ struct af_instance *af_control_any_rev(struct af_stream *s, int cmd, void *arg) } return NULL; } + +/* Send control to all filters. Never stop, even if a filter returns AF_OK. */ +void af_control_all(struct af_stream *s, int cmd, void *arg) +{ + for (struct af_instance *af = s->first; af; af = af->next) + af->control(af, cmd, arg); +} diff --git a/audio/filter/af.h b/audio/filter/af.h index 5c7450721e..7dee490665 100644 --- a/audio/filter/af.h +++ b/audio/filter/af.h @@ -99,6 +99,7 @@ struct af_stream { // Parameters for af_control_* enum af_control { AF_CONTROL_REINIT = 1, + AF_CONTROL_RESET, AF_CONTROL_COMMAND_LINE, AF_CONTROL_SET_RESAMPLE_RATE, AF_CONTROL_SET_FORMAT, @@ -125,6 +126,7 @@ void af_uninit(struct af_stream *s); struct af_instance *af_add(struct af_stream *s, char *name, char **args); struct mp_audio *af_play(struct af_stream *s, struct mp_audio *data); struct af_instance *af_control_any_rev(struct af_stream *s, int cmd, void *arg); +void af_control_all(struct af_stream *s, int cmd, void *arg); double af_calc_filter_multiplier(struct af_stream *s); double af_calc_delay(struct af_stream *s); diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c index f659511f82..95a5547ab5 100644 --- a/audio/filter/af_lavrresample.c +++ b/audio/filter/af_lavrresample.c @@ -93,11 +93,19 @@ static int get_delay(struct af_resample *s) { return avresample_get_delay(s->avrctx); } +static void drop_all_output(struct af_resample *s) +{ + while (avresample_read(s->avrctx, NULL, 1000) > 0) {} +} #else static int get_delay(struct af_resample *s) { return swr_get_delay(s->avrctx, s->ctx.in_rate); } +static void drop_all_output(struct af_resample *s) +{ + while (swr_drop_output(s->avrctx, 1000) > 0) {} +} #endif static double af_resample_default_cutoff(int filter_size) @@ -273,6 +281,9 @@ static int control(struct af_instance *af, int cmd, void *arg) case AF_CONTROL_SET_RESAMPLE_RATE: out->rate = *(int *)arg; return AF_OK; + case AF_CONTROL_RESET: + drop_all_output(s); + return AF_OK; } return AF_UNKNOWN; } diff --git a/audio/filter/af_scaletempo.c b/audio/filter/af_scaletempo.c index 9ec7b6b89b..f7e58f0923 100644 --- a/audio/filter/af_scaletempo.c +++ b/audio/filter/af_scaletempo.c @@ -428,6 +428,11 @@ static int control(struct af_instance *af, int cmd, void *arg) } return AF_OK; } + case AF_CONTROL_RESET: + s->bytes_queued = 0; + s->bytes_to_slide = 0; + s->frames_stride_error = 0; + memset(s->buf_overlap, 0, s->bytes_overlap); } return AF_UNKNOWN; } -- cgit v1.2.3