This document describes the audio processing signal chain for the Web Audio Mastering application. The app is built around an export-parity master preview: FX ON playback, metering, and export all use the same full-chain render.
The app keeps three core buffers:
originalBuffer: decoded input audio (DC offset removed)normalizedBuffer: LUFS-normalized copy used only for FX OFF (Level Match) and as a last-resort fallbackcachedRenderBuffer: full-chain mastered preview buffer (includes soft clip + final true peak limiter when enabled)
Where full-chain rendering happens:
- Preferred: Web Worker full-chain render (
web/workers/dsp-worker.js, viarenderFullChain(..., mode: 'export')) - Fallback: main-thread offline render (
web/ui/renderer.js)
- FX ON (Master Preview):
cachedRenderBuffer-> output (direct) - FX OFF (Bypass):
- Level Match ON:
normalizedBuffer-> output - Level Match OFF:
originalBuffer-> output
- Level Match ON:
Meters follow the audio that is actually playing, so when FX ON is active the meter includes the final limiter behavior because the limiter is baked into the preview buffer.
This is the canonical ordering for parity (Worker path).
- Input Gain (pre-FX)
- Dynamic Processor (De-harsh) (optional)
- Exciter (Add Air) (optional)
- Multiband Saturation (Tape Warmth) (optional)
- Multiband Transient Shaper (Add Punch) (optional)
- Final Filters (cleanup)
- HPF 30 Hz (only when Clean Low End is enabled)
- LPF 18 kHz (always)
- EQ (5-band) + Cut Mud (optional)
- Glue Compression (optional)
- Stereo Processing
- M/S Stereo Width
- Center Bass (mono bass below ~200 Hz) (optional)
- LUFS normalization (gain-only; peak control happens below) (optional)
- Mastering soft clipper (optional, when True Peak Limit is enabled)
- Lookahead true peak limiter (optional, when True Peak Limit is enabled)
File: web/lib/dsp/dynamic-processor.js
Purpose: Intelligent multiband dynamics processor that combines:
- Multiband Compression (7 bands with per-band attack/release)
- Dynamic EQ (resonance detection and surgical peak cutting)
- De-esser behavior (fast attack in 3-12kHz range)
Default: ENABLED - Essential for AI-generated audio
| Band | Frequency Range | Attack | Release | Threshold | Ratio | Purpose |
|---|---|---|---|---|---|---|
| Sub | 0-80 Hz | 30ms | 200ms | -12 dB | 2:1 | Gentle control |
| Bass | 80-250 Hz | 20ms | 150ms | -15 dB | 2.5:1 | Tighten low end |
| Low-mid | 250-1000 Hz | 10ms | 100ms | -18 dB | 3:1 | Control mud |
| Mid | 1-3 kHz | 8ms | 80ms | -20 dB | 3.5:1 | Presence control |
| Presence | 3-6 kHz | 3ms | 40ms | -24 dB | 5:1 | De-esser zone |
| Brilliance | 6-12 kHz | 2ms | 30ms | -26 dB | 6:1 | AI artifact zone |
| Air | 12-20 kHz | 5ms | 50ms | -22 dB | 3:1 | High freq control |
Resonance Detection:
- Tracks running average spectrum per bin
- Identifies peaks >1.5x the local average
- Applies surgical dynamic cuts to resonant frequencies
AI Artifact Mode:
- Extra 50% more aggressive processing in 5-12kHz range
- Where AI audio artifacts typically live
Mastering Preset (Default):
- Dynamic EQ sensitivity: 0.4
- Max cut: -8 dB
- Soft knees (+4 dB wider)
- 70% wet / 30% dry for transparency
- Split signal into 7 frequency bands via FFT
- Per-band envelope followers track signal level
- Soft-knee gain computers determine compression
- Resonance detector finds peaks sticking out from average
- Dynamic EQ applies additional cuts to resonant bins
- Overlap-add reconstruction with gain applied per-bin
File: web/lib/dsp/exciter.js
Purpose: Adds harmonic content to high frequencies for enhanced clarity and presence ("air").
Default: ENABLED
Parameters:
| Parameter | Value | Description |
|---|---|---|
hpfFreq |
3500 Hz | High-pass filter cutoff |
hpfSlope |
12 dB/oct | Filter slope (LR2) |
drive |
2.0 | Saturation drive amount |
bias |
0.1 | Bias for even harmonics |
mix |
18% | Parallel mix (additive) |
Algorithm:
- High-pass filter isolates frequencies above 3.5kHz
- Tanh saturation with bias generates harmonics
- Parallel addition:
output = dry + (saturated * mix)
Character: Adds presence and sparkle without harshness.
File: web/lib/dsp/multiband-saturation.js
Purpose: Warm harmonic coloring with frequency-dependent saturation.
Default: ENABLED
Crossover Frequencies:
| Band | Frequency Range |
|---|---|
| Low | 0 - 200 Hz |
| Mid | 200 Hz - 4 kHz |
| High | 4 kHz+ |
Tape Warmth Preset:
| Band | Drive | Bias | Mix | Gain |
|---|---|---|---|---|
| Low | 0.2 | 0.0 | 30% | 0 dB |
| Mid | 0.4 | 0.1 | 50% | 0 dB |
| High | 0.3 | 0.05 | 40% | 0 dB |
Bypass Envelope:
| Parameter | Value | Description |
|---|---|---|
| Threshold | -24 dB | Below this, bypass saturation |
| Knee | 6 dB | Soft transition zone |
| Window | 100 ms | Analysis window |
| Lookahead | 5 ms | Envelope opens before transients |
Algorithm:
- Linkwitz-Riley LR4 crossover (-24 dB/oct) splits into 3 bands
- Each band:
wet = (tanh(drive * (sample + bias)) - biasOffset) * makeup - Bypass envelope prevents saturating quiet sections (noise amplification)
- Bands summed back together
File: web/lib/dsp/multiband-transient.js
Purpose: Per-band transient enhancement for punch and snap.
Default: ENABLED
Crossover Frequencies:
| Band | Frequency Range |
|---|---|
| Low | 0 - 200 Hz |
| Mid | 200 Hz - 4 kHz |
| High | 4 kHz+ |
Band Settings:
| Band | Fast Attack | Fast Release | Slow Attack | Slow Release | Transient Gain | Sustain Gain |
|---|---|---|---|---|---|---|
| Low | 5 ms | 50 ms | 25 ms | 250 ms | +5 dB | -2 dB |
| Mid | 3 ms | 40 ms | 20 ms | 200 ms | +4 dB | 0 dB |
| High | 5 ms | 30 ms | 15 ms | 150 ms | 0 dB | 0 dB |
Algorithm:
- Fast and slow envelope followers track signal
- Transient detection:
diff = fastEnv - slowEnv - Positive diff = transient -> boost
- Negative diff = sustain -> cut (optional)
- 20ms smoothing prevents artifacts
Character:
- Low band: Adds kick/bass punch
- Mid band: Adds snare/vocal attack
- High band: Left alone (avoid harshness)
File: web/lib/dsp/final-filters.js (applyFinalFilters)
Purpose: Clean up frequency extremes before loudness/peak control.
Applied in the full-chain render:
| Filter | Enabled When | Type | Frequency | Slope |
|---|---|---|---|---|
| HPF | Clean Low End | Highpass (biquad) | 30 Hz | 12 dB/oct |
| LPF | Always | Lowpass (1-pole) | 18 kHz | 6 dB/oct |
Rationale:
- HPF removes sub-bass rumble and DC offset remnants
- LPF removes ultrasonic content that can cause inter-sample peaks
File: web/lib/dsp/normalizer.js, web/lib/dsp/lufs.js
Purpose: Normalize to target integrated loudness per ITU-R BS.1770-4.
Default: ENABLED
Parameters:
| Parameter | Default | Description |
|---|---|---|
| Target LUFS | -14 LUFS | User configurable (-16 to -6) |
| Ceiling | -1 dBTP | True peak ceiling |
Algorithm (ITU-R BS.1770-4):
- K-weighting filters:
- High shelf: 1681.97 Hz, +4 dB, Q=0.71
- High pass: 38.14 Hz, Q=0.5
- 400ms blocks with 75% overlap
- Absolute gate: -70 LUFS
- Relative gate: -10 dB below ungated mean
- Integrated loudness from gated blocks
Gain Application:
- Calculate required gain:
targetLUFS - currentLUFS - Apply gain to all samples
- Full-chain render applies gain only (
skipLimiter: true); peak control happens in the soft clipper + final limiter stages below.
File: web/lib/dsp/soft-clipper.js
Purpose: Mastering-grade peak reduction using saturation curves with lookahead. Reduces the peak-to-loudness ratio before limiting, allowing louder masters without heavy limiter pumping.
Default: ENABLED (when True Peak Limit is on)
Parameters:
| Parameter | Value | Description |
|---|---|---|
ceiling |
-1 dB | Target ceiling (matches limiter) |
lookaheadMs |
0.5 ms | Very short lookahead for transients |
releaseMs |
10 ms | Fast release for transparency |
drive |
1.5 | Saturation intensity |
Algorithm:
- Gain Envelope Calculation:
- Scan all channels for peaks above threshold (ceiling + 3dB)
- Calculate required gain reduction using tanh saturation curve
- Apply lookahead window (0.5ms) to catch transients early
- Envelope Smoothing:
- Instant attack (gain reduction applied immediately)
- Exponential release (10ms time constant)
- Prevents gain pumping artifacts
- Final Safety Clip:
- Apply smoothed gain envelope to samples
- Gentle tanh saturation for any remaining peaks above ceiling
- Maximum 10% additional reduction for peaks
Rationale: When normalizing quiet sources (e.g., -18 LUFS) to loud targets (e.g., -14 to -9 LUFS), the required gain can push peaks far above the ceiling. Without soft clipping, the limiter must do heavy lifting, causing pumping and squashing. The soft clipper gently shaves peaks before they hit the limiter, resulting in more transparent limiting.
File: web/lib/dsp/limiter.js
Purpose: Transparent peak control with true-peak detection.
Default: ENABLED
Parameters:
| Parameter | Value | Description |
|---|---|---|
| Ceiling | -1 dBTP | True peak ceiling (linear: 0.891) |
| Lookahead | 3 ms | See peaks before they arrive |
| Release | 100 ms | Gain recovery time |
| Knee | 3 dB | Soft knee width |
| Preserve Transients | true | Gentler limiting on transients |
Two-Stage Architecture:
Stage 1: Lookahead Gain Reduction
- 4x oversampled true-peak detection (Catmull-Rom interpolation)
- Gain envelope calculated with lookahead
- Smooth attack/release for transparency
Stage 2: Soft-Knee Saturation Safety
- Catches any remaining peaks
- Tanh sigmoid curve (no hard clipping)
- Oversampled to handle inter-sample peaks
Transient Preservation:
- Analyzes crest factor (peak/RMS ratio)
- High crest factor = transient
- Transients get slightly higher effective ceiling (+0.5 dB max)
File: web/lib/dsp/constants.js
HIGH_SHELF_FREQ: 1681.97 Hz
HIGH_SHELF_GAIN: 4.0 dB
HIGH_SHELF_Q: 0.71
HIGH_PASS_FREQ: 38.14 Hz
HIGH_PASS_Q: 0.5BLOCK_SIZE: 400 ms
BLOCK_OVERLAP: 75%
ABSOLUTE_GATE: -70 LUFS
RELATIVE_GATE: -10 dB
LOUDNESS_OFFSET: -0.691CEILING: -1 dBTP (0.891 linear)
LOOKAHEAD: 3 ms
RELEASE: 100 ms
KNEE: 3 dB
PRESERVE_TRANSIENTS: trueSAMPLE_RATE: 48000 Hz (default export)
BIT_DEPTH: 24 (default export)
TARGET_LUFS: -14| Feature | Default | UI Control |
|---|---|---|
| De-harsh | ON | Quick Fix panel |
| Clean Low End | ON | Quick Fix panel |
| Add Punch | ON | Quick Fix panel |
| Add Air | ON | Polish panel |
| Tape Warmth | ON | Polish panel |
| Mono Bass | ON | Stereo panel |
| Normalize Loudness | ON | Loudness panel |
| True Peak Limit | ON | Loudness panel |
| Target LUFS | -14 | Loudness slider |
| Ceiling | -1 dB | Loudness fader |
| Stereo Width | 100% | Stereo slider |
| Sample Rate | 48 kHz | Output panel |
| Bit Depth | 24-bit | Output panel |
web/lib/dsp/
├── index.js # Main exports (barrel file)
├── constants.js # All constants
├── utils.js # Utility functions (dB conversion, etc.)
├── fft.js # FFT processor
├── lufs.js # LUFS measurement
├── true-peak.js # True peak detection
├── normalizer.js # LUFS normalization
├── limiter.js # Lookahead limiter
├── soft-clipper.js # Mastering soft clipper with lookahead
├── dynamic-processor.js # Hybrid multiband dynamics (De-harsh)
├── exciter.js # High-frequency exciter
├── saturation.js # Single-band saturation
├── multiband-saturation.js # 3-band saturation (Tape Warmth)
├── multiband-transient.js # 3-band transient shaper (Add Punch)
├── transient.js # Single-band transient shaper
├── stereo.js # Stereo processing (M/S, width)
├── dynamic-leveler.js # Dynamic range leveling
├── multiband.js # Multiband compression
└── dc-offset.js # DC offset removal
web/workers/
├── worker-interface.js # Worker messaging + progress plumbing
└── dsp-worker.js # Full-chain render implementation (preview/export parity)
web/ui/
├── renderer.js # Main-thread offline render fallback
└── encoder.js # WAV encoder (supports async/progress)
- v1.3.3 - Master preview uses full-chain cached render (export parity); export WAV encoding reports smooth progress
- v1.3.2 - Added mastering soft clipper with lookahead before limiter
- v1.3.1 - Hybrid Dynamic Processor (De-harsh) replaces Tame Harshness
- v1.3.0 - Removed FFmpeg dependency, pure JavaScript LUFS + Web Audio export
- v1.2.x - Multiband transient shaper, cached buffer architecture
- v1.1.x - Multiband saturation, exciter
- v1.0.x - Initial release with basic chain