Z zvuk
Guide

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

ts ts
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

ts ts
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

Don't set attack below ~20 ms for VO.
Voice transients are spiky; a too-fast attack creates pumping artifacts. 80 ms is a good default; 40 ms for very urgent VO.
Don't duck the music bus that plays the VO.
Place the Ducker on a different bus (music, ambience). The source bus you key from must contain only the trigger material.