Normalize Module — Post-Render Peak/RMS Normalisation
A shared builtin module that applies peak or RMS normalisation to rendered
audio during WAV export. Runs post-render in the renderToBuffer() Promise
callback, operating directly on the final Float32Array of samples.
Used by all six synth engines.
Exports
| Export | Signature | Purpose |
|---|---|---|
paramDefs |
{} |
5 parameter definitions (normalize, normTarget, normMode, normCeiling, normDC) |
createNormalizeModule |
() → {id, type, params, state, apply} |
Creates a module object with shared apply logic and a state object for the meter |
startNormMeter |
(state) → undefined |
Finds the normalize card, builds pre/after/gain meter UI, starts a RAF loop reading from state |
Params
| Param | Type/Range | Default | Description |
|---|---|---|---|
normalize |
checkbox | true | Enable normalisation |
normTarget |
–12–0 dB | −1 | Target peak or RMS level |
normMode |
peak/rms | rms | Peak: loudest sample hits target. RMS: matches perceived loudness. |
normCeiling |
checkbox | false | Hard-clip any sample exceeding target after normalisation |
normDC |
checkbox | false | Remove DC offset before normalising |
Apply Logic
The apply function is called by engine.js's renderToBufferInternal for
every builtin module after the OfflineAudioContext render completes:
engine.modules.forEach(mod => {
if (mod.type === 'builtin' && mod.apply) {
mod.apply(samples, params);
}
});
Processing order:
1. Set target from params.normTarget (fallback –1 dB)
2. If normalize is off, set state.disabled = true and return
3. Optional DC removal: subtract the sample mean
4. RMS or peak mode: compute pre-level, apply gain, record gain value
5. Optional ceiling: hard-clamp to ±targetLin
Meter
startNormMeter locates the normalize section card (by [data-key="normTarget"]),
appends a meter row showing pre-level, target level, and applied gain in dB.
It reads from the shared state object written by apply:
Pre: ████████░░ –18.3 dB
After:████████████ –1.0 dB
Gain: +17.3 dB
The meter shows "Off:" with dashed values when normalisation is disabled, and "..." before the first render completes.
Integration
import { startNormMeter } from './modules/normalize.js';
startNormMeter(SynthX.modules.find(m => m.id === 'normalize').state);
Files
| File | Purpose |
|---|---|
modules/normalize.js |
Module definition |
All 6 engines/*.js |
Each replaces its inline normalise with createNormalizeModule() |
All 6 init-*.js |
Each calls startNormMeter() after initSynth |