Sidechain ducking
Drop the music when the VO speaks. Smoothly. Without writing your own envelope follower.
The shape
A Ducker lives on the target bus (the one being
ducked) and listens to a source bus (the one whose loudness drives
the duck). When the source's RMS exceeds the threshold, the target's
output gain drops over attack ms; when the source quiets, gain
recovers over release ms.
Wiring
import { Ducker } from 'zvuk';
const ducker = new Ducker(engine.context, engine.bus('voice'), {
amount: 0.6, // 60% drop at peak
attack: 80, // ms — how fast we duck
release: 400, // ms — how slow we recover
threshold: 0.05, // RMS amplitude on source to trigger
});
engine.bus('music').addFx(ducker); Live tuning
ducker.setAmount(0.8); // duck harder during boss VO
ducker.setThreshold(0.02); // more sensitive — duck even on quiet whispers Why not just use DynamicsCompressorNode?
Web Audio's compressor is internally-keyed only — it compresses based on
its own input. To get true sidechain (key from a different bus) you need
an envelope follower on the source bus driving a gain on the target. The
Ducker is exactly that, packaged.
Latency
The follower runs on the main thread at ~60 Hz. That's perfectly fine for speech ducking, where the smallest meaningful event (a syllable) is ~100 ms. For sample-accurate audio-rate sidechain (e.g. compressing a kick under a snare), use a custom AudioWorklet — that's planned for a future release.
Pitfalls
attack below ~20 ms for VO.