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

limiting.h

The true-peak limiter.

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

Design notes

effects.h's Limiter guarantees its ceiling against SAMPLE peaks, and a DAC does not play samples: it plays the band-limited curve through them, which swings past the samples between two of them. A "-1 dBFS" master can leave the converter at +0.5 dBTP; streaming loudness specs are written in dBTP for exactly this reason. This limiter's detector is the inter-sample peak estimator of ITU-R BS.1770-4 Annex 2, the polyphase interpolation metering.h's TruePeakMeter implements (computed windowed sinc, phases normalised to unity DC), taken further than the meter's 4x: 8x with 64 taps a phase (see Detector); and the gain engine is the same textbook look-ahead machine the Limiter already proved: a sliding minimum over the window (O(1), monotonic deque) feeding a boxcar, so the gain ramps linearly and lands exactly as the peak arrives.

Two honest details:

  • The interpolating detector describes the signal 32 SAMPLES AGO (its FIR is centred), so the signal path is delayed by lookahead + 32 and that whole figure is the reported latency. A peak's attenuation still gets the full look-ahead window to ramp in.
  • The 8x estimate can under-read the continuous peak by a fraction of a dB (BS.1770 quotes the bound for 4x), and the base-rate gain ramp modulates the signal slightly. Both are covered by a fixed 0.25 dB detection margin, and the test file checks the result the only honest way: it reconstructs the OUTPUT at 16x and measures the real overshoot.

Included by dsp.h, after metering.h (whose TruePeakMeter was the detector before the limiter got its own).

Types 1

A look-ahead limiter that holds its ceiling against TRUE peaks -- the inter-sample peaks a converter plays -- rather than against sample values (see the file comment for the gain engine, and Detector for the estimator).

Stereo and linked: one gain for both channels, so the image holds still. Call prepare() before audio; it works out the release and the look-ahead for the rate and clears the state. Then setCeiling() (dB, default 0), setRelease() (ms, default 80) and setLookahead() (ms, default 2, rounded to whole samples, at most 4094 of them) run on the audio thread with process(): the same look-ahead again is free, a different one clears the state. The signal comes out latencySamples() late, the look-ahead plus the detector's 32-sample centre; report it to the host, and again when the look-ahead changes. gainReduction() is in dB, positive while limiting.

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