Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.

View in English Always switch to English

Grundkonzepte hinter der Web Audio API

Dieser Artikel erklärt einige der Audiotheorien, welche die Funktionsweise der Web Audio API-Features betreffen, um Ihnen zu helfen, informierte Entscheidungen bei der Gestaltung der Audioverwaltung in Ihrer App zu treffen. Wenn Sie kein Tontechniker sind, bietet dieser Artikel genügend Hintergrundinformationen, um zu verstehen, warum die Web Audio API so funktioniert, wie sie es tut.

Audiographen

Die Web Audio API umfasst das Verwalten von Audiovorgängen innerhalb eines Audio-Kontextes, und ist so konzipiert, dass sie modular routing ermöglicht. Jedes Audio-Knoten führt eine grundlegende Audiooperation aus und ist mit einem oder mehreren anderen Audio-Knoten verbunden, um einen Audio-Routing-Graphen zu bilden. Mehrere Quellen mit unterschiedlichen Kanal-Layouts werden unterstützt, sogar innerhalb eines einzelnen Kontextes. Dieses modulare Design bietet die Flexibilität, komplexe Audiofunktionen mit dynamischen Effekten zu erstellen.

Audio-Knoten werden über ihre Eingänge und Ausgänge verbunden und bilden eine Kette, die mit einer oder mehreren Quellen beginnt, über einen oder mehrere Knoten verläuft und dann an einem Ziel endet (obwohl Sie kein Ziel bereitstellen müssen, wenn Sie nur einige Audiodaten visualisieren möchten). Ein einfacher, typischer Arbeitsablauf für Web-Audio könnte folgendermaßen aussehen:

  1. Erstellen Sie den Audio-Kontext.
  2. Erstellen Sie Audioquellen innerhalb des Kontextes (wie <audio>, einen Oszillator oder einen Stream).
  3. Erstellen Sie Audiodaten-Effekte (wie den Reverb, Biquadratsfilter, Panner oder Kompressor-Knoten).
  4. Wählen Sie das endgültige Ziel für das Audio (wie die Lautsprecher des Benutzer-PCs).
  5. Verbinden Sie die Quell-Knoten mit null oder mehr Effekt-Knoten und dann mit dem gewählten Ziel.

Hinweis: Die Kanalsymbolik ist ein numerischer Wert, zum Beispiel 2.0 oder 5.1, der die Anzahl der Audiokanäle eines Signals darstellt. Die erste Zahl gibt die Anzahl der Audiokanäle im vollen Frequenzbereich an, die das Signal enthält. Die Zahl nach dem Punkt zeigt die Anzahl der Kanäle, die für Tieffrequenzeffekt (LFE)-Ausgaben reserviert sind; diese werden oft Subwoofer genannt.

Ein einfaches Boxdiagramm mit einer äußeren Box, die als Audiokontext bezeichnet wird, und drei inneren Boxen, die als Quellen, Effekte und Ziel bezeichnet werden. Die drei inneren Boxen haben Pfeile dazwischen, die von links nach rechts zeigen, was den Fluss von Audioinformationen anzeigt.

Jeder Ein- oder Ausgang besteht aus einem oder mehreren Audio-Kanälen, die zusammen ein spezifisches Audio-Layout darstellen. Jede diskrete Kanalstruktur wird unterstützt, einschließlich Mono, Stereo, Quad, 5.1 und so weiter.

Zeigen Sie die Fähigkeit von Audio-Knoten, sich über ihre Eingänge und Ausgänge zu verbinden und die Kanäle innerhalb dieser Eingänge/Ausgänge.

Sie haben mehrere Möglichkeiten, Audio zu erhalten:

  • Ton kann direkt in JavaScript von einem Audio-Knoten (wie einem Oszillator) generiert werden.
  • Er kann aus rohen PCM-Daten erstellt werden (wie .WAV-Dateien oder andere Formate, die von decodeAudioData() unterstützt werden).
  • Er kann aus HTML-Media-Elementen generiert werden, wie <video> oder <audio>.
  • Er kann aus einem WebRTC MediaStream stammen, wie z.B. einer Webcam oder einem Mikrofon.

Audiodaten: was in einem Sample steckt

Wenn ein Audiosignal verarbeitet wird, erfolgt die Abtastung. Abtastung ist die Umwandlung eines kontinuierlichen Signals in ein diskretes Signal. Anders ausgedrückt, eine kontinuierliche Schallwelle, wie ein Live-Auftritt einer Band, wird in eine Folge digitaler Samples (ein diskretes Zeitsignal) umgewandelt, das es einem Computer ermöglicht, das Audio in diskreten Blöcken zu verarbeiten.

Mehr Informationen finden Sie auf der Wikipedia-Seite Sampling (Signalverarbeitung).

Audiodaten-Puffer: Frames, Samples und Kanäle

Ein AudioBuffer ist mit drei Parametern definiert:

  • der Anzahl der Kanäle (1 für Mono, 2 für Stereo usw.),
  • seiner Länge, d.h. die Anzahl der Sample-Frames im Puffer,
  • und der Abtastrate, der Anzahl von Sample-Frames, die pro Sekunde abgespielt werden.

Ein Sample ist ein einzelner 32-Bit-Float-Wert, der den Wert des Audiostreams zu einem bestimmten Zeitpunkt innerhalb eines bestimmten Kanals (links oder rechts, falls stereo) repräsentiert. Ein Frame oder Sample-Frame ist die Menge aller Werte für alle Kanäle, die zu einem bestimmten Zeitpunkt abgespielt werden: alle Samples aller Kanäle, die gleichzeitig abspielen (zwei für ein Stereo-Sound, sechs für 5.1 usw.).

Die Abtastrate ist die Anzahl dieser Samples (oder Frames, da alle Samples eines Frames gleichzeitig abgespielt werden), die in einer Sekunde abgespielt werden, gemessen in Hz. Je höher die Abtastrate, desto besser die Klangqualität.

Schauen wir uns einen Mono- und einen Stereo-Audiopuffer an, jeweils eine Sekunde lang bei einer Rate von 44100Hz:

  • Der Mono-Puffer wird 44.100 Samples und 44.100 Frames haben. Die length-Eigenschaft wird 44.100 sein.
  • Der Stereo-Puffer wird 88.200 Samples, aber immer noch 44.100 Frames haben. Die length-Eigenschaft wird noch 44100 sein, da sie der Anzahl der Frames entspricht.

Ein Diagramm, das mehrere Frames in einem Audiopuffer in einer langen Linie zeigt, wobei jeder Frame zwei Samples enthält, da der Puffer zwei Kanäle hat und es also stereo ist.

Wenn ein Puffer abgespielt wird, hören Sie zuerst das linkeste Sample-Frame, dann das direkt daneben, dann das nächste, und so weiter, bis zum Ende des Puffers. Im Falle von Stereo hören Sie beide Kanäle gleichzeitig. Sample-Frames sind nützlich, weil sie unabhängig von der Anzahl der Kanäle sind und die Zeit auf ideale Weise für präzise Audiomanipulation darstellen.

Hinweis: Um aus einer Frame-Anzahl eine Zeit in Sekunden zu erhalten, teilen Sie die Anzahl der Frames durch die Abtastrate. Um die Anzahl der Frames aus der Anzahl der Samples zu erhalten, müssen Sie nur den letzteren Wert durch die Kanalanzahl teilen.

Hier sind ein paar einfache Beispiele:

js
const context = new AudioContext();
const buffer = new AudioBuffer(context, {
  numberOfChannels: 2,
  length: 22050,
  sampleRate: 44100,
});

Hinweis: In der digitalen Audioverarbeitung ist 44.100 Hz (alternativ dargestellt als 44,1 kHz) eine gebräuchliche Abtastfrequenz. Warum 44,1 kHz?

Erstens, weil der Hörbereich des menschlichen Ohrs grob 20 Hz bis 20.000 Hz beträgt. Nach dem Nyquist-Shannon-Sampling-Theorem muss die Abtastfrequenz größer als das Doppelte der maximalen Frequenz sein, die man reproduzieren möchte. Daher muss die Abtastrate größer als 40.000 Hz sein.

Zweitens müssen Signale Tiefpass-gefiltert werden, bevor sie abgetastet werden, ansonsten tritt Aliasing auf. Während ein idealer Tiefpassfilter perfekt Frequenzen unter 20 kHz durchlassen würde (ohne sie zu dämpfen) und Frequenzen über 20 kHz perfekt abschneiden würde, ist in der Praxis ein Übergangsband notwendig, in welchem Frequenzen teilweise gedämpft werden. Je breiter dieses Übergangsband ist, desto einfacher und kostengünstiger ist es, einen Anti-Alias-Filter herzustellen. Die Abtastfrequenz von 44,1 kHz ermöglicht ein 2,05 kHz Übergangsband.

Wenn Sie diesen Aufruf oben verwenden, erhalten Sie einen Stereo-Puffer mit zwei Kanälen, der bei einer Wiedergabe in einem AudioContext bei 44100 Hz (sehr verbreitet, die meisten normalen Soundkarten laufen mit dieser Rate) 0,5 Sekunden dauert: 22.050 Frames/44.100 Hz = 0,5 Sekunden.

js
const context = new AudioContext();
const buffer = new AudioBuffer(context, {
  numberOfChannels: 1,
  length: 22050,
  sampleRate: 22050,
});

Wenn Sie diesen Aufruf verwenden, erhalten Sie einen Mono-Puffer (einzelkanaliger Puffer), der bei einer Wiedergabe in einem AudioContext bei 44.100 Hz automatisch auf 44.100 Hz resampled wird (und daher 44.100 Frames erhält) und 1,0 Sekunde dauert: 44.100 Frames/44.100 Hz = 1 Sekunde.

Hinweis: Audio-Resampling ist sehr ähnlich zum Bild-Resizing. Angenommen, Sie haben ein 16 x 16 Bild, möchten es aber auf ein 32 x 32 Bereich füllen. Sie ändern (oder resampeln) die Größe. Das Ergebnis hat eine geringere Qualität (es kann verschwommen oder kantig sein, abhängig vom Resampling-Algorithmus), aber es funktioniert, wobei das geänderte Bild weniger Speicherplatz benötigt. Resampled-Audio ist dasselbe: Sie sparen Platz, aber in der Praxis können Sie keine hohen Frequenzinhalte oder Höhentöne korrekt reproduzieren.

Planare vs. verwobene Puffer

Die Web Audio API verwendet ein Planar-Pufferformat. Die linken und rechten Kanäle werden so gespeichert:

LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRR (for a buffer of 16 frames)

Diese Struktur ist weit verbreitet in der Audiobearbeitung, da sie das unabhängige Bearbeiten jedes Kanals erleichtert.

Die Alternative ist die Verwendung eines verwobenen Pufferformats:

LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR (for a buffer of 16 frames)

Dieses Format ist weit verbreitet zum Speichern und Abspielen von Audio ohne viel Bearbeitung, zum Beispiel: .WAV-Dateien oder ein dekodierter MP3-Stream.

Da die Web Audio API für die Verarbeitung konzipiert ist, stellt sie nur Planar-Puffer zur Verfügung. Sie verwendet das Planar-Format, konvertiert das Audio aber in das verwobene Format, wenn es zur Wiedergabe an die Soundkarte gesendet wird. Umgekehrt beginnt die API beim Dekodieren eines MP3 mit dem verwobenen Format und konvertiert es zum Planar-Format zum Verarbeiten.

Audiokanäle

Jeder Audiopuffer kann unterschiedliche Anzahlen an Kanälen enthalten. Die meisten modernen Audiogeräte verwenden die grundlegenden Mono (nur ein Kanal) und Stereo (linke und rechte Kanäle) Einstellungen. Einige komplexere Sets unterstützen Surround-Sound-Einstellungen (wie Quad und 5.1), die dank ihrer hohen Kanalanzahl zu einem reichhaltigeren Klangerlebnis führen können. Wir stellen die Kanäle normalerweise mit den in der unten stehenden Tabelle angegebenen Standardabkürzungen dar:

Name Kanäle
Mono 0: M: Mono
Stereo 0: L: links 1: R: rechts
Quad 0: L: links 1: R: rechts 2: SL: Surround links 3: SR: Surround rechts
5.1 0: L: links 1: R: rechts 2: C: Center 3: LFE: Subwoofer 4: SL: Surround links 5: SR: Surround rechts

Up-Mixing und Down-Mixing

Wenn die Anzahl der Kanäle des Eingangs und der Ausgang nicht übereinstimmen, muss ein Up-Mixing oder Down-Mixing durchgeführt werden. Die folgenden Regeln, gesteuert durch die Einstellung der AudioNode.channelInterpretation-Eigenschaft auf speakers oder discrete, gelten:

Interpretation Eingangskanäle Ausgangskanäle Mischregeln
speakers 1 (Mono) 2 (Stereo) Up-Mix von Mono zu Stereo.
Der M-Eingangskanal wird für beide Ausgangskanäle (L und R) verwendet.
output.L = input.M
output.R = input.M
1 (Mono) 4 (Quad) Up-Mix von Mono zu Quad.
Der M-Eingangskanal wird für die nicht-Surround-Ausgangskanäle (L und R) verwendet. Surround-Ausgangskanäle (SL und SR) sind stumm.
output.L = input.M
output.R = input.M
output.SL = 0
output.SR = 0
1 (Mono) 6 (5.1) Up-Mix von Mono zu 5.1.
Der M-Eingangskanal wird für den Center-Ausgangskanal (C) verwendet. Alle anderen (L, R, LFE, SL und SR) sind stumm.
output.L = 0
output.R = 0

output.C = input.M
output.LFE = 0
output.SL = 0
output.SR = 0
2 (Stereo) 1 (Mono) Down-Mix von Stereo zu Mono.
Beide Eingangskanäle (L und R) werden gleichmäßig kombiniert, um den einzigartigen Ausgangskanal (M) zu erzeugen.
output.M = 0.5 * (input.L + input.R)
2 (Stereo) 4 (Quad) Up-Mix von Stereo zu Quad.
Die L und R-Eingangskanäle werden für ihre nicht-Surround entsprechenden Ausgangskanäle (L und R) verwendet. Surround-Ausgangskanäle (SL und SR) sind stumm.
output.L = input.L
output.R = input.R
output.SL = 0
output.SR = 0
2 (Stereo) 6 (5.1) Up-Mix von Stereo zu 5.1.
Die L und R-Eingangskanäle werden für ihre nicht-Surround entsprechenden Ausgangskanäle (L und R) verwendet. Surround-Ausgangskanäle (SL und SR), ebenso wie der Center (C) und Subwoofer (LFE)-Kanäle, bleiben stumm.
output.L = input.L
output.R = input.R
output.C = 0
output.LFE = 0
output.SL = 0
output.SR = 0
4 (Quad) 1 (Mono) Down-Mix von Quad zu Mono.
Alle vier Eingangskanäle (L, R, SL und SR) werden gleichmäßig kombiniert, um den einzigartigen Ausgangskanal (M) zu erzeugen.
output.M = 0.25 * (input.L + input.R + input.SL + input.SR)
4 (Quad) 2 (Stereo) Down-Mix von Quad zu Stereo.
Beide linken Eingangskanäle (L und SL) werden gleichmäßig kombiniert, um den einzigartigen linken Ausgangskanal (L) zu erzeugen. Ebenso werden beide rechten Eingangskanäle (R und SR) gleichmäßig kombiniert, um den einzigartigen rechten Ausgangskanal (R) zu erzeugen.
output.L = 0.5 * (input.L + input.SL)
output.R = 0.5 * (input.R + input.SR)
4 (Quad) 6 (5.1) Up-Mix von Quad zu 5.1.
Die L, R, SL und SR-Eingangskanäle werden für ihre entsprechenden Ausgangskanäle (L und R) verwendet. Center (C) und Subwoofer (LFE)-Kanäle sind stumm.
output.L = input.L
output.R = input.R
output.C = 0
output.LFE = 0
output.SL = input.SL
output.SR = input.SR
6 (5.1) 1 (Mono) Down-Mix von 5.1 zu Mono.
Die linken (L und SL), rechten (R und SR) und zentralen Kanäle werden alle zusammen gemischt. Die Surround-Kanäle werden leicht gedämpft, und die normalen seitlichen Kanäle werden leistungs-kompensiert, damit sie als Einzelkanal zählen, durch Multiplikation mit √2/2. Der Subwoofer (LFE) Kanal geht verloren.
output.M = 0.7071 * (input.L + input.R) + input.C + 0.5 * (input.SL + input.SR)
6 (5.1) 2 (Stereo) Down-Mix von 5.1 zu Stereo.
Der zentrale Kanal (C) wird mit jedem seitlichen Surround-Kanal (SL oder SR) summiert und mit jedem seitlichen Kanal gemischt. Da er auf zwei Kanäle gemischt wird, wird er mit weniger Leistung gemischt: in jedem Fall wird er durch √2/2 multipliziert. Der Subwoofer (LFE) Kanal geht verloren.
output.L = input.L + 0.7071 * (input.C + input.SL)
output.R = input.R + 0.7071 * (input.C + input.SR)
6 (5.1) 4 (Quad) Down-Mix von 5.1 zu Quad.
Der zentrale (C) wird mit den seitlichen nicht-Surround-Kanäle (L und R) gemischt. Da er auf zwei Kanäle gemischt wird, wird er mit weniger Leistung gemischt: in jedem Fall wird er durch √2/2 multipliziert. Die Surround-Kanäle werden unverändert übernommen. Der Subwoofer (LFE) Kanal geht verloren.
output.L = input.L + 0.7071 * input.C
output.R = input.R + 0.7071 * input.C
output.SL = input.SL
output.SR = input.SR
Andere, nicht standardisierte Layouts Nicht-standardisierte Kanallayouts verhalten sich, als ob channelInterpretation auf discrete gesetzt ist.
Die Spezifikation erlaubt ausdrücklich die zukünftige Definition neuer Lautsprecher-Layouts. Daher ist dieser Fallback nicht zukunftssicher, da das Verhalten der Browser für eine bestimmte Anzahl von Kanälen in Zukunft ändern kann.
discrete jegliche (x) jegliche (y) wo x<y Up-Mix diskreter Kanäle.
Füllen Sie jeden Ausgangskanal mit seinem entsprechenden Eingang — das heißt, dem Eingangs-kanal mit demselben Index. Kanäle ohne entsprechendes Eingangskanal werden stummgeschaltet.
jegliche (x) jegliche (y) wo x>y Down-Mix diskreter Kanäle.
Füllen Sie jeden Ausgangskanal mit seinem entsprechenden Eingang — das heißt, dem Eingangs-kanal mit demselben Index. Eingabekanäle ohne entsprechendes Ausgangskanal werden verworfen.

Visualisierungen

Im Allgemeinen erhalten wir den Ausgang über die Zeit, um Audio-Visualisierungen zu erzeugen, indem wir normalerweise seine Verstärkung oder Frequenzdaten lesen. Dann, mit einem grafischen Tool, wandeln wir die erhaltenen Daten in eine visuelle Darstellung um, z. B. in ein Diagramm. Die Web Audio API bietet einen AnalyserNode, der das Audiosignal, das durch ihn hindurchfließt, nicht verändert. Zusätzlich gibt er die Audiodaten aus, welche uns ermöglicht, diese durch eine Technologie wie <canvas> zu verarbeiten.

Ohne den Audiostream zu ändern, ermöglicht Ihnen der Knoten, die Frequenz- und Zeitdomaindaten damit zu erhalten, unter Verwendung einer FFT.

Sie können Daten mit den folgenden Methoden abrufen:

AnalyserNode.getFloatFrequencyData()

Kopiert die aktuellen Frequenzdaten in ein Float32Array-Array, das an ihn übergeben wird.

AnalyserNode.getByteFrequencyData()

Kopiert die aktuellen Frequenzdaten in ein Uint8Array (unsigned byte Array), das an ihn übergeben wird.

AnalyserNode.getFloatTimeDomainData()

Kopiert die aktuelle Wellenform- oder Zeitdomaindaten in ein Float32Array-Array, das an ihn übergeben wird.

AnalyserNode.getByteTimeDomainData()

Kopiert die aktuelle Wellenform- oder Zeitdomaindaten in ein Uint8Array (unsigned byte Array), das an ihn übergeben wird.

Hinweis: Für weitere Informationen siehe unser Artikel Visualisierungen mit Web Audio API.

Räumliche Klangverarbeitung

Die räumliche Klangverarbeitung ermöglicht es uns, die Position und das Verhalten eines Audiosignals an einem bestimmten Punkt im physischen Raum zu modellieren, um zu simulieren, wie der Hörer dieses Audio hört. In der Web Audio API wird die räumliche Klangverarbeitung durch den PannerNode und den AudioListener gehandhabt.

Der Panner verwendet rechtshändige kartesische Koordinaten, um die Position der Audioquelle als Vektor und ihre Orientierung als einen 3D-Richtungskegel zu beschreiben. Der Kegel kann recht groß sein, zum Beispiel für omnidirektionale Quellen.

Der PannerNode definiert eine räumliche Position und Orientierung für ein gegebenes Signal.

Ähnlich beschreibt die Web Audio API den Hörer mit rechtshändigen kartesischen Koordinaten: seine Position als ein Vektor und seine Orientierung als zwei Richtungsvektoren, Oben und Vorne. Diese Vektoren definieren die Richtung des oberen Teils des Kopfes des Hörers und die Richtung, in die die Nase des Hörers zeigt. Die Vektoren sind zueinander senkrecht.

Wir sehen die Position, die „oben“ und die „vorne“ Vektoren eines AudioListeners, wobei die „oben“ und „vorne“ Vektoren im 90°-Winkel zueinander stehen.

Hinweis: Für weitere Informationen siehe unser Artikel Web Audio Raumklangverarbeitung Grundlagen.

Fan-In und Fan-Out

In Audiobegriffen beschreibt Fan-In den Prozess, bei dem ein ChannelMergerNode eine Reihe von Mono-Eingangsquellen nimmt und ein einziges multisignaliges Signal ausgibt:

Fan-In-Prozessdiagramm. Mehrere punktlose Pfeile, die Mono-Eingangsquellen darstellen, kombinieren sich, um einen einzelnen gepunkteten Pfeil auszugeben, der ein einzelnes multisignaliges Signal darstellt

Fan-Out beschreibt den entgegengesetzten Prozess, bei dem ein ChannelSplitterNode eine multisignalige Eingangsquelle nimmt und mehrere Mono-Ausgangssignale ausgibt:

Fan-Out-Prozessdiagramm. Ein einzelner punktloser Pfeil, der eine multisignalige Eingangsquelle darstellt, teilt sich auf, um mehrere gepunktete Pfeile auszugeben, die mehrere Mono-Ausgangssignale darstellen