Start · Sprachen · JavaScript · Referenz · BaseAudioContext.createConvolver()

BaseAudioContext.createConvolver()

Methode

Erstellt einen <code>ConvolverNode</code>, der ein Audiosignal mit einer Impulsantwort faltet, z. B. um realistischen Raumhall zu erzeugen.

seit JavaScript Baseline: alle modernen Browser (Web Audio API) Kategorie: webapi

Signatur

BaseAudioContext.prototype.createConvolver()

Beschreibung

Die Methode createConvolver() eines AudioContext oder OfflineAudioContext liefert einen neuen ConvolverNode. Dieser Knoten führt eine lineare Faltung (Convolution) zwischen dem Eingangssignal und einer Impulsantwort (Impulse Response, IR) durch. Damit kann man die akustischen Eigenschaften eines echten Raums wie einer Kirche, eines Konzertsaals oder eines Treppenhauses auf beliebiges Audio übertragen.

Die Impulsantwort ist ein AudioBuffer. Man weist sie der Eigenschaft convolver.buffer zu. Meist lädt man dafür eine WAV-Datei per fetch() und dekodiert sie mit decodeAudioData(). Man kann die IR aber auch synthetisch aus abklingendem Rauschen erzeugen. Solange kein Puffer gesetzt ist, gibt der Knoten Stille aus.

In der Praxis mischt man das trockene Originalsignal (dry) mit dem verhallten Signal (wet) über zwei GainNodes. Mit der Eigenschaft normalize (Standard: true) wird die Lautstärke der IR automatisch angeglichen. Das verhindert, dass stark unterschiedliche Impulsantworten zu großen Pegelsprüngen führen.

Als moderne Alternative gibt es den Konstruktor new ConvolverNode(context, { buffer, disableNormalization }). Mit ihm lassen sich die Optionen direkt beim Erzeugen setzen.

Rückgabewert

Typ
ConvolverNode
Beschreibung
Ein neuer ConvolverNode ohne gesetzten buffer und mit normalize = true.

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 setupReverb = async () => {
  const convolver = ctx.createConvolver();
  convolver.buffer = await loadImpulse('/audio/ir/concert-hall.wav');

  const audioEl = document.querySelector('audio');
  const source = ctx.createMediaElementSource(audioEl);

  source.connect(convolver);
  convolver.connect(ctx.destination);
  console.log('Hall aktiv, IR-Länge:', convolver.buffer.duration.toFixed(2), 's');
};

// Wegen der Autoplay-Richtlinie erst nach einer Nutzeraktion starten
document.querySelector('#start').addEventListener('click', async () => {
  await ctx.resume();
  await setupReverb();
});
Hall aktiv, IR-Länge: 2.40 s

Synthetische Impulsantwort (ohne Datei)

const ctx = new AudioContext();

// Abklingendes Stereo-Rauschen als künstlicher Raum
const createImpulse = (seconds = 2, decay = 3) => {
  const length = 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(3, 4);
console.log(convolver.normalize, convolver.buffer.numberOfChannels);
true 2

Dry/Wet-Mischung mit regelbarem Hallanteil

const ctx = new AudioContext();
const osc = ctx.createOscillator();
const dry = ctx.createGain();
const wet = ctx.createGain();
const convolver = ctx.createConvolver();

// Kurze Impulsantwort aus Rauschen
const len = ctx.sampleRate * 1.5;
const ir = ctx.createBuffer(2, len, ctx.sampleRate);
for (let c = 0; c < 2; c++) {
  const d = ir.getChannelData(c);
  for (let i = 0; i < len; i++) d[i] = (Math.random() * 2 - 1) * Math.exp(-i / (len / 5));
}
convolver.buffer = ir;

const setMix = (amount) => {
  // amount: 0 = trocken, 1 = nur Hall
  dry.gain.value = 1 - amount;
  wet.gain.value = amount;
};
setMix(0.35);

osc.connect(dry).connect(ctx.destination);
osc.connect(convolver).connect(wet).connect(ctx.destination);

osc.start();
osc.stop(ctx.currentTime + 0.3); // kurzer Ton, der Hall klingt nach
console.log(`Dry: ${dry.gain.value}, Wet: ${wet.gain.value}`);
Dry: 0.65, Wet: 0.35

// Wichtig · Fallstricke

  • Abtastrate: Der AudioBuffer der Impulsantwort muss dieselbe sampleRate wie der Kontext haben, sonst wird ein NotSupportedError geworfen. decodeAudioData() rechnet die Daten automatisch passend um.
  • Kanäle: Erlaubt sind IR-Puffer mit 1, 2 oder 4 Kanälen. Andere Kanalzahlen führen zu einem NotSupportedError.
  • normalize vor buffer setzen: Die Normalisierung wird nur beim Zuweisen des Puffers berechnet. Eine spätere Änderung von normalize wirkt erst beim nächsten Setzen von buffer.
  • Performance: Lange Impulsantworten (mehrere Sekunden, Stereo) kosten viel CPU, besonders auf Mobilgeräten. Kürze die IR, wenn das Audio aussetzt.
  • Autoplay: Ein AudioContext startet oft im Zustand suspended. Rufe ctx.resume() nach einer Nutzeraktion auf.
  • CORS: Wird eine IR-Datei von einer fremden Domain per fetch() geladen, muss der Server passende CORS-Header senden.
  • Kompatibilität: In allen modernen Browsern verfügbar. Ältere Safari-Versionen brauchen das Präfix webkitAudioContext.