Signatur
Beschreibung
Die Eigenschaft outputBuffer des AudioProcessingEvent enthält einen AudioBuffer. In diesen Puffer schreibt der Ereignis-Handler eines ScriptProcessorNode die Audiodaten, die der Knoten ausgeben soll. Die Eigenschaft selbst ist schreibgeschützt. Den Inhalt der Kanäle, die Sie über getChannelData() erhalten, dürfen Sie aber beliebig verändern.
Der Puffer hat genau so viele Sample-Frames wie der beim Erzeugen des Knotens angegebene bufferSize (256 bis 16384). Die Zahl der Kanäle entspricht dem Argument numberOfOutputChannels von createScriptProcessor(). Typische Anwendungen sind eigene Effekte wie Verstärkung, Verzerrung oder Bitcrusher, das Erzeugen von Rauschen oder Tönen und das einfache Durchreichen von Daten aus dem inputBuffer.
Wenn Sie in einem Durchlauf nichts in den outputBuffer schreiben, ist die Ausgabe in diesem Block still, denn der Puffer ist mit Nullen vorbelegt. Sie sollten die Werte im Bereich von -1.0 bis 1.0 halten, sonst kommt es zu Übersteuerung (Clipping).
Rückgabewert
Float32Array pro Kanal über getChannelData(kanal) erreichbar.Beispiele
Weißes Rauschen erzeugen
const ctx = new AudioContext();
// 4096 Frames, 0 Eingänge, 2 Ausgangskanäle
const noise = ctx.createScriptProcessor(4096, 0, 2);
noise.onaudioprocess = (event) => {
const { outputBuffer } = event;
for (let ch = 0; ch < outputBuffer.numberOfChannels; ch++) {
const out = outputBuffer.getChannelData(ch);
for (let i = 0; i < out.length; i++) {
out[i] = (Math.random() * 2 - 1) * 0.2; // leise halten
}
}
};
noise.connect(ctx.destination);
// Hinweis: Den AudioContext erst nach einer Benutzeraktion starten
document.querySelector('#start').addEventListener('click', () => ctx.resume());
Eingangssignal verstärken und begrenzen
const ctx = new AudioContext();
const audioEl = document.querySelector('audio');
const source = ctx.createMediaElementSource(audioEl);
const processor = ctx.createScriptProcessor(2048, 2, 2);
const gain = 1.5;
processor.addEventListener('audioprocess', ({ 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++) {
// Verstärken und auf [-1, 1] begrenzen
output[i] = Math.max(-1, Math.min(1, input[i] * gain));
}
}
});
source.connect(processor).connect(ctx.destination);
Eigenschaften des Ausgabe-Puffers prüfen
const ctx = new AudioContext({ sampleRate: 48000 });
const proc = ctx.createScriptProcessor(1024, 1, 2);
proc.onaudioprocess = (e) => {
const buf = e.outputBuffer;
console.log(buf.length, buf.numberOfChannels, buf.sampleRate);
proc.onaudioprocess = null; // nur einmal ausgeben
};
proc.connect(ctx.destination);
ctx.resume();
// Wichtig · Fallstricke
Veraltet: ScriptProcessorNode und AudioProcessingEvent gelten als veraltet. Der Code läuft auf dem Haupt-Thread, deshalb kann es bei hoher Last zu Aussetzern und Latenz kommen. Für neue Projekte ist AudioWorkletNode mit AudioWorkletProcessor der bessere Weg: Dort schreiben Sie in das Argument outputs der Methode process(). Die Browser unterstützen die alte API zwar weiterhin, sie kann aber künftig entfernt werden.
- Sie dürfen dem
outputBufferkeinen eigenen Puffer zuweisen. Schreiben Sie die Daten immer in die Arrays, diegetChannelData()liefert. - Lassen Sie die Referenzen auf die Kanal-Arrays nicht über den Handler hinaus bestehen. Die Daten gelten nur während des aktuellen Events.
- Manche Browser (z. B. ältere Chrome-Versionen) lösen
audioprocessnur aus, wenn der Knoten mit einem Ziel verbunden ist. Verbinden Sie ihn deshalb mitctx.destination. - Größere
bufferSize-Werte verringern das Risiko von Aussetzern, erhöhen aber die Latenz.