feat: v0.2.0 deep-dive voicing pass, M2 presets, DE localisation, app icon#20
Merged
Merged
Conversation
…n, app icon Research-driven rework of the Drive -> Clipper -> Tone portion of the signal chain (docs/design-brief.md, docs/research-notes.md), sourced from published tube-screamer circuit analyses, a purpose-built commercial pedal's own documentation, and publicly reported artist workflows - not measured against physical reference hardware. New controls inside the oversampled block: bite_amount (frequency- dependent gain INSIDE the drive-to-clipper path via a ~700 Hz low-shelf, 0% bit-identical to v0.1), knee_soften (drive-dependent knee rounding via src/dsp/KneeSoftening.h, 0% bit-identical to v0.1), and asymmetry_amount (exposes the previously-fixed Asymmetric voicing bias, default reproduces v0.1's a=0.2 exactly). Tone (cut-only, 1-8 kHz) is replaced by Bite Tilt, a bidirectional +/-3 kHz shelf that can darken and brighten; an old v0.1 session's tone value is lossily migrated onto an equivalent Bite Tilt position on load. Defaults changed: Tight 130 -> 100 Hz (the sourced 80-120 Hz workflow sweet spot's midpoint), Drive 8 -> 3 dB (the best-documented "near-zero drive, Level does the pushing" workflow). The Voicing enum's persisted indices remain frozen. Implements the suite-wide M2 preset system (.scaffold/specs/preset-system-m2.md) for the first time in this repo: src/presets/PresetManager (factory presets embedded via BinaryData, user presets on disk, dirty tracking, prev/next, single-file and zip-bank import/export, user-wins-over-factory default resolution) and src/presets/PresetBar, copied verbatim from the Nave pilot implementation per docs/preset-system-notes.md's replication recipe. Ships with nine factory presets (docs/presets.md: a certified Default plus eight use-case presets from the brief) and a German frame-string localisation (resources/i18n/de.txt, selected via SystemStats::getUserLanguage()). The app icon is now wired into the built AU/VST3/Standalone via ICON_BIG (previously missing - no patch release had shipped since it was added to docs/README). Also folds in the suite-wide release.yml fix: an idempotent create-release job so gh release upload has an object to attach assets to on a fresh tag push (both platform jobs now needs: create-release). 96 Catch2 tests green (up from the 54 on main): new DSP-primitive tests (KneeSofteningTests.cpp), asymmetry-sweep and v0.1 backward-compatibility regression tests, Bite frequency-dependent-gain and Knee Soften drive-dependence spectral proofs, Bite Tilt bidirectionality/no-op/ subsumes-v0.1-Tone tests, state-migration tests, the M2 PresetManager suite, and i18n frame tests - full breakdown in the PR description. 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 rework of Overture's Drive -> Clipper -> Tone chain (
docs/design-brief.md,docs/research-notes.md), the M2 preset system, a German i18n frame, and housekeeping (app icon wiring, release workflow fix).DSP rework
biteAmount("Bite", 0-100%, default 65%): frequency-dependent gain inside the drive-to-clipper path via a fixed ~700 Hz low-shelf (anchored to the sourced ~720 Hz reference-circuit feedback corner), applied to the oversampled signal immediately before the voicing dispatch. Bass is clipped less than treble - the reference circuit's actual tightening mechanism, not an approximation via a separate pre-clip filter (Tight keeps doing that unchanged job). Skipped entirely (not unity-gain) at 0% - bit-identical to v0.1's flat-gain clipper.kneeSoften("Knee Soften", 0-100%, default 40%): drive-dependent knee softening (src/dsp/KneeSoftening.h), blending each voicing's raw output towardtanh(raw), scaled by(kneeSoften/100) * driveIntensity. Applies to all three voicings including Hard Clip (zero knee at 0%, any Drive). Algebraically always 0 atkneeSoften = 0, so Drive-invariant, matching v0.1.asymmetryAmount("Asymmetry", 0-100%, default 40%): exposes the Asymmetric voicing's previously-fixed bias (a = 0.2) as a 0.0-0.5 mapped control. Default reproduces v0.1's fixed bias exactly.biteTilt("Bite Tilt", -100%..+100%, default 0%) replacestone: a single 2nd-order RBJ high-shelf around a fixed ~3 kHz corner, bidirectional (v0.1's Tone could only ever darken). Flat is a true no-op (filter skipped, not unity-gain). A v0.1 session'stonevalue is lossily migrated to an equivalentbiteTiltposition on load (OvertureAudioProcessor::setStateInformation()), detected beforeapvts.replaceState()runs.tight130 -> 100 Hz (midpoint of the sourced 80-120 Hz workflow sweet spot),drive8 -> 3 dB (best-documented "near-zero drive, Level does the pushing" workflow). Voicing enum indices remain frozen.ArrayCoefficients+ovtr::applyBiquadCoefficientspatternmainalready established for Tight/Tone (issue Unconditional per-block heap allocation in OvertureEngine::process() via IIR::Coefficients::make{High,Low}Pass #12) -tests/AllocationTests.cppextended accordingly.M2 preset system
Copied verbatim from the Nave pilot implementation (
src/presets/PresetManager.{h,cpp},src/presets/PresetBar.{h,cpp}) per.scaffold/specs/preset-system-m2.md. Nine factory presets (docs/presets.md): a certified Default (= Classic Boost's settings, the shipped defaults) plus the brief's eight named presets (Clean Push, Classic Boost, Drop-Tune Tight, Smooth Push, Own Distortion, Fuzz-Adjacent Lead, Parallel Grit, De-Fizz Cleanup).i18n
German localisation of the preset-bar frame (
resources/i18n/de.txt,src/presets/Localisation.{h,cpp}), auto-selected viaSystemStats::getUserLanguage(). Core/DSP parameter names are never translated (verified bytests/LocalisationTests.cpp).Housekeeping
ICON_BIG "docs/assets/icon.png"added tojuce_add_plugin()- previously missing (no patch release had shipped since the icon was added to docs/README)..github/workflows/release.yml: added an idempotentcreate-releasejob (both platform jobs nowneeds: create-release) - suite-wide fix ported frombasilica-audio/cryptamain, folded into this PR per the orchestrator's flow addition (nothing else had touched this file).docs/architecture.md,docs/manual.md,README.md,CHANGELOG.md,CLAUDE.mdupdated for v0.2.0.Scope note on the "0% = v0.1-identical" guarantee
The brief's guarantee 1 ("bite_amount = 0 and knee_soften = 0 reproduce v0.1's exact transfer function bit-for-bit... for all three voicings, at every Drive level") is tested at the clipper-transfer-function level (
tests/ClipperVoicingTests.cpp's new backward-compatibility test, comparing the composed dispatch against the unmodifiedClipperVoicings::processSampleprimitive bit-for-bit) rather than as a whole-engine snapshot diff against v0.1's actual binary output. Tight/Drive/Oversample/Level/Mix are structurally unchanged code (only Tight/Drive's default values moved), so a whole-engine null test on those specifically would be redundant; Bite/Bite Tilt's own "skip when off" behaviour is separately verified by their own dedicated spectral/no-op tests.Test plan
cmake --build build --target Tests Overture_Standalone && ctest --test-dir build --output-on-failure- 96/96 test cases, 21278/21278 assertions passed (up from 54 onmain).tests/AllocationTests.cpp, extended from issue Unconditional per-block heap allocation in OvertureEngine::process() via IIR::Coefficients::make{High,Low}Pass #12's original Tight/Tone guard).bite_amount = 0/knee_soften = 0reproduce v0.1's clipper dispatch bit-for-bit, all three voicings (tests/ClipperVoicingTests.cpp).biteAmountat a fixed Drive (tests/EngineTests.cpp).kneeSoften; zero atkneeSoften = 0regardless of Drive (tests/EngineTests.cpp).a = 0.2(tests/ClipperVoicingTests.cpp).tests/EngineTests.cpp).tonemaps to the documentedbiteTiltequivalent, new parameters fall back to their own defaults (tests/StateTests.cpp).tests/PresetManagerTests.cpp, 16 cases).de.txtparses, every TRANS() key used by the preset frame is present, parameter names are verifiably absent from the mapping (tests/LocalisationTests.cpp).tests/RobustnessTests.cpp).🤖 Generated with Claude Code