compressors.h
The hardware compressors: opto, FET, VCA.
#include <sonore/compressors.h>- 3types
- Guides: Getting started, MIDI and MPE
On this page
Design notes
dsp.h's Compressor is the textbook feed-forward design: a detector, a gain computer with a soft knee, a multiplier. Every classic compressor is that diagram with one box replaced by a piece of hardware whose physics is the sound, and "make it sound like an LA-2A" was being answered by turning the textbook's release knob. These are the three gain elements that define the three families, each modelled from what the element does:
OptoCompressor the LA-2A's T4 cell: an electroluminescent panel driven
by the sidechain, lighting a cadmium-sulphide photocell
whose resistance sets the gain. The panel is fast; the
photocell is not, and its recovery depends on how long
and how brightly it was lit. The manufacturer's own
figures, which the model reproduces: 10 ms attack, 50%
of the release in about 60 ms and the rest in 0.5 to
5 seconds, longer after longer compression. Two states
-- a fast one and a slow "memory" that fills while the
cell is lit -- and the release follows whichever is
higher, which is exactly that shape. No ratio control:
the T4's own curve is a soft 3:1 in Compress and steeper
in Limit, and Peak Reduction sets how hard it is lit.
FetCompressor the 1176: a FET as the shunt leg of an attenuator, its
channel resistance set by the sidechain. Two things the
circuit does that a gain computer does not: it is a
FEEDBACK compressor (the sidechain reads the OUTPUT), so
the ratio buttons set a loop gain and the effective
knee and timing are program-dependent; and a FET in its
triode region has a channel conductance that depends on
the drain voltage -- the signal -- which is where the
1176's even-harmonic grain under gain reduction comes
from. Attack 20 to 800 microseconds, release 50 to
1100 ms, the four ratios and "all buttons in".
The loop is SOLVED each sample, not delayed. A digital
feedback compressor that feeds back last sample's output
has a unit delay in a loop whose gain is 3 to 19, and at
a 20 microsecond attack -- one sample -- it limit-cycles;
that is why software 1176s quietly lengthen the attack.
The output level is the fixed point of "what the
detector sees is what the attenuator made", a monotone
equation in |y| that bisection finds exactly, the same
move zero-delay feedback makes for a filter. Then the
FET's signal-dependent conductance makes the sample the
root of a quadratic, which has a closed form.
VcaCompressor the dbx 160 and the SSL bus compressor: a VCA whose gain
is exactly exponential in its control voltage, so the
ratio is exactly the ratio and the element itself adds
nothing -- which is the point of a VCA and the reason
this one measures under -60 dB of distortion at 10 dB
of gain reduction where the FET measures -40. The dbx
detects true RMS through a single time constant (its
"program-dependent" feel is the RMS integrator); the
SSL detects peaks and offers the two-capacitor auto
release, fast then slow. OverEasy is a wide soft knee.
The detector and knee mathematics are Giannoulis, Massberg & Reiss, "Digital Dynamic Range Compressor Design -- A Tutorial and Analysis" (JAES 2012); the time constants and curves are the manufacturers' published specifications; the gain elements are the physics stated above. Every figure quoted is measured in the unit test.
Included by dsp.h.
Types 3
The LA-2A-style optical compressor: an electroluminescent panel lighting a photocell, with the cell's two-speed release that lengthens after longer compression (see the file comment for the physics and the published figures it reproduces).
One channel, per sample. Call setSampleRate() in prepare(), before any audio: the panel's and the cell's time constants are worked out there for the rate. The setters and process() then run on the audio thread, in the DSP's own process(). There is no ratio, attack or release to set: Peak Reduction (0..1) is how hard the panel is lit, Mode picks the Compress or the Limit curve, makeup is in dB and the sidechain emphasis is 0..1. computeGain() takes the detector separately and returns the gain, which is how a key input or a stereo link is done: one instance, one detector, the gain applied to both channels. reset() empties the cell's memory and lands the glides.
The 1176-style FET compressor: a feedback design whose loop is solved exactly each sample, with the FET's signal-dependent channel giving the even-harmonic grain under gain reduction (see the file comment).
One channel, per sample. Call setSampleRate() in prepare(); the setters and process() then run on the audio thread. As on the hardware there is no threshold: setInput() (dB) is how hard the cell is driven against a fixed one at -18 dB, and setOutput() (dB) is the makeup. Attack is clamped to 20..800 microseconds and release to 50..1100 ms; Ratio::AllButtons lowers the threshold by 8 dB and doubles the grain (0..0.5, default 0.2). No key input: a feedback compressor's detector hears its own output.
The VCA compressor of the dbx 160 and the SSL bus compressor: a gain element exactly exponential in its control voltage, so the ratio set is the ratio measured, with a true-RMS or a peak detector and the SSL's two-capacitor auto release (see the file comment).
One channel, per sample. Call setSampleRate() in prepare(); the setters and process() then run on the audio thread. Threshold, knee and makeup are in dB, the ratio is N for N:1 (at least 1), attack, release and the RMS time in ms. With the RMS detector (the default) attack and release smooth the gain after the RMS integrator; with Peak they time the detector. Auto release, with either, replaces the release with the two-capacitor curve. computeGain() takes the detector separately and returns the gain, for a key input or a stereo link. MultibandDynamics is built on this.