Crypta — User Manual

Split your bass. Compress the lows. Twist the guts out of the highs.

What it is

Crypta is a parallel bass processor built for metal production, in the lineage of the reference plugin class for parallel-bus bass processing. As of v0.2.0 it splits your bass signal into three bands — low, mid, and high — with two cascaded 4th-order Linkwitz-Riley ("LR4") crossovers, keeps the low band tight with a parallel compressor, 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 a cabinet-simulation IR loader.

Research-derived rebuild (v0.2.0)

v0.2.0 is a research-driven rewrite of v0.1.x's simpler two-band (low/high) topology, sourced against the reference plugin class's own official user manual, a third-party professional review, the same design lineage's hardware product manual, and general parallel-bus-compression community/vendor consensus — not measured against any reference plugin's actual audio output, DSP source code, or hardware unit by this project. See docs/design-brief.md and docs/research-notes.md for the full sourcing, and the same disclosure v0.1.x already carried: voicing character (drive-gain ranges, mid-filter hump/scoop settings) is engineering-tuned, not yet finalized by ear against reference material.

Where it sits in a heavy-music chain

Crypta is designed to be the bass-specific voicing stage in the Basilica Audio suite:

Signal flow

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

The Mid and High bands share the same oversampling anti-aliasing headroom (each 4x oversampled independently, but identically configured, so they report identical latency); the low band carries a matching compensation delay, plus a phase-alignment allpass filter tied to Split High's own cutoff, so all three bands sum flat and stay time-aligned at the final sum. The IR loader (cabinet simulation) sits after the Mid+High sum and before the final three-way sum — the Low band never passes through it, matching the reference class's "low band bypasses the cabsim" architecture. See docs/architecture.md for the full technical breakdown, including exactly how the latency and phase-alignment compensation work.

Reported latency

Crypta is not zero-latency: oversampling is its source. Reported latency is a function of the sample rate alone, identical across both Drive Engines at every rate (44.1 / 48 / 96 / 192 kHz), and independent of host block size (tests/LatencyTests.cpp, "T14"). This is deliberate: the two engines can have different intrinsic latencies (Circuit's oversampling factor adapts to the host rate — 4x at or below 50 kHz, 2x at or below 100 kHz, 1x above; Classic is always 4x), so rather than re-report latency whenever you automate Drive Engine — which hosts handle poorly mid-transport — the plugin reports the maximum across both engines and pads the Circuit path up to it. Switching Drive Engine therefore never shifts your track by a sample.

One consequence worth knowing: the reported figure is the oversampling delay, not a full group-delay description. On Classic, a test impulse peaks within 1 sample of the reported latency; on Circuit it peaks within 32 samples, because the two extra IIRs Circuit's High band carries (the 10 Hz DC blocker and the drive-tracked pole) move the impulse's peak by up to roughly 25 samples (about 0.5 ms) without changing what gets reported. No single number can describe a frequency-dependent group delay - what is guaranteed instead is that the reported figure matches across engines and rates, and that the three-way band sum stays flat (≤ 1.0 dB deviation) at every split-frequency combination tested.

No absolute sample count is pinned as a constant in this manual - check your host's own plugin-delay-compensation readout for the exact figure at your session's sample rate.

Presets

Crypta ships with a preset system: a horizontal bar at the top of the plugin window lets you step through factory and user presets (< / preset name / >), save/save-as/delete your own, and import/export single presets or preset banks (zip files of multiple presets). Nine factory presets ship in v0.2.0 — see docs/presets.md for what each one demonstrates. User presets are stored per-plugin under:

A fresh instance loads a user "Default" preset if you've saved one ("Set current as default" in the preset menu), otherwise the factory "Default" preset (matching the plain parameter defaults documented below).

The interface

The plugin window is laid out in signal order, left to right and top to bottom, in ten sections: Input, Noise Gate, Crossover, Low Band, Drive Engine, Mid Band, High Band, Cabinet, EQ, Output. Whatever you see further right or further down happens later in the chain. Every one of the plugin's 54 parameters is on the front panel — nothing is hidden behind a menu.

Knobs. Drag up/down or left/right to turn; hold Shift while dragging for fine adjustment. Knobs with a fixed set of positions (Gate Mode, Low Comp Detector, Drive Engine, High Voicing) click into their detents and show the option's name. Double-click a value box to type an exact number.

Keyboard. Every control is reachable with Tab, in signal order — and Tab never gets stuck inside one section. With a knob focused:

Key Step
← / → / ↑ / ↓ 1 % of the knob's range (choice knobs: one position)
Shift + arrow fine — 0.1 % of the range
Page Up / Page Down 10 % of the range
Home / End minimum / maximum

Toggles (the lamp switches) respond to Space and Return. Ctrl/Cmd-modified arrows are left alone, so your host's own shortcuts keep working. The focused control is always marked with a gold ring.

Screen readers. Every control announces its name, its role and its current value with units ("Gate Threshold, slider, −60.00 dB"), and each section is announced as a named group. The four meters can be queried on demand and read out their current value ("Input peak level meter, −8.2 dBFS"); they deliberately do not interrupt you on every update.

Meters. Four needle meters read the metering added in v0.3.0:

Meter Scale Reads
IN −60…+6 dBFS Input block peak, before anything else
GATE 0…20 dB How much the noise gate is currently pulling down
COMP 0…20 dB How much the low band's parallel compressor is pulling down
OUT −60…+6 dBFS Output block peak, after everything

The peak meters rise fast and fall slowly, so a transient is actually visible, and the scale from 0 dBFS up is engraved in red — the needle turns red there too, but the position alone already tells you. Gain-reduction needles rest at the right and swing left as reduction deepens. All metering runs on the interface thread; it costs the audio engine nothing.

Resizing. Drag the grip in the bottom-right corner. The window keeps its aspect ratio and scales between 60 % and 180 % — it is a pure zoom, so nothing re-flows or gets clipped at any size. The size you choose is saved with the session and with the plugin instance, so a reopened project comes back the way you left it. A project saved before this version opens at 100 %.

Engines (NEW in v0.3.0)

Three parameters select between the v0.2.0 DSP and its v0.3.0 replacement. A new instance boots into the new engines; any session or preset you saved before v0.3.0 keeps the old ones, so nothing you have already made changes how it sounds. Switch freely — the change is crossfaded, not stepped.

Parameter Options Default (fresh instance) What changes
Drive Engine Classic / Circuit Circuit Classic is the v0.2.0 Mid and High band exactly. Circuit rebuilds both from circuit models, with far less aliasing (25–30 dB better) and per-voicing pre/post-emphasis networks.
Low Comp Detector Classic Peak / Smooth RMS Smooth RMS Classic Peak is the v0.2.0 detector. Smooth RMS measures over a window longer than one bass cycle, so the low band stops tremoloing on sustained low notes.
Gate Mode Classic / Modern Modern Classic is the v0.2.0 gate. Modern adds hysteresis, hold, a detector-only sidechain highpass and a straight-line release.

If you preferred the old sound, set the relevant engine to Classic — it is preserved exactly, not approximated.

Parameter reference

Unless noted otherwise, all continuous parameters are smoothed to avoid zipper noise when automated.

IO / Global

Parameter Range Default Unit What it does
Input Gain −24 … +24 0 dB Trims the signal before anything else in the chain. Use this to get a hot but not clipping signal into the gate/compressor/drive/voicing stages - all of their thresholds are calibrated assuming a reasonably "line level" input.
Output Gain −24 … +24 0 dB Final output trim, applied after everything else (including the safety clip). The control's own default is 0 dB, but a fresh instance starts on the factory Default preset, which sets −2.8 dB — the derived trim that keeps a −12 dBFS bass DI under full scale (every factory preset carries such a trim where it needs one).
Bypass off/on off Forces a bit-exact passthrough of the input signal. Also exposed as the plugin's host-facing bypass parameter, so your DAW's own bypass button/automation lane works too.
Safety Clip off/on off A soft ceiling clip on the very last stage before the output trim. Off by default; turn it on as a safety net against accidental hard-clipped overs, not as a tone-shaping tool. As of v0.3.0 it is antialiased and is genuinely transparent below the ceiling — arming it no longer colours anything until something actually reaches the ceiling.
Clip Ceiling −12 … 0 0 dBFS Where the safety clip starts working. Only read while Safety Clip is on. 0 dBFS reproduces the v0.2.0 behaviour.

Noise Gate (full-band, before the crossover splits)

Sits ahead of both crossovers, so it gates the input signal as a whole rather than per band.

Gate Ratio is Classic-only. Modern is a gate with a range floor rather than a ratio expander, and ignores it.

Parameter Range Default Unit What it does
Gate Enable off/on off Enables the gate. Off by default - most already-tracked bass DI/amp signals don't need one, and an incorrectly-set gate can chop off legitimate low-level playing (ghost notes, decays).
Gate Threshold −80 … 0 −60 dB Signal level below which the gate starts attenuating.
Gate Ratio 1 … 20 10 :1 How aggressively the gate attenuates once below threshold. Higher = closer to a hard mute.
Gate Attack 0.1 … 50 1 ms How fast the gate opens once the signal crosses back above threshold.
Gate Release 5 … 500 100 ms How fast the gate closes once the signal drops below threshold.
Gate Hysteresis 0 … 12 4 dB Modern only. How far below the threshold the signal must fall before the gate starts closing. This is what stops a note decaying through the threshold from making the gate stutter.
Gate Hold 0 … 500 20 ms Modern only. Keeps the gate open for this long after the signal drops, and restarts on each new transient — so it does not slam shut between fast notes.
Gate SC Highpass 20 … 400 80 Hz Modern only. Highpasses the gate's detector only; the audio is untouched. Raise it if a ringing low string is holding the gate open.
Gate Range 6 … 90 60 dB Modern only. How far a fully closed gate attenuates, and the height the release ramp falls through. A gate that only ducks 12 dB often sounds more natural than one that shuts completely.

Split Low / Split High (two cascaded crossovers, NEW topology in v0.2.0)

Parameter Range Default Unit What it does
Split Low 60 … 400 120 Hz The LR4 split point between the Low band and everything above it. Log-scaled control. Lower it to push more of the fundamental into the (compressed-only) Low band; raise it to give the Mid band more low-mid content to work with.
Split High 300 … 2000 600 Hz The LR4 split point between the Mid band and the High band. Log-scaled control.

Split High is always kept at least a fraction of an octave above Split Low internally (a reasoned safety margin against a degenerate near-zero-width Mid band) — if you push the two close together, Split High's effective value will float slightly above whatever you've set Split Low to, rather than collapsing the Mid band to nothing.

Low band: parallel compressor + level

The low band is compressed in parallel: the compressed signal is blended back with its own uncompressed self via Mix, rather than replacing it outright, which is what keeps the low end feeling tight and controlled without ever sounding squashed or lifeless. v0.2.0 re-sources the ballistics defaults to the reference class's own fixed, sourced values — a fast, gentle "glue" bus compressor, not the heavier "New York style" squash v0.1.x's defaults implied (see docs/research-notes.md §3–4 for the full sourcing).

Parameter Range Default Unit What it does
Low Comp Threshold −60 … 0 −18 dB Level above which the low-band compressor engages.
Low Comp Ratio 1 … 20 2 :1 Compression ratio above threshold.
Low Comp Attack 0.1 … 100 3 ms How fast the compressor clamps down once above threshold.
Low Comp Release 5 … 1000 6 ms How fast the compressor lets go once back under threshold. Range floor lowered from 10 ms in v0.1.x so the sourced 6 ms default is reachable.
Low Comp Makeup −12 … +24 0 dB Gain applied to the compressed (wet) signal before it's blended back with the dry low band - use this to bring the compressed signal back up to match the dry level, so Mix behaves as a true "how much compression character" control rather than also changing overall loudness.
Low Comp Mix 0 … 100 100 % Blend between the dry (uncompressed) and wet (compressed + makeup) low band. 0% = compressor has no audible effect; 100% = fully compressed.
Low Level −24 … +12 0 dB Level trim on the low band, applied after compression and before the bands are summed back together.
Low Comp Knee 0 … 18 6 dB Smooth RMS only. Width of the soft knee around the threshold. 0 dB is a hard knee; wider settings start compressing gradually as the signal approaches the threshold, which is much less obvious on sustained bass.
Low Comp Auto Release off/on on Smooth RMS only. Stretches the release on sustained material while leaving it at the set value for transients, so a held low note is not pumped.
Low Comp Auto Makeup off/on off Read by both detectors. Adds a fixed boost that compensates roughly half the gain the compressor takes away at the threshold, so changing the threshold does not also change your level. Summed with the manual Makeup control.

The gain reduction both detectors apply is published to the meters (and to any UI that asks for it) in positive dB. On Smooth RMS the figure is the detector's own gain; on Classic Peak it is estimated from the block's peak either side of the compressor, because juce::dsp::Compressor does not expose its internal gain — accurate on the steady material a meter is read against, worst-case-per-block on fast transients.

Low band: Graaawl (NEW in v0.4.0)

Graaawl puts the woody, vocal, aggressive grind of a Warwick Thumb onto your low end without making it flabby. Off by default.

It is not low-frequency distortion, and that distinction is the whole design. The Thumb's growl is an asymmetric upper-mid character around 700 Hz – 2.2 kHz, with a formant-like resonance near 1 kHz, sitting on top of a low end that stays tight. So Crypta generates that harmonic content in a parallel branch — an asymmetric saturator followed by a band-pass onto the formant window — and blends it on top of the untouched low band. Your fundamental never goes through a shaper. Measured on a 50 Hz probe with Amount at 100 %: the energy in the 20–150 Hz sub region changes by less than 0.01 dB, while the 700 Hz – 2.2 kHz window gains real signal.

It sits after the low-band compressor and before Low Level, so the compressor has already made the input level predictable and the Amount control means the same thing from note to note.

Parameter Range Default Unit What it does
Graaawl off/on off Enables the growl branch. Switched off it is a bit-exact bypass — not "almost transparent", literally the same samples.
Graaawl Amount 0 … 100 0 % How much growl is blended on top of the low band. A linear gain on the harmonic branch, so halving it is −6 dB. Level-dependent by design: the growl shows up when you dig in.
Graaawl Tone 0 … 100 50 % Moves the formant window: 800 Hz at 0 %, ~1130 Hz at 50 %, 1600 Hz at 100 %. Lower is woodier and louder (low harmonics carry more energy), higher is more nasal and more restrained.

The branch is antialiased arithmetically (ADAA-1) rather than by oversampling, which is why Graaawl adds no latency at all — switching it on mid-session can never shift your track. Measured alias-to-signal on a hot 50 Hz probe at 100 % Amount: −86 dB at Tone 0, −105 dB at Tone 100.

Mid band: drive + level (NEW in v0.2.0)

A dedicated mid band with staged/cascaded saturation, structurally similar to the High band's Wool voicing (two cascaded soft-clip stages) but with no filter, tone, or blend control of its own — matching the reference class's own Mid band exactly ("Mid Drive... Mid Level" only). This band's job is a distinct "throatier" grind character, separate from the High band's own presence/fuzz/harshness-control role.

Parameter Range Default Unit What it does
Mid Drive 0 … 100 30 % Staged saturation amount. 0% is an exact passthrough; increasing it blends progressively toward a fully cascaded-tanh-driven signal.
Mid Level −24 … +12 0 dB Level trim on the mid band, applied after drive and before the bands are summed back together.

High band: Tight, voicing, drive, tone, blend, level

Three selectable distortion voicings, each 4x oversampled to keep the nonlinear shaping stage's aliasing out of the audible band.

Parameter Range Default Unit What it does
High Tight 20 … 500 100 Hz NEW in v0.2.0: a pre-drive high-pass filter, now applied ahead of every voicing (was a Razor-only fixed 200 Hz internal constant in v0.1.x). This is the primary "how much fuzz vs. tightness" control for the whole High band, and also tames harshness on high-drive settings - pull it down toward its floor for maximum fuzz, push it up for a tighter, more controlled top end.
High Voicing Gnaw / Wool / Razor Gnaw Selects the distortion character. See below.
High Drive 0 … 100 50 % How hard the signal is pushed into the selected voicing's nonlinearity.
High Tone 0 … 100 50 % Post-shaper tone control: a low-pass sweeping from dark (0%) to bright (100%), tucking away or opening up fizz/harshness from the distortion stage.
High Blend 0 … 100 100 % Blend between the clean (pre-voicing) and fully distorted high band. 0% = clean high band (voicing has no audible effect); 100% = fully distorted.
High Level −24 … +12 0 dB Level trim on the high band, applied after voicing/blend and before the bands are summed back together.
High Bias 0 … 100 0 % Circuit only. Offsets the clipper so it saturates asymmetrically, buying even-order harmonics: on the symmetric voicings, H2/H1 rises by at least 20 dB going from bias 0 to bias 100 (tests/CircuitDriveTests.cpp, "T4"). 0 % is exactly the v0.2.0 character. The offset is removed again downstream by a 10 Hz blocker, so this never puts meaningful DC on your output (measured ≤ −80 dBFS at every voicing and bias setting).

Voicings:

All three keep their v0.2.0 placement — Gnaw flat, Wool a −6 dB/Q 0.9 scoop at 500 Hz, Razor a +5 dB/Q 1.0 hump at 900 Hz — but on the Circuit engine the nonlinearity and the filtering around it are rebuilt from circuit models rather than being three settings of one curve (src/dsp/CircuitDrive.cpp).

Gnaw and Razor also share a drive-tracked post-clip pole on Circuit: it opens to 61 kHz at Drive 0 (transparent) and slides down to 5.1–6.9 kHz at full drive, moving continuously in between rather than sitting at a single fixed corner.

Starting points, not final voicing: the drive-gain ranges and mid-filter hump/scoop settings for the Classic engine, and the Circuit voicing constants alike, are engineering defaults - tuned for musical usefulness and mathematically bounded (no runaway output at any drive setting), not yet finalized by ear against reference material. The suite's open ear-tuning gates (issues #15/#16/#17, #34) still apply to the Circuit engine specifically.

Post-sum 4-band EQ

Applied after all three bands are summed back together (and after the IR loader). Off by default; when off, the EQ stage is skipped entirely (guaranteed transparent, not just set to unity gain). v0.2.0 re-anchors the default corner frequencies to a sourced bass-tone-stack frequency set from the same design lineage as the reference class (v0.1.x's defaults were unsourced placeholders).

Parameter Range Default Unit What it does
EQ Enable off/on off Enables the EQ stage.
EQ Low Shelf Frequency 40 … 400 80 Hz Low shelf corner frequency.
EQ Low Shelf Gain −18 … +18 0 dB Low shelf boost/cut.
EQ Peak 1 Frequency 100 … 2000 500 Hz First parametric peak band's centre frequency.
EQ Peak 1 Gain −18 … +18 0 dB First peak band's boost/cut.
EQ Peak 1 Q 0.2 … 5.0 0.7 First peak band's bandwidth (higher = narrower).
EQ Peak 2 Frequency 500 … 8000 2800 Hz Second parametric peak band's centre frequency - a "presence/definition" high-mid anchor.
EQ Peak 2 Gain −18 … +18 0 dB Second peak band's boost/cut.
EQ Peak 2 Q 0.2 … 5.0 0.7 Second peak band's bandwidth.
EQ High Shelf Frequency 2000 … 16000 5000 Hz High shelf corner frequency.
EQ High Shelf Gain −18 … +18 0 dB High shelf boost/cut.

IR loader (cabinet simulation)

A convolution-based cab-sim stage that now processes only the Mid+High post-sum signal (relocated in v0.2.0 - it sat post-everything in v0.1.x). Off by default. With no impulse response loaded, this stage is a guaranteed bit-exact passthrough at every session sample rate, so turning it on before loading an IR never changes your sound. The Low band is structurally never passed through this stage, matching the reference class's "low band bypasses the cabsim" architecture - your fundamental/sub content stays uncolored regardless of what cab IR you load.

Parameter Range Default Unit What it does
IR Enable off/on off Enables the IR loader stage.
IR Mix 0 … 100 100 % Blend between the dry (pre-convolution) and fully convolved Mid+High signal.

Loading impulse responses: the IR-loading engine and its factory-IR slot mechanics are complete — decoding an embedded WAV, installing it, and clearing back to the passthrough identity IR are all implemented and tested (getNumFactoryImpulseResponses() / loadFactoryImpulseResponse() / clearImpulseResponse()). The Cabinet section of the editor currently exposes the two parameters above and nothing else: there is no in-plugin file browser yet, and a host or wrapper that calls the plugin's IR-loading entry point works today.

What is not shipped is content: Crypta bundles no cabinet IRs, and that is a deliberate licensing decision rather than an unfinished feature. Bundling a cab IR means redistributing someone else's recording inside every copy of the plugin, so the bar is a licence that is beyond doubt — CC0, an explicit public-domain dedication, or our own capture. "Free download" and "royalty free" are not licences. Nothing has cleared that bar yet; the bar itself is enforced in code (src/dsp/FactoryIRs.h) and asserted by the test suite, so an unverified IR cannot slip into a release build. Until then, load your own IRs — the stage is a guaranteed bit-exact passthrough with nothing loaded, at every session sample rate.

State migration

v0.2.x → v0.3.0

Opening a session or loading a preset saved before v0.3.0 sets Drive Engine, Low Comp Detector and Gate Mode to their Classic values, so your saved work sounds exactly as it did. This applies to host sessions and to your own saved presets alike, including a user preset named "Default" — so if you had saved your own default, that is still what you get on a new instance.

The one deliberate exception is the safety clip: if you had it switched on, v0.3.0's clipper is not bit-identical to v0.2.0's. It aliases far less and is transparent below the ceiling; the difference is confined to material that was actually being clipped.

New parameters (High Bias, the knee and auto controls, the Modern gate's controls, Clip Ceiling) are either neutral by default or are only read when their engine is selected, which legacy state never selects.

v0.1.x → v0.2.0

If you open a Crypta v0.1.x session, the old single Crossover Frequency value is migrated to the new Split High parameter, clamped into its new 300–2000 Hz range (v0.1.x's own shipped default, 250 Hz, is below that floor, so an untouched v0.1.x session lands exactly at 300 Hz on reopen). Split Low and every new Mid-band/Tight parameter fall back to their v0.2.0 defaults. Any low-band compressor settings you had explicitly changed away from v0.1.x's old defaults are preserved as-is — only the shipped default changed, not your own deliberate settings. This is a best-effort, lossy, one-directional migration; re-check your low/mid/high balance after reopening an old session.

Under the hood

Everything below is measured in-tree and runs on every CI push (macOS + Windows, Release, .github/workflows/ci.yml, plus pluginval --strictness-level 10 on both platforms and auval -strict on macOS). See docs/architecture.md for the full derivations.

One shared oversampling region, not two

v0.2.0 ran two independent 4x oversampling instances — one inside the Mid band, one inside the High band. The Circuit engine collapses them into one: the remainder is upsampled once, split by a second Linkwitz-Riley crossover running at the oversampled rate, processed there, summed and downsampled once (src/dsp/CircuitDrive.{h,cpp}). The saved region pays for the extra per-voicing filtering. The oversampling factor adapts to the host rate — 4x at or below 50 kHz, 2x at or below 100 kHz, 1x (ADAA only) above — and that trade is tested, not assumed: 2x at 96 kHz measures at least as clean as 4x at 48 kHz, tone for tone (tests/AliasingTests.cpp, "T1: dropping to 2x at 96 kHz costs nothing measurable"). Both engines stay prepared at all times, so Drive Engine is automatable; a switch crossfades over 256 samples (5.3 ms at 48 kHz) and flushes the incoming engine's state first, because the idle engine's oversampling history otherwise releases a stale-audio burst on switch-back (measured: a 1.96 peak before the flush existed, 1.39 after, tests/CircuitDriveTests.cpp, "T18").

Antialiasing done arithmetically, on top of oversampling

src/dsp/ADAAShaper.h implements first-order antiderivative antialiasing (Parker, Zavalishin & Le Bivic, DAFx-16): closed forms where the antiderivative is elementary (tanhln cosh, hard clip → piecewise), and a 2048-point cubic-interpolated table with a Simpson-integrated antiderivative where it is not, so the curve and its integral stay mutually consistent — pinned directly by a test, because a mismatch would show up as a DC step under overload rather than as a small error (tests/AliasingTests.cpp, "T2"). Measured result: the Circuit engine beats the engine it replaces by 25–30 dB across a 1.2–10 kHz sweep at full drive (recorded: Circuit −81.9 / −64.0 / −57.1 / −51.9 dB vs. Classic −48.0 / −36.2 / −27.9 / −22.7 dB at 1244 / 2489 / 4978 / 9956 Hz), and clears −80 dB or better through the whole bass register (311, 622, 1244 Hz) (tests/AliasingTests.cpp, "T1").

Per-voicing circuit topologies

See the Voicings note above the parameter tables for what changed in Gnaw, Wool and Razor. The drive-tracked post-clip pole Gnaw and Razor share uses a square-law (audio-taper) mapping rather than a linear one, specifically so the pole stays above 12 kHz at half drive instead of collapsing to roughly 9 kHz and making the middle of the drive range audibly duller than the circuit being modelled (tests/CircuitDriveTests.cpp, "T3"). Every automatable scalar in the Circuit engine — drive gains, blend, bias offset, band levels, and the two one-pole filter coefficients themselves — is ramped across the block rather than held constant across it; a per-block-constant parameter measured as roughly −27 dBc of broadband non-harmonic spurs on a fast drive sweep before this existed (src/dsp/CircuitDrive.h, RampedScalar).

A low-band detector that stops the bass tremoloing

v0.2.0's low band used a peak detector with the sourced 6 ms "glue" release, and a 6 ms release follows the individual half-cycles of a bass fundamental, so the gain reduction rippled at twice the note frequency. Low Comp Detector = Smooth RMS (src/dsp/LevelDetector.h) is a log-domain RMS detector with a soft knee, program-dependent release and auto-makeup. Measured ripple on an 80 Hz tone 6 dB over threshold: over 1 dB → under 0.5 dB, while still genuinely compressing (tests/LevelDetectorTests.cpp, "T7"). The auto-makeup sign is worth knowing: −0.5·T·(1 − 1/R) with a negative threshold gives a positive gain — the easy slip (−0.5·T·(1/R − 1)) produces attenuation instead, which the test suite pins at three anchors to 0.1 dB, plus an assertion that the result is a boost at all ("T8").

A gate with hysteresis, and the test that proves it

Gate Mode = Modern (src/dsp/GateEngine.h) runs its control path per sample and adds hysteresis (0–12 dB), retriggering hold (0–500 ms), a detector-only sidechain highpass (20–400 Hz) and a dB-linear release. The cleanest proof point: a 500 Hz tone dithering ±1.5 dB around the threshold at 3 Hz for two seconds — a single-threshold gate chatters continuously through that; with a 4 dB hysteresis window this one opens once and then makes exactly zero transitions for the rest of the render (tests/GateEngineTests.cpp, "T11"). The release is fit by least squares against the ideal −range/release slope at R² > 0.99. Gate Ratio is Classic-only; Modern ignores it — it is a gate with a range floor, not a ratio expander.

A safety clip that is transparent until it isn't

The v0.2.0 safety clip was a raw per-sample std::tanh on the full mix, which lowpassed everything whenever it was merely armed. src/dsp/OutputClipper.h applies ADAA to the clipper's residual instead of the whole signal — algebraically the antialiased clipper plus an exact compensator for the droop and delay that naive ADAA would otherwise apply to material nowhere near the ceiling. Measured deviation across 40 Hz – 20 kHz while armed but not clipping: 0.13 dB (tests/OutputClipperTests.cpp, "T13"). One documented wrinkle: the compensator is a first difference and can push a sample back over the ceiling on fast material (measured 1.15 against a ceiling of 1.0), so a final hard bound is applied - it never engages below the ceiling, so transparency below it is untouched.

Nothing you already made changes

A fresh instance boots into Circuit / Smooth RMS / Modern; every pre-v0.3.0 session and preset gets the legacy engines injected, through two independent migration paths because presets never pass through setStateInformation() at all (see State migration, above). The proof is against real committed output, not just the migration code: tests/GoldenRenderTests.cpp renders four committed v0.2.0 state fixtures (Gnaw / Wool / Razor / Gnaw-with-clip) and asserts sample-exact equality (memcmp == 0) on macOS, the golden platform; on Windows the bar is ≤ −60 dB relative, with the worst of three fixtures measured at −73 dB. The fixtures are asserted to carry no stateVersion attribute, so a regenerated fixture cannot silently turn the migration test into a tautology.

Engineering hygiene

Zero heap allocations on the audio thread, on both engines, with every v0.3.0 feature live simultaneously — Circuit drive, Modern gate, Smooth RMS detector with auto-makeup, the safety clip and the EQ (tests/RobustnessTests.cpp, [realtime]). Reported latency is a function of sample rate alone (see Reported latency, above). reset() flushes every stage (crossover memory, gate/compressor envelopes, oversampling state, the latency-compensation delay line, EQ biquad history, the convolution engine), so a host transport stop/loop/rewind never leaves stale state ringing into whatever plays next (tests/ResetTests.cpp). The low band is structurally excluded from the cab-sim: its own isolated output is bit-exact identical whether the IR loader is on or off, regardless of which IR is loaded (tests/LowBandIsolationTests.cpp).

Known limitations

Tips