World-class 16-line FDN reverb with Jot absorption and Hadamard mixing.
Architecture:
Input (mono sum)
|
v
[Pre-delay: 0-200ms]
|
v
[Input Diffusion: 8 cascaded allpass, 1.0-9.5ms]
|
+--> [Early Reflections: 40 taps with progressive HF absorption, L/R decorrelated]
|
+--> [ER-to-Late gap]
| |
| v
| [Parallel Allpass Diffuser: 16 parallel AP + Hadamard -> 16 delay + Hadamard]
| (2-step, 16^2 = 256 echo paths, each FDN line gets unique dense input)
| |
| v
| [FDN Core: 16 delay lines]
| +- Read with dual smooth-random-LFO modulated delay
| +- Householder 16x16 reflection (I - (2/N)J, lossless) feedback mix
| +- Jot absorption filter (1st-order shelving) per line
| +- Bass shelf (1-pole) per line
| +- 2 feedback allpass per line
| +- DC blocker + soft limiter
| +- Write back + input injection
| |
| v
| [Output: sign-weighted + Dattorro multi-tap]
| |
| v
| [Output Diffusion: 2 allpass/channel, L/R decorrelated]
|
v
[Combine early + late] -> [Tone EQ: Biquad LP + HP (12 dB/oct)] -> DryWetMixer -> Output
Key features:
- Jot absorption filter (Jot 1991): 1st-order pole-zero shelving IIR per delay line for smooth frequency-dependent decay, the #1 factor for natural sound. DC and Nyquist gains anchor the mid/HF T60 exactly; the transition sits at the high crossover. Separate bass shelf for independent LF control.
- Householder 16x16 FDN feedback (I - (2/N)J): unitary reflection, eigenvalues {-1 once, +1 x15}, |lambda|=1 so it is lossless and zero-coloring. (The Hadamard 16x16 below is the input diffuser's mix, not the feedback matrix.)
- Parallel allpass diffuser (Signalsmith-inspired): 16 parallel allpass
- 2-step Hadamard mixing (all eigenvalues +/-1) -> 256 unique echo paths per input sample. Each FDN line receives a different, densely-mixed version of the input.
- Feedback allpass: 2 regular allpass per delay line for in-loop density
- Output diffusion: 2 allpass per channel with decorrelated delays, smears residual temporal patterns
- Smooth random modulation (Lexicon-style): Hermite-interpolated noise replaces periodic sine LFOs for organic character
- Multi-tap output (Dattorro-style): 7 taps/channel from different delay line positions for true temporal decorrelation
- Tone correction EQ: Biquad high/low cut (12 dB/oct) for tonal shaping
- Early reflections: 40-tap with progressive frequency absorption simulating wall absorption; late taps are naturally darker
- Soft saturation: fast branchless rational soft-clip (transparent below +/-1), more musical than a hard clamp, prevents pipeline stalls.
- Allpass interpolation: in modulated FDN reads, preserves HF over hundreds of feedback iterations (linear/cubic causes cumulative dulling)
- Stereo width: M/S width control on late reverb tail
- Eco quality mode (setQuality): opt-in reduced engine (8 FDN lines, control-rate modulation, linear allpass interpolation, no extra output taps, single-stage input scatter, 12 early taps) at a fraction of the CPU cost, for embedded and other constrained targets. The default Full quality path is bit-identical to previous releases.
Threading: prepare() belongs to the setup thread (allocates). processBlock(), processSample() and reset() belong to the audio thread. All setters are lock-free atomic publications, safe from any thread; topology changes (type, quality) and coefficient refreshes are drained at the start of the next processBlock()/processSample() on the audio thread. Non-finite setter arguments are ignored.
Four levels of API complexity:
- Level 1:
reverb.setType(Hall);
- Level 2:
reverb.setSize(0.7f); reverb.setDamping(0.3f);
- Level 3:
reverb.setHighDecayMultiplier(0.4f);
- Level 4: Inherit and override protected members.
References:
- Jot & Chaigne (1991): FDN with frequency-dependent decay (shelving absorption)
- Dattorro (1997, JAES): multi-tap output, plate topology
- Griesinger / Lexicon 480L: random modulation, Spin/Wander
- Sean Costello / Valhalla DSP: practical FDN design, absorbent allpass
- Valimaki et al. (2012, IEEE): "50 Years of Artificial Reverberation"
- Smith (CCRMA): Hadamard matrices, prime power delay selection
Dependencies: RingBuffer.h, DryWetMixer.h, DspMath.h, Biquad.h, AudioSpec.h, AudioBuffer.h, DenormalGuard.h, StateBlob.h.
16-line FDN reverb with Jot absorption and 6 presets.
void setType(Type type) noexcept
void setMix(T dryWet) noexcept
void processBlock(AudioBufferView< T > buffer) noexcept
Processes an audio block in-place with zero allocations.
void setHighDecayMultiplier(T mult) noexcept
Sets HF decay as a multiplier of mid decay time.
void prepare(const AudioSpec &spec)
Prepares the reverberation engine and allocates required memory.
void setDecay(T seconds) noexcept
void setBassDecayMultiplier(T mult) noexcept
Sets bass decay as a multiplier of mid decay time.
Definition in file AlgorithmicReverb.h.