* feat(core): add a lookahead true-peak limiter FX (truepeak) The existing limiter is an envelope follower with no lookahead and no inter-sample detection, so a -14 dB ceiling can leave the true peak several dB over. truepeak estimates the true peak on a 4x polyphase interpolator, takes the minimum required gain over a lookahead window and smooths it with a boxcar of the same length, so the gain is already down when the peak leaves the delay line. Release is exponential and can only lower the gain further; channels share one gain. The offline render lengthens the OfflineAudioContext by the chain's latency and drops the lead-in, so a limited clip stays sample-aligned with its source. Preview plays the lookahead (about 3.3 ms at the default). — Jerrai * docs(audio): truepeak ceiling is a 4x estimate; measure it with an ideal interpolator The unit test's meter was a 96-tap Kaiser sinc, which rolls off near Nyquist and reads full-band noise about 0.5 dB low, so the PR reported a 0.3 dB broadband overshoot. Against an ideal 16x interpolation (zero-padded FFT, cross-checked with a 16x soxr resample) hot full-band white noise ends 1.2 to 1.7 dB over the ceiling (median 1.4 over 28 runs of 10 to 30 s). ffmpeg's ebur128 true peak is also a 4x meter and reads the same files 0.1 dB over. - The test meter is now the FFT interpolation. Tolerances are what it measures on each fixed signal: tones 0.01 dB (they land on the ceiling), the dense program 0.5 dB (reads 0.445, the old 0.4 passed only because the meter read low), and a new full-band noise case at -1, -6 and -14 dBTP with 1.35 dB (reads 1.09 to 1.31). - audio-effects.mdx and the hyperframes-audio skill say the ceiling is a 4x estimate, give the measured overshoot and recommend a 2 dB margin under a hard delivery limit. - skills-manifest.json regenerated. — Jerrai * fix(core): truepeak UI copy no longer promises a hard ceiling The registry description and the rack summary said the true peak is never above the ceiling. The limiter holds a 4x estimate, and full-band noise can land up to about 1.7 dB above it, as the docs now say. The summary reads "held near", the description names the estimate and the overshoot, and the rack blurb says "holds ... to a ceiling". No skill file changed, so the skills manifest is unchanged. — Jerrai * fix(core): Studio truepeak copy states the 4x-estimate margin The ceiling control was labelled "Never exceed" and the module said the mix "must not clip", so a Studio user never saw that dense full-band content can end up to about 1.7 dB above the ceiling. The label is now "Target ceiling" with a hint that names the 4x estimate and the headroom to leave, the blurb says "toward a target ceiling", the rack summary says peaks are pulled down toward the value, and the registry hint no longer says "highest true peak allowed". The audio skill's "hard dBTP ceiling" wording is gone and the skills manifest is regenerated. A copy test keeps the promise out. — Jerrai * fix(core): truepeak clears on a seek, and the review nits (fallow, comments) - Unexport TRUE_PEAK_OVERSAMPLE, TRUE_PEAK_DETECTOR_DELAY and truePeakLookaheadSamples: nothing imports them (Fallow audit). - A persistent group bus keeps its chain across a seek, so the limiter's delay line and held gain carried over. The worklet takes __hfReset, the graph exposes FxChainHandle.reset(), and reanchor() calls it. - The processor-loading harness is shared by the truepeak and worklet tests (it was a 12-line clone); the test FFT no longer repeats audioCarve's bit-reversal; two test bodies are under the CRAP threshold. - Comment blocks cut to four lines or fewer (Comments check). - Docs state the preview delay in ms. — Jerrai
7.8 KiB
Effect registry
Every effect, its parameters and the usable range of each. Values outside a range are clamped on read, so anything that parses is safe to realise. AUTO marks a parameter an automation lane can drive; anything unmarked cannot move over time (see the note at the bottom).
Generated from HF_AUDIO_FX in @hyperframes/core/audio-fx, which is the source
of truth — if this table and the code disagree, the code is right.
Filter — which frequencies a track may occupy
| Effect | Parameter |
|---|---|
highpass |
frequency 20–20000 Hz (300, log) AUTO · q 0.1–20 (0.707, log) AUTO · poles 1|2 (2) |
lowpass |
frequency 100–20000 Hz (8000, log) AUTO · q 0.1–20 (0.707, log) AUTO · poles 1|2 (2) |
peaking |
frequency 20–20000 Hz (1000, log) AUTO · gain −40–40 dB (0) AUTO · q 0.1–20 (1, log) AUTO |
lowshelf |
frequency 20–2000 Hz (200, log) AUTO · gain −40–40 dB (0) AUTO |
highshelf |
frequency 500–20000 Hz (4000, log) AUTO · gain −40–40 dB (0) AUTO |
q is bandwidth — higher is narrower. poles is the slope: 2 is the usual
biquad (12 dB/oct), 1 is gentler (6 dB/oct). Shelving filters have no q: the
Web Audio spec leaves it unused for them, so a control would have moved nothing.
Dynamics — how level behaves over time
| Effect | Parameter |
|---|---|
gain |
gain −60–12 dB (0) AUTO |
compressor |
threshold −60–0 dB (−24) · ratio 1–20 (4) · attack 0.01–2000 ms (20, log) · release 0.01–9000 ms (250, log) · knee 1–8 (2.83) · makeup 0–36 dB (0) · mix 0–1 (1) |
limiter |
limit −24–0 dB (−1) · attack 0.1–80 ms (5) · release 1–8000 ms (50, log) · level_out −24–24 dB (0) |
truepeak |
ceiling −24–0 dBTP (−1) · lookahead 0.5–10 ms (3) · release 10–2000 ms (80, log) |
gate |
threshold −80–0 dB (−35) · range −80–0 dB (−24) · ratio 1–20 (10) · attack 0.01–9000 ms (1, log) · release 0.01–9000 ms (100, log) · knee 1–8 (2.83) |
Cuts on gain go to −60 dB, boosts stop at +12: it is a level stage for making
room, and a chain that could add 40 dB would clip long before that was useful.
knee of 1 is a hard corner, higher eases into it. mix below 1 blends the dry
signal back in (parallel compression). range is how far down the gate pulls
when closed — a gate that pulls all the way to silence sounds like a switch.
limiter follows the signal's level and has no lookahead, so it does not
guarantee a peak ceiling. For a delivery ceiling use truepeak: it estimates the
inter-sample (true) peak at 4x, looks lookahead ms ahead, and holds that estimate
at ceiling dBTP. It delays its output by lookahead plus about 0.3 ms; the
render trims the delay, live preview plays it.
The ceiling is a 4x estimate, so the real true peak can end above it. Against an
ideal 16x interpolation, tones, pink noise and a dense mix ended at most 0.6 dB
over; full-band white noise driven 8 dB or more into the limiter ended 1.2 to 1.7
dB over (median 1.4). A 4x meter such as ffmpeg ebur128=peak=true reads that
noise about 0.1 dB over and will not show it. Under a hard delivery limit set
ceiling at least 2 dB below it (−3 dBTP for a −1 dBTP limit).
Nonlinear — changes the waveform's shape
| Effect | Parameter |
|---|---|
saturate |
type tanh|atan|cubic|exp|alg|quintic|sin|erf|hard (tanh) · threshold −40–0 dB (−6) · output −24–24 dB (0) AUTO · oversample 1–8× (4) |
bitcrush |
bits 1–32 (8) · samples 1–250× (1) · mix 0–1 (1) |
tanh is the gentlest curve and hard is outright clipping. Higher oversample
costs more CPU and keeps aliasing down. samples repeats each sample N times — a
crude downsample, which is where the lo-fi character comes from.
Time — space and width
| Effect | Parameter |
|---|---|
delay |
time 1–5000 ms (250, log) AUTO · feedback 0.01–0.95 (0.35) AUTO · mix 0–1 (0.4) AUTO |
reverb |
size 0.05–1 (0.7) · damping 0–1 (0.5) · wet 0–1 (0.35) AUTO · dry 0–1 (0.7) AUTO |
chorus |
delay 1–100 ms (7) AUTO · depth 0–10 ms (2) AUTO · speed 0.01–10 Hz (1) AUTO · mix 0–1 (0.5) AUTO |
phaser |
in_gain 0–1 (0.4) AUTO · out_gain 0–2 (0.74) AUTO · delay 0.1–5 ms (3) · decay 0–0.99 (0.4) · speed 0.1–2 Hz (0.5) AUTO · type 0|1 (0) |
Reverb convolves a generated impulse, and both preview and render generate the
same one — so a room is reproducible without shipping an impulse file. Higher
damping rolls the top off the tail faster, which is what makes a large room
sound like a soft one. feedback near the top of its range is a very long tail;
it is bounded below 1 because at 1 it never decays.
Why some parameters cannot be automated
Automation is handed to the audio thread once, as native AudioParam ramps and
curves, which is what keeps it sample-accurate and identical between preview and
render. A parameter can therefore only be automated if an AudioParam backs it.
Three kinds do not:
- worklet processor options —
compressor,limiter,truepeak,gateandbitcrushare AudioWorklets configured wholesale, so none of their parameters are automatable at all. - a WaveShaper curve —
saturate'stype,thresholdandoversamplerebuild the curve; only itsoutputstage is a real param. - a convolution impulse —
reverb'ssizeanddampingregenerate the impulse;wet/dryare gain stages and automate fine.
To make one of those behave differently over time, automate a gain stage
around it instead: a lane on a gain before a compressor changes how hard the
compressor is driven, which is most of what automating its threshold would have
done.