Dynamic True-Peak Limiter — User Guide
Linked multi-channel dynamic limiting with a 4×+ oversampled peak-detection sidechain, soft knee, lookahead, asymmetric release, and a final Sinc70 peak ceiling.
What this does
Dynamic True-Peak Limiter is a gain-reduction processor, not a hard sample clipper. It builds an oversampled linked peak sidechain, converts that sidechain into a target gain curve, applies future-window lookahead and a causal exponential release, resamples the gain envelope back to the source sampling rate, and multiplies the original waveform by that envelope.
The final stage measures positive and negative extrema with Praat's Sinc70 interpolation. Depending on Peak_normalize_to_ceiling, it either applies only the attenuation needed to keep the result at or below the requested ceiling, or applies a global gain so every non-silent result reaches that ceiling.
This script does not perform LUFS loudness normalization, and the documentation does not claim compliance with a particular broadcast or mastering standard. The implemented protection is the specific 4×+ oversampled sidechain plus final Sinc70 ceiling described below.
Quick start
- In Praat, select exactly one Sound object.
- Run script… →
Limiter.praat. - Choose a preset, or leave Preset = Custom and set Threshold, Ceiling, Release, Lookahead, and Knee manually.
- Leave Peak_normalize_to_ceiling = no if you want a ceiling that attenuates only when necessary. Enable it if you deliberately want the final non-silent result globally scaled to the ceiling.
- Click OK. The result is created as
<source>_limited.
Presets
Choosing a named preset overrides the corresponding dynamics parameters before validation. Peak_normalize_to_ceiling, Visualize, and Play remain controlled by their form fields.
| Preset | Threshold | Ceiling | Release | Lookahead | Knee |
|---|---|---|---|---|---|
| -1 dBTP Transparent Limiter | -1.0 dB | -1.0 dBTP | 40 ms | 3 ms | 3 dB |
| -0.3 dBTP Peak Maxima | -0.3 dB | -0.3 dBTP | 15 ms | 1.5 ms | 1 dB |
| -2 dBTP Gentle Limiter | -2.0 dB | -2.0 dBTP | 50 ms | 5 ms | 4 dB |
| -1 dBTP Streaming Ceiling | -1.0 dB | -1.0 dBTP | 30 ms | 2.5 ms | 2 dB |
| -1.5 dBTP Smooth Limiter | -1.5 dB | -1.0 dBTP | 60 ms | 4 ms | 6 dB |
| -0.1 dBTP Brickwall Fast | -0.1 dB | -0.1 dBTP | 5 ms | 1 ms | 0 dB |
Parameters
| Parameter | Default | Implemented behavior |
|---|---|---|
| Preset | Custom | Custom plus six named parameter sets. |
| Threshold_dB | -1.0 dB | Level around which the dynamic gain law operates. Must be ≤ 0 dB. If Threshold is numerically above Ceiling, it is silently reduced to the Ceiling value before processing. |
| Ceiling_dBTP | -1.0 dBTP | Final peak ceiling. Must be ≤ 0 dBTP. |
| Release_ms | 30 ms | Time constant for return toward unity gain. Must be at least 1 ms. |
| Lookahead_ms | 3 ms | Future-window minimum applied to the target gain. Must be ≥ 0 and shorter than half the Sound duration. |
| Knee_dB | 2 dB | Width of the continuous soft-knee region. 0 dB selects hard-knee gain computation. |
| Peak_normalize_to_ceiling | No | No: final global stage only attenuates if the measured peak exceeds Ceiling. Yes: every non-silent result is globally scaled up or down to the Ceiling. |
| Visualize | Yes | Draw the limiter diagnostic figure in the Picture window. |
| Play | Yes | Play the completed result. |
Processing engine
1. 4×+ oversampled linked sidechain
The sidechain sampling rate is:
target_sr = max(source_sr × 4, 176400 Hz)
Before resampling, v3.4 estimates the temporary allocation as ceil(duration × target_sr) × channels. If this exceeds 20,000,000 sample values, the script exits instead of silently lowering the oversampling factor.
2. Multi-channel peak detector
For mono input, the sidechain is simply the absolute value of the oversampled signal. For multi-channel input, the detector is linked:
sidechain(t) = max(|ch1(t)|, |ch2(t)|, ...)
One gain envelope therefore controls all channels together.
3. Target gain and soft knee
Let L be the sidechain level in dB. With Knee_dB > 0, the lower and upper knee boundaries are Threshold - Knee/2 and Threshold + Knee/2. Below the lower boundary the target gain is 1. Above the upper boundary the gain is the ratio required to bring the detected level to Threshold. Inside the knee, the reduction follows the implemented quadratic transition:
GR_dB = -((L - lower_dB)^2) / (2 × Knee_dB)
gain = 10^(GR_dB / 20)
With Knee_dB = 0, gain remains 1 below Threshold and becomes Threshold - L dB above Threshold. Target gain is clamped to 0.0001 ... 1.0.
4. Lookahead
The target gain is replaced by the minimum gain required within the requested future window. This brings gain reduction forward so attenuation can already be present when a detected peak arrives. A zero lookahead leaves this step inactive.
5. Causal asymmetric release
When the newly requested gain is lower than the previous envelope sample, attenuation is taken immediately. When less attenuation is required, the envelope returns toward unity exponentially:
alpha = exp(-1 / (oversampled_sr × release_seconds))
release_factor = 1 - alpha
next_gain = previous_gain + (1 - previous_gain) × release_factor
The envelope is then resampled back to the source sampling rate and clamped again to 0.0001 ... 1.0 to remove any interpolation overshoot.
6. Audio multiplication
output[channel, sample] = input[channel, sample] × gain_envelope[sample]
The dynamic stage itself never applies gain above unity.
Multi-channel behavior
The processor accepts exactly one selected Sound object but does not restrict its channel count. Detection is fully linked across channels: whichever channel has the largest instantaneous oversampled absolute value controls the common gain envelope. The result keeps the source channel count, sampling rate, time domain, and duration.
This linking prevents left/right or other channel relationships from being altered by independent gain reduction.
Final ceiling and peak normalization
After dynamic limiting, the script measures both positive and negative extrema using Sinc70 interpolation and uses the larger absolute value as the current peak.
| Peak_normalize_to_ceiling | Final behavior |
|---|---|
| No | If the measured peak is above Ceiling, the whole result is attenuated just enough to reach the ceiling. If it is already below, no global gain is applied. |
| Yes | Every non-silent result is globally scaled so its measured peak reaches the Ceiling. This can either attenuate or boost the result. A genuinely silent result is left unchanged. |
The report distinguishes Max Dynamic Gain Reduction, the signed Final Global Gain, and Total Peak Attenuation. Positive normalization gain is not counted as attenuation; negative final gain is.
Visualization
When Visualize = yes, v3.4 draws an 8-inch diagnostic layout:
- Header: source name, preset, and ceiling.
- Input Wave: source waveform with ±Threshold reference lines.
- Output Wave: limited waveform with ±Ceiling reference lines.
- Gain Target: the final dynamic gain envelope after lookahead, release, resampling, and clamping; unity is shown as a dashed reference.
- Summary: input/output Sinc70 peaks, maximum dynamic gain reduction, final-stage gain or safety attenuation, and total peak attenuation.
The Input and Output waveform panels use the same explicit vertical amplitude range, so their amplitudes and their Threshold/Ceiling reference lines are directly comparable.
Outputs & cautions
- Result name:
<source>_limited. - Channels: preserved.
- Sampling rate: preserved in the result; oversampling is temporary and used only for detection/envelope construction.
- Duration and time domain: preserved.
- Intermediate objects: oversampled Sound, sidechain, target gain, and final gain envelope are removed before completion.
- Determinism: no random process is used.
Threshold and Ceiling are different controls. Threshold defines where and how the dynamic gain law starts reducing peaks; Ceiling is enforced only in the final global stage. With the Smooth Limiter preset, for example, Threshold is -1.5 dB while Ceiling is -1.0 dBTP.
Peak normalization is optional and is not loudness normalization. Enabling it can increase the entire file's gain if the dynamically limited result sits below the requested ceiling.