summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/options.rst8
-rw-r--r--options/options.c3
-rw-r--r--options/options.h1
-rw-r--r--player/audio.c39
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: