diff options
Diffstat (limited to 'player/audio.c')
-rw-r--r-- | player/audio.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/player/audio.c b/player/audio.c index 5b19e2fc0c..ab4e50b1b9 100644 --- a/player/audio.c +++ b/player/audio.c @@ -45,9 +45,14 @@ static int update_playback_speed_filters(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; - double speed = opts->playback_speed; + double speed = mpctx->audio_speed; struct af_stream *afs = mpctx->d_audio->afilter; + // Use pitch correction only for speed adjustments by the user, not minor + // sync correction ones. + bool use_pitch_correction = opts->pitch_correction && + opts->playback_speed != 1.0; + // 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}); @@ -63,7 +68,7 @@ static int update_playback_speed_filters(struct MPContext *mpctx) return 0; int method = AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE; - if (opts->pitch_correction) + if (use_pitch_correction) method = AF_CONTROL_SET_PLAYBACK_SPEED; if (!af_control_any_rev(afs, method, &speed)) { @@ -88,6 +93,8 @@ static int recreate_audio_filters(struct MPContext *mpctx) if (update_playback_speed_filters(mpctx) < 0) { mpctx->opts->playback_speed = 1.0; + mpctx->speed_factor_a = 1.0; + mpctx->audio_speed = 1.0; mp_notify(mpctx, MP_EVENT_CHANGE_ALL, NULL); } @@ -117,11 +124,20 @@ int reinit_audio_filters(struct MPContext *mpctx) return 1; } -void set_playback_speed(struct MPContext *mpctx, double new_speed) +// Call this if opts->playback_speed or mpctx->speed_correction changes. +void update_playback_speed(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; - opts->playback_speed = new_speed; + double old_speed_factor_a = mpctx->speed_factor_a; + double old_audio_speed = mpctx->audio_speed; + + mpctx->audio_speed = opts->playback_speed * mpctx->speed_factor_a; + mpctx->video_speed = opts->playback_speed * mpctx->speed_factor_v; + + if (mpctx->speed_factor_a == old_speed_factor_a && + mpctx->audio_speed == old_audio_speed) + return; if (!mpctx->d_audio || mpctx->d_audio->afilter->initialized < 1) return; @@ -300,7 +316,7 @@ void reinit_audio_chain(struct MPContext *mpctx) if (recreate_audio_filters(mpctx) < 0) goto init_error; - set_playback_speed(mpctx, opts->playback_speed); + update_playback_speed(mpctx); return; @@ -349,9 +365,9 @@ double written_audio_pts(struct MPContext *mpctx) // accept everything to internal buffers yet buffered_output += mp_audio_buffer_seconds(mpctx->ao_buffer); - // Filters divide audio length by playback_speed, so multiply by it + // Filters divide audio length by audio_speed, so multiply by it // to get the length in original units without speedup or slowdown - a_pts -= buffered_output * mpctx->opts->playback_speed; + a_pts -= buffered_output * mpctx->audio_speed; return a_pts + get_track_video_offset(mpctx, mpctx->current_track[0][STREAM_AUDIO]); @@ -363,7 +379,7 @@ double playing_audio_pts(struct MPContext *mpctx) double pts = written_audio_pts(mpctx); if (pts == MP_NOPTS_VALUE || !mpctx->ao) return pts; - return pts - mpctx->opts->playback_speed * ao_get_delay(mpctx->ao); + return pts - mpctx->audio_speed * ao_get_delay(mpctx->ao); } static int write_to_ao(struct MPContext *mpctx, struct mp_audio *data, int flags) @@ -378,7 +394,7 @@ static int write_to_ao(struct MPContext *mpctx, struct mp_audio *data, int flags #endif if (data->samples == 0) return 0; - double real_samplerate = out_format.rate / mpctx->opts->playback_speed; + double real_samplerate = out_format.rate / mpctx->audio_speed; int played = ao_play(mpctx->ao, data->planes, data->samples, flags); assert(played <= data->samples); if (played > 0) { @@ -406,7 +422,7 @@ static bool get_sync_samples(struct MPContext *mpctx, int *skip) struct mp_audio out_format = {0}; ao_get_format(mpctx->ao, &out_format); - double play_samplerate = out_format.rate / opts->playback_speed; + double play_samplerate = out_format.rate / mpctx->audio_speed; if (!opts->initial_audio_sync) { mpctx->audio_status = STATUS_FILLING; @@ -483,7 +499,7 @@ void fill_audio_out_buffers(struct MPContext *mpctx, double endpts) struct mp_audio out_format = {0}; ao_get_format(mpctx->ao, &out_format); - double play_samplerate = out_format.rate / opts->playback_speed; + double play_samplerate = out_format.rate / mpctx->audio_speed; // If audio is infinitely fast, somehow try keeping approximate A/V sync. if (mpctx->audio_status == STATUS_PLAYING && ao_untimed(mpctx->ao) && |