Start · Sprachen · JavaScript · Referenz · ScriptProcessorNode: audioprocess

ScriptProcessorNode: audioprocess

Ereignis

Wird ausgelöst, sobald ein Eingabepuffer eines <code>ScriptProcessorNode</code> zur Verarbeitung bereitsteht – der Handler liest Samples aus <code>inputBuffer</code> und schreibt nach <code>outputBuffer</code>.

seit JavaScript Veraltet (deprecated) – in allen gängigen Browsern deprecated seit ja Kategorie: webapi

Signatur

scriptProcessorNode.addEventListener("audioprocess", handler)

Beschreibung

Das Ereignis audioprocess ist das Herzstück eines ScriptProcessorNode: Jedes Mal, wenn die Web Audio API einen Block von Samples (Größe = bufferSize, z. B. 4096) gesammelt hat, ruft sie den Handler mit einem AudioProcessingEvent auf. Darin stehen inputBuffer (eingehende Daten), outputBuffer (zu füllende Ausgabe) und playbackTime (Zeitpunkt, zu dem die Ausgabe im AudioContext hörbar wird).

Registriert wird der Handler entweder mit addEventListener("audioprocess", handler) oder über die Eigenschaft onaudioprocess. Typische Einsätze waren eigene Effekte (Verstärkung, Verzerrung), Pegelmessung (VU-Meter), Aufnahme von Mikrofondaten oder das Erzeugen synthetischer Klänge in JavaScript.

Wichtig: Der Handler läuft auf dem Haupt-Thread. Blockierendes JavaScript, Layout-Arbeit oder Garbage Collection können daher zu Aussetzern (Knacksern) führen. Die gesamte Schnittstelle ist veraltet und wurde durch AudioWorkletNode mit einem AudioWorkletProcessor ersetzt, der in einem eigenen Audio-Thread läuft. Für neuen Code sollte ausschließlich AudioWorklet verwendet werden.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname "audioprocess".
$handler Pflicht (event: AudioProcessingEvent) => void Callback, das ein AudioProcessingEvent mit inputBuffer, outputBuffer (beide AudioBuffer) und playbackTime (number, Sekunden) erhält.
$options boolean|AddEventListenerOptions false Übliche Optionen von addEventListener, z. B. { once: true } oder { signal }.

Rückgabewert

Typ
void
Beschreibung
Der Handler gibt nichts zurück; das Ergebnis wird direkt in event.outputBuffer geschrieben.

Beispiele

Weißes Rauschen per addEventListener erzeugen

const ctx = new AudioContext();
// 4096 Samples Puffer, 0 Eingänge, 1 Ausgangskanal
const processor = ctx.createScriptProcessor(4096, 0, 1);

const onProcess = (event) => {
  const output = event.outputBuffer.getChannelData(0);
  for (let i = 0; i < output.length; i++) {
    output[i] = (Math.random() * 2 - 1) * 0.1; // leises Rauschen
  }
};

processor.addEventListener("audioprocess", onProcess);
processor.connect(ctx.destination);

// Nach 2 Sekunden stoppen: Listener entfernen und Knoten trennen
setTimeout(() => {
  processor.removeEventListener("audioprocess", onProcess);
  processor.disconnect();
}, 2000);

Lautstärke halbieren über onaudioprocess

const ctx = new AudioContext();
const osc = ctx.createOscillator();
const processor = ctx.createScriptProcessor(2048, 1, 1);

processor.onaudioprocess = ({ inputBuffer, outputBuffer }) => {
  for (let ch = 0; ch < outputBuffer.numberOfChannels; ch++) {
    const input = inputBuffer.getChannelData(ch);
    const output = outputBuffer.getChannelData(ch);
    for (let i = 0; i < input.length; i++) {
      output[i] = input[i] * 0.5;
    }
  }
};

osc.connect(processor);
processor.connect(ctx.destination);
osc.start();
osc.stop(ctx.currentTime + 1);

// Handler wieder abmelden
osc.addEventListener("ended", () => {
  processor.onaudioprocess = null;
  processor.disconnect();
});

Mikrofon-Pegel (RMS) messen

const startMeter = async () => {
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
  const ctx = new AudioContext();
  const source = ctx.createMediaStreamSource(stream);
  const processor = ctx.createScriptProcessor(4096, 1, 1);

  processor.addEventListener("audioprocess", (event) => {
    const data = event.inputBuffer.getChannelData(0);
    let sum = 0;
    for (const sample of data) sum += sample * sample;
    const rms = Math.sqrt(sum / data.length);
    console.log(`Pegel: ${rms.toFixed(3)} @ ${event.playbackTime.toFixed(2)} s`);
  });

  source.connect(processor);
  // Verbindung zum Ziel nötig, sonst feuert das Ereignis in manchen Browsern nicht
  processor.connect(ctx.destination);
};

startMeter();
Pegel: 0.012 @ 0.19 s Pegel: 0.087 @ 0.28 s ...

// Wichtig · Fallstricke

  • Veraltet: ScriptProcessorNode und audioprocess sind aus der Spezifikation als deprecated markiert. Browser unterstützen sie noch, eine Entfernung ist aber möglich. Verwende AudioWorkletNode (in allen modernen Browsern verfügbar, nur in sicheren Kontexten/HTTPS).
  • Haupt-Thread: Der Handler konkurriert mit DOM- und UI-Arbeit. Größere bufferSize-Werte (4096, 8192, 16384) verringern Aussetzer, erhöhen aber die Latenz.
  • Ausgang verbinden: In Chromium feuert das Ereignis nur zuverlässig, wenn der Knoten mit ctx.destination (direkt oder indirekt) verbunden ist – auch wenn nur analysiert werden soll. Dann den Ausgabepuffer mit Nullen belassen.
  • Puffer nicht speichern: inputBuffer/outputBuffer können wiederverwendet werden. Wer Daten aufzeichnet, muss sie kopieren (z. B. new Float32Array(data)).
  • Wird outputBuffer nicht beschrieben, entsteht Stille. Keine Allokationen im Handler, um GC-Pausen zu vermeiden.
  • Ein angehaltener AudioContext (Autoplay-Richtlinie) löst keine Ereignisse aus – ggf. ctx.resume() nach Nutzerinteraktion aufrufen.