From e094e9cb75f9802d8da07eb75cee4d91c9786558 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 10 Nov 2014 20:16:25 +0100 Subject: audio: change how filters are inserted on playback speed changes Use a pseudo-filter when changing speed with resampling, instead of somehow changing a samplerate somewhere. This uses the same underlying mechanism, but is a bit more structured and cleaner. It also makes some of the following changes easier. Since we now always use filters to change audio speed, move most of the work set_playback_speed() does to recreate_audio_filters(). --- player/audio.c | 90 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 48 insertions(+), 42 deletions(-) (limited to 'player/audio.c') diff --git a/player/audio.c b/player/audio.c index fb3f571cdf..413cbf4a32 100644 --- a/player/audio.c +++ b/player/audio.c @@ -43,25 +43,61 @@ #include "core.h" #include "command.h" +static int try_filter(struct MPContext *mpctx, + char *name, char *label, char **args) +{ + struct dec_audio *d_audio = mpctx->d_audio; + + if (af_find_by_label(d_audio->afilter, label)) + return 0; + + struct af_instance *af = af_add(d_audio->afilter, name, args); + if (!af) + return -1; + + af->label = talloc_strdup(af, label); + + return 1; +} + static int recreate_audio_filters(struct MPContext *mpctx) { assert(mpctx->d_audio); - struct af_stream *afs = mpctx->d_audio->afilter; struct MPOpts *opts = mpctx->opts; + struct af_stream *afs = mpctx->d_audio->afilter; - struct mp_audio in_format; - mp_audio_buffer_get_format(mpctx->d_audio->decode_buffer, &in_format); - int new_srate = in_format.rate; - - if (!af_control_any_rev(afs, AF_CONTROL_SET_PLAYBACK_SPEED, - &opts->playback_speed)) - { - new_srate = in_format.rate * opts->playback_speed; - if (new_srate != afs->output.rate) - opts->playback_speed = new_srate / (double)in_format.rate; + double speed = opts->playback_speed; + + if (speed != 1.0) { + int method = AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE; + if (speed > 1.0 && opts->pitch_correction) + method = AF_CONTROL_SET_PLAYBACK_SPEED; + if (!af_control_any_rev(afs, method, &speed)) { + if (af_remove_by_label(afs, "playback-speed") < 0) + return -1; + + // Compatibility: if the user uses --af=scaletempo, always use + // this filter to change speed. Don't insert a second "scaletempo" + // filter either. + if (!af_control_any_rev(afs, AF_CONTROL_SET_PLAYBACK_SPEED, &speed)) + { + char *filter = method == AF_CONTROL_SET_PLAYBACK_SPEED + ? "scaletempo" : "forcespeed"; + if (try_filter(mpctx, filter, "playback-speed", NULL) < 0) + return -1; + // Try again. + if (!af_control_any_rev(afs, method, &speed)) + return -1; + } + } + } else { + if (af_remove_by_label(afs, "playback-speed") < 0) + return -1; + // The filters could be inserted by the user (we don't remove them). + af_control_any_rev(afs, AF_CONTROL_SET_PLAYBACK_SPEED, &speed); + af_control_any_rev(afs, AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE, &speed); } - afs->input.rate = new_srate; if (af_init(afs) < 0) { MP_ERR(mpctx, "Couldn't find matching filter/ao format!\n"); @@ -88,23 +124,6 @@ int reinit_audio_filters(struct MPContext *mpctx) return 1; } -static int try_filter(struct MPContext *mpctx, - char *name, char *label, char **args) -{ - struct dec_audio *d_audio = mpctx->d_audio; - - if (af_find_by_label(d_audio->afilter, label)) - return 0; - - struct af_instance *af = af_add(d_audio->afilter, name, args); - if (!af) - return -1; - - af->label = talloc_strdup(af, label); - - return 1; -} - void set_playback_speed(struct MPContext *mpctx, double new_speed) { struct MPOpts *opts = mpctx->opts; @@ -117,19 +136,6 @@ void set_playback_speed(struct MPContext *mpctx, double new_speed) if (!mpctx->d_audio) return; - if (new_speed > 1.0 && opts->pitch_correction) { - if (!af_control_any_rev(mpctx->d_audio->afilter, - AF_CONTROL_SET_PLAYBACK_SPEED, - &new_speed)) - { - if (try_filter(mpctx, "scaletempo", "playback-speed", NULL) < 0) - return; - } - } else { - if (af_remove_by_label(mpctx->d_audio->afilter, "playback-speed") < 0) - return; - } - recreate_audio_filters(mpctx); } -- cgit v1.2.3