FX
Reverb
Convolution reverb with synthetic-IR fallback. Use a real impulse response for spaces, or skip it for ambient wash.
TL;DR
Wraps a ConvolverNode with dry/wet mixing and pre-delay.
Pass an impulse AudioBuffer for a real space, or omit it
and zvuk generates a synthetic exponential-decay noise IR — cheap,
not as character-rich, but plenty for atmosphere.
API surface
class Reverb implements FxInsert {
readonly input: GainNode;
readonly output: GainNode;
bypassed: boolean;
setWet(mix: number): void; // 0..1
setImpulse(buffer: AudioBuffer): void;
dispose(): void;
}
interface ReverbConfig {
wet?: number; // default 0.3
impulse?: AudioBuffer; // your own IR
decay?: { seconds?: number; preDelay?: number };
} Live demo
Wet mix slider, decay length (regenerates the IR), bypass toggle.
Recipes
Synthetic IR
import { Reverb } from 'zvuk';
// Synthetic IR — ~free, fine for atmosphere.
const verb = new Reverb(engine.context, {
wet: 0.3,
decay: { seconds: 1.5, preDelay: 0.02 },
});
engine.bus('music').addFx(verb); Real impulse response
// Real impulse response — load like any other audio asset.
const irBuf = await fetch('/ir/cathedral.wav')
.then((r) => r.arrayBuffer())
.then((ab) => engine.context.decodeAudioData(ab));
const verb = new Reverb(engine.context, { wet: 0.4, impulse: irBuf });
engine.bus('music').addFx(verb); Wet driven by a Parameter
// Drive wet from a Parameter so multiple things tilt with one knob.
const intensity = engine.parameter('intensity', 0.3);
intensity.bindTo((v) => verb.setWet(v), { from: 0.1, to: 0.6 }); Pitfalls
Don't reverb SFX.
Individual hits get smeared and mushy. Reserve reverb for music, ambience,
voice — long-tailed sources. SFX want to land sharp.
Don't ship a 5-second IR for a UI bus.
Convolution cost scales with IR length × buffer rate. A 5 s IR at 48 kHz
is the same compute every frame whether the bus has audio or not. Keep
IRs under 2 s unless you actually need a cathedral.