From 6650b11a9f73660f7028b0748cb9bb01d0cf0ffc Mon Sep 17 00:00:00 2001 From: llyyr Date: Mon, 25 Sep 2023 17:35:56 +0530 Subject: [PATCH] audio: allow specifying pitch correction filter Currently, the `audio-pitch-correction` flag is a bool which automatically inserts "scaletempo2" when needed. This hard default doesn't allow any nice way to insert the "rubberband" filter instead. This commit plumbs a way to get the filter name to auto_filters, and changes `audio-pitch-correction` to accept . "yes" is kept to not break configs suddenly, and is aliased to scaletempo2. --- DOCS/man/options.rst | 18 ++++++++++++++---- filters/f_auto_filters.c | 10 ++++++++-- filters/f_output_chain.c | 17 ++++++++++++++++- filters/f_output_chain.h | 4 ++-- options/options.c | 6 ++++-- options/options.h | 2 +- player/audio.c | 8 +++++++- 7 files changed, 52 insertions(+), 13 deletions(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 9c9371d4a61e0..7fd19a66766f7 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -1846,10 +1846,20 @@ Video Audio ----- -``--audio-pitch-correction=`` - If this is enabled (default), playing with a speed different from normal - automatically inserts the ``scaletempo2`` audio filter. For details, see - audio filter section. +``--audio-pitch-correction=|yes>`` + If this is set to "yes" (default), playing with a speed different from + normal automatically inserts the ``scaletempo2`` audio filter. Aditionally, + a ```` can be one of the following: + + :scaletempo: The original pitch correction filter used in mpv, similar to + and generally worse than scaletempo2 in every use case. + :scaletempo2: This algorithm is ported from chromium. Also aliased to "yes" + (Default) + :rubberband: High quality pitch correction with librubberband. Uses more + CPU cycles than the others, but often achieves higher quality + with its R3 engine. + + For details, see audio filter section. ``--audio-device=`` Use the given audio device. This consists of the audio output name, e.g. diff --git a/filters/f_auto_filters.c b/filters/f_auto_filters.c index c8b31f60fb459..385ea1bca9268 100644 --- a/filters/f_auto_filters.c +++ b/filters/f_auto_filters.c @@ -310,6 +310,7 @@ struct aspeed_priv { struct mp_subfilter sub; double cur_speed, cur_speed_drop; int current_filter; + const char *name; }; static void aspeed_process(struct mp_filter *f) @@ -340,9 +341,9 @@ static void aspeed_process(struct mp_filter *f) if (req_filter) { if (req_filter == 1) { - MP_VERBOSE(f, "adding scaletempo2\n"); + MP_VERBOSE(f, "adding %s\n", p->name); p->sub.filter = mp_create_user_filter(f, MP_OUTPUT_CHAIN_AUDIO, - "scaletempo2", NULL); + p->name, NULL); } else if (req_filter == 2) { MP_VERBOSE(f, "adding drop\n"); p->sub.filter = mp_create_user_filter(f, MP_OUTPUT_CHAIN_AUDIO, @@ -372,6 +373,11 @@ static bool aspeed_command(struct mp_filter *f, struct mp_filter_command *cmd) { struct aspeed_priv *p = f->priv; + if (cmd->type == MP_FILTER_COMMAND_TEXT) { + p->name = cmd->cmd; + return true; + } + if (cmd->type == MP_FILTER_COMMAND_SET_SPEED) { p->cur_speed = cmd->speed; return true; diff --git a/filters/f_output_chain.c b/filters/f_output_chain.c index 2d4dcba4177f6..c984520aa1b5b 100644 --- a/filters/f_output_chain.c +++ b/filters/f_output_chain.c @@ -478,8 +478,21 @@ static void set_speed_any(struct mp_user_filter **filters, int num_filters, } } +static void set_speed_params_any(struct mp_user_filter **filters, int num_filters, + int command, const char *name) +{ + for (int n = num_filters - 1; n >= 0; n--) { + struct mp_filter_command cmd = { + .type = command, + .cmd = name, + }; + mp_filter_command(filters[n]->f, &cmd); + } +} + void mp_output_chain_set_audio_speed(struct mp_output_chain *c, - double speed, double resample, double drop) + double speed, double resample, double drop, + const char *name) { struct chain *p = c->f->priv; @@ -491,6 +504,8 @@ void mp_output_chain_set_audio_speed(struct mp_output_chain *c, // otherwise use the builtin ones. set_speed_any(p->user_filters, p->num_user_filters, MP_FILTER_COMMAND_SET_SPEED, &speed); + set_speed_params_any(p->post_filters, p->num_post_filters, + MP_FILTER_COMMAND_TEXT, name); set_speed_any(p->post_filters, p->num_post_filters, MP_FILTER_COMMAND_SET_SPEED, &speed); set_speed_any(p->user_filters, p->num_user_filters, diff --git a/filters/f_output_chain.h b/filters/f_output_chain.h index f06769cdd9b55..fb3c1a79efc2c 100644 --- a/filters/f_output_chain.h +++ b/filters/f_output_chain.h @@ -77,8 +77,8 @@ bool mp_output_chain_update_filters(struct mp_output_chain *p, // Desired audio speed, with resample being strict resampling. void mp_output_chain_set_audio_speed(struct mp_output_chain *p, - double speed, double resample, double drop); - + double speed, double resample, double drop, + const char *name); // Total delay incurred by the filter chain, as measured by the recent filtered // frames. The intention is that this sums the measured delays for each filter, // so if a filter is removed, the caller can estimate how much audio is missing diff --git a/options/options.c b/options/options.c index 507b4b6067e5a..f80642b93ef42 100644 --- a/options/options.c +++ b/options/options.c @@ -595,7 +595,9 @@ static const m_option_t mp_opts[] = { {"audio-format", OPT_AUDIOFORMAT(audio_output_format), .flags = UPDATE_AUDIO}, {"speed", OPT_DOUBLE(playback_speed), M_RANGE(0.01, 100.0)}, - {"audio-pitch-correction", OPT_BOOL(pitch_correction)}, + {"audio-pitch-correction", OPT_CHOICE(pitch_correction, + {"no", 0}, {"yes", 1}, + {"scaletempo2", 1}, {"rubberband", 2}, {"scaletempo", 3})}, // set a-v distance {"audio-delay", OPT_FLOAT(audio_delay)}, @@ -948,7 +950,7 @@ static const struct MPOpts mp_default_opts = { .audio_display = 1, .audio_output_format = 0, // AF_FORMAT_UNKNOWN .playback_speed = 1., - .pitch_correction = true, + .pitch_correction = 1, .audiofile_auto = -1, .coverart_whitelist = true, .osd_bar_visible = true, diff --git a/options/options.h b/options/options.h index 58c15b9f74752..c9ffcb07650c2 100644 --- a/options/options.h +++ b/options/options.h @@ -299,7 +299,7 @@ typedef struct MPOpts { int audio_output_format; int force_srate; double playback_speed; - bool pitch_correction; + int pitch_correction; struct m_obj_settings *vf_settings; struct m_obj_settings *af_settings; struct filter_opts *filter_opts; diff --git a/player/audio.c b/player/audio.c index 4ea2d09f94547..8939575c3b975 100644 --- a/player/audio.c +++ b/player/audio.c @@ -57,6 +57,12 @@ static void update_speed_filters(struct MPContext *mpctx) double speed = mpctx->opts->playback_speed; double resample = mpctx->speed_factor_a; double drop = 1.0; + char *pitch_correction_filters[] = {NULL, + "scaletempo2", + "rubberband", + "scaletempo", + }; + char *name = pitch_correction_filters[mpctx->opts->pitch_correction]; if (!mpctx->opts->pitch_correction) { resample *= speed; @@ -76,7 +82,7 @@ static void update_speed_filters(struct MPContext *mpctx) } } - mp_output_chain_set_audio_speed(ao_c->filter, speed, resample, drop); + mp_output_chain_set_audio_speed(ao_c->filter, speed, resample, drop, name); } static int recreate_audio_filters(struct MPContext *mpctx)