Start · Sprachen · JavaScript · Referenz · AudioWorkletProcessor.process()

AudioWorkletProcessor.process()

Methode

Implementiert in einer von <code>AudioWorkletProcessor</code> abgeleiteten Klasse den Audio-Algorithmus, der pro Render-Quantum (128 Samples) auf dem Audio-Thread aufgerufen wird.

seit JavaScript Baseline: alle modernen Browser (Chrome 66+, Firef Kategorie: webapi

Signatur

AudioWorkletProcessor.prototype.process(inputs, outputs, parameters)

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), kein console.log im Dauerbetrieb – das führt zu Knacksern durch Garbage Collection und Aussetzer.
  • Leere Eingänge: Ist kein Knoten verbunden, ist inputs[0] ein leeres Array. Immer input.length prüfen, bevor auf input[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.length verwenden; künftige Spezifikationen erlauben andere Render-Quantum-Größen.
  • Rückgabewert: Fehlt ein return, ergibt sich undefined (falsy) – der Prozessor kann dann unerwartet beendet werden, sobald keine Eingänge mehr anliegen. Firefox und Chrome verhielten sich hier historisch unterschiedlich; explizit true/false zurückgeben.
  • Ausnahmen: Wirft process() einen Fehler, wird der Prozessor stillgelegt und am AudioWorkletNode ein processorerror-Event ausgelöst.
  • Kompatibilität: Audio Worklets erfordern einen sicheren Kontext (HTTPS oder localhost). Im Worklet-Scope stehen keine DOM-APIs, kein fetch und kein setTimeout zur Verfügung; Kommunikation nur über this.port.