Skip to content

Commit

Permalink
audio: add pitch-shifting feature
Browse files Browse the repository at this point in the history
Uses resampling in tandem with a time-stretching audio filter to
change the audio's pitch while leaving its tempo intact.
  • Loading branch information
myQwil committed Aug 6, 2024
1 parent 0818f60 commit 81fb2c6
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 5 deletions.
1 change: 1 addition & 0 deletions DOCS/interface-changes/pitch-shift.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add `--pitch` option
5 changes: 5 additions & 0 deletions DOCS/man/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
3 changes: 3 additions & 0 deletions options/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)},

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -1127,6 +1129,7 @@ static const struct MPOpts mp_default_opts = {
.watch_later_options = (char *[]){
"start",
"speed",
"pitch",
"edition",
"volume",
"mute",
Expand Down
1 change: 1 addition & 0 deletions options/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
15 changes: 11 additions & 4 deletions player/audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -66,14 +67,20 @@ static void update_speed_filters(struct MPContext *mpctx)
if (mpctx->display_sync_active) {
switch (mpctx->video_out->opts->video_sync) {
case VS_DISP_ADROP:
drop *= speed * resample;
resample = speed = 1.0;
drop *= speed * resample / pitch;
resample = pitch;
speed = 1.0;
break;
case VS_DISP_TEMPO:
speed = mpctx->audio_speed;
resample = 1.0;
speed = mpctx->audio_speed / pitch;
resample = pitch;
break;
default: goto normal;
}
} else {
normal:
resample *= pitch;
speed /= pitch;
}

mp_output_chain_set_audio_speed(ao_c->filter, speed, resample, drop);
Expand Down
18 changes: 17 additions & 1 deletion player/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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},
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -7438,7 +7453,8 @@ 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);
}
Expand Down

0 comments on commit 81fb2c6

Please sign in to comment.