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>
131 lines
16 KiB
XML
131 lines
16 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<index version="1" name="jsfx">
|
|
<category name="Effects/Passive Four">
|
|
<reapack name="PassiveFour.jsfx" type="effect" desc="Passive Four (prototype)">
|
|
<metadata>
|
|
<description>Prototype stage of an open-source 4-band passive-style tube EQ, inspired by classic bridged-T passive EQs (not affiliated with or endorsed by any hardware manufacturer). Single self-contained JSFX with a native @gfx interface.</description>
|
|
</metadata>
|
|
<version name="0.8.0" author="Passive Four contributors" time="2026-09-14T09:00:00Z">
|
|
<changelog>Replaces 0.7.0's Bandwidth mechanism entirely. A Plugin Doctor side-by-side against a real UADx Manley Massive Passive VST showed 0.7.0's Rq (parallel Q-spoiling resistor) approach didn't work: pushed wide enough to matter, it flattened the entire spectrum toward a constant gain floor instead of broadening the peak, since Rq caps the branch's impedance everywhere, not just near resonance. Bandwidth now varies the L/C characteristic-impedance ratio instead (same L*C product, so the same resonant frequency) - a branch built this way keeps genuinely unbounded impedance at the frequency extremes regardless of ratio, matching how real analog bandwidth pots work. Verified end to end: PassiveFour.jsfx's own Lo-band boost curve now matches a real captured reference measurement within ~0.2-1.6 dB from 5 Hz to 20 kHz. tools/check.sh also gained a 48/96 kHz sample-rate check.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/PassiveFour.jsfx</source>
|
|
<source file="lib/wdf.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/wdf.jsfx-inc</source>
|
|
<source file="lib/band.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/band.jsfx-inc</source>
|
|
</version>
|
|
<version name="0.7.0" author="Passive Four contributors" time="2026-09-13T14:00:00Z">
|
|
<changelog>Independent Bandwidth knob per band. wdf_boost_cut_band() gained an Rq (Q-spoiling) resistor wired in parallel with each branch's bare L-C pair (not in series with Rboost/Rcut - a series resistor there is numerically indistinguishable from just changing Rboost/Rcut, confirmed by experiment). In parallel, Rq is shorted out exactly at resonance, so it widens the -3 dB bandwidth without changing the peak dB. Motivated by a concrete symptom: without bandwidth control, the resonance narrowed sharply as Amount increased (~1.7 octaves at 50% down to ~0.5 at 100% on one band), the opposite of the real unit's documented "wider when boosted more" behavior.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/PassiveFour.jsfx</source>
|
|
<source file="lib/wdf.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/wdf.jsfx-inc</source>
|
|
<source file="lib/band.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/band.jsfx-inc</source>
|
|
</version>
|
|
<version name="0.6.0" author="Passive Four contributors" time="2026-09-13T13:00:00Z">
|
|
<changelog>Each band's independent Boost/Cut knobs replaced with a single 3-way Mode switch (CUT/OFF/BOOST) + one Amount knob, matching the real hardware's single center-detented control per band (confirmed via tools/probe_enable_param.lua against a real UADx Manley Massive Passive VST - CUT and BOOST can never be engaged simultaneously on one band). Amount now follows a curve fit to that VST's actual measured cut/boost dB at its 0/5/10/15/20 dB dial marks, analytically inverted to the exact Rboost/Rcut pot value needed. Breaking change: old boost/cut slider automation no longer applies.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/PassiveFour.jsfx</source>
|
|
<source file="lib/wdf.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/wdf.jsfx-inc</source>
|
|
<source file="lib/band.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/band.jsfx-inc</source>
|
|
</version>
|
|
<version name="0.5.0" author="Passive Four contributors" time="2026-09-13T08:00:00Z">
|
|
<changelog>All 4 bands, each with its own real stepped frequency table (read off a UADx Manley Massive Passive panel photo). Bands run in series per channel with a per-band make-up gain, so each is transparent (0 dB) at rest instead of compounding insertion loss across 4 bands.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/PassiveFour.jsfx</source>
|
|
<source file="lib/wdf.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/wdf.jsfx-inc</source>
|
|
<source file="lib/band.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/band.jsfx-inc</source>
|
|
</version>
|
|
<version name="0.4.0" author="Passive Four contributors" time="2026-09-13T07:00:00Z">
|
|
<changelog>Real proportional-Q boost/cut: separate Boost and Cut knobs sharing one L-C pair through a resistive pad (a documented real passive-EQ design principle), so they interact instead of simply adding/canceling in dB. Replaces the old bandwidth-only "peak" band; no independent Bandwidth/Q control yet in this topology.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/PassiveFour.jsfx</source>
|
|
<source file="lib/wdf.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/wdf.jsfx-inc</source>
|
|
<source file="lib/band.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/band.jsfx-inc</source>
|
|
</version>
|
|
<version name="0.3.6" author="Passive Four contributors" time="2026-09-13T06:00:00Z">
|
|
<changelog>Fix "knob moves but the sound doesn't change" - band coefficients are now recomputed every sample instead of cached in @slider, which wasn't guaranteed to re-run after a @gfx knob's slider_automate() call.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/PassiveFour.jsfx</source>
|
|
<source file="lib/wdf.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/wdf.jsfx-inc</source>
|
|
<source file="lib/band.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/band.jsfx-inc</source>
|
|
</version>
|
|
<version name="0.3.5" author="Passive Four contributors" time="2026-09-13T05:00:00Z">
|
|
<changelog>Fix "knob_hit undefined" and the earlier "wdf_inductor_R undefined" for real - functions must be defined inside @init, not just before it, to be visible elsewhere. Verified locally against a built ysfx_tool/ysfx_render instead of by REAPER round-trip.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/PassiveFour.jsfx</source>
|
|
<source file="lib/wdf.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/wdf.jsfx-inc</source>
|
|
<source file="lib/band.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/band.jsfx-inc</source>
|
|
</version>
|
|
<version name="0.3.4" author="Passive Four contributors" time="2026-09-13T04:00:00Z">
|
|
<changelog>Fix "wdf_inductor_R undefined" - JSFX imports are not transitive; the main file now imports wdf.jsfx-inc directly instead of relying on band.jsfx-inc's own import of it.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/PassiveFour.jsfx</source>
|
|
<source file="lib/wdf.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/wdf.jsfx-inc</source>
|
|
<source file="lib/band.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/band.jsfx-inc</source>
|
|
</version>
|
|
<version name="0.3.3" author="Passive Four contributors" time="2026-09-13T03:00:00Z">
|
|
<changelog>Fix a syntax error on startup - EEL2 code has no scientific-notation literal syntax, unlike slider range declarations ("100e-9" is only valid there).</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/PassiveFour.jsfx</source>
|
|
<source file="lib/wdf.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/wdf.jsfx-inc</source>
|
|
<source file="lib/band.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/band.jsfx-inc</source>
|
|
</version>
|
|
<version name="0.3.2" author="Passive Four contributors" time="2026-09-13T02:00:00Z">
|
|
<changelog>Fix "import: has no @init or other code" - the lib/ includes contained only function definitions, which REAPER rejects for imported files.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/PassiveFour.jsfx</source>
|
|
<source file="lib/wdf.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/wdf.jsfx-inc</source>
|
|
<source file="lib/band.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/band.jsfx-inc</source>
|
|
</version>
|
|
<version name="0.3.1" author="Passive Four contributors" time="2026-09-13T01:00:00Z">
|
|
<changelog>Round rotary knobs (drag vertically), logarithmic frequency mapping, instead of horizontal bars.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/PassiveFour.jsfx</source>
|
|
<source file="lib/wdf.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/wdf.jsfx-inc</source>
|
|
<source file="lib/band.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/band.jsfx-inc</source>
|
|
</version>
|
|
<version name="0.3.0" author="Passive Four contributors" time="2026-09-13T00:00:00Z">
|
|
<changelog>First real DSP: a single resonant "peak" band (Wave Digital Filter), frequency + bandwidth controls. Passive-only for now (gain <= 0 dB everywhere) until a make-up gain stage is added later.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/PassiveFour.jsfx</source>
|
|
<source file="lib/wdf.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/wdf.jsfx-inc</source>
|
|
<source file="lib/band.jsfx-inc">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/Effects/Passive%20Four/lib/band.jsfx-inc</source>
|
|
</version>
|
|
</reapack>
|
|
</category>
|
|
<category name="Effects/Passive Four Dev Tools">
|
|
<reapack name="impulse_gen.jsfx" type="effect" desc="Passive Four - impulse generator (measurement helper)">
|
|
<metadata>
|
|
<description>Outputs a single impulse at render start, silence after. Not an EQ - a measurement helper: place before a plugin under test in a track's FX chain and render to WAV to capture that plugin's impulse response for offline analysis (see this project's tools/analyze.py-style scripts). Part of the Passive Four project's dev tooling, not the plugin itself.</description>
|
|
</metadata>
|
|
<version name="1.0.0" author="Passive Four contributors" time="2026-09-13T09:00:00Z">
|
|
<changelog>Initial release.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/tools/impulse_gen.jsfx</source>
|
|
</version>
|
|
</reapack>
|
|
</category>
|
|
<category name="Scripts/Passive Four Dev Tools">
|
|
<reapack name="dump_fx_params.lua" type="script" desc="Passive Four - dump a plugin's FX parameter map">
|
|
<metadata>
|
|
<description>Read-only: lists every parameter (index, name, value, min, max, normalized) of the plugin on the selected track that has a "Ch1LoFreq" parameter (a Manley Massive Passive-style EQ), to the ReaScript console and a text file next to the project. First step toward automating reference measurements of a third-party plugin - see this project's tools/sweep_fx_params.lua and tools/README.md.</description>
|
|
</metadata>
|
|
<version name="1.0.0" author="Passive Four contributors" time="2026-09-13T09:00:00Z">
|
|
<changelog>Initial release.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/tools/dump_fx_params.lua</source>
|
|
</version>
|
|
</reapack>
|
|
<reapack name="sweep_fx_params.lua" type="script" desc="Passive Four - automated sweep-response capture of a reference plugin">
|
|
<metadata>
|
|
<description>Sweeps all 4 bands of a Manley Massive Passive-style EQ (frequency/gain/bandwidth/shape) on the selected track, rendering the plugin's response to a sweep media item for each point (a labeled WAV) plus a CSV manifest of the plugin's own real-world parameter values - no REAPER UI clicking needed. Needs a sweep audio item on the track and some render setup - see the comments at the top of the script and tools/README.md. Pair with this project's tools/deconvolve_sweep.py (run locally, not via ReaPack - it's a plain Python script, not a REAPER format) to recover impulse responses from the rendered sweep responses.</description>
|
|
</metadata>
|
|
<version name="1.0.2" author="Passive Four contributors" time="2026-09-13T12:00:00Z">
|
|
<changelog>Fix Enable/Gain semantics: probe_enable_param.lua confirmed ChXxxEnable is a 3-way CUT/OUT/BOOST switch (not a plain IN/OUT toggle) and ChXxxGain is a unidirectional 0-20 dB amount (not a bidirectional +/-dB value). Every render before this fix had "isolated" bands sitting in CUT instead of OUT, and only ever swept Gain in the BOOST direction. Band isolation now sets inactive bands to OUT (0.5); the old single gain_sweep is now two sweeps (gain_sweep_cut, gain_sweep_boost) run with Enable pinned to CUT/BOOST respectively.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/tools/sweep_fx_params.lua</source>
|
|
</version>
|
|
<version name="1.0.1" author="Passive Four contributors" time="2026-09-13T10:00:00Z">
|
|
<changelog>Switch from impulse_gen.jsfx (didn't render reliably through this plugin) to a sweep media item as the test signal, deconvolved afterward with tools/deconvolve_sweep.py.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/tools/sweep_fx_params.lua</source>
|
|
</version>
|
|
<version name="1.0.0" author="Passive Four contributors" time="2026-09-13T09:00:00Z">
|
|
<changelog>Initial release: all 4 bands (Lo/LoMid/HiMid/Hi), 17 points each (baseline, freq/gain/bandwidth sweeps, bell-vs-shelf).</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/tools/sweep_fx_params.lua</source>
|
|
</version>
|
|
</reapack>
|
|
<reapack name="probe_enable_param.lua" type="script" desc="Passive Four - probe a plugin's Enable/Gain/Shape parameter semantics">
|
|
<metadata>
|
|
<description>Diagnostic: reads the plugin's own formatted display string for Ch1LoEnable, Ch1LoGain, and Ch1LoShape at 9 points across each parameter's normalized range (e.g. to settle whether Enable is a plain IN/OUT switch or a 3-way CUT/OUT/BOOST switch), restoring the original values afterward. Output goes to the ReaScript console and a text file next to the project. Part of this project's reference-measurement tooling - see tools/README.md.</description>
|
|
</metadata>
|
|
<version name="1.0.0" author="Passive Four contributors" time="2026-09-13T11:00:00Z">
|
|
<changelog>Initial release: probes Ch1LoEnable, Ch1LoGain, Ch1LoShape.</changelog>
|
|
<source main="main">https://git.cybergate.ch/cybergate/jsfx/raw/branch/main/tools/probe_enable_param.lua</source>
|
|
</version>
|
|
</reapack>
|
|
</category>
|
|
</index>
|