Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,31 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.2.0] - 2026-07-16

### Changed (headline: 2-band → 3-band topology rebuild)

- **Restructured 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 ("bass, mids, and high frequencies are processed separately" - see `docs/design-brief.md`/`docs/research-notes.md` for the full sourcing). Two cascaded 4th-order Linkwitz-Riley crossovers replace v0.1.x's 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) further splits the remainder into Mid and High. `Split High` is always clamped at least 1/3 octave above `Split Low` (`src/dsp/SplitGap.h`) to prevent a degenerate near-zero-width Mid band.
- **Added a new Mid band** (`src/dsp/MidBand.h/.cpp`): staged/cascaded drive-only saturation (0-100%, default 30%) plus an independent output Level, no filter/tone/blend - matching the reference class's own Mid band exactly. Runs its own 4x-oversampled shaping stage.
- **Promoted the High band's pre-drive highpass ("Tight") from a Razor-only fixed 200 Hz internal constant to a first-class, voicing-independent control** (20-500 Hz, default 100 Hz), applied ahead of all three voicings (Gnaw/Wool/Razor) - closing the gap identified in the design brief's "Why v1 falls short" analysis.
- **Re-sourced the low-band parallel compressor's ballistics defaults** to the reference class's own fixed, documented "glue" bus-compressor values: ratio 4:1 → **2:1**, attack 10 ms → **3 ms**, release 120 ms → **6 ms** (release range floor lowered from 10 ms to 5 ms, a breaking pre-1.0 change, so the sourced default is reachable). Retires the v0.1.x manual's "New York style" framing, which characterized the wrong sub-genre of parallel compression for what the reference class actually implements - see `docs/research-notes.md` §3-4.
- **Relocated the IR loader (cab-sim convolution)** to process only the Mid+High post-sum signal, never the Low band - matching the reference class's "low band bypasses the cabsim" architecture. Structurally enforced (not just conventional) and directly tested (`tests/LowBandIsolationTests.cpp`): the Low band's own isolated output is bit-exact identical whether the IR loader is on or off, or which IR is loaded.
- **Re-anchored the post-sum 4-band EQ's default corner frequencies** to a sourced bass-tone-stack frequency set from the same design lineage as the reference class: Low Shelf 100 → **80 Hz**, Peak 2 2500 → **2800 Hz**, High Shelf 8000 → **5000 Hz** (Peak 1's existing 500 Hz default already matched the sourced anchor). Dormant-until-engaged (EQ ships off by default), so not an audible v0.1.x → v0.2.0 change unless a user or preset turns the EQ on.
- **Added a phase-alignment allpass filter for the Low band** (`src/dsp/PhaseAlignFilter.h`), required to make the new cascaded (not parallel) crossover topology actually flat-sum - discovered and fixed during this rebuild: a naive cascade of two independent LR4 crossovers does *not* flat-sum on its own (deviations up to −10 dB were measured at close `Split Low`/`Split High` ratios before this fix). The fix is proven algebraically, not just empirically - see `docs/architecture.md`'s "Cascaded 3-band flat-sum and phase alignment" section for the full derivation. This is a genuine engineering necessity this rebuild surfaced, not something anticipated by the original design brief.
- **Lossy state migration for v0.1.x sessions**: the old single `Crossover Frequency` (`crossoverFreq`) parameter is migrated to the new `Split High` parameter on load, clamped into its 300–2000 Hz range. v0.1.x's shipped default (250 Hz) sits below that floor, so the single most common migration path - an untouched v0.1.x session - lands exactly at the 300 Hz floor (dedicated regression test in `tests/StateMigrationTests.cpp`). `Split Low` and every new Mid-band/Tight parameter fall back to their v0.2.0 defaults; any low-band compressor values a user had explicitly changed away from v0.1.x's old defaults are preserved as-is.
- Docs rewritten to match: `docs/manual.md`, `docs/architecture.md`, `README.md` (signal-flow diagrams, parameter tables, feature list). `docs/design-brief.md` and `docs/research-notes.md` added (the binding brief and its sourcing for this rebuild).

### Added (M2 preset system)

- Suite-wide M2 preset system (`.scaffold/specs/preset-system-m2.md`), ported from `basilica-audio/nave`'s pilot implementation: `src/presets/PresetManager.{h,cpp}` (factory + user presets, save/save-as/delete/rename, default resolution, import/export of single presets and zip banks, dirty-state tracking) and `src/presets/PresetBar.{h,cpp}` (a horizontal preset strip docked at the top of the editor).
- Nine factory presets (`presets/factory/*.json`, category `Init`/`Bass`) - see `docs/presets.md` for what each demonstrates: **Default**, **Glue & Grind**, **Sub Lock**, **Throat**, **Fuzz Wall**, **Cut Through**, **Definition Only**, **Clean Low, Loud Top**, **Cab-Colored Grind**.
- German localisation of the preset UI frame (`resources/i18n/de.txt`), auto-selected via `SystemStats::getUserLanguage()`. Core/DSP terminology (parameter names, units) is never translated.
- User presets stored at `~/Library/Audio/Presets/Yves Vogl/Crypta/` (macOS) / `%APPDATA%\Yves Vogl\Crypta\Presets\` (Windows).

### Fixed

- Discovered and fixed during the topology rebuild: a naive cascade of two independent LR4 crossovers does not flat-sum (see the phase-alignment entry above) - this was never an issue in v0.1.x's single-crossover topology, so it is not a regression from any prior release, but a new correctness requirement introduced by the 3-band rebuild itself.

## [0.1.1] - 2026-07-16

### Changed
Expand Down
28 changes: 27 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "Minimum macOS deployment ta
# here at the top level avoids it being enabled implicitly deeper inside
# JUCE's CMake helpers, which has been observed to break Ninja's generate
# step (missing CMAKE_C_COMPILE_OBJECT rule variable).
project(Crypta VERSION 0.1.1 LANGUAGES C CXX)
project(Crypta VERSION 0.2.0 LANGUAGES C CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand Down Expand Up @@ -56,6 +56,30 @@ juce_add_plugin(Crypta
ICON_BIG "docs/assets/icon.png"
)

# ==============================================================================
# Embedded assets: M2 preset system factory presets (presets/factory/*.json)
# and the M2 i18n frame's German translation (resources/i18n/de.txt). See
# src/presets/PresetManager.h and src/presets/Localisation.h - both consume
# these purely via BinaryData:: symbols passed in from PluginProcessor.cpp/
# PluginEditor.cpp, never by including BinaryData.h themselves, so they stay
# portable to sibling plugins (see docs/preset-system-notes.md in
# basilica-audio/nave, the M2 pilot this suite-wide pattern was replicated
# from).
# ==============================================================================

juce_add_binary_data(CryptaBinaryData SOURCES
presets/factory/default.json
presets/factory/glueAndGrind.json
presets/factory/subLock.json
presets/factory/throat.json
presets/factory/fuzzWall.json
presets/factory/cutThrough.json
presets/factory/definitionOnly.json
presets/factory/cleanLowLoudTop.json
presets/factory/cabColoredGrind.json
resources/i18n/de.txt
)

# ==============================================================================
# SharedCode: an INTERFACE target carrying the plugin's sources, definitions,
# and library links so that both the plugin targets (AU/VST3/Standalone) and
Expand Down Expand Up @@ -86,9 +110,11 @@ target_compile_definitions(SharedCode INTERFACE
target_link_libraries(SharedCode INTERFACE
juce::juce_audio_utils
juce::juce_dsp
juce::juce_gui_basics
juce::juce_recommended_config_flags
juce::juce_recommended_lto_flags
juce::juce_recommended_warning_flags
CryptaBinaryData
)

target_link_libraries(Crypta PRIVATE SharedCode)
Expand Down
77 changes: 41 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,56 +6,60 @@

> Formerly **Twist Your Guts**, renamed to Crypta as part of the suite's move to Basilica Audio naming (the crypt: the basilica's low-end foundation). If you have a v0.1.0-era session referencing the old plugin identity (`com.yvesvogl.twistyourguts`, plugin code `Tygt`), see the [Unreleased] entry in [`CHANGELOG.md`](CHANGELOG.md) — the new bundle ID and plugin code (`com.yvesvogl.crypta`, `Cryp`) mean DAWs treat this as a new plugin, so existing sessions will need to be re-pointed at the new plugin.

[![CI](https://github.com/metal-up-your-ass/Crypta/actions/workflows/ci.yml/badge.svg)](https://github.com/metal-up-your-ass/Crypta/actions/workflows/ci.yml)
[![CI](https://github.com/basilica-audio/Crypta/actions/workflows/ci.yml/badge.svg)](https://github.com/basilica-audio/Crypta/actions/workflows/ci.yml)
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)

> **Work in progress.** Crypta is pre-1.0 and under active development (v0.1.0). Binaries for macOS and Windows are available from the [Releases](../../releases) page (macOS builds are signed & notarized); building from source works too. Expect breaking changes until v1.0.0 ships (see [Roadmap](#roadmap)).
> **Work in progress.** Crypta is pre-1.0 and under active development (v0.2.0). Binaries for macOS and Windows are available from the [Releases](../../releases) page (macOS builds are signed & notarized); building from source works too. Expect breaking changes until v1.0.0 ships (see [Roadmap](#roadmap)).

## What it is

Crypta is a Parallax-style bass plugin built on JUCE 8. It splits your bass signal into low and high bands with a linear-phase-adjacent Linkwitz-Riley crossover, compresses the low band in parallel, and runs the high band through a choice of three distortion voicings before summing everything back together through a 4-band EQ and an impulse-response (cab sim) loader. See [`docs/manual.md`](docs/manual.md) for the full parameter reference and usage tips.
Crypta is a Parallax-style bass plugin built on JUCE 8. As of v0.2.0 it splits your bass signal into **three** bands — low, mid, and high with two cascaded 4th-order Linkwitz-Riley crossovers, compresses the low band in parallel, drives the mid band with staged saturation, and runs the high band through a choice of three distortion voicings before summing everything back together through a 4-band EQ and an impulse-response (cab sim) loader. v0.2.0 also adds a full preset system (factory + user presets, import/export, German localisation). See [`docs/manual.md`](docs/manual.md) for the full parameter reference and usage tips, and [`docs/design-brief.md`](docs/design-brief.md)/[`docs/research-notes.md`](docs/research-notes.md) for the research behind the v0.2.0 topology rebuild.

## Features

- **Noise gate** — full-band, ahead of the crossover split
- **LR4 crossover band-split** — 4th-order Linkwitz-Riley split, adjustable 60 Hz – 1000 Hz (default 250 Hz)
- **Low band**: parallel ("New York style") compressor with makeup gain, wet/dry mix, and output level
- **High band**: three distortion voicings, each 4x oversampled to keep aliasing under control, with independent drive/tone
- **Noise gate** — full-band, ahead of both crossover splits
- **Two cascaded LR4 crossover splits** — Split Low (60–400 Hz, default 120 Hz) and Split High (300–2000 Hz, default 600 Hz), building a genuine 3-band (low/mid/high) topology, replacing v0.1.x's 2-band split
- **Low band**: parallel "glue" compressor (re-sourced fast/gentle ballistics, ratio 2:1 / attack 3 ms / release 6 ms) with makeup gain, wet/dry mix, and output level
- **Mid band** (NEW): staged/cascaded drive-only saturation, no filter/tone/blend — a distinct "throatier" character separate from the high band
- **High band**: three distortion voicings, each 4x oversampled to keep aliasing under control, now with a shared, voicing-independent **Tight** pre-drive highpass (was Razor-only in v0.1.x)
- **Gnaw** — op-amp-style hard clip
- **Wool** — cascaded soft-clip fuzz with a mid scoop
- **Razor** — tight overdrive: pre-clip highpass, soft clip, mid hump
- Clean/distorted blend control per voicing, plus output level
- **4-band EQ** post-sum (LowShelf / Peak / Peak / HighShelf)
- **IR loader** (cabinet simulation) on the output stage — convolution engine is live; bundled factory IRs and a GUI file browser land in a later milestone
- **Delay-compensated signal path** — the high band's oversampling latency is reported to the host and the low band is time-aligned to match
- **Presets** with full state save/recall *(planned — a dedicated preset manager/versioning scheme is a later milestone; APVTS state save/load already round-trips today)*
- **Razor** — tight overdrive: soft clip, mid hump
- Clean/distorted blend control, plus drive/tone/output level
- **4-band EQ** post-sum (LowShelf / Peak / Peak / HighShelf), re-anchored default frequencies (80/500/2800/5000 Hz, sourced from the same design lineage's hardware tone stack)
- **IR loader** (cabinet simulation), relocated in v0.2.0 to process only the Mid+High post-sum signal — the low band never passes through it, matching the reference class's own architecture. Convolution engine is live; bundled factory IRs and a GUI file browser land in a later milestone
- **Delay-compensated, phase-aligned signal path** — the Mid+High branch's shared oversampling latency is reported to the host, the low band is time-aligned to match, and a phase-alignment allpass filter keeps the cascaded three-way sum flat-magnitude
- **Presets** — factory + user presets, save/save-as/delete, import/export (single files and zip banks), German localisation of the preset UI frame
- **State migration** — a v0.1.x session's single crossover frequency is migrated to the new Split High parameter on load
- **Metering** throughout the signal chain *(planned, alongside the custom GUI)*

## Signal flow

```
Input Trim → Gate → LR4 Split (60–1000 Hz, default 250 Hz)
Input Trim → Gate → LR4 Split Low (60–400 Hz, default 120 Hz)
┌─────────────┴─────────────┐
│ │
Low band High band
Parallel Comp Voicing → Drive → Tone → Blend
→ Makeup → Mix │
│→ Level → Level
└─────────────┬─────────────┘
Sum (delay-compensated)
4-band EQ
IR loader
Safety Clip (optional)
Output Trim
┌─────────────┴───────────────────────────────┐
│ │
Low band Remainder → LR4 Split High (300–2000 Hz, default 600 Hz)
Parallel Comp → Level │
│ ┌───────────────────┴───────────────────┐
│ Mid band High band
│ Drive → Level Tight → Voicing → Drive → Tone → Blend → Level
│ └───────────────────┬───────────────────┘
│ Mid+High sum → IR loader (cab sim)
│ │
└──────────── Phase-align + delay ───────────────┘
Sum (delay-compensated)
4-band EQ
Safety Clip (optional)
Output Trim
```

The high band runs 4x oversampled for the distortion stage; the low band is delay-compensated to stay time-aligned with it before the sum. See [`docs/architecture.md`](docs/architecture.md) for the full breakdown, including the latency-compensation strategy, and [`docs/manual.md`](docs/manual.md) for the full parameter reference.
The Mid and High bands each run 4x oversampled (identically configured, so their latencies match exactly); the low band is delay-compensated and phase-aligned to stay both time- and magnitude-flat with them before the sum. See [`docs/architecture.md`](docs/architecture.md) for the full breakdown, including the latency-compensation strategy and the phase-alignment proof, and [`docs/manual.md`](docs/manual.md) for the full parameter reference.

## Parameters

Expand All @@ -65,9 +69,10 @@ See [`docs/manual.md`](docs/manual.md) for the complete, musically-annotated par
|---|---|
| IO / Global | Input Gain, Output Gain, Bypass, Safety Clip |
| Noise Gate | Enable, Threshold, Ratio, Attack, Release |
| Crossover | Frequency (60–1000 Hz) |
| Crossover | Split Low (60–400 Hz), Split High (300–2000 Hz) |
| Low band | Comp Threshold/Ratio/Attack/Release/Makeup/Mix, Level |
| High band | Voicing (Gnaw/Wool/Razor), Drive, Tone, Blend, Level |
| Mid band | Drive, Level |
| High band | Tight, Voicing (Gnaw/Wool/Razor), Drive, Tone, Blend, Level |
| EQ | Enable, Low Shelf Freq/Gain, Peak 1 Freq/Gain/Q, Peak 2 Freq/Gain/Q, High Shelf Freq/Gain |
| IR loader | Enable, Mix |

Expand Down Expand Up @@ -111,7 +116,7 @@ ctest --test-dir build --output-on-failure
|---|---|---|
| M0 | Bootstrap — project skeleton, CI, docs | Done |
| M1 | DSP completion & test coverage — gate, crossover, parallel compressor, 3 voicings (oversampled), 4-band EQ, IR loader, latency compensation, broadened test suite | Done (v0.1.0) |
| M2 | Presets & state recall — preset manager, factory presets, versioned state | Planned |
| M2 | Deep-dive topology rebuild (2-band → 3-band) + presets & state recall — preset manager, 9 factory presets, state migration, German localisation | Done (v0.2.0) |
| M3 | GUI & accessibility — custom LookAndFeel, metering UI, accessibility pass | Planned |
| M4 | Release: signing, notarization, v1.0.0 — installers, tagged release | Planned |

Expand All @@ -132,4 +137,4 @@ Tagged releases (`v*`) are built and published automatically by [`.github/workfl
- **macOS** — AU (`.component`), VST3 (`.vst3`), and Standalone, Universal Binary (arm64 + x86_64), signed with a Developer ID Application certificate (org-level secrets, shared across the Basilica Audio suite), notarized, and stapled. Installs and opens without a Gatekeeper warning.
- **Windows** — VST3 and Standalone, **unsigned**. On first run, Windows SmartScreen may show a "Windows protected your PC" warning; choose **More info → Run anyway** to proceed. A signed Windows build is a documented future improvement, not yet available.

See [`v0.1.0`](https://github.com/metal-up-your-ass/Crypta/releases/tag/v0.1.0) for the most recent published release (under the plugin's prior identity as Twist Your Guts); the next tagged release under the Crypta identity is planned as `v0.2.0`.
See [`v0.1.1`](https://github.com/basilica-audio/Crypta/releases/tag/v0.1.1) for the most recent published release; `v0.2.0` is the next tagged release, shipping the 2-band → 3-band topology rebuild and the M2 preset system.
Loading