diff options
author | ferreum <code@ferreum.de> | 2023-08-19 10:18:38 +0200 |
---|---|---|
committer | Niklas Haas <github-daiK1o@haasn.dev> | 2023-09-20 14:36:23 +0200 |
commit | f52cf90fedc3daf94fbf2118c6a5dd474c8e6c74 (patch) | |
tree | c7e8565c5cd680e12e8a556fe072f0f509141cb5 /audio/filter/af_scaletempo2.c | |
parent | 33d6d0f311b410a5a5a6acb1838a41ec3e91c25b (diff) | |
download | mpv-f52cf90fedc3daf94fbf2118c6a5dd474c8e6c74.tar.bz2 mpv-f52cf90fedc3daf94fbf2118c6a5dd474c8e6c74.tar.xz |
af_scaletempo2: fix speed change latency and pts spikes
The internal time update function involved multiple problems:
- Time was updated after WSOLA iteration. The means speed was updated
one iteration later than it could be.
- The update functions caused spikes of too many or too few samples
advanced, leading to audio glitches on speed changes.
- The inconsistent updates made it very difficult to produce gapless
audio packets.
- The `output_time` update function involved complicated feedback:
`search_block_index` influenced how many frames from `input_buffer`
are retained, which influenced how much `output_time` is changed,
which influenced `search_block_index`.
With these changes:
- Time is updated before WSOLA iterations. Speed changes are effective
instantly.
- There are no spikes in playback speed during speed changes.
- No significant gaps are introduced in output packets.
- The time update function becomes (function calls omitted for brevity)
output_time += ola_hop_size * playback_rate
Functions received a `playback_rate` parameter to check how many samples
are needed before iteration. Internal state is only updated when the
iteration is actually run, so the speed is allowed to change until
enough data is received.
Diffstat (limited to 'audio/filter/af_scaletempo2.c')
-rw-r--r-- | audio/filter/af_scaletempo2.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/audio/filter/af_scaletempo2.c b/audio/filter/af_scaletempo2.c index cf74e6504f..0dc0a974d4 100644 --- a/audio/filter/af_scaletempo2.c +++ b/audio/filter/af_scaletempo2.c @@ -29,7 +29,7 @@ static void process(struct mp_filter *f) return; while (!p->initialized || !p->pending || - !mp_scaletempo2_frames_available(&p->data)) + !mp_scaletempo2_frames_available(&p->data, p->speed)) { bool eof = false; if (!p->pending || !mp_aframe_get_size(p->pending)) { @@ -65,12 +65,12 @@ static void process(struct mp_filter *f) int frame_size = mp_aframe_get_size(p->pending); uint8_t **planes = mp_aframe_get_data_ro(p->pending); int read = mp_scaletempo2_fill_input_buffer(&p->data, - planes, frame_size, final); + planes, frame_size, final, p->speed); mp_aframe_skip_samples(p->pending, read); } p->sent_final |= final; - if (mp_scaletempo2_frames_available(&p->data)) { + if (mp_scaletempo2_frames_available(&p->data, p->speed)) { if (eof) { mp_pin_out_repeat_eof(p->in_pin); // drain more next time } @@ -89,7 +89,7 @@ static void process(struct mp_filter *f) } assert(p->pending); - if (mp_scaletempo2_frames_available(&p->data)) { + if (mp_scaletempo2_frames_available(&p->data, p->speed)) { struct mp_aframe *out = mp_aframe_new_ref(p->cur_format); int out_samples = p->data.ola_hop_size; if (mp_aframe_pool_allocate(p->out_pool, out, out_samples) < 0) { |