summaryrefslogtreecommitdiffstats
path: root/audio/filter/af_scaletempo2.c
diff options
context:
space:
mode:
authorferreum <code@ferreum.de>2023-08-19 10:18:38 +0200
committerNiklas Haas <github-daiK1o@haasn.dev>2023-09-20 14:36:23 +0200
commitf52cf90fedc3daf94fbf2118c6a5dd474c8e6c74 (patch)
treec7e8565c5cd680e12e8a556fe072f0f509141cb5 /audio/filter/af_scaletempo2.c
parent33d6d0f311b410a5a5a6acb1838a41ec3e91c25b (diff)
downloadmpv-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.c8
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) {