Signatur
Beschreibung
Der Konstruktor IIRFilterNode() erzeugt einen Audio-Knoten, der einen allgemeinen IIR-Filter umsetzt. Anders als beim BiquadFilterNode gibt es keine vorgefertigten Filtertypen wie lowpass oder peaking. Stattdessen legst du die Übertragungsfunktion direkt über zwei Koeffizienten-Arrays fest: feedforward für den Zähler (b-Koeffizienten) und feedback für den Nenner (a-Koeffizienten).
Der Filter berechnet für jedes Sample y[n] = (Σ b[k]·x[n−k] − Σ a[k]·y[n−k]) / a[0]. Das eignet sich für Filter höherer Ordnung, für Nachbauten klassischer Analogschaltungen oder für Koeffizienten, die du mit einem Filterdesign-Werkzeug (etwa MATLAB oder SciPy) berechnet hast.
Die Koeffizienten werden einmalig beim Erzeugen festgelegt und lassen sich danach nicht mehr ändern. Anders als beim Biquad gibt es keine AudioParam-Eigenschaften zur Automation. Wenn sich die Filterkurve im Lauf der Zeit ändern soll, erzeugst du einen neuen Knoten und blendest zwischen den beiden über. Mit getFrequencyResponse() kannst du Betrag und Phase des Frequenzgangs abfragen, zum Beispiel für eine Visualisierung.
Gleichwertig zum Konstruktor ist die Fabrikmethode BaseAudioContext.createIIRFilter(feedforward, feedback). Der Konstruktor hat den Vorteil, dass er zusätzlich die allgemeinen AudioNodeOptions wie channelCount annimmt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $context Pflicht | BaseAudioContext | Der AudioContext oder OfflineAudioContext, zu dem der Knoten gehören soll. |
|
| $options Pflicht | IIRFilterOptions | Ein Objekt mit den Filter-Koeffizienten. Es ist Pflicht, weil feedforward und feedback angegeben werden müssen. |
|
| $options.feedforward Pflicht | number[] | Die Zähler-Koeffizienten (bk) der Übertragungsfunktion. Erlaubt sind 1 bis 20 Werte, von denen mindestens einer ungleich 0 sein muss. | |
| $options.feedback Pflicht | number[] | Die Nenner-Koeffizienten (ak). Erlaubt sind 1 bis 20 Werte. Der erste Wert (a[0]) darf nicht 0 sein. |
|
| $options.channelCount | number | 2 | Die Kanalanzahl für das Up- und Downmixing am Eingang (aus AudioNodeOptions). |
| $options.channelCountMode | "max" | "clamped-max" | "explicit" | "max" | Legt fest, wie sich die Kanalanzahl am Eingang ergibt. |
| $options.channelInterpretation | "speakers" | "discrete" | "speakers" | Legt fest, wie Kanäle beim Mischen aufeinander abgebildet werden. |
Rückgabewert
IIRFilterNode mit einem Eingang und einem Ausgang, der das Signal mit den übergebenen Koeffizienten filtert.Beispiele
Einfacher Tiefpass erster Ordnung
const ctx = new AudioContext();
// y[n] = 0.1·x[n] + 0.9·y[n-1] → sanfter Tiefpass
const lowpass = new IIRFilterNode(ctx, {
feedforward: [0.1],
feedback: [1, -0.9]
});
const osc = new OscillatorNode(ctx, { type: 'sawtooth', frequency: 220 });
osc.connect(lowpass).connect(ctx.destination);
// Audio startet erst nach einer Nutzeraktion
document.querySelector('#play').addEventListener('click', async () => {
await ctx.resume();
osc.start();
osc.stop(ctx.currentTime + 2);
});
Frequenzgang abfragen
const ctx = new AudioContext();
const filter = new IIRFilterNode(ctx, {
feedforward: [0.1],
feedback: [1, -0.9]
});
const freqs = new Float32Array([100, 1000, 5000, 10000]);
const mag = new Float32Array(freqs.length);
const phase = new Float32Array(freqs.length);
filter.getFrequencyResponse(freqs, mag, phase);
freqs.forEach((f, i) => {
const db = 20 * Math.log10(mag[i]);
console.log(`${f} Hz: ${db.toFixed(1)} dB`);
});
Offline-Rendering mit extern berechneten Koeffizienten
// Koeffizienten z. B. aus scipy.signal.butter(2, 0.1)
const b = [0.02008337, 0.04016673, 0.02008337];
const a = [1, -1.56101808, 0.64135154];
const render = async (inputBuffer) => {
const off = new OfflineAudioContext(
inputBuffer.numberOfChannels,
inputBuffer.length,
inputBuffer.sampleRate
);
const src = new AudioBufferSourceNode(off, { buffer: inputBuffer });
const iir = new IIRFilterNode(off, { feedforward: b, feedback: a });
src.connect(iir).connect(off.destination);
src.start();
return off.startRendering(); // Promise<AudioBuffer>
};
try {
new IIRFilterNode(new OfflineAudioContext(1, 1, 44100), {
feedforward: [1],
feedback: [0, 1] // a[0] = 0 ist ungültig
});
} catch (e) {
console.log(e.name);
}
// Wichtig · Fallstricke
- Die Koeffizienten sind unveränderlich: Nach dem Erzeugen lassen sie sich nicht mehr ändern. Für Automation oder Filter-Sweeps nimmst du einen
BiquadFilterNodeoder tauschst den Knoten mit einer Überblendung aus. - Fehler: Ein
NotSupportedErrortritt auf, wenn ein Array leer ist oder mehr als 20 Werte hat. EinInvalidStateErrortritt auf, wenn allefeedforward-Werte 0 sind oderfeedback[0]0 ist. - Stabilität: Der Browser prüft nicht, ob die Koeffizienten einen stabilen Filter ergeben. Instabile Filter (Pole außerhalb des Einheitskreises) können sich aufschaukeln und laute Übersteuerungen oder
NaN-Werte erzeugen. Prüfe deine Koeffizienten deshalb vorher. - Abtastrate: Die Koeffizienten gelten für eine bestimmte Abtastrate. Wenn
ctx.sampleRateabweicht (44,1 kHz statt 48 kHz), verschiebt sich der Frequenzgang. - Browser-Kompatibilität: Der Konstruktor wird in allen aktuellen Browsern unterstützt (Chrome 55+, Firefox 53+, Safari 14.1+). Für ältere Safari-Versionen greifst du auf
ctx.createIIRFilter()zurück. - Die Wiedergabe über einen
AudioContextsetzt wegen der Autoplay-Richtlinien der Browser meist eine Nutzeraktion voraus.