Files
julienandClaude Sonnet 5 daead8a1d9 Replace 0.7.0's Rq bandwidth mechanism with an L/C-ratio approach (0.8.0)
A Plugin Doctor side-by-side of a real UADx Manley Massive Passive VST
against PassiveFour.jsfx (band 1/Lo, ~150 Hz, ~5.7 dB boost) showed 0.7.0's
Bandwidth knob wasn't remotely close: the real curve is a broad, low-
shelf-like plateau spanning ~100-300 Hz, decaying gracefully out past 5 Hz
and 10+ kHz; ours was a narrow spike.

Root cause: Rq (0.7.0's parallel Q-spoiling resistor) caps a branch's
impedance at Rq everywhere, not just near resonance. A real L-C branch's
impedance keeps rising toward infinity far from resonance; a parallel Rq
never lets it, so pushing Rq low enough to matter didn't broaden the peak
so much as flatten the entire spectrum toward a constant gain floor
(measured directly: +4.8 dB everywhere, five octaves from center, at a
middling "wide" setting).

wdf_boost_cut_band() drops Rq entirely. Bandwidth is now the caller's
responsibility (PassiveFour.jsfx's process_band()): scale L up and C down
by the same z0_ratio, keeping L*C (and the resonant frequency) fixed while
changing the characteristic impedance sqrt(L/C). A branch built this way
still has unbounded impedance at the frequency extremes regardless of
ratio, so it can't degenerate into a flat floor - and this is how real
analog bandwidth pots actually work.

Verified end to end against the same real captured Lo-band measurement
(docs/passive-four/reference-measurements-2026-09-13.txt): PassiveFour.jsfx's
own curve now matches within ~0.2-1.6 dB from 5 Hz to 20 kHz, down from
being off by multiple dB at most frequencies.

Caught a second bug while implementing the fix: an early draft applied an
extra sqrt() to z0_ratio before scaling L/C, silently halving the knob's
effect in log-scale terms versus what BW_RATIO_MIN implied. Found by
re-deriving the L/C-ratio math from scratch (Z0_new/Z0_old = ratio needs
L *= ratio, C /= ratio directly, no sqrt) and re-validating
tools/analyze_boostcut.py's analytical reference against the corrected
formula (0.000 dB match) instead of trusting the first plausible-looking
result.

tools/check.sh also gained a 48 kHz/96 kHz sample-rate check (WDF port
resistances depend on 1/srate; previously only exercised at 44100).

circuit-notes.md documents this fix and separately answers an external
architecture review's other points (per-sample recomputation is
intentional/bug-fix-verified not an oversight, wdf_peak_band() is a
validation-only harness not used by the plugin, frequency prewarping is
handled via WDF port resistances and actively verified by the analytical
comparisons, and the 4-band cascade is a deliberate buffered-stages
design) - most were based on parts of the codebase that don't apply to the
shipped plugin or were already validated.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 05:32:59 +02:00
..