mirror of
https://github.com/mpv-player/mpv.git
synced 2026-10-29 07:06:59 +08:00
audio: make changing playback speed slightly more robust
Always use af_scaletempo if it's inserted, even if the option --audio-pitch-correction=no is set. Make sure all filters are reset on speed change. It's conceivable that dynamic changes to the filter chain at runtime leave filters around without resetting their speed parameters. Also move the code to a separate function.
This commit is contained in:
+43
-36
@@ -60,47 +60,54 @@ static int try_filter(struct MPContext *mpctx,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int update_playback_speed_filters(struct MPContext *mpctx)
|
||||
{
|
||||
struct MPOpts *opts = mpctx->opts;
|
||||
double speed = opts->playback_speed;
|
||||
struct af_stream *afs = mpctx->d_audio->afilter;
|
||||
|
||||
// Make sure only exactly one filter changes speed; resetting them all
|
||||
// and setting 1 filter is the easiest way to achieve this.
|
||||
af_control_all(afs, AF_CONTROL_SET_PLAYBACK_SPEED, &(double){1});
|
||||
af_control_all(afs, AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE, &(double){1});
|
||||
|
||||
if (speed == 1.0)
|
||||
return af_remove_by_label(afs, "playback-speed");
|
||||
|
||||
// Compatibility: if the user uses --af=scaletempo, always use this
|
||||
// filter to change speed. Don't insert a second filter (any) either.
|
||||
if (!af_find_by_label(afs, "playback-speed") &&
|
||||
af_control_any_rev(afs, AF_CONTROL_SET_PLAYBACK_SPEED, &speed))
|
||||
return 0;
|
||||
|
||||
int method = AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE;
|
||||
if (opts->pitch_correction)
|
||||
method = AF_CONTROL_SET_PLAYBACK_SPEED;
|
||||
|
||||
if (!af_control_any_rev(afs, method, &speed)) {
|
||||
if (af_remove_by_label(afs, "playback-speed") < 0)
|
||||
return -1;
|
||||
|
||||
char *filter = method == AF_CONTROL_SET_PLAYBACK_SPEED
|
||||
? "scaletempo" : "lavrresample";
|
||||
if (try_filter(mpctx, filter, "playback-speed", NULL) < 0)
|
||||
return -1;
|
||||
// Try again.
|
||||
if (!af_control_any_rev(afs, method, &speed))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int recreate_audio_filters(struct MPContext *mpctx)
|
||||
{
|
||||
assert(mpctx->d_audio);
|
||||
|
||||
struct MPOpts *opts = mpctx->opts;
|
||||
if (update_playback_speed_filters(mpctx) < 0)
|
||||
return -1;
|
||||
|
||||
struct af_stream *afs = mpctx->d_audio->afilter;
|
||||
|
||||
double speed = opts->playback_speed;
|
||||
|
||||
if (speed != 1.0) {
|
||||
int method = AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE;
|
||||
if (opts->pitch_correction)
|
||||
method = AF_CONTROL_SET_PLAYBACK_SPEED;
|
||||
if (!af_control_any_rev(afs, method, &speed)) {
|
||||
if (af_remove_by_label(afs, "playback-speed") < 0)
|
||||
return -1;
|
||||
|
||||
// Compatibility: if the user uses --af=scaletempo, always use
|
||||
// this filter to change speed. Don't insert a second "scaletempo"
|
||||
// filter either.
|
||||
if (!af_control_any_rev(afs, AF_CONTROL_SET_PLAYBACK_SPEED, &speed))
|
||||
{
|
||||
char *filter = method == AF_CONTROL_SET_PLAYBACK_SPEED
|
||||
? "scaletempo" : "lavrresample";
|
||||
if (try_filter(mpctx, filter, "playback-speed", NULL) < 0)
|
||||
return -1;
|
||||
// Try again.
|
||||
if (!af_control_any_rev(afs, method, &speed))
|
||||
return -1;
|
||||
} else {
|
||||
method = AF_CONTROL_SET_PLAYBACK_SPEED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (af_remove_by_label(afs, "playback-speed") < 0)
|
||||
return -1;
|
||||
// The filters could be inserted by the user (we don't remove them).
|
||||
af_control_any_rev(afs, AF_CONTROL_SET_PLAYBACK_SPEED, &speed);
|
||||
af_control_any_rev(afs, AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE, &speed);
|
||||
}
|
||||
|
||||
if (afs->initialized < 1 && af_init(afs) < 0) {
|
||||
MP_ERR(mpctx, "Couldn't find matching filter/ao format!\n");
|
||||
return -1;
|
||||
|
||||
Reference in New Issue
Block a user