Start · Sprachen · JavaScript · Referenz · AnalyserNode.getFloatFrequencyData()

AnalyserNode.getFloatFrequencyData()

Methode

Kopiert die aktuellen Frequenzdaten (Spektrum) als Dezibel-Werte in ein übergebenes <code>Float32Array</code>.

seit JavaScript Baseline: alle modernen Browser (Web Audio API) Kategorie: webapi

Signatur

AnalyserNode.prototype.getFloatFrequencyData(array)

Beschreibung

Die Methode getFloatFrequencyData() eines AnalyserNode führt eine schnelle Fourier-Transformation (FFT) auf die zuletzt verarbeiteten Audiodaten aus und schreibt das Ergebnis in das übergebene Float32Array. Jedes Element enthält die Lautstärke eines Frequenzbereichs (Bins) in Dezibel (dB). Das sind typischerweise negative Werte, etwa zwischen -100 und 0; Stille ergibt -Infinity.

Die Anzahl der Frequenz-Bins entspricht analyser.frequencyBinCount (also fftSize / 2). Jeder Bin deckt eine Bandbreite von sampleRate / fftSize Hertz ab. Bin i steht ungefähr für die Frequenz i * sampleRate / fftSize.

Verwende die Methode, wenn du das Spektrum mit voller Genauigkeit brauchst, zum Beispiel für Tonhöhen- oder Frequenzanalysen, Messwerkzeuge oder eine exakte dB-Skala. Für einfache Visualisierungen reicht oft getByteFrequencyData(). Diese Variante liefert Werte zwischen 0 und 255, die schon auf minDecibels/maxDecibels skaliert sind.

Die Glättung zwischen aufeinanderfolgenden Aufrufen steuert smoothingTimeConstant. Die Methode gibt nichts zurück, sondern verändert das übergebene Array direkt. Deshalb solltest du ein Array einmal anlegen und in jedem Animations-Frame wiederverwenden.

Parameter

Name Typ Default Beschreibung
$array Pflicht Float32Array Ziel-Array, in das die Frequenzwerte in dB geschrieben werden. Hat es weniger Elemente als frequencyBinCount, werden überzählige Werte verworfen. Hat es mehr, bleiben die restlichen Elemente unverändert.

Beispiele

Spektrum eines Oszillators auslesen

const ctx = new AudioContext();
const osc = new OscillatorNode(ctx, { frequency: 440 });
const analyser = new AnalyserNode(ctx, { fftSize: 2048 });

osc.connect(analyser).connect(ctx.destination);
osc.start();

const data = new Float32Array(analyser.frequencyBinCount);

setTimeout(() => {
  analyser.getFloatFrequencyData(data);
  // Bin mit dem höchsten Pegel suchen
  let maxIndex = 0;
  for (let i = 1; i < data.length; i++) {
    if (data[i] > data[maxIndex]) maxIndex = i;
  }
  const hz = maxIndex * ctx.sampleRate / analyser.fftSize;
  console.log(`Dominante Frequenz: ~${hz.toFixed(0)} Hz`);
  osc.stop();
}, 500);
Dominante Frequenz: ~445 Hz (je nach sampleRate, z. B. 48000 Hz)

Echtzeit-Spektrum auf ein Canvas zeichnen

const canvas = document.querySelector('canvas');
const g = canvas.getContext('2d');

const start = async () => {
  const ctx = new AudioContext();
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
  const source = ctx.createMediaStreamSource(stream);
  const analyser = ctx.createAnalyser();
  analyser.fftSize = 1024;
  source.connect(analyser);

  const data = new Float32Array(analyser.frequencyBinCount);
  const { minDecibels, maxDecibels } = analyser;

  const draw = () => {
    requestAnimationFrame(draw);
    analyser.getFloatFrequencyData(data);
    g.fillStyle = '#000';
    g.fillRect(0, 0, canvas.width, canvas.height);
    const barWidth = canvas.width / data.length;
    data.forEach((db, i) => {
      // dB-Wert auf 0..1 normieren (−Infinity abfangen)
      const v = Math.max(0, (db - minDecibels) / (maxDecibels - minDecibels));
      const h = v * canvas.height;
      g.fillStyle = `hsl(${(i / data.length) * 300}, 80%, 55%)`;
      g.fillRect(i * barWidth, canvas.height - h, barWidth, h);
    });
  };
  draw();
};

document.querySelector('#start').addEventListener('click', start);

Pegel eines Frequenzbands ermitteln (z. B. Bass)

const bandLevel = (analyser, data, fromHz, toHz) => {
  analyser.getFloatFrequencyData(data);
  const binHz = analyser.context.sampleRate / analyser.fftSize;
  const from = Math.floor(fromHz / binHz);
  const to = Math.min(data.length - 1, Math.ceil(toHz / binHz));
  let sum = 0;
  for (let i = from; i <= to; i++) {
    // dB in lineare Leistung umrechnen, mitteln, zurück in dB
    sum += 10 ** (data[i] / 10);
  }
  return 10 * Math.log10(sum / (to - from + 1));
};

// Nutzung: const bass = bandLevel(analyser, data, 20, 150);
// console.log(`Bass: ${bass.toFixed(1)} dB`);
Bass: -42.3 dB (Beispielwert)

// Wichtig · Fallstricke

  • Werte sind Dezibel und meist negativ: Bei Stille oder bevor Audio fließt, enthält das Array -Infinity. Fange das vor Rechnungen oder beim Zeichnen ab, zum Beispiel mit Math.max() oder Number.isFinite().
  • minDecibels/maxDecibels wirken hier nicht: Die beiden Eigenschaften skalieren nur getByteFrequencyData(). Die Float-Werte sind ungeklemmte Rohwerte in dB.
  • Das Array muss ein Float32Array sein: Andere Typen (etwa Array oder Float64Array) lösen einen TypeError aus.
  • Performance: Lege das Array einmal an und verwende es wieder, statt es in jedem Frame neu zu erzeugen. Ein größeres fftSize gibt eine feinere Frequenzauflösung, reagiert aber träger und kostet mehr Rechenzeit.
  • Autoplay-Richtlinie: Ein AudioContext startet oft im Zustand suspended und muss nach einer Nutzeraktion mit ctx.resume() gestartet werden. Bis dahin liefert die Methode nur -Infinity.
  • Browser-Unterstützung: Die Methode läuft in allen modernen Browsern. Sehr alte WebKit-Versionen brauchten webkitAudioContext.