diff options
-rw-r--r-- | DOCS/man/options.rst | 8 | ||||
-rw-r--r-- | options/options.c | 3 | ||||
-rw-r--r-- | options/options.h | 1 | ||||
-rw-r--r-- | player/audio.c | 39 |
4 files changed, 49 insertions, 2 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index e8e41331d6..45f0d7358a 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -95,6 +95,9 @@ Playback Control ``--speed=<0.01-100>`` Slow down or speed up playback by the factor given as parameter. + If ``--audio-pitch-correction`` is used, playing with a speed higher than + normal automatically inserts the ``scaletempo`` audio filter. + ``--loop=<N|inf|no>`` Loops playback ``N`` times. A value of ``1`` plays it one time (default), ``2`` two times, etc. ``inf`` means forever. ``no`` is the same as ``1`` and @@ -755,6 +758,11 @@ Video Audio ----- +``--audio-pitch-correction=<yes|no`` + If this is enabled, playing with a speed higher than normal automatically + inserts the ``scaletempo`` audio filter. For details, see audio filter + section. + ``--ao=<driver1[:suboption1[=value]:...],driver2,...[,]>`` Specify a priority list of audio output drivers to be used. For interactive use one would normally specify a single one to use, but in diff --git a/options/options.c b/options/options.c index e76a20d2c8..bc016dfd14 100644 --- a/options/options.c +++ b/options/options.c @@ -249,6 +249,8 @@ const m_option_t mp_opts[] = { OPT_DOUBLE("speed", playback_speed, M_OPT_RANGE | M_OPT_FIXED, .min = 0.01, .max = 100.0), + OPT_FLAG("audio-pitch-correction", pitch_correction, 0), + // set a-v distance OPT_FLOATRANGE("audio-delay", audio_delay, 0, -100.0, 100.0), @@ -639,6 +641,7 @@ const struct MPOpts mp_default_opts = { .audio_output_channels = MP_CHMAP_INIT_STEREO, .audio_output_format = 0, // AF_FORMAT_UNKNOWN .playback_speed = 1., + .pitch_correction = 1, .movie_aspect = -1., .field_dominance = -1, .sub_auto = 0, diff --git a/options/options.h b/options/options.h index eda99a88cb..580a0cc780 100644 --- a/options/options.h +++ b/options/options.h @@ -205,6 +205,7 @@ typedef struct MPOpts { int force_srate; int dtshd; double playback_speed; + int pitch_correction; struct m_obj_settings *vf_settings, *vf_defs; struct m_obj_settings *af_settings, *af_defs; int deinterlace; diff --git a/player/audio.c b/player/audio.c index f532f1167b..969b0ca816 100644 --- a/player/audio.c +++ b/player/audio.c @@ -88,6 +88,23 @@ 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; @@ -97,8 +114,23 @@ void set_playback_speed(struct MPContext *mpctx, double new_speed) opts->playback_speed = new_speed; - if (mpctx->d_audio) - recreate_audio_filters(mpctx); + 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); } void reset_audio_state(struct MPContext *mpctx) @@ -155,6 +187,7 @@ void reinit_audio_chain(struct MPContext *mpctx) return; } + // Weak gapless audio: drain AO on decoder format changes if (mpctx->ao_decoder_fmt && (mpctx->initialized_flags & INITIALIZED_AO) && !mp_audio_config_equals(mpctx->ao_decoder_fmt, &in_format) && opts->gapless_audio < 0) @@ -222,6 +255,8 @@ void reinit_audio_chain(struct MPContext *mpctx) if (recreate_audio_filters(mpctx) < 0) goto init_error; + set_playback_speed(mpctx, opts->playback_speed); + return; init_error: |