LadderPrewarpSpanShiftFor switches bands per sample against a swept corner, stepping the ring's pitch once per note #87

Closed
opened 2026-09-09 22:28:37 +00:00 by bcox · 1 comment
Owner

LadderPrewarpSpanShiftFor selects one of two prewarp spans depending on whether the corner is above or below kLadderPrewarpLowBandCeiling (4800 Hz), and it is evaluated per sample against the corner the filter is actually running at.

For resonance in roughly (0.625, 0.75) the warp fraction is clamped at kUnit above 4800 Hz and sits below it underneath, so g — and therefore the ringing corner's pitch — steps discontinuously as the corner sweeps through that boundary.

The mechanism predates kLadderGate: any kLadder patch modulating its cutoff across 4800 Hz hits it. What is new is that a low-pass gate sweeps eight or nine octaves on every note, so the crossing goes from something a patch might do to something a gate patch does every time it is struck.

ladder-kick is unaffected — at resonance 0.90 it is clamped under both shifts. The window is narrow and the artefact is a small pitch step during the attack.

Raised because no test or lane would ever surface it, and because it is the one place the design's claim that "the shared ladder branch is answerable to the filter and not to where its cutoff came from" is slightly less true than elsewhere. Not obviously worth fixing; worth knowing before someone authors a gate patch that sits in that resonance window.

`LadderPrewarpSpanShiftFor` selects one of two prewarp spans depending on whether the corner is above or below `kLadderPrewarpLowBandCeiling` (4800 Hz), and it is evaluated per sample against the corner the filter is actually running at. For resonance in roughly (0.625, 0.75) the warp `fraction` is clamped at `kUnit` above 4800 Hz and sits below it underneath, so `g` — and therefore the ringing corner's pitch — steps discontinuously as the corner sweeps through that boundary. The mechanism predates `kLadderGate`: any `kLadder` patch modulating its cutoff across 4800 Hz hits it. What is new is that a low-pass gate sweeps eight or nine octaves on **every note**, so the crossing goes from something a patch might do to something a gate patch does every time it is struck. `ladder-kick` is unaffected — at resonance 0.90 it is clamped under both shifts. The window is narrow and the artefact is a small pitch step during the attack. Raised because no test or lane would ever surface it, and because it is the one place the design's claim that "the shared ladder branch is answerable to the filter and not to where its cutoff came from" is slightly less true than elsewhere. Not obviously worth fixing; worth knowing before someone authors a gate patch that sits in that resonance window.
Author
Owner

Answered with a measurement on ladder-gate-followups, commit 696cb75 -- and the answer moves on two of the issue's own points.

The characterization was too narrow. Measured with a ONE-increment cutoff move across the boundary, as the change in the resonant peak's height:

r step r step
0.51 +0.15 dB 0.63 +2.41 dB
0.55 +0.82 dB 0.66 +1.88 dB
0.60 +1.91 dB 0.70 +0.98 dB
0.624 +2.47 dB 0.74 +0.17 dB
0.78 0.00 dB

The worst is at r = 0.624 -- the lower edge of the (0.625, 0.75) window, not inside it -- and it runs down to 0.5, where the warp arm stops running at all. Above 0.75 both spans clamp and there is no step, which confirms ladder-kick at 0.90 is clear.

moog-lead is not clear. It is at resonance 0.55 and its cutoff envelope opens from 600 Hz to full open, so it crosses the boundary on every note for +0.82 dB. The issue checked ladder-kick and tb303-line, both at 0.90.

Smoothing does not work, and that is the part worth keeping. The two spans are not a coarse sampling of one curve: each reaches full warp strictly below its own band's measured onset, so a blend lands between those placements -- above the lower band's onset, where the lower band applies. A blend across the octave under the boundary was built and measured. It removes the step exactly, at every resonance, and puts 4000 Hz/r = 0.65 at 56.15 cents against 53.12 uncorrected -- net worse than no correction, the single-band failure the two-band placement exists to prevent, reproducing dsp/va_filter.h's own recorded 56.15 to two decimals.

The whole suite accepted that regression, which is its own finding -- see the comment on #84.

So the step stands, pinned rather than fixed: bounded under 3.2 dB, exactly zero above r = 0.75, and harder at 0.624 than at 0.70. Widening the low band's span trips the bound at 3.79 dB; blending the step away trips the peak-location assertion, so a future genuine fix has to touch this test deliberately rather than quietly.

Closing it properly means a span that tracks the onset table continuously rather than one interpolated between two points on it -- a re-derivation against that table, not a smoothing. That is a stage of work, not a follow-up, and is currently untracked.

Answered with a measurement on `ladder-gate-followups`, commit 696cb75 -- and the answer moves on two of the issue's own points. **The characterization was too narrow.** Measured with a ONE-increment cutoff move across the boundary, as the change in the resonant peak's height: | r | step | r | step | |---|---|---|---| | 0.51 | +0.15 dB | 0.63 | +2.41 dB | | 0.55 | +0.82 dB | 0.66 | +1.88 dB | | 0.60 | +1.91 dB | 0.70 | +0.98 dB | | 0.624 | **+2.47 dB** | 0.74 | +0.17 dB | | | | 0.78 | 0.00 dB | The worst is at r = 0.624 -- the *lower edge* of the (0.625, 0.75) window, not inside it -- and it runs down to 0.5, where the warp arm stops running at all. Above 0.75 both spans clamp and there is no step, which confirms `ladder-kick` at 0.90 is clear. **`moog-lead` is not clear.** It is at resonance 0.55 and its cutoff envelope opens from 600 Hz to full open, so it crosses the boundary on every note for +0.82 dB. The issue checked `ladder-kick` and `tb303-line`, both at 0.90. **Smoothing does not work, and that is the part worth keeping.** The two spans are not a coarse sampling of one curve: each reaches full warp strictly below its own band's measured onset, so a blend lands between those placements -- above the lower band's onset, where the lower band applies. A blend across the octave under the boundary was built and measured. It removes the step exactly, at every resonance, and puts 4000 Hz/r = 0.65 at **56.15 cents against 53.12 uncorrected** -- net worse than no correction, the single-band failure the two-band placement exists to prevent, reproducing `dsp/va_filter.h`'s own recorded 56.15 to two decimals. **The whole suite accepted that regression**, which is its own finding -- see the comment on #84. So the step stands, pinned rather than fixed: bounded under 3.2 dB, exactly zero above r = 0.75, and harder at 0.624 than at 0.70. Widening the low band's span trips the bound at 3.79 dB; blending the step away trips the peak-location assertion, so a future genuine fix has to touch this test deliberately rather than quietly. Closing it properly means a span that tracks the onset table continuously rather than one interpolated between two points on it -- a re-derivation against that table, not a smoothing. That is a stage of work, not a follow-up, and is currently untracked.
bcox closed this issue 2026-09-10 18:52:17 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
bcox/tymbal#87
No description provided.