Start · Sprachen · JavaScript · Referenz · AudioWorkletGlobalScope.registerProcessor()

AudioWorkletGlobalScope.registerProcessor()

Methode

Registriert im AudioWorklet-Kontext eine von <code>AudioWorkletProcessor</code> abgeleitete Klasse unter einem Namen, damit ein <code>AudioWorkletNode</code> sie später instanziieren kann.

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

Signatur

AudioWorkletGlobalScope.registerProcessor(name, processorCtor)

Beschreibung

registerProcessor() ist eine globale Funktion, die nur im AudioWorkletGlobalScope verfügbar ist, also in dem Modul, das per audioContext.audioWorklet.addModule() geladen wird. Mit ihr meldest du eine eigene Audio-Verarbeitungsklasse unter einem eindeutigen Namen an. Im Haupt-Thread erzeugt anschließend new AudioWorkletNode(context, name) eine Instanz dieses Prozessors, die direkt im Audio-Rendering-Thread läuft.

Die übergebene Klasse muss von AudioWorkletProcessor erben und eine Methode process(inputs, outputs, parameters) bereitstellen. Optional kann sie über einen statischen Getter parameterDescriptors automatisierbare AudioParam-Werte festlegen. Diese Descriptors werden bei der Registrierung einmal ausgelesen und geprüft.

Du brauchst die Methode immer dann, wenn eingebaute Knoten wie GainNode oder BiquadFilterNode nicht reichen, etwa für eigene Synthesizer, Effekte, Pegelmesser oder Analysen mit geringer Latenz, ohne den Haupt-Thread zu belasten.

Parameter

Name Typ Default Beschreibung
$name Pflicht string Eindeutiger, nicht leerer Name, unter dem der Prozessor registriert wird. Genau dieser Name wird später an den Konstruktor von AudioWorkletNode übergeben.
$processorCtor Pflicht typeof AudioWorkletProcessor Klassenkonstruktor, der von AudioWorkletProcessor erbt. Er darf optional einen statischen Getter parameterDescriptors haben, der ein iterierbares Objekt von AudioParamDescriptor-Objekten liefert.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Wenn die Registrierung fehlschlägt, wird eine Ausnahme ausgelöst.

Beispiele

Einfacher Rausch-Generator registrieren

// white-noise-processor.js (läuft im AudioWorkletGlobalScope)
class WhiteNoiseProcessor extends AudioWorkletProcessor {
  process(inputs, outputs) {
    const output = outputs[0];
    for (const channel of output) {
      for (let i = 0; i < channel.length; i++) {
        channel[i] = Math.random() * 2 - 1;
      }
    }
    return true; // Prozessor weiterlaufen lassen
  }
}

registerProcessor('white-noise', WhiteNoiseProcessor);

// main.js (Haupt-Thread)
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('white-noise-processor.js');
const noise = new AudioWorkletNode(ctx, 'white-noise');
noise.connect(ctx.destination);

Prozessor mit automatisierbarem Parameter (Gain)

// gain-processor.js
class SimpleGainProcessor extends AudioWorkletProcessor {
  static get parameterDescriptors() {
    return [{
      name: 'gain',
      defaultValue: 0.5,
      minValue: 0,
      maxValue: 1,
      automationRate: 'a-rate'
    }];
  }

  process(inputs, outputs, parameters) {
    const input = inputs[0];
    const output = outputs[0];
    const gain = parameters.gain;
    for (let ch = 0; ch < input.length; ch++) {
      for (let i = 0; i < input[ch].length; i++) {
        // Array hat Länge 1, wenn der Wert im Block konstant ist
        const g = gain.length > 1 ? gain[i] : gain[0];
        output[ch][i] = input[ch][i] * g;
      }
    }
    return true;
  }
}

registerProcessor('simple-gain', SimpleGainProcessor);

// main.js
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('gain-processor.js');
const osc = new OscillatorNode(ctx);
const gainNode = new AudioWorkletNode(ctx, 'simple-gain');
gainNode.parameters.get('gain').linearRampToValueAtTime(0, ctx.currentTime + 2);
osc.connect(gainNode).connect(ctx.destination);
osc.start();

Pegelmesser mit Nachrichten an den Haupt-Thread

// meter-processor.js
class MeterProcessor extends AudioWorkletProcessor {
  process(inputs) {
    const samples = inputs[0][0];
    if (samples) {
      let sum = 0;
      for (const s of samples) sum += s * s;
      this.port.postMessage(Math.sqrt(sum / samples.length));
    }
    return true;
  }
}

registerProcessor('meter', MeterProcessor);

// main.js
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('meter-processor.js');
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const source = ctx.createMediaStreamSource(stream);
const meter = new AudioWorkletNode(ctx, 'meter');
meter.port.onmessage = ({ data }) => console.log('RMS:', data.toFixed(3));
source.connect(meter);
RMS: 0.012 RMS: 0.087 ...

// Wichtig · Fallstricke

  • Nur im Worklet-Kontext: registerProcessor gibt es im Haupt-Thread nicht. Ein Aufruf dort löst einen ReferenceError aus.
  • Name doppelt vergeben: Ist der Name bereits registriert, wird eine NotSupportedError-DOMException ausgelöst. Ein leerer Name ebenfalls.
  • Ungültiger Konstruktor: Ist processorCtor kein Konstruktor oder hat sein prototype kein Objekt, wird ein TypeError ausgelöst. Dasselbe gilt, wenn parameterDescriptors kein iterierbares Objekt liefert. Doppelte Parameternamen oder ein defaultValue außerhalb von minValue/maxValue führen zu NotSupportedError bzw. InvalidStateError.
  • Reihenfolge: new AudioWorkletNode() darf erst aufgerufen werden, nachdem das Promise von addModule() erfüllt ist. Sonst schlägt der Aufruf fehl, weil der Name noch unbekannt ist.
  • Rückgabewert von process(): Gibt process() false zurück, darf der Browser den Knoten beenden, sobald keine aktiven Eingänge mehr anliegen. Für Generatoren solltest du true zurückgeben.
  • Performance: process() läuft im Echtzeit-Audio-Thread, jeweils für Blöcke von meist 128 Samples. Vermeide dort Speicheranlagen, console.log und aufwendige Berechnungen, sonst entstehen Aussetzer.
  • Sicherer Kontext: AudioWorklet ist nur über HTTPS bzw. localhost verfügbar. Das Modul unterliegt denselben CORS- und CSP-Regeln wie andere Skripte.