Signatur
Beschreibung
process() ist die zentrale Methode jedes eigenen Audio-Worklet-Prozessors. Die Methode wird nicht von AudioWorkletProcessor selbst bereitgestellt, sondern muss in der abgeleiteten Klasse implementiert werden. Die Web-Audio-Engine ruft sie synchron auf dem Audio-Rendering-Thread auf, jeweils für einen Block von 128 Sample-Frames (ein sogenanntes Render-Quantum).
Über inputs liest man die eingehenden Samples, in outputs schreibt man die berechneten Samples. Beide Arrays sind dreifach verschachtelt: Eingang/Ausgang → Kanal → Float32Array mit den Samples (Wertebereich üblicherweise −1 bis 1). Die Ausgabepuffer sind beim Aufruf mit Nullen vorbelegt. Über parameters erhält man die aktuellen Werte der per static get parameterDescriptors() deklarierten AudioParams.
Der Rückgabewert steuert die Lebensdauer des Prozessors: Gibt man true zurück, bleibt der Knoten aktiv, auch wenn keine Eingänge verbunden sind (z. B. bei Oszillatoren oder Hall-Fahnen). Bei false darf der Browser den Prozessor abbauen, sobald keine aktiven Eingänge mehr bestehen. Die Registrierung erfolgt im Worklet-Skript mit registerProcessor(), die Verwendung im Haupt-Thread mit new AudioWorkletNode().
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $inputs Pflicht | Float32Array[][] | Array der Eingänge; jeder Eingang ist ein Array von Kanälen, jeder Kanal ein Float32Array mit 128 Samples. Ein nicht verbundener Eingang hat null Kanäle (leeres Array). |
|
| $outputs Pflicht | Float32Array[][] | Array der Ausgänge mit derselben Struktur wie inputs. Die Puffer sind mit 0 vorbelegt und müssen in-place beschrieben werden – eine Neuzuweisung hat keine Wirkung. |
|
| $parameters Pflicht | Object<string, Float32Array> | Objekt mit einem Eintrag pro deklariertem AudioParam. Das Array hat entweder 128 Werte (bei Automatisierung, a-rate) oder genau 1 Wert, wenn der Parameter im Block konstant ist. |
Beispiele
Einfacher Gain-Prozessor mit AudioParam
// gain-processor.js (Worklet-Skript)
class GainProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
return [{ name: 'gain', defaultValue: 0.5, minValue: 0, maxValue: 1 }];
}
process(inputs, outputs, parameters) {
const input = inputs[0];
const output = outputs[0];
const gain = parameters.gain;
for (let ch = 0; ch < input.length; ch++) {
const inCh = input[ch];
const outCh = output[ch];
for (let i = 0; i < inCh.length; i++) {
// Länge 1 = konstanter Wert, sonst Wert pro Sample
outCh[i] = inCh[i] * (gain.length > 1 ? gain[i] : gain[0]);
}
}
return true; // Prozessor aktiv halten
}
}
registerProcessor('gain-processor', GainProcessor);
Prozessor im Haupt-Thread laden und verbinden
// main.js
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('gain-processor.js');
const osc = new OscillatorNode(ctx, { frequency: 440 });
const gainNode = new AudioWorkletNode(ctx, 'gain-processor');
osc.connect(gainNode).connect(ctx.destination);
osc.start();
// AudioParam automatisieren -> parameters.gain hat dann 128 Werte
const gain = gainNode.parameters.get('gain');
gain.linearRampToValueAtTime(0, ctx.currentTime + 2);
Rauschgenerator ohne Eingang, stoppbar per Nachricht
// noise-processor.js
class NoiseProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.running = true;
this.port.onmessage = (e) => {
if (e.data === 'stop') this.running = false;
};
}
process(inputs, outputs) {
for (const channel of outputs[0]) {
for (let i = 0; i < channel.length; i++) {
channel[i] = Math.random() * 2 - 1;
}
}
// false -> Browser darf den Prozessor freigeben
return this.running;
}
}
registerProcessor('noise-processor', NoiseProcessor);
// main.js:
// const noise = new AudioWorkletNode(ctx, 'noise-processor');
// noise.connect(ctx.destination);
// setTimeout(() => noise.port.postMessage('stop'), 1000);
// Wichtig · Fallstricke
- Echtzeit-Thread:
process()muss innerhalb von ca. 2,9 ms (128 Samples bei 44,1 kHz) fertig sein. Keine Speicherreservierung in der Schleife (neue Arrays, Objekte, Closures), keinconsole.logim Dauerbetrieb – das führt zu Knacksern durch Garbage Collection und Aussetzer. - Leere Eingänge: Ist kein Knoten verbunden, ist
inputs[0]ein leeres Array. Immerinput.lengthprüfen, bevor aufinput[0]zugegriffen wird. - Parameter-Länge:
parameters[name]kann die Länge 1 oder 128 haben – beide Fälle behandeln. - Blockgröße: Nicht fest mit 128 rechnen, sondern
channel.lengthverwenden; künftige Spezifikationen erlauben andere Render-Quantum-Größen. - Rückgabewert: Fehlt ein
return, ergibt sichundefined(falsy) – der Prozessor kann dann unerwartet beendet werden, sobald keine Eingänge mehr anliegen. Firefox und Chrome verhielten sich hier historisch unterschiedlich; explizittrue/falsezurückgeben. - Ausnahmen: Wirft
process()einen Fehler, wird der Prozessor stillgelegt und amAudioWorkletNodeeinprocessorerror-Event ausgelöst. - Kompatibilität: Audio Worklets erfordern einen sicheren Kontext (HTTPS oder localhost). Im Worklet-Scope stehen keine DOM-APIs, kein
fetchund keinsetTimeoutzur Verfügung; Kommunikation nur überthis.port.