Skip to content

Feedback Network

Tier: Algorithms | ComponentType: 32 | Params: 6

8-line feedback delay network with Hadamard mixing matrix, prime-length delays, one-pole LP damping, and LFO modulation for algorithmic reverb.

Overview

FeedbackNetwork implements a Feedback Delay Network (FDN) -- a standard building block for algorithmic reverberation. Eight delay lines of mutually prime lengths are interconnected through an orthogonal Hadamard mixing matrix. On each sample, all delay outputs are read, mixed through the matrix, filtered, scaled by feedback, and written back. This creates a dense, colorless reverberation that decays naturally over time.

The Size parameter scales all delay lengths simultaneously, controlling the perceived room size. Feedback controls the decay time -- values near 1.0 produce long, sustained reverb tails, while values above 1.0 allow controlled buildup (kept stable by tanh soft clipping). Damping applies a one-pole lowpass filter inside each delay's feedback path, causing high frequencies to decay faster than low frequencies -- mimicking air absorption in real rooms.

Mod Rate and Mod Depth add sinusoidal modulation to each delay's read position (up to \(\pm 5\) samples), creating subtle pitch-shifting that decorrelates the delay lines and reduces metallic coloration. The eight LFO phases are spread evenly across one cycle for maximum decorrelation.

The Hadamard(8) matrix divided by \(\sqrt{8}\) is used as the mixing matrix. This is orthogonal and energy-preserving, ensuring that the network neither amplifies nor attenuates signal energy through the mixing stage alone.

File Locations

Path
Header Sources/FolioDSP/include/FolioDSP/Algorithms/FeedbackNetwork.h
Implementation Sources/FolioDSP/src/Algorithms/FeedbackNetwork.cpp
Tests Tests/FolioDSPTests/FeedbackNetworkTests.swift
Bridge Sources/FolioDSPBridge/src/FolioDSPBridge.mm (FeedbackNetworkBridge)

Parameters

Index Name Description Min Max Default Min Default Max Default Unit
0 Size Delay length multiplier 0.05 5.0 0.1 3.0 1.0
1 Feedback Feedback amount (>1.0 = runaway) 0.0 1.1 0.0 1.05 0.85
2 Damping One-pole LP coefficient per delay 0.0 0.99 0.0 0.95 0.4
3 Mod Rate LFO modulation rate 0.0 5.0 0.0 2.0 0.5 Hz
4 Mod Depth LFO modulation depth (\(\pm\)5 samples max) 0.0 1.0 0.0 1.0 0.2
5 Mix Dry/wet blend 0.0 100.0 0.0 100.0 50.0 %

Processing Algorithm

The process() function executes these steps for each input sample:

1. Read from Delay Lines

Each of the 8 delay lines is read with LFO-modulated tap position:

\[\phi_i \mathrel{+}= \frac{f_{\text{mod}}}{f_s}\]
\[\text{offset}_i = \sin(2\pi \cdot \phi_i) \cdot d_{\text{mod}} \cdot 5\]
\[\text{delaySamples}_i = D_i \cdot \text{size} + \text{offset}_i\]
\[r_i = \text{delay}_i.\text{read}(\text{delaySamples}_i)\]

where \(D_i\) are the base prime delay lengths and the LFO phases \(\phi_i\) are initialized spread evenly: \(\phi_i = i / 8\).

Base delay lengths (in samples, all prime): 1087, 1283, 1447, 1663, 1823, 2011, 2179, 2381.

2. Hadamard Mixing

The 8 delay readings are mixed through the Hadamard(8) matrix, normalized by \(1/\sqrt{8}\):

\[m_i = \sum_{j=0}^{7} \frac{H_{ij}}{\sqrt{8}} \cdot r_j\]

The Hadamard matrix \(H_8\) is orthogonal: \(H \cdot H^T = 8I\), so dividing by \(\sqrt{8}\) makes it energy-preserving.

3. Damping, Feedback, and Write

For each delay line, the mixed signal passes through a one-pole lowpass filter, is scaled by feedback, summed with input, soft-clipped, and written back:

\[s_i[n] = s_i[n-1] + (1 - d_{\text{damp}}) \cdot (m_i - s_i[n-1])\]
\[w_i = \tanh(s_i \cdot f_b + x)\]
\[\text{delay}_i.\text{write}(w_i)\]

The one-pole lowpass with coefficient \(d_{\text{damp}}\) causes high frequencies to decay faster. At \(d_{\text{damp}} = 0\), the filter is bypassed (full bandwidth). At \(d_{\text{damp}} = 0.99\), only very low frequencies survive.

4. Output Summation

The wet output sums all 8 delay readings, normalized by \(1/\sqrt{8}\):

\[y_{\text{wet}} = \frac{1}{\sqrt{8}} \sum_{i=0}^{7} r_i\]

5. Dry/Wet Mix

\[y = x \cdot (1 - \text{mix}) + y_{\text{wet}} \cdot \text{mix}\]

where \(\text{mix} = \text{mixPct} / 100\).

Core Equations

\[m_i = \sum_{j} \frac{H_{ij}}{\sqrt{8}} \cdot r_j\]
\[s_i[n] = s_i[n-1] + (1 - d) \cdot (m_i - s_i[n-1])\]
\[w_i = \tanh(s_i \cdot f_b + x)\]
\[y_{\text{wet}} = \frac{1}{\sqrt{8}} \sum_i r_i\]

Approximate decay time (T60):

\[T_{60} \approx \frac{-3 \cdot \bar{D}}{f_s \cdot \log_{10}(f_b)}\]

where \(\bar{D}\) is the average delay length in samples scaled by size.

Snapshot Fields

Field Type Range Unit Description
Input Level Float 0--1 Smoothed input amplitude
Output Level Float 0--1 Smoothed output amplitude
Decay Time Float 0--10 s Estimated T60 decay time
Damping Float 0--1 Current damping coefficient
Drive Float 0--1.1 Current feedback amount
Delay Levels Float[8] 0--1 Per-delay-line signal levels

Implementation Notes

  • Prime delay lengths are chosen to minimize common factors between lines, reducing the chance of resonant coloration. The specific primes (1087--2381) span roughly 25--54 ms at 44100 Hz, covering a natural room reflection range.
  • Hadamard matrix is precomputed as a static const float[8][8], with each entry already divided by \(\sqrt{8}\). This avoids per-sample division.
  • CircularBuffer<32768> per delay line provides up to ~743 ms of delay at 44100 Hz. With size multiplier up to 5.0, the maximum effective delay is \(2381 \times 5 = 11905\) samples (~270 ms), well within the buffer capacity.
  • Tanh soft clipping in the feedback path prevents runaway when feedback exceeds 1.0, allowing controlled self-oscillation without hard clipping artifacts.
  • Level tracking uses exponential smoothing with coefficient 0.01 for both overall and per-delay-line levels.
  • T60 calculation in the snapshot uses the clamped feedback value (\(\leq 0.999\)) to avoid division by zero at \(f_b = 1.0\).
  • All parameters use std::atomic<float> for lock-free thread safety.
  • Snapshot emission is decimated to ~60 fps (every 735 samples at 44.1 kHz).

Equation Summary

y = Hadamard(8 * delay[t]) * fb