Multiband Compressor — v3.2 User Guide

Three-band dynamics processing with a complementary crossover split, calibrated absolute RMS thresholds, stereo-linked envelope compression, per-band makeup gain, solo monitoring, and optional final peak normalization.

Author: Shai Cohen Affiliation: Department of Music, Bar-Ilan University, Israel Version: 3.2 (2026) License: MIT License Repo: GitHub
Contents:

What this does

Multiband Compressor v3.2 separates one selected Sound into LOW, MID and HIGH components, compresses each component independently, and then recombines the processed bands. Each band has its own RMS threshold, compression ratio and makeup gain; Attack and Release are shared across the three bands.

The crossover split is complementary before dynamics processing: LOW and HIGH are obtained with Praat Hann-band filters, while MID is calculated as original - LOW - HIGH. Therefore the three unprocessed bands sum exactly back to the source sample values. Once the bands receive different gain envelopes and makeup gains, their sum is intentionally no longer identical to the source.

Threshold semantics: the thresholds in v3.2 are absolute RMS levels in dBFS. They are not “dB below the peak of each band” and they do not move when the input is peak-normalized or made quieter.

Quick start

  1. Select exactly one Sound object in Praat.
  2. Run Multiband_Compressor.praat.
  3. Choose Custom or one of the seven named presets.
  4. For Custom, set the two crossover frequencies and the LOW/MID/HIGH RMS threshold, ratio and makeup values.
  5. Set global Attack_ms and Release_ms. Optionally enable final peak normalization or solo one band.
  6. Run the script. Full-mix output is named <source>_multiband; solo outputs use _LOW_solo, _MID_solo or _HIGH_solo.
Default behavior: Custom mode uses 200 / 2000 Hz crossovers, thresholds of -20 / -18 / -15 dBFS, ratios of 2:1 / 2:1 / 3:1, 0 dB makeup, 10 ms attack and 100 ms release. Peak_normalize_output is Off by default.

Presets

Named presets override the crossover and per-band threshold/ratio/makeup values. The global Attack, Release, peak-normalize, Solo, Visualize and Play settings remain those chosen in the form.

PresetCrossoversLOWMIDHIGH
Master Bus (gentle glue)150 / 3000 Hz-18 dBFS · 2:1 · +1 dB-16 dBFS · 1.5:1 · 0 dB-14 dBFS · 2:1 · +1 dB
Vocal Polish200 / 4000 Hz-24 dBFS · 4:1 · -2 dB-18 dBFS · 2.5:1 · +2 dB-20 dBFS · 2:1 · +1 dB
Bass Control120 / 2500 Hz-15 dBFS · 6:1 · +3 dB-20 dBFS · 1.5:1 · 0 dB-18 dBFS · 1.5:1 · 0 dB
Brighten & Punch200 / 3500 Hz-18 dBFS · 3:1 · +2 dB-20 dBFS · 2:1 · 0 dB-12 dBFS · 2.5:1 · +3 dB
De-Harsh250 / 2500 Hz-20 dBFS · 1.5:1 · 0 dB-16 dBFS · 3:1 · -1 dB-10 dBFS · 4:1 · -2 dB
Dense Broadcast Style150 / 3000 Hz-20 dBFS · 4:1 · +2 dB-18 dBFS · 3:1 · +2 dB-16 dBFS · 3:1 · +1 dB
Lo-Fi Crush300 / 2000 Hz-25 dBFS · 8:1 · +4 dB-22 dBFS · 6:1 · +3 dB-20 dBFS · 10:1 · +2 dB

Complementary three-band split

Band construction

LOW = Filter (pass Hann band): 0, Low_mid_crossover_Hz, 100
HIGH = Filter (pass Hann band): Mid_high_crossover_Hz, 0, 100
MID = original - LOW - HIGH

The Hann filters use a 100 Hz smoothing width. The MID residual is computed sample-by-sample from the original Sound, so before compression:

LOW + MID + HIGH = original

Validation requires Low_mid_crossover_Hz < Mid_high_crossover_Hz, LOW-MID at least 20 Hz, and MID-HIGH below Nyquist - 100 Hz.

Compression engine

Absolute RMS detector

Dynamic bands are analysed with Praat Intensity. The detector hop is 1 ms (gate_sr = 1000). Praat Intensity values are converted to the script's absolute dBFS calibration by:

level_dBFS = level_SPL - 93.9794

The intensity pitch floor is chosen dynamically as max(100, ceil(9.6 / duration)) Hz. This allows the script to process files down to its validated minimum duration of 5 ms rather than using one fixed analysis floor for every input.

Static compression law

if level_dBFS > threshold_dBFS: gr_dB = (threshold_dBFS - level_dBFS) * (1 - 1/ratio) else: gr_dB = 0 target_gain = 10^(gr_dB/20)

A ratio of 1:1 with 0 dB makeup is a transparent bypass for that band. A ratio of 1:1 with non-zero makeup applies only the static makeup gain and skips envelope analysis.

Attack and release

The target gain is smoothed at the 1 kHz control rate. Gain moving downward uses the Attack coefficient; recovery toward unity uses Release:

Nattack = max(round(Attack_ms * 1000 / 1000), 1) Nrelease = max(round(Release_ms * 1000 / 1000), 1) attack_coef = 1 - exp(-4.6 / Nattack) release_coef = 1 - exp(-4.6 / Nrelease)

Because the control grid is 1 ms, entered times are quantized to integer control samples and cannot become shorter than one control sample. For example, values below about 1 ms still use a one-sample coefficient.

Resampling and channel linking

The mono gain envelope is resampled to the source sampling rate with Praat's quality-50 resampler, clamped to 0…1 against interpolation overshoot, and then applied identically to every channel of the band. This makes dynamics processing channel-linked: stereo or multichannel image changes are not driven by independent gain envelopes.

Makeup gain is applied after the gain-reduction envelope.

Parameters & defaults

ParameterDefaultMeaning / validation
PresetCustomCustom or seven named recipes.
Low_mid_crossover_Hz200 HzMust be ≥20 Hz and strictly below Mid_high.
Mid_high_crossover_Hz2000 HzMust be strictly below Nyquist − 100 Hz.
Low_RMS_threshold_dBFS-20 dBFSAbsolute RMS threshold for LOW.
Mid_RMS_threshold_dBFS-18 dBFSAbsolute RMS threshold for MID.
High_RMS_threshold_dBFS-15 dBFSAbsolute RMS threshold for HIGH.
Low_ratio2.0:1Must be ≥1.
Mid_ratio2.0:1Must be ≥1.
High_ratio3.0:1Must be ≥1.
Low / Mid / High makeup_dB0 / 0 / 0 dBStatic gain after compression; may be positive or negative.
Attack_ms10 msPositive value; implemented on the 1 ms control grid.
Release_ms100 msPositive value; implemented on the 1 ms control grid.
Peak_normalize_outputOffIf enabled, Praat Scale peak: 0.95 is applied to the final full-mix or solo result.
SoloOff (full mix)Off, LOW, MID or HIGH.
VisualizeOnDraws the AudioTools diagnostic page.
PlayOnPlays the selected result after processing.

Output, normalization and solo monitoring

v3.2 always creates the rendered Sound as a copy of the original source container and writes the processed samples into that copy. This is deliberate: the output inherits the source sample grid, sampling frequency, channel count and xmin/xmax time domain rather than relying on metadata from one filtered band.

Solo settingOutput nameSamples written
Off<source>_multibandLOW + MID + HIGH after their separate compression/makeup stages.
Solo LOW<source>_LOW_soloProcessed LOW band only.
Solo MID<source>_MID_soloProcessed MID band only.
Solo HIGH<source>_HIGH_soloProcessed HIGH band only.

Peak_normalize_output is optional and Off by default. If enabled, the selected result is scaled so its sample/interpolated peak reaches 0.95. This is a full peak normalization operation, not merely a clip-prevention ceiling, so it can also raise a quiet result.

Current implementation detail: v3.2 calls Scale peak: 0.95 directly when peak normalization is enabled; it does not first test for an all-silent result.

After processing, the script measures an Interpolated Peak using Sinc70 and an RMS level. If the interpolated peak exceeds 0 dBFS it reports a clipping warning. This value is not presented as a standards-compliant true-peak measurement.

Visualization

When Visualize is enabled, v3.2 draws an AudioTools-style diagnostic page containing:

Scale interpretation: the waveform panels use Praat's automatic vertical scaling independently. They are useful for inspecting shape and activity, but panel heights should not be read as a common-amplitude before/after comparison.

Implementation notes and limitations