audio: add pitch-shifting feature

Uses resampling in tandem with a time-stretching audio filter to
change the audio's pitch while leaving its tempo intact.
This commit is contained in:
Mike Will 2024-03-27 06:14:57 -04:00 committed by Kacper Michajłow
parent 763bcd3e52
commit 88885c0401
6 changed files with 43 additions and 12 deletions

View File

@ -0,0 +1 @@
add `--pitch` option

View File

@ -237,6 +237,11 @@ Playback Control
speed higher than normal automatically inserts the ``scaletempo2`` audio
filter.
``--pitch=<0.01-100>``
Raise or lower the audio's pitch by the factor given as parameter. Does not
affect playback speed. Playing with an altered pitch automatically inserts
the ``scaletempo2`` audio filter.
``--pause``
Start the player in paused state.

View File

@ -675,6 +675,7 @@ static const m_option_t mp_opts[] = {
{"audio-channels", OPT_CHANNELS(audio_output_channels), .flags = UPDATE_AUDIO},
{"audio-format", OPT_AUDIOFORMAT(audio_output_format), .flags = UPDATE_AUDIO},
{"speed", OPT_DOUBLE(playback_speed), M_RANGE(0.01, 100.0)},
{"pitch", OPT_DOUBLE(playback_pitch), M_RANGE(0.01, 100.0)},
{"audio-pitch-correction", OPT_BOOL(pitch_correction)},
@ -1036,6 +1037,7 @@ static const struct MPOpts mp_default_opts = {
.audio_display = 1,
.audio_output_format = 0, // AF_FORMAT_UNKNOWN
.playback_speed = 1.,
.playback_pitch = 1.,
.pitch_correction = true,
.audiofile_auto = -1,
.osd_bar_visible = true,
@ -1127,6 +1129,7 @@ static const struct MPOpts mp_default_opts = {
.watch_later_options = (char *[]){
"start",
"speed",
"pitch",
"edition",
"volume",
"mute",

View File

@ -323,6 +323,7 @@ typedef struct MPOpts {
int audio_output_format;
int force_srate;
double playback_speed;
double playback_pitch;
bool pitch_correction;
struct m_obj_settings *vf_settings;
struct m_obj_settings *af_settings;

View File

@ -54,6 +54,7 @@ static void update_speed_filters(struct MPContext *mpctx)
if (!ao_c)
return;
double pitch = mpctx->opts->playback_pitch;
double speed = mpctx->opts->playback_speed;
double resample = mpctx->speed_factor_a;
double drop = 1.0;
@ -63,17 +64,22 @@ static void update_speed_filters(struct MPContext *mpctx)
speed = 1.0;
}
if (mpctx->display_sync_active) {
switch (mpctx->video_out->opts->video_sync) {
case VS_DISP_ADROP:
drop *= speed * resample;
resample = speed = 1.0;
break;
case VS_DISP_TEMPO:
speed = mpctx->audio_speed;
resample = 1.0;
break;
}
int video_sync = mpctx->display_sync_active ?
mpctx->video_out->opts->video_sync : VS_NONE;
switch (video_sync) {
case VS_DISP_ADROP:
drop *= speed * resample / pitch;
resample = pitch;
speed = 1.0;
break;
case VS_DISP_TEMPO:
speed = mpctx->audio_speed / pitch;
resample = pitch;
break;
default:
resample *= pitch;
speed /= pitch;
break;
}
mp_output_chain_set_audio_speed(ao_c->filter, speed, resample, drop);

View File

@ -431,6 +431,19 @@ static int mp_property_playback_speed(void *ctx, struct m_property *prop,
return mp_property_generic_option(mpctx, prop, action, arg);
}
/// Playback pitch (RW)
static int mp_property_playback_pitch(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
if (action == M_PROPERTY_PRINT || action == M_PROPERTY_FIXED_LEN_PRINT) {
*(char **)arg = mp_format_double(NULL, mpctx->opts->playback_pitch, 2,
false, false, action != M_PROPERTY_FIXED_LEN_PRINT);
return M_PROPERTY_OK;
}
return mp_property_generic_option(mpctx, prop, action, arg);
}
static int mp_property_av_speed_correction(void *ctx, struct m_property *prop,
int action, void *arg)
{
@ -3983,6 +3996,7 @@ static const struct m_property mp_properties_base[] = {
// General
{"pid", mp_property_pid},
{"speed", mp_property_playback_speed},
{"pitch", mp_property_playback_pitch},
{"audio-speed-correction", mp_property_av_speed_correction, .priv = "a"},
{"video-speed-correction", mp_property_av_speed_correction, .priv = "v"},
{"display-sync-active", mp_property_display_sync_active},
@ -4402,6 +4416,7 @@ static const struct property_osd_display {
.seek_bar = OSD_SEEK_INFO_BAR},
{"hr-seek", "hr-seek"},
{"speed", "Speed"},
{"pitch", "Pitch"},
{"clock", "Clock"},
{"edition", "Edition"},
// audio
@ -7438,7 +7453,7 @@ void mp_option_change_callback(void *ctx, struct m_config_option *co, int flags,
run_command_opts(mpctx);
}
if (opt_ptr == &opts->playback_speed) {
if (opt_ptr == &opts->playback_speed || opt_ptr == &opts->playback_pitch) {
update_playback_speed(mpctx);
mp_wakeup_core(mpctx);
}