Start · Sprachen · JavaScript · Referenz · AnalyserNode

AnalyserNode

Schnittstelle

Ein <code>AudioNode</code>, der das durchlaufende Audiosignal unverändert weiterreicht und dabei Echtzeitdaten zu Frequenz und Zeitbereich (Wellenform) liefert.

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

Signatur

interface AnalyserNode extends AudioNode

Beschreibung

AnalyserNode ist Teil der Web Audio API und dient der Visualisierung und Analyse von Audiosignalen, zum Beispiel für Spektrum-Analysatoren, Oszilloskop-Darstellungen, Pegelanzeigen (VU-Meter) oder eine einfache Tonhöhenerkennung. Der Knoten hat genau einen Eingang und einen Ausgang. Das Signal läuft unverändert hindurch, deshalb kann man ihn an jeder Stelle eines Audio-Graphen einfügen.

Einen Analyser legt man mit audioCtx.createAnalyser() oder mit dem Konstruktor new AnalyserNode(context, options) an. Die Daten liest man in einer Schleife (meist mit requestAnimationFrame) über vier Methoden aus:

  • getByteFrequencyData(Uint8Array) und getFloatFrequencyData(Float32Array) liefern das Frequenzspektrum, berechnet per FFT.
  • getByteTimeDomainData(Uint8Array) und getFloatTimeDomainData(Float32Array) liefern die Wellenform.

Wichtige Eigenschaften: fftSize (Zweierpotenz von 32 bis 32768, Standard 2048), frequencyBinCount (nur lesbar, entspricht fftSize / 2), minDecibels und maxDecibels (Wertebereich für die Byte-Skalierung, Standard −100 bis −30 dB) sowie smoothingTimeConstant (zeitliche Glättung von 0 bis 1, Standard 0.8).

Jedes Frequenz-Bin deckt sampleRate / fftSize Hertz ab. Ein größerer fftSize ergibt eine feinere Frequenzauflösung, reagiert aber zeitlich träger.

Parameter

Name Typ Default Beschreibung
$context Pflicht BaseAudioContext Der AudioContext oder OfflineAudioContext, zu dem der Knoten gehört (nur beim Konstruktor).
$options.fftSize number 2048 FFT-Größe als Zweierpotenz zwischen 32 und 32768.
$options.minDecibels number -100 Untere dB-Grenze für die Skalierung von getByteFrequencyData().
$options.maxDecibels number -30 Obere dB-Grenze. Sie muss größer sein als minDecibels.
$options.smoothingTimeConstant number 0.8 Glättung zwischen aufeinanderfolgenden Analyse-Frames, Wert von 0 bis 1.
$options.channelCount / channelCountMode / channelInterpretation number | string 1 / "max" / "speakers" Allgemeine AudioNode-Optionen zur Kanalbehandlung.

Rückgabewert

Typ
AnalyserNode
Beschreibung
Eine neue AnalyserNode-Instanz, die mit dem angegebenen Kontext verbunden ist.

Beispiele

Analyser erzeugen und konfigurieren

const audioCtx = new AudioContext();

// Variante 1: Fabrikmethode
const analyser = audioCtx.createAnalyser();
analyser.fftSize = 256;

// Variante 2: Konstruktor mit Optionen
const analyser2 = new AnalyserNode(audioCtx, {
  fftSize: 1024,
  smoothingTimeConstant: 0.6,
  minDecibels: -90,
  maxDecibels: -10
});

console.log(analyser.frequencyBinCount);  // fftSize / 2
console.log(analyser2.frequencyBinCount);
console.log(`Hz pro Bin: ${audioCtx.sampleRate / analyser2.fftSize}`);
128 512 Hz pro Bin: 46.875 (bei 48000 Hz Abtastrate)

Spektrum-Balken eines Audio-Elements auf ein Canvas zeichnen

const audio = document.querySelector('audio');
const canvas = document.querySelector('canvas');
const ctx2d = canvas.getContext('2d');
const audioCtx = new AudioContext();

const source = audioCtx.createMediaElementSource(audio);
const analyser = audioCtx.createAnalyser();
analyser.fftSize = 256;

// Quelle -> Analyser -> Lautsprecher
source.connect(analyser).connect(audioCtx.destination);

const data = new Uint8Array(analyser.frequencyBinCount);

const draw = () => {
  requestAnimationFrame(draw);
  analyser.getByteFrequencyData(data); // Werte 0–255
  ctx2d.clearRect(0, 0, canvas.width, canvas.height);
  const barWidth = canvas.width / data.length;
  data.forEach((value, i) => {
    const h = (value / 255) * canvas.height;
    ctx2d.fillStyle = `hsl(${i * 2}, 80%, 50%)`;
    ctx2d.fillRect(i * barWidth, canvas.height - h, barWidth - 1, h);
  });
};

// AudioContext erst nach einer Nutzeraktion starten (Autoplay-Richtlinie)
audio.addEventListener('play', async () => {
  await audioCtx.resume();
  draw();
});

Mikrofonpegel (RMS) messen

const startMeter = async () => {
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
  const audioCtx = new AudioContext();
  const mic = audioCtx.createMediaStreamSource(stream);
  const analyser = new AnalyserNode(audioCtx, { fftSize: 2048 });
  mic.connect(analyser); // nicht an destination -> keine Rückkopplung

  const buf = new Float32Array(analyser.fftSize);
  const tick = () => {
    analyser.getFloatTimeDomainData(buf); // Werte -1 bis 1
    const rms = Math.sqrt(buf.reduce((s, v) => s + v * v, 0) / buf.length);
    const db = 20 * Math.log10(rms || 1e-8);
    console.log(`Pegel: ${db.toFixed(1)} dBFS`);
    requestAnimationFrame(tick);
  };
  tick();
};

document.querySelector('#start').addEventListener('click', startMeter);
Pegel: -42.3 dBFS Pegel: -38.9 dBFS ...

// Wichtig · Fallstricke

  • Zeitbereich und Frequenz haben unterschiedliche Puffergrößen: Für Zeitbereichsdaten gehört ein Puffer der Länge fftSize, für Frequenzdaten einer der Länge frequencyBinCount. Ist der Puffer kürzer, wird abgeschnitten. Ist er länger, bleibt der Rest unverändert.
  • fftSize muss eine Zweierpotenz zwischen 32 und 32768 sein, sonst wird ein IndexSizeError geworfen. Wird minDecibels größer oder gleich maxDecibels gesetzt, kommt ebenfalls ein IndexSizeError.
  • getByteTimeDomainData() liefert Werte von 0 bis 255. Stille entspricht dem Wert 128, nicht 0.
  • getFloatFrequencyData() liefert Dezibel-Werte. Bei Stille ist das -Infinity, das muss man beim Zeichnen abfangen.
  • Autoplay-Richtlinien: Ein AudioContext startet im Zustand suspended, bis eine Nutzeraktion stattfindet. Dann audioCtx.resume() aufrufen.
  • CORS: Stammt ein Medium aus einer fremden Quelle und fehlen CORS-Header (crossorigin-Attribut), liefert createMediaElementSource() nur Stille, und der Analyser gibt Nullwerte zurück.
  • Rückkopplung vermeiden: Mikrofon-Signale für die reine Analyse nicht mit destination verbinden.
  • Performance: Datenpuffer einmal anlegen und wiederverwenden, statt sie in jedem Frame neu zu erzeugen. Große fftSize-Werte kosten mehr Rechenzeit.
  • Browser-Kompatibilität: Der Konstruktor new AnalyserNode() wird von allen aktuellen Browsern unterstützt. Sehr alte Safari-Versionen brauchen webkitAudioContext und createAnalyser().