diff options
author | wm4 <wm4@nowhere> | 2014-11-10 20:16:25 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2014-11-10 22:02:05 +0100 |
commit | e094e9cb75f9802d8da07eb75cee4d91c9786558 (patch) | |
tree | 84f6ba161fdcb0515c840ca7dd8db60be681dc65 /player/audio.c | |
parent | 995a6af78734820007eb8a1ae3b543fd9d9636e1 (diff) | |
download | mpv-e094e9cb75f9802d8da07eb75cee4d91c9786558.tar.bz2 mpv-e094e9cb75f9802d8da07eb75cee4d91c9786558.tar.xz |
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().
Diffstat (limited to 'player/audio.c')
-rw-r--r-- | player/audio.c | 90 |
1 files changed, 48 insertions, 42 deletions
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); } |