feat: Gate worklet output at startup to prevent underrun clicks - #87
Open
bhj wants to merge 1 commit into
Open
Conversation
A bursty stretch stage refills the output buffer one hop at a time while the render thread drains one block per quantum, so the buffer's trough rides at exactly one render block. Wherever the stage's production schedule comes up a few frames short, the block is zero-filled — an audible click of up to full signal amplitude (measured: 1-8 sample dropouts). SoundTouchProcessorBase now supports holding extraction for startupHoldBlocks render blocks after the output buffer first fills a block. Held blocks are emitted before any real output, so the added silence is inaudible, and the unconsumed frames become a permanent cushion under the trough. The phase vocoder worklet holds one block: a 128-frame cushion (16x the worst measured shortfall) for one render block (~2.9 ms) of added latency. Warmup blocks no longer count as underruns, so the metric now reports only real faults. Measured A/B (real pipeline, gate vs none) across the full fftSize/overlapFactor grid at 44.1/48/96 kHz: group delay shifts by exactly 128 frames with output otherwise bit-identical, and hop-aligned pitch ratios drop from 9-21 underruns per 20 s to zero at every functional configuration. Arbitrary (unaligned) ratios are a sustained stretch/transposer rate mismatch that outruns any fixed cushion — the gate only delays onset there; matching the transposer to the stage's realized tempo is the actual fix for that case. Configs with hop <= 128 starve with or without the gate because PhaseVocoder.process() handles at most one hop per call (unlike Stretch, which loops until input is exhausted) — a pre-existing defect to fix separately. The default of 0 leaves the other worklets' timing unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hey again :)
This came up while trying to switch my bespoke phase vocoder implementation over to v2.1.1. Can't say I noticed the transients myself, but it's plausible. It does add ~3ms of latency which seemed like a reasonable tradeoff for correctness.
Model used: Anthropic Fable 5
Highlighting the two other issues the model called out:
Already a PR for this with #85
I'll look at creating a separate PR for this - not sure how invasive it may end up being.