Search guides and the APICtrl K
  1. API reference
  2. DSP

spring.h

A spring reverb.

#include <sonore/spring.h>
On this page

Design notes

A spring is not a room. Its impulse response is a train of echoes, one per trip along the coil, and every echo is a CHIRP: the coil is dispersive, so the frequencies travel at different speeds and a click comes out as a sweep. That sweep is the "boing", and no delay-and-filter reverb makes it.

The model is the dispersive waveguide of Abel, Berners, Costello & Smith ("Spring reverb emulation using dispersive allpass filters in a waveguide structure", AES 121, 2006), in the form Parker & Välimäki make cheap ("Efficient dispersion generation structures for spring reverb emulation", EURASIP JASP 2011): the dispersion is a long cascade of identical allpass sections inside a feedback loop with the coil's transit delay and a lowpass for the loss. Each pass through the loop disperses the pulse a little more, which is exactly what a real spring does to it.

The sections are SECOND order, with their pole angle at the spring's transition frequency. The first draft used first-order allpasses, whose group delay grows monotonically toward Nyquist: 0.2 samples per stage at DC, 19 at Nyquist and 0.6 at 15 kHz -- a chirp that lives entirely in the last kilohertz below Nyquist, where nobody hears it. A helical spring's dispersion peaks at a transition frequency of a few kilohertz, and the audible "boing" is the sweep up to it. A second-order allpass with its poles at that frequency puts the group-delay peak there: at radius r the peak is about (1+r)/(1-r) samples per section, so 64 sections at r = 0.9 hold the transition frequency back by ~1200 samples (25 ms at 48 kHz) while DC goes through almost at once. tension is the radius.

Two coils with different lengths give a stereo pair that decorrelate the way two springs in a tank do. A short, lightly dispersed parallel path carries the high-frequency "wire" component that arrives ahead of the chirps.

Included by dsp.h.

Types 1

template <int Stages = 64, int MaxDelay = 8192> class SpringReverb

A spring reverb tank: two dispersive coils, each a feedback loop of a transit delay, a lowpass and Stages second-order allpasses, so every echo comes back as the chirp that makes the "boing", plus a short bright "wire" path ahead of them (see the file comment for the model).

Stereo in and out, the input summed to mono. Call prepare() before audio; it applies the parameters for the rate and clears the coils. A coil is at most MaxDelay samples, so a long spring at a high rate shrinks both coils together; transitSamples() says what each got. setParameters() and process() run on the audio thread, and a change lands at once, the decay and the coil lengths unsmoothed. Report tailSamples() to the host.

↑↓ to move↵ to openEvery public name in the headers, and every guide