mirror of
https://github.com/mpv-player/mpv.git
synced 2025-12-28 05:33:14 +00:00
af_rubberband: add af-command and option to change the pitch
This allows both fixed and dynamic control over the audio pitch using librubberband, which was previously not exposed to the user.
This commit is contained in:
@@ -413,9 +413,13 @@ Available filters are:
|
|||||||
``rubberband``
|
``rubberband``
|
||||||
High quality pitch correction with librubberband. This can be used in place
|
High quality pitch correction with librubberband. This can be used in place
|
||||||
of ``scaletempo``, and will be used to adjust audio pitch when playing
|
of ``scaletempo``, and will be used to adjust audio pitch when playing
|
||||||
at speed different from normal.
|
at speed different from normal. It can also be used to adjust audio pitch
|
||||||
|
without changing playback speed.
|
||||||
|
|
||||||
This filter has a number of sub-options. You can list them with
|
``<pitch-scale>``
|
||||||
|
Sets the pitch scaling factor. Frequencies are multiplied by this value.
|
||||||
|
|
||||||
|
This filter has a number of additional sub-options. You can list them with
|
||||||
``mpv --af=rubberband=help``. This will also show the default values
|
``mpv --af=rubberband=help``. This will also show the default values
|
||||||
for each option. The options are not documented here, because they are
|
for each option. The options are not documented here, because they are
|
||||||
merely passed to librubberband. Look at the librubberband documentation
|
merely passed to librubberband. Look at the librubberband documentation
|
||||||
@@ -424,6 +428,13 @@ Available filters are:
|
|||||||
(The mapping of the mpv rubberband filter sub-option names and values to
|
(The mapping of the mpv rubberband filter sub-option names and values to
|
||||||
those of librubberband follows a simple pattern: ``"Option" + Name + Value``.)
|
those of librubberband follows a simple pattern: ``"Option" + Name + Value``.)
|
||||||
|
|
||||||
|
This filter supports the following ``af-command`` commands:
|
||||||
|
|
||||||
|
``set-pitch``
|
||||||
|
Set the ``<pitch-scale>`` argument dynamically. This can be used to
|
||||||
|
change the playback pitch at runtime. Note that speed is controlled
|
||||||
|
using the standard ``speed`` property, not ``af-command``.
|
||||||
|
|
||||||
``lavfi=graph``
|
``lavfi=graph``
|
||||||
Filter audio using FFmpeg's libavfilter.
|
Filter audio using FFmpeg's libavfilter.
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
struct priv {
|
struct priv {
|
||||||
RubberBandState rubber;
|
RubberBandState rubber;
|
||||||
double speed;
|
double speed;
|
||||||
|
double pitch;
|
||||||
struct mp_audio *pending;
|
struct mp_audio *pending;
|
||||||
bool needs_reset;
|
bool needs_reset;
|
||||||
// Estimate how much librubberband has buffered internally.
|
// Estimate how much librubberband has buffered internally.
|
||||||
@@ -44,6 +45,14 @@ static void update_speed(struct af_instance *af, double new_speed)
|
|||||||
rubberband_set_time_ratio(p->rubber, 1.0 / p->speed);
|
rubberband_set_time_ratio(p->rubber, 1.0 / p->speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void update_pitch(struct af_instance *af, double new_pitch)
|
||||||
|
{
|
||||||
|
struct priv *p = af->priv;
|
||||||
|
|
||||||
|
p->pitch = new_pitch;
|
||||||
|
rubberband_set_pitch_scale(p->rubber, p->pitch);
|
||||||
|
}
|
||||||
|
|
||||||
static int control(struct af_instance *af, int cmd, void *arg)
|
static int control(struct af_instance *af, int cmd, void *arg)
|
||||||
{
|
{
|
||||||
struct priv *p = af->priv;
|
struct priv *p = af->priv;
|
||||||
@@ -72,6 +81,7 @@ static int control(struct af_instance *af, int cmd, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
update_speed(af, p->speed);
|
update_speed(af, p->speed);
|
||||||
|
update_pitch(af, p->pitch);
|
||||||
control(af, AF_CONTROL_RESET, NULL);
|
control(af, AF_CONTROL_RESET, NULL);
|
||||||
|
|
||||||
return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE;
|
return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE;
|
||||||
@@ -87,6 +97,19 @@ static int control(struct af_instance *af, int cmd, void *arg)
|
|||||||
p->pending = NULL;
|
p->pending = NULL;
|
||||||
p->rubber_delay = 0;
|
p->rubber_delay = 0;
|
||||||
return AF_OK;
|
return AF_OK;
|
||||||
|
case AF_CONTROL_COMMAND: {
|
||||||
|
char **args = arg;
|
||||||
|
if (!strcmp(args[0], "set-pitch")) {
|
||||||
|
char *endptr;
|
||||||
|
double pitch = strtod(args[1], &endptr);
|
||||||
|
if (*endptr || pitch < 0.01 || pitch > 100.0)
|
||||||
|
return CONTROL_ERROR;
|
||||||
|
update_pitch(af, pitch);
|
||||||
|
return CONTROL_OK;
|
||||||
|
} else {
|
||||||
|
return CONTROL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return AF_UNKNOWN;
|
return AF_UNKNOWN;
|
||||||
}
|
}
|
||||||
@@ -187,6 +210,7 @@ const struct af_info af_info_rubberband = {
|
|||||||
.priv_size = sizeof(struct priv),
|
.priv_size = sizeof(struct priv),
|
||||||
.priv_defaults = &(const struct priv) {
|
.priv_defaults = &(const struct priv) {
|
||||||
.speed = 1.0,
|
.speed = 1.0,
|
||||||
|
.pitch = 1.0,
|
||||||
.opt_pitch = RubberBandOptionPitchHighConsistency,
|
.opt_pitch = RubberBandOptionPitchHighConsistency,
|
||||||
.opt_transients = RubberBandOptionTransientsMixed,
|
.opt_transients = RubberBandOptionTransientsMixed,
|
||||||
.opt_formant = RubberBandOptionFormantPreserved,
|
.opt_formant = RubberBandOptionFormantPreserved,
|
||||||
@@ -220,6 +244,7 @@ const struct af_info af_info_rubberband = {
|
|||||||
OPT_CHOICE("channels", opt_channels, 0,
|
OPT_CHOICE("channels", opt_channels, 0,
|
||||||
({"apart", RubberBandOptionChannelsApart},
|
({"apart", RubberBandOptionChannelsApart},
|
||||||
{"together", RubberBandOptionChannelsTogether})),
|
{"together", RubberBandOptionChannelsTogether})),
|
||||||
|
OPT_DOUBLE("pitch-scale", pitch, M_OPT_RANGE, .min = 0.01, .max = 100),
|
||||||
{0}
|
{0}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user