Skip to content

feat: v0.2.0 deep-dive rework, M2 preset system, i18n frame#22

Merged
yves-vogl merged 1 commit into
mainfrom
feat/v0.2.0-deep-dive-and-presets
Jul 16, 2026
Merged

feat: v0.2.0 deep-dive rework, M2 preset system, i18n frame#22
yves-vogl merged 1 commit into
mainfrom
feat/v0.2.0-deep-dive-and-presets

Conversation

@yves-vogl

Copy link
Copy Markdown
Contributor

Summary

Research-derived deep-dive rework of Triptych's per-band compressor voicing, plus the suite-wide M2 preset system and a German i18n frame. Ships as v0.2.0.

Deep-dive voicing rework (docs/design-brief.md, sourced in docs/research-notes.md)

  • New soft-knee stage. v0.1 wrapped juce::dsp::Compressor directly, whose gain formula (gain = (env < threshold) ? 1.0 : pow(env * thresholdInverse, ratioInverse - 1.0)) is a hard knee with zero transition width - confirmed by reading the JUCE 8.0.14 source, and no knee parameter existed anywhere in v0.1's ParameterLayout.cpp. BandCompressor now drives juce::dsp::BallisticsFilter directly (the same envelope-follower class Compressor used internally) through a from-scratch gain computer, src/dsp/KneeGainComputer.{h,cpp}, implementing the standard quadratic soft-knee interpolation (Giannoulis/Massberg/Reiss, JAES 2012) with a new per-band Knee parameter (0-100%, default 50%). Knee's extent is threshold-relative: at 100% it spans [2 * thresholdDb, 0], matching the Weiss DS1-MK3 manual's documented "0 to twice the threshold value" convention. At 0%, KneeGainComputer::computeGainLinear() takes a dedicated linear-domain fast path that reproduces v0.1's exact hard-knee formula bit-for-bit - a tested regression guarantee (tests/KneeGainComputerTests.cpp, tests/BandCompressorTests.cpp).
  • Per-band default recalibration. v0.1 gave Low/Mid/High one identical, uniform default (threshold -18 dB, ratio 4:1, attack 10 ms, release 100 ms). Research into the mastering multiband-compressor reference class documented two opposite philosophies (peak control vs. density/knit-together) and band-position-dependent ballistics that v0.1's uniform default matched neither of. New defaults: Low -24 dB/2.5:1/25 ms/180 ms, Mid -30 dB/1.8:1/10 ms/100 ms (the v0.1 anchor), High -20 dB/2:1/5 ms/55 ms - encoded as a standing invariant (lowAttack > midAttack > highAttack, lowRelease > midRelease > highRelease), not just a one-time value, in tests/VoicingGuaranteesTests.cpp.
  • Explicitly out of scope (named, not implied as parity with the reference class): external sidechain and adjustable crossover slopes (already deferred from M1, unchanged reasoning); newly identified as v0.2.0 gaps and deferred to M2+/M3: per-band Mid/Side processing, an RMS/Peak-selectable detector mode, and program-dependent/auto-release. See docs/architecture.md's "Deferred from v0.2.0" section and docs/design-brief.md's honesty section.
  • This voicing is research-derived, sourced from published manufacturer manuals (Weiss DS1-MK3, FabFilter Pro-MB) and a mastering-engineer technique article (Sound on Sound), not measured against reference hardware - flagged explicitly in the manual/CHANGELOG per the sibling Miserere v2 brief's framing.

M2 preset system (.scaffold/specs/preset-system-m2.md)

  • src/presets/ (PresetManager/PresetBar/Localisation) copied verbatim from the basilica-audio/nave pilot implementation - see docs/preset-system-notes.md in that repo for the replication recipe.
  • Eight factory presets (presets/factory/*.json, docs/presets.md): Default, Density Glue, Peak Control, Low-End Tighten, De-Harsh Highs, Mastering Safety Ceiling, Parallel-Style Density, Hard Limiter Ceiling.
  • German localisation of the preset bar's frame strings (resources/i18n/de.txt), selected automatically for de* system languages; parameter names/units are never translated.
  • State migration is tolerant: a pre-v0.2.0 session missing the new Knee parameter IDs loads cleanly with Knee at its declared default (50%), not 0/garbage - relies on AudioProcessorValueTreeState::replaceState()'s own existing "missing ID keeps current value" behaviour, no special-case code needed (tests/StateTests.cpp's migration-tolerance test).

Housekeeping

  • ICON_BIG "docs/assets/icon.png" was already present in CMakeLists.txt (added by the concurrent patch-release PR) - verified, not re-added.
  • .github/workflows/release.yml's create-release fix was already merged to main before this branch was cut - verified present.
  • docs/manual.md updated for the new Knee parameter, per-band defaults, presets, and i18n.

Test plan

  • cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug (CPM_SOURCE_CACHE, native arm64) configures cleanly.
  • cmake --build build --target Tests Triptych_Standalone --parallel 4 builds cleanly (no new warnings beyond JUCE's own pre-existing splash-screen pragma note).
  • ctest --test-dir build --output-on-failure - 73/73 tests green (up from 42; all v0.1 test intent preserved, two tests pinned to Knee 0% to keep their exact v0.1 regression assertions, adjusted defaults elsewhere per ParameterTests.cpp).
  • CI matrix (macOS + Windows, pluginval strictness 10 + auval) - pending this PR's checks.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

Research-derived voicing rework (docs/design-brief.md, sourced in
docs/research-notes.md): replaces juce::dsp::Compressor's hard-knee-only
gain formula with a from-scratch, threshold-relative soft-knee gain
computer (src/dsp/KneeGainComputer.{h,cpp}, driven by
juce::dsp::BallisticsFilter) and a new per-band Knee parameter (0-100%,
default 50%, bit-for-bit identical to v0.1 at 0%). Per-band
Threshold/Ratio/Attack/Release defaults now diverge (Low/Mid/High) instead
of sharing one uniform default, encoding the documented peak-control vs.
density mastering philosophies and per-band ballistics as standing
invariants rather than one-time values.

Adds the suite-wide M2 preset system (src/presets/, copied from the
basilica-audio/nave pilot implementation): factory/user presets, default
resolution, import/export (single files and zip banks), dirty-state
tracking, and a PresetBar editor strip. Ships eight factory presets
(docs/presets.md) and a German localisation of the preset bar's frame
strings (resources/i18n/de.txt).

State migration is tolerant: sessions saved before v0.2.0 (missing the new
Knee parameter IDs) load cleanly with Knee at its declared default.

Test suite grows from 42 to 73 Catch2 cases: Knee null test and curve-shape
guarantees, per-band-default-divergence and attack/release-ordering
regression guarantees, the full M2 preset system suite, a state
migration-tolerance test, and i18n coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@yves-vogl
yves-vogl merged commit 82e009f into main Jul 16, 2026
2 checks passed
@yves-vogl
yves-vogl deleted the feat/v0.2.0-deep-dive-and-presets branch July 16, 2026 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant