feat: v0.2.0 deep-dive 2-band -> 3-band rebuild + M2 preset system#66
Merged
Conversation
Research-driven rebuild (docs/design-brief.md, docs/research-notes.md),
restructuring the signal path from a 2-band (low/high) split to a genuine
3-band (low/mid/high) split matching the reference class's own defining
architecture, plus the suite-wide M2 preset system.
Topology:
- Two cascaded LR4 crossovers replace the single split: Split Low
(60-400 Hz, default 120 Hz, was Crossover Frequency) peels off the Low
band; Split High (300-2000 Hz, default 600 Hz, NEW) splits the remainder
into Mid and High. Clamped >=1/3 octave apart (src/dsp/SplitGap.h).
- New Mid band (src/dsp/MidBand.h/.cpp): staged/cascaded drive-only
saturation (0-100%, default 30%) + Level, no filter/tone/blend, its own
4x-oversampled shaping stage.
- High band's pre-drive highpass ("Tight", 20-500 Hz, default 100 Hz) is
promoted from a Razor-only fixed 200 Hz constant to a first-class,
voicing-independent control applied ahead of all three voicings.
- Low-band compressor ballistics re-sourced to the reference class's fixed
"glue" values: ratio 4:1->2:1, attack 10->3ms, release 120->6ms (range
floor 10->5ms). Retires the "New York style" framing.
- IR loader relocated to process only the Mid+High post-sum signal, never
the Low band - structurally enforced and tested
(tests/LowBandIsolationTests.cpp).
- EQ default corner frequencies re-anchored: 100->80Hz, 2500->2800Hz,
8000->5000Hz (dormant unless EQ is enabled).
- Added src/dsp/PhaseAlignFilter.h: a naive cascade of two independent LR4
crossovers does not flat-sum on its own (up to -10dB deviation measured
at close split ratios) - fixed with an allpass compensation filter on the
Low band, proven algebraically in docs/architecture.md, not just
empirically.
- Lossy v0.1.x state migration: the old crossoverFreq value maps to the new
Split High parameter, clamped into its 300-2000Hz range (v0.1.x's 250Hz
default lands exactly at the 300Hz floor - dedicated regression test).
M2 preset system (ported from basilica-audio/nave's pilot):
- src/presets/PresetManager.{h,cpp}, src/presets/PresetBar.{h,cpp},
src/presets/Localisation.{h,cpp} (copied verbatim per the replication
recipe).
- Nine factory presets (presets/factory/*.json, docs/presets.md).
- German localisation of the preset UI frame (resources/i18n/de.txt).
- CMakeLists.txt: juce_add_binary_data(CryptaBinaryData ...), links
juce_gui_basics + CryptaBinaryData into SharedCode.
- PluginEditor now docks a PresetBar above the existing generic editor.
Tests: 53 -> 96 Catch2 cases (all v0.1.1 regression coverage kept green;
new: SplitGapTests, MidBandTests, ThreeBandFlatSumTests,
StateMigrationTests, LowBandIsolationTests, TopologyRobustnessTests,
PresetManagerTests, plus Voicing/GainStaging/Latency/Parameter/State test
updates for the new topology).
Docs rewritten: docs/manual.md, docs/architecture.md, README.md,
CHANGELOG.md (v0.2.0 entry). docs/design-brief.md and
docs/research-notes.md added as the binding brief for this rebuild.
Version bumped to 0.2.0.
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.
Summary
Research-driven v0.2.0 rebuild (
docs/design-brief.md,docs/research-notes.md) restructuring Crypta's signal path from a 2-band (low/high) split to a genuine 3-band (low/mid/high) split matching the reference plugin class's own defining architecture, plus the suite-wide M2 preset system.Topology (headline change)
Crossover Frequency) peels off the Low band; Split High (300–2000 Hz, default 600 Hz, NEW) splits the remainder into Mid and High. The two are clamped ≥1/3 octave apart (src/dsp/SplitGap.h) to prevent a degenerate near-zero-width Mid band.src/dsp/MidBand.h/.cpp): staged/cascaded drive-only saturation (0–100%, default 30%) + Level, no filter/tone/blend — matching the reference class's own Mid band exactly.tests/LowBandIsolationTests.cpp).src/dsp/PhaseAlignFilter.h(unplanned engineering necessity, discovered during this rebuild): a naive cascade of two independent LR4 crossovers does not flat-sum on its own — up to −10 dB deviation was measured at close split ratios. Fixed with an allpass compensation filter on the Low band; the fix is proven algebraically (not just empirically) indocs/architecture.md's "Cascaded 3-band flat-sum and phase alignment" section.crossoverFreqvalue maps to the newsplitHighHz, clamped into 300–2000 Hz. v0.1.x's shipped default (250 Hz) lands exactly at the 300 Hz floor — dedicated regression test intests/StateMigrationTests.cpp.M2 preset system (ported from
basilica-audio/nave's pilot)src/presets/PresetManager.{h,cpp},PresetBar.{h,cpp},Localisation.{h,cpp}— copied verbatim per the replication recipe.presets/factory/*.json, documented indocs/presets.md): Default, Glue & Grind, Sub Lock, Throat, Fuzz Wall, Cut Through, Definition Only, Clean Low/Loud Top, Cab-Colored Grind.resources/i18n/de.txt); core/DSP terminology is never translated.CMakeLists.txt:juce_add_binary_data(CryptaBinaryData ...), linksjuce_gui_basics+CryptaBinaryDataintoSharedCode.PluginEditornow docks aPresetBarabove the existing generic editor.Version
Bumped to 0.2.0.
Test plan
ctest --test-dir build --output-on-failure— 96/96 Catch2 tests green locally (Debug, native arm64), up from 53 pre-rebuild. All v0.1.1 regression coverage (reset(), midFilter reset, tail length, oversized-block chunking) stays green.SplitGapTests,MidBandTests,ThreeBandFlatSumTests(3-band flat-sum incl. the minimum-gap clamp boundary),StateMigrationTests(incl. the untouched-v1-default → exactly-300Hz test),LowBandIsolationTests(IR-routing guarantee),TopologyRobustnessTests(NaN/Inf sweep of every new/changed control),PresetManagerTests(17 cases, ported from nave).cmake --build build --target Tests Crypta_Standalone— both build clean (Debug, Ninja, native arm64).🤖 Generated with Claude Code