Signatur
Beschreibung
getFrequencyResponse() wertet die Übertragungsfunktion eines IIR-Filters (Infinite Impulse Response) für eine Liste von Frequenzen aus. Die Grundlage sind die Koeffizienten feedforward und feedback, die beim Erzeugen des Knotens mit AudioContext.createIIRFilter() oder new IIRFilterNode() festgelegt wurden. Für jede Frequenz in frequencyArray schreibt die Methode den linearen Betrag (Verstärkungsfaktor) in magResponseOutput und die Phasenverschiebung im Bogenmaß in phaseResponseOutput.
Typische Anwendungsfälle sind die Visualisierung von Filterkurven (z. B. Equalizer-Anzeigen auf einem <canvas>), das Prüfen selbst berechneter Koeffizienten vor dem Einsatz sowie der Vergleich verschiedener Filterentwürfe. Die Methode verarbeitet kein Audiosignal – sie rechnet rein mathematisch und funktioniert daher auch in einem angehaltenen AudioContext oder in einem OfflineAudioContext.
Anders als beim BiquadFilterNode lassen sich die Koeffizienten eines IIRFilterNode nach der Erzeugung nicht mehr ändern. Die Frequenzantwort eines Knotens ist deshalb konstant; sie muss nur einmal berechnet werden. Für eine andere Kurve erzeugt man einen neuen Knoten.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $frequencyArray Pflicht | Float32Array | Frequenzen in Hertz, für die die Antwort berechnet werden soll. Sinnvoll ist der Bereich von 0 bis zur Nyquist-Frequenz (sampleRate / 2). |
|
| $magResponseOutput Pflicht | Float32Array | Ausgabe-Array, das mit dem linearen Betrag (Verstärkungsfaktor, nicht dB) je Frequenz befüllt wird. Muss genauso lang sein wie frequencyArray. |
|
| $phaseResponseOutput Pflicht | Float32Array | Ausgabe-Array, das mit der Phasenverschiebung im Bogenmaß (−π bis π) je Frequenz befüllt wird. Muss genauso lang sein wie frequencyArray. |
Rückgabewert
magResponseOutput und phaseResponseOutput geschrieben.Beispiele
Frequenzantwort eines einpoligen Tiefpasses berechnen
// Einpoliger Tiefpass: y[n] = 0.1·x[n] + 0.9·y[n-1]
const ctx = new OfflineAudioContext(1, 1, 48000);
const filter = ctx.createIIRFilter([0.1], [1, -0.9]);
const freqs = new Float32Array([0, 1000, 24000]);
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: ${mag[i].toFixed(3)} (${db.toFixed(2)} dB)`);
});
console.log(`Phase bei 1000 Hz: ${phase[1].toFixed(3)} rad`);
Filterkurve logarithmisch auf ein Canvas zeichnen
const ctx = new AudioContext();
const filter = new IIRFilterNode(ctx, {
feedforward: [0.0675, 0.1349, 0.0675],
feedback: [1, -1.1430, 0.4128]
});
const canvas = document.querySelector('#kurve');
const g = canvas.getContext('2d');
const { width, height } = canvas;
// Frequenzen logarithmisch von 20 Hz bis Nyquist verteilen
const nyquist = ctx.sampleRate / 2;
const freqs = new Float32Array(width);
for (let x = 0; x < width; x++) {
freqs[x] = 20 * Math.pow(nyquist / 20, x / (width - 1));
}
const mag = new Float32Array(width);
const phase = new Float32Array(width);
filter.getFrequencyResponse(freqs, mag, phase);
// Bereich +12 dB (oben) bis -48 dB (unten)
const dbToY = (db) => ((12 - db) / 60) * height;
g.clearRect(0, 0, width, height);
g.beginPath();
mag.forEach((m, x) => {
const y = dbToY(20 * Math.log10(Math.max(m, 1e-6)));
x === 0 ? g.moveTo(x, y) : g.lineTo(x, y);
});
g.strokeStyle = '#0a7';
g.stroke();
Randfälle: ungültige Frequenzen und falsche Array-Längen
const ctx = new OfflineAudioContext(1, 1, 44100);
const filter = ctx.createIIRFilter([0.1], [1, -0.9]);
// Frequenzen außerhalb von [0, Nyquist] liefern NaN
const freqs = new Float32Array([-100, 30000]);
const mag = new Float32Array(2);
const phase = new Float32Array(2);
filter.getFrequencyResponse(freqs, mag, phase);
console.log(mag, phase);
// Unterschiedliche Längen werfen eine Ausnahme
try {
filter.getFrequencyResponse(freqs, new Float32Array(1), phase);
} catch (err) {
console.log(err.name);
}