Web Audio API-Konzepte



Guten Tag, Freunde!

In diesem Artikel werden einige Konzepte aus der Musiktheorie erlÀutert, mit denen die Web Audio API (WAA) arbeitet. Wenn Sie diese Konzepte kennen, können Sie fundierte Entscheidungen treffen, wenn Sie Audio in einer Anwendung entwerfen. Dieser Artikel macht Sie nicht zu einem erfahrenen Toningenieur, aber er hilft Ihnen zu verstehen, warum WAA so funktioniert, wie es funktioniert.

Audio-Schaltung


Die Essenz von WAA besteht darin, einige Operationen mit Ton in einem Audiokontext auszufĂŒhren. Diese API wurde speziell fĂŒr das modulare Routing entwickelt. Die Grundoperationen mit Sound sind Audioknoten, die miteinander verbunden sind und ein Routing-Diagramm (Audio-Routing-Diagramm) bilden. Mehrere Quellen - mit unterschiedlichen Kanaltypen - werden in einem einzigen Kontext verarbeitet. Dieser modulare Aufbau bietet die notwendige FlexibilitĂ€t, um komplexe Funktionen mit dynamischen Effekten zu erstellen.

Audioknoten sind ĂŒber Ein- und AusgĂ€nge miteinander verbunden, bilden eine Kette, die von einer oder mehreren Quellen ausgeht, durch einen oder mehrere Knoten verlĂ€uft und am Ziel endet. GrundsĂ€tzlich können Sie beispielsweise auf ein Ziel verzichten, wenn Sie nur einige Audiodaten visualisieren möchten. Ein typischer Web-Audio-Workflow sieht ungefĂ€hr so ​​aus:

  1. Erstellen Sie einen Audiokontext
  2. Erstellen Sie im Kontext Quellen wie <audio>, einen Oszillator (Soundgenerator) oder einen Stream
  3. Erstellen Sie Effektknoten wie Hall , Biquad-Filter, Panner oder Kompressor
  4. WĂ€hlen Sie ein Ziel fĂŒr Audio aus, z. B. Lautsprecher auf dem Computer eines Benutzers
  5. Stellen Sie durch Effekte eine Verbindung zwischen Quellen zu einem Ziel her



Kanalbezeichnung


Die Anzahl der verfĂŒgbaren AudiokanĂ€le wird hĂ€ufig in numerischem Format angegeben, z. B. 2.0 oder 5.1. Dies wird als Kanalbezeichnung bezeichnet. Die erste Ziffer gibt den gesamten Frequenzbereich an, den das Signal enthĂ€lt. Die zweite Ziffer gibt die Anzahl der KanĂ€le an, die fĂŒr die NiederfrequenzeffektausgĂ€nge - Subwoofer - reserviert sind .

Jeder Eingang oder Ausgang besteht aus einem oder mehreren KanĂ€len, die gemĂ€ĂŸ einer bestimmten Audio-Schaltung aufgebaut sind. Es gibt verschiedene diskrete Kanalstrukturen wie Mono, Stereo, Quad, 5.1 usw.



Audioquellen können auf viele Arten erhalten werden. Der Ton kann sein:

  • Wird von JavaScript ĂŒber einen Audioknoten (z. B. einen Oszillator) generiert.
  • Erstellt aus Rohdaten mit PCM (Pulse Code Modulation)
  • Abgeleitet von HTML-Medienelementen (wie <video> oder <audio>)
  • Abgeleitet von einem WebRTC-Medienstrom (z. B. einer Webcam oder einem Mikrofon)

Audiodaten: Was ist im Beispiel


Abtasten bedeutet, ein kontinuierliches Signal in ein diskretes (geteiltes) (analoges zu digitales) Signal umzuwandeln. Mit anderen Worten, eine kontinuierliche Schallwelle, wie beispielsweise ein Live-Konzert, wird in eine Folge von Samples umgewandelt, die es dem Computer ermöglichen, das Audio in separaten Blöcken zu verarbeiten.

Audiopuffer: Frames, Samples und KanÀle


AudioBuffer akzeptiert die Anzahl der KanĂ€le als Parameter (1 fĂŒr Mono, 2 fĂŒr Stereo usw.), die LĂ€nge - die Anzahl der Sample-Frames im Puffer und die Sampling-Frequenz - die Anzahl der Frames pro Sekunde.

Ein Beispiel ist ein einfacher 32-Bit-Gleitkommawert (float32), der der Wert des Audiostreams zu einem bestimmten Zeitpunkt und in einem bestimmten Kanal (links oder rechts usw.) ist. Ein Sample-Frame oder Frame ist eine Reihe von Werten aller KanĂ€le, die zu einem bestimmten Zeitpunkt wiedergegeben werden: Alle Abtastwerte aller gleichzeitig wiedergegebenen KanĂ€le (zwei fĂŒr Stereo, sechs fĂŒr 5.1 usw.).

Die Abtastrate ist die Anzahl der Abtastwerte (oder Frames, da alle Samples in einem Frame gleichzeitig abgespielt werden), die in einer Sekunde wiedergegeben und in Hertz (Hz) gemessen werden. Je höher die Frequenz, desto besser die KlangqualitÀt.

Schauen wir uns Mono- und Stereopuffer an, die jeweils eine Sekunde lang sind und mit einer Frequenz von 44100 Hz reproduziert werden:

  • Der Monopuffer hat 44100 Samples und 44100 Frames. Der Wert der Eigenschaft "length" betrĂ€gt 44100
  • Der Stereopuffer enthĂ€lt 88.200 Samples, aber auch 44.100 Frames. Der Wert der Eigenschaft "length" ist 44100 - die LĂ€nge entspricht der Anzahl der Frames



Wenn die Wiedergabe des Puffers beginnt, hören wir zuerst das Bild ganz links des Samples, dann das nÀchste Bild rechts usw. Bei Stereo hören wir beide KanÀle gleichzeitig. Sample-Frames sind unabhÀngig von der Anzahl der KanÀle und bieten die Möglichkeit einer sehr genauen Audioverarbeitung.

Hinweis: Um die Zeit in Sekunden aus der Anzahl der Frames zu ermitteln, muss die Anzahl der Frames durch die Abtastrate dividiert werden. Teilen Sie letztere durch die Anzahl der KanÀle, um die Anzahl der Frames aus der Anzahl der Samples zu ermitteln.

Beispiel:

let context = new AudioContext()
let buffer = context.createBuffer(2, 22050, 44100)

Hinweis: Bei digitalem Audio sind 44100 Hz oder 44,1 kHz die Standardabtastfrequenz. Aber warum 44,1 kHz?

Erstens, weil der Bereich der hörbaren Frequenzen (vom menschlichen Ohr unterscheidbare Frequenzen) zwischen 20 und 20.000 Hz variiert. Nach dem Satz von Kotelnikov sollte die Abtastfrequenz die höchste Frequenz im Signalspektrum mehr als verdoppeln. Daher sollte die Abtastfrequenz grĂ¶ĂŸer als 40 kHz sein.

Zweitens mĂŒssen die Signale mit einem Tiefpassfilter gefiltert werden.Andernfalls kommt es zu einer Überlappung der spektralen „SchwĂ€nze“ (Frequenzwechsel, Frequenzmaskierung, Aliasing), und die Form des rekonstruierten Signals wird verzerrt. Idealerweise sollte ein Tiefpassfilter Frequenzen unter 20 kHz (ohne DĂ€mpfung) durchlassen und Frequenzen ĂŒber 20 kHz fallen lassen. In der Praxis ist ein gewisses Übergangsband (zwischen dem Durchlassband und dem UnterdrĂŒckungsband) erforderlich, in dem die Frequenzen teilweise gedĂ€mpft sind. Eine einfachere und wirtschaftlichere Möglichkeit hierfĂŒr ist die Verwendung eines Änderungsfilters. Bei einer Abtastfrequenz von 44,1 kHz betrĂ€gt das Übergangsband 2,05 kHz.

Im obigen Beispiel erhalten wir einen Stereopuffer mit zwei KanÀlen, der in einem Audiokontext mit einer Frequenz von 44100 Hz (Standard) und einer LÀnge von 0,5 Sekunden (22050 Bilder / 44100 Hz = 0,5 s) wiedergegeben wird.

let context = new AudioContext()
let buffer = context.createBuffer(1, 22050, 22050)

In diesem Fall erhalten wir einen Monopuffer mit einem Kanal, der in einem Audiokontext mit einer Frequenz von 44100 Hz wiedergegeben wird. Er wird auf 44100 Hz ĂŒberabtastet (und die Frames auf 44100 erhöht) und 1 Sekunde lang (44100 Frames / 44100 Hz = 1 s).

Hinweis: Das Audio-Resampling („Resampling“) ist dem Ändern der GrĂ¶ĂŸe („Resizing“) von Bildern sehr Ă€hnlich. Angenommen, wir haben ein 16x16-Bild, möchten diesen Bereich jedoch mit einer GrĂ¶ĂŸe von 32x32 fĂŒllen. Wir Ă€ndern die GrĂ¶ĂŸe. Das Ergebnis ist von geringerer QualitĂ€t (je nach Zoom-Algorithmus kann es verschwommen oder zerrissen sein), aber es funktioniert. Resampled Audio ist dasselbe: Wir sparen Platz, aber in der Praxis ist es unwahrscheinlich, dass eine hohe KlangqualitĂ€t erzielt wird.

Planare und gestreifte Puffer


WAA verwendet ein planares Pufferformat. Der linke und der rechte Kanal interagieren wie folgt:

LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRR ( ,   16 )

In diesem Fall arbeitet jeder Kanal unabhÀngig von den anderen.

Eine Alternative ist die Verwendung eines alternativen Formats:

LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR ( ,   16 )

Dieses Format wird hĂ€ufig fĂŒr die MP3-Decodierung verwendet.

WAA verwendet nur das planare Format, da es fĂŒr die Tonverarbeitung besser geeignet ist. Das planare Format wird alternierend konvertiert, wenn Daten zur Wiedergabe an die Soundkarte gesendet werden. Beim Decodieren von MP3s wird das Inverse konvertiert.

AudiokanÀle


Verschiedene Puffer enthalten eine unterschiedliche Anzahl von KanĂ€len: von einfachem Mono (ein Kanal) und Stereo (linker und rechter Kanal) bis zu komplexeren Sets wie Quad und 5.1 mit einer unterschiedlichen Anzahl von Samples in jedem Kanal, die einen satteren (satteren) Klang liefern. KanĂ€le werden normalerweise durch AbkĂŒrzungen dargestellt:
Mono0: M: Mono
Stereo0: L: links
1: R: rechts
Quadro0: L: links
1: R: rechts
3: SL: zusÀtzlich links (linker Kanal schafft die Umgebung; Surround links)
4: SR: zusÀtzlich rechts (Surround rechts)
5.10: L: links
1: R: rechts
2: C: Mitte
3: LFE: Subwoofer
4: SL: extra links
5: SR: extra rechts

Aufmischen und Abmischen


Wenn die Anzahl der KanĂ€le am Ein- und Ausgang nicht ĂŒbereinstimmt, mischen Sie nach oben oder unten. Das Mischen wird durch die AudioNode.channelInterpretation-Eigenschaft gesteuert:
EingangskanÀleAusgangskanÀleMischregeln
Standard-Kanalmischungsschemata - werden verwendet, wenn die Eigenschaft channelInterpretation fĂŒr Lautsprecher (Lautsprecher) festgelegt ist.
1 (Mono)2 (Stereo)Mischen Sie von Mono zu Stereo.
Der Eingangskanal M wird fĂŒr beide AusgangskanĂ€le (L und R) verwendet.
output.L = input.M
output.R = input.M
1 (Mono)4 (Quad)Mischen Sie von Mono zu Quad.
Der Eingangskanal M wird fĂŒr die HauptkanĂ€le (L und R) verwendet. ZusĂ€tzliche KanĂ€le werden gedĂ€mpft.
output.L = input.M
output.R = input.M
output.SL = 0
output.SR = 0
1 (Mono)6 (5.1)5.1.
©. (L, R, LFE, SL SR) .
output.L = 0
output.R = 0
output.C = input.M
output.LFE = 0
output.SL = 0
output.SR = 0
2 ()1 ().
(L R) (M).
output.M = 0.5 * (input.L + input.R)
2 ()4 ().
L R (L R). (SL SR) .
output.L = input.L
output.R = input.R
output.SL = 0
output.SR = 0
2 ()6 (5.1)5.1.
L R (L R). (SL SR), © (LFE) .
output.L = input.L
output.R = input.R
output.C = 0
output.LFE = 0
output.SL = 0
output.SR = 0
4 ()1 ().
(L, R, SL SR) (M).
output.M = 0.25 * (input.L + input.R + input.SL + input.SR)
4 ()2 ().
(L SL) (L). (R SR) — ¼.
output.L = 0.5 * (input.L + input.SL)
output.R = 0.5 * (input.R + input.SR)
4 ()6 (5.1)5.1.
L, R, SL SR . © (LFE) .
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 ()5.1 .
(L SL), (R SR) () . , , — √2 / 2. (LFE) .
output.M = 0.7071 * (input.L + input.R) + input.C + 0.5 * (input.SL + input.SR)
6 (5.1)2 ()5.1 .
© (SL SR) (L R). √2 / 2. (LFE) .
output.L = input.L + 0.7071 * (input.C + input.SL)
output.R = input.R + 0.7071 * (input.C + input.SR)
6 (5.1)4 ()5.1 .
() (L R). √2 / 2. . (LFE) .
output.L = input.L + 0.7071 * input.C
output.R = input.R + 0.7071 * input.C
output.SL = input.SL
output.SR = input.SR
— , channelInterpretation discrete.
(x)(y), x<y.
( ). , , .
(x)(y), x>yJeder Ausgangskanal wird mit seinem analogen Eingang (mit demselben Index) kombiniert. KanÀle ohne entsprechende AusgangskanÀle werden verworfen.

Visualisierung


Die Visualisierung basiert auf dem Empfang von Audioausgabedaten, z. B. Daten zur Amplitude oder Frequenz, und deren anschließender Verarbeitung mithilfe einer beliebigen Grafiktechnologie. WAA verfĂŒgt ĂŒber einen AnalyzerNode, der das durchgelassene Signal nicht verzerrt. Gleichzeitig können Daten aus Audio extrahiert und weiter ĂŒbertragen werden, z. B. an & ltcanvas>.



Die folgenden Methoden können zum Extrahieren von Daten verwendet werden:

  • AnalyzerNode.getFloatByteFrequencyData () - kopiert die aktuellen Frequenzdaten in das Float32Array
  • AnalyzerNode.getByteFrequencyData () - kopiert die aktuellen Frequenzdaten in ein Uint8Array (vorzeichenloses Byte-Array)
  • AnalyserNode.getFloatTimeDomainData() — Float32Array
  • AnalyserNode.getByteTimeDomainData() — Uint8Array


Mit der Audio-RÀumlichkeit (verarbeitet von PannerNode und AudioListener) können Sie die Position und Richtung des Signals an einem bestimmten Punkt im Raum sowie die Position des Hörers simulieren.

Die Position des Panners wird mit rechtshĂ€ndigen kartesischen Koordinaten beschrieben. FĂŒr die Bewegung wird der Geschwindigkeitsvektor verwendet, der zur Erzeugung des Doppler-Effekts erforderlich ist . FĂŒr die Richtung wird der Richtungskegel verwendet. Dieser Kegel kann bei multidirektionalen Schallquellen sehr groß sein.



Die Position des Hörers wird wie folgt beschrieben: Bewegung - unter Verwendung des Geschwindigkeitsvektors, der Richtung, in der sich der Kopf des Hörers befindet - unter Verwendung von zwei Richtungsvektoren, vorne und oben. Das Einrasten erfolgt an der Oberseite des Kopfes und der Nase des Hörers im rechten Winkel.



Kreuzung und Verzweigung


Eine Verbindung beschreibt einen Prozess, bei dem ein ChannelMergerNode mehrere Eingangs-Monoquellen empfÀngt und diese zu einem einzigen mehrkanaligen Ausgangssignal kombiniert.



Die Verzweigung ist der umgekehrte Prozess (implementiert ĂŒber ChannelSplitterNode).



Ein Beispiel fĂŒr die Arbeit mit WAA finden Sie hier . Der Quellcode fĂŒr das Beispiel ist hier . Hier ist ein Artikel darĂŒber, wie alles funktioniert.

Vielen Dank fĂŒr Ihre Aufmerksamkeit.

All Articles