Signatur
Beschreibung
Der Konstruktor AudioWorkletProcessor() wird nie direkt von Ihrem Code aufgerufen. Stattdessen leiten Sie im Worklet-Skript eine eigene Klasse von AudioWorkletProcessor ab und registrieren sie mit registerProcessor(name, Klasse). Sobald im Hauptthread ein new AudioWorkletNode(context, name, options) erzeugt wird, instanziiert die Web-Audio-API die passende Prozessor-Klasse im AudioWorkletGlobalScope und reicht dabei die Optionen an den Konstruktor weiter.
Im Konstruktor Ihrer Unterklasse müssen Sie super(options) aufrufen. Danach steht this.port (ein MessagePort) für die Kommunikation mit dem Hauptthread zur Verfügung. Der Konstruktor ist der richtige Ort, um Zustände zu initialisieren, etwa Puffer, Phasen von Oszillatoren oder Werte aus options.processorOptions.
Die eigentliche Verarbeitung passiert in der Methode process(inputs, outputs, parameters), die für jeden Render-Quantum-Block (normalerweise 128 Samples) aufgerufen wird. Automatisierbare Parameter deklarieren Sie über den statischen Getter parameterDescriptors.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $options | AudioWorkletNodeOptions | Das Optionsobjekt, das beim Erzeugen des AudioWorkletNode übergeben wurde (strukturiert geklont). Enthält u. a. numberOfInputs, numberOfOutputs, outputChannelCount, parameterData und processorOptions (beliebige eigene Daten). |
Rückgabewert
AudioWorkletNode verbunden ist.Beispiele
Eigenen Prozessor ableiten und registrieren (gain-processor.js)
// Datei: gain-processor.js — läuft im AudioWorkletGlobalScope
class GainProcessor extends AudioWorkletProcessor {
constructor(options) {
super(options); // Pflicht!
this.gain = options.processorOptions?.initialGain ?? 1;
// Nachrichten aus dem Hauptthread empfangen
this.port.onmessage = (event) => {
if (typeof event.data.gain === 'number') this.gain = event.data.gain;
};
}
process(inputs, outputs) {
const input = inputs[0];
const output = outputs[0];
for (let ch = 0; ch < output.length; ch++) {
const inCh = input[ch];
const outCh = output[ch];
if (!inCh) continue;
for (let i = 0; i < outCh.length; i++) {
outCh[i] = inCh[i] * this.gain;
}
}
return true; // Prozessor am Leben halten
}
}
registerProcessor('gain-processor', GainProcessor);
Prozessor im Hauptthread über AudioWorkletNode instanziieren
// Hauptthread (z. B. nach einem Klick, wegen Autoplay-Richtlinien)
const start = async () => {
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('gain-processor.js');
// Dieser Aufruf löst intern new GainProcessor(options) aus
const node = new AudioWorkletNode(ctx, 'gain-processor', {
processorOptions: { initialGain: 0.5 }
});
const osc = new OscillatorNode(ctx, { frequency: 440 });
osc.connect(node).connect(ctx.destination);
osc.start();
// Lautstärke später über den MessagePort ändern
setTimeout(() => node.port.postMessage({ gain: 0.1 }), 1000);
};
document.querySelector('#play').addEventListener('click', start, { once: true });
Weißes Rauschen mit AudioParam aus parameterDescriptors
// noise-processor.js
class NoiseProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
return [{ name: 'amplitude', defaultValue: 0.2, minValue: 0, maxValue: 1 }];
}
constructor(options) {
super(options);
this.port.postMessage(`Prozessor gestartet, Rate: ${sampleRate} Hz`);
}
process(inputs, outputs, parameters) {
const amp = parameters.amplitude;
for (const channel of outputs[0]) {
for (let i = 0; i < channel.length; i++) {
// Länge 1 = konstanter Wert im Block, sonst pro Sample
const a = amp.length > 1 ? amp[i] : amp[0];
channel[i] = (Math.random() * 2 - 1) * a;
}
}
return true;
}
}
registerProcessor('noise-processor', NoiseProcessor);
// Hauptthread:
// const noise = new AudioWorkletNode(ctx, 'noise-processor');
// noise.port.onmessage = (e) => console.log(e.data);
// noise.parameters.get('amplitude').setValueAtTime(0.05, ctx.currentTime);
// Wichtig · Fallstricke
- Kein direkter Aufruf:
new AudioWorkletProcessor()bzw.new MeineKlasse()außerhalb des Instanziierungsvorgangs durchAudioWorkletNodewirft einenTypeError. Im Hauptthread gibt es die Klasse gar nicht. super(options)nicht vergessen: Ohne diesen Aufruf gibt es keinthisund keinenport.- Nur strukturiert klonbare Daten:
processorOptionswird per Structured Clone übertragen – Funktionen, DOM-Knoten usw. sind nicht erlaubt und führen zu einemDataCloneError. - Echtzeit-Thread: Im Konstruktor und besonders in
process()keine aufwendigen Operationen oder häufigen Speicherzuweisungen ausführen, sonst entstehen Knackser (Buffer-Underruns). Puffer am besten im Konstruktor vorab anlegen. - Rückgabewert von
process(): Wirdfalsezurückgegeben, kann der Prozessor vom Browser beendet werden, sobald keine Eingänge mehr aktiv sind. - Kompatibilität: Wird in allen aktuellen Browsern unterstützt (Chrome 66+, Firefox 76+, Safari 14.1+). Nur in sicheren Kontexten (HTTPS oder localhost) verfügbar; das Modul muss über
audioWorklet.addModule()geladen werden, bevor der Node erstellt wird.