A reverb
Parallel feedback delays and short diffusion stages — building a tail one repeat at a time.
Anyone who wants space rather than an echo.
An echo has a repeat you can point to. A reverb turns many overlapping repeats into a tail. This compact network sends the input through four parallel feedback delays, averages their returns, then passes that mixture through two short diffusion stages.
It is a useful way to learn how a reverberant tail is assembled. It has no frequency-dependent damping control and is not a model of a particular room.
Controls#
| Parameter | Default | Range | Meaning |
|---|---|---|---|
size | 0.88 | 0.30–0.96 | Comb feedback gain. Higher values lengthen the tail; this does not change delay lengths. |
diffuse | 0.5 | 0–0.85 | Feedback amount in the two short diffusion stages. |
mix | 0.35 | 0–1 | Blend from dry input to reverb return. |
level | 1.0 | 0–1 | Output gain. |
Both input and output are mono. Begin with a short sound so the tail remains audible after the source ends.
The complete patch#
processor Reverb
{
input stream float in;
param float size = 0.88f [0.30f, 0.96f] smooth 40.0f;
param float diffuse = 0.5f [0.0f, 0.85f] smooth 40.0f;
param float mix = 0.35f [0.0f, 1.0f] smooth 25.0f;
param float level = 1.0f [0.0f, 1.0f] smooth 20.0f;
output stream float out;
float c1[2048];
float c2[2048];
float c3[2048];
float c4[2048];
float a1[1024];
float a2[1024];
float pos = 0.0f;
void main()
{
loop
{
let w = int(pos);
let g = min(size, 0.96f);
let r1 = w - 1557;
let r2 = w - 1617;
let r3 = w - 1491;
let r4 = w - 1422;
let d1 = c1[r1];
let d2 = c2[r2];
let d3 = c3[r3];
let d4 = c4[r4];
c1[w] = in + d1 * g;
c2[w] = in + d2 * g;
c3[w] = in + d3 * g;
c4[w] = in + d4 * g;
let combs = (d1 + d2 + d3 + d4) * 0.25f;
let ag = min(diffuse, 0.85f);
let p1 = a1[w - 225];
a1[w] = combs + p1 * ag;
let ap1 = p1 - combs * ag;
let p2 = a2[w - 556];
a2[w] = ap1 + p2 * ag;
let ap2 = p2 - ap1 * ag;
let next = pos + 1.0f;
pos = next > 2047.0f ? 0.0f : next;
out <- (in * (1.0f - mix) + ap2 * mix) * level;
advance();
}
}
}Why several delays?#
Each comb reads a different point in its buffer: 1,557, 1,617, 1,491 or 1,422 samples behind the shared write position. Those different spacings spread the repeats across time. They are fixed sample counts, so their durations change with sample rate. At 48 kHz they are roughly 30–34 ms long.
The four reads are averaged before entering the two diffusion stages. These stages combine a short delayed value with a scaled version of their input, creating more overlapping arrivals. The final dry/wet blend keeps the direct sound available alongside the tail.
All six buffers share a position counter because they advance together. Their power-of-two capacities handle wrapping independently. The delay offset and the buffer capacity are different things: a 2,048-element buffer can implement a 1,557-sample delay.
Try it#
Set mix to 1 and listen to the tail alone. Bring size down, then up, while
keeping diffuse fixed. Next hold size steady and change diffuse. This
separates the effect of feedback duration from the effect of the later stages.
To develop this design: add a lowpass inside each comb's feedback path for a tail that loses brightness over time. That would require additional filter state; there is no damping parameter in the patch as written.
Next: a chorus, where the delay moves.