Signatur
Beschreibung
ConvolverNode gehört zur Web Audio API und führt eine lineare Faltung des Eingangssignals mit einer Impulsantwort durch. Die Impulsantwort ist eine Aufnahme davon, wie ein Raum (Kirche, Konzertsaal, Badezimmer) oder ein Gerät (Lautsprecherbox, Federhall) auf einen kurzen Impuls reagiert. Wird ein beliebiges Signal damit gefaltet, klingt es so, als wäre es in diesem Raum bzw. durch dieses Gerät abgespielt worden.
Der Knoten hat genau einen Eingang und einen Ausgang. Instanzen erzeugt man mit new ConvolverNode(context, options) oder mit der Fabrikmethode BaseAudioContext.createConvolver(). Die Impulsantwort weist man über die Eigenschaft buffer zu. Meist lädt man sie als WAV-Datei per fetch() und dekodiert sie mit decodeAudioData(). Man kann sie aber auch selbst erzeugen, etwa als abklingendes Rauschen.
Wichtige Eigenschaften:
buffer: einAudioBuffer(Mono, Stereo oder 4 Kanäle) mit der Impulsantwort, odernull.normalize: einboolean, Standard isttrue. Er legt fest, ob die Impulsantwort beim Zuweisen anbufferanhand ihrer Leistung (RMS) auf eine gleichmäßige Lautstärke skaliert wird.
In der Praxis schaltet man den Convolver fast immer parallel zum trockenen Signal (Dry/Wet-Mix). Das Verhältnis steuert man mit zwei GainNodes.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $context Pflicht | BaseAudioContext | Der AudioContext oder OfflineAudioContext, zu dem der Knoten gehört (nur beim Konstruktor). |
|
| $options | ConvolverOptions | {} | Optionales Objekt mit buffer (AudioBuffer | null), disableNormalization (boolean, Standard false) sowie den allgemeinen AudioNodeOptions channelCount, channelCountMode und channelInterpretation. |
Rückgabewert
ConvolverNode-Instanz, die mit dem angegebenen Kontext verbunden werden kann.Beispiele
Hall mit geladener Impulsantwort
const ctx = new AudioContext();
const loadImpulse = async (url) => {
const res = await fetch(url);
const data = await res.arrayBuffer();
return ctx.decodeAudioData(data);
};
const startReverb = async () => {
const impulse = await loadImpulse('/audio/konzertsaal.wav');
const convolver = new ConvolverNode(ctx, { buffer: impulse });
const osc = new OscillatorNode(ctx, { type: 'sawtooth', frequency: 220 });
osc.connect(convolver).connect(ctx.destination);
osc.start();
osc.stop(ctx.currentTime + 0.5);
console.log('Kanäle der Impulsantwort:', convolver.buffer.numberOfChannels);
};
document.querySelector('#play').addEventListener('click', async () => {
await ctx.resume();
await startReverb();
});
Synthetische Impulsantwort ohne Datei erzeugen
const ctx = new AudioContext();
// Abklingendes Stereo-Rauschen als künstlicher Raum
const createImpulse = (seconds = 2.5, decay = 3) => {
const length = Math.floor(ctx.sampleRate * seconds);
const impulse = ctx.createBuffer(2, length, ctx.sampleRate);
for (let ch = 0; ch < 2; ch++) {
const data = impulse.getChannelData(ch);
for (let i = 0; i < length; i++) {
data[i] = (Math.random() * 2 - 1) * (1 - i / length) ** decay;
}
}
return impulse;
};
const convolver = ctx.createConvolver();
convolver.buffer = createImpulse();
console.log(convolver.normalize, convolver.buffer.duration.toFixed(1));
Dry/Wet-Mix für ein Audio-Element
const ctx = new AudioContext();
const audioEl = document.querySelector('audio');
const source = ctx.createMediaElementSource(audioEl);
const convolver = new ConvolverNode(ctx);
const dry = new GainNode(ctx, { gain: 0.7 });
const wet = new GainNode(ctx, { gain: 0.3 });
source.connect(dry).connect(ctx.destination);
source.connect(convolver).connect(wet).connect(ctx.destination);
const res = await fetch('/audio/kirche.wav');
convolver.buffer = await ctx.decodeAudioData(await res.arrayBuffer());
// Regler 0..1 steuert den Hallanteil
document.querySelector('#mix').addEventListener('input', (e) => {
const mix = Number(e.target.value);
wet.gain.setTargetAtTime(mix, ctx.currentTime, 0.05);
dry.gain.setTargetAtTime(1 - mix, ctx.currentTime, 0.05);
});
// Wichtig · Fallstricke
- Setze
normalizevorbuffer: Die Normalisierung wird nur in dem Moment berechnet, in dembufferzugewiesen wird. Wenn dunormalizedanach änderst, hat das erst beim nächsten Zuweisen eine Wirkung. Im Konstruktor entsprichtdisableNormalization: truedem Wertnormalize = false. - Abtastrate: Die Abtastrate des
AudioBuffermuss der des Kontexts entsprechen, sonst wird einNotSupportedErrorgeworfen.decodeAudioData()rechnet die Datei automatisch auf die Rate des Kontexts um. - Kanalanzahl: Die Impulsantwort darf nur 1, 2 oder 4 Kanäle haben. Für
channelCountsind nur 1 oder 2 erlaubt, undchannelCountModedarf nicht"max"sein. - Leistung: Die Faltung ist rechenintensiv. Lange Impulsantworten mit mehreren Sekunden kosten viel CPU, vor allem auf Mobilgeräten. Nutze einen gemeinsamen Convolver als Hall-Bus, statt für jede Quelle einen eigenen anzulegen.
- Autoplay: Browser starten einen
AudioContextim Zustandsuspended. Rufectx.resume()daher erst nach einer Nutzerinteraktion auf. - CORS: Impulsantworten von fremden Domains brauchen passende CORS-Header. Bei
createMediaElementSource()mit fremden Quellen bleibt der Ausgang ohne CORS stumm. - Kompatibilität: Die Schnittstelle wird in allen modernen Browsern unterstützt. Den Konstruktor
new ConvolverNode()gibt es erst in neueren Versionen; sehr alte Safari-Versionen brauchencreateConvolver()bzw.webkitAudioContext.