Web Audio und 3D Soundscapes Implementierung

In diesem Lernprogramm werden Web Audio in eine einfache API eingebunden, die sich auf das Spielen von Klängen innerhalb eines 3D-Koordinatenraums konzentriert und für interaktive interaktive Anwendungen einschließlich 3D-Spielen verwendet werden kann.

Dieses Tutorial ist das zweite in einer zweiteiligen Serie. Wenn Sie das erste Tutorial der Serie nicht gelesen haben, sollten Sie dies vor dem Lesen dieses Tutorials tun, da Sie hier die verschiedenen Web-Audio-Elemente kennenlernen, die wir hier verwenden werden.

Demonstration

Bevor wir loslegen, hier eine kleine Demonstration, die die vereinfachte API verwendet, die wir in diesem Tutorial behandeln werden. Sounds (dargestellt durch die weißen Quadrate) werden zufällig in einem 3D-Koordinatenraum mit der kopfbezogenen Übertragungsfunktion (HRTF), die Web Audio für uns bereitstellt, positioniert und abgespielt.

Die Quelldateien für die Demonstration sind an dieses Tutorial angehängt.

Überblick

Da die vereinfachte API (AudioPlayer) bereits für dieses Lernprogramm erstellt wurde und zum Download zur Verfügung steht, werfen wir einen Blick auf die AudioPlayer-API und den dazugehörigen Code.

Bevor Sie dieses Tutorial fortsetzen, lesen Sie bitte Das vorherige Tutorial dieser Serie, falls Sie dies noch nicht getan haben und in der Welt von Web Audio noch nicht bekannt sind.

Musikplayer

Das Musikplayer Klasse enthält unsere vereinfachte API und ist auf der Fenster Objekt neben den Standard-Web-Audioklassen, wenn und nur wenn Web-Audio vom Webbrowser unterstützt wird. Das bedeutet, dass wir die Existenz der Klasse prüfen sollten, bevor wir versuchen, sie zu verwenden.

if (window.AudioPlayer! == undefined) audioPlayer = neuer AudioPlayer ()

(Wir hätten versuchen können, ein neues zu schaffen Musikplayer Objekt innerhalb eines versuche es… fangen Anweisung, aber eine einfache bedingte Prüfung funktioniert einwandfrei.)

Hinter den Kulissen der Musikplayer schafft ein neues AudioContext Objekt und ein neues AudioGainNode Objekt für uns und verbindet das GainNode Einwände gegen die Ziel Knoten von der freigelegt AudioContext Objekt.

var m_context = new AudioContext () var m_gain = m_context.createGain ()… m_gain.connect (m_context.destination)

Wenn Sounds erzeugt und abgespielt werden, werden sie mit dem verbunden m_gain Knoten, ermöglicht dies die einfache Steuerung der Lautstärke (Amplitude) aller Sounds.

Das Musikplayer konfiguriert auch das Audio Hörer, ausgesetzt durch m_context, Daher stimmt es mit dem üblichen 3D-Koordinatensystem überein, das mit WebGL verwendet wird. Das Positive z Achse zeigt auf den Betrachter (mit anderen Worten, er zeigt aus dem 2D-Bildschirm heraus), das Positive y Achse zeigt nach oben und das Positive x Achse zeigt nach rechts.

m_context.listener.setOrientation (0, 0, -1, 0, 1, 0)

Die Position der Hörer ist immer Null; Es befindet sich in der Mitte des Audiokoordinatensystems.

Sounds laden

Bevor wir Sounds erstellen oder abspielen können, müssen wir die Sounddateien laden. zum glück genug Musikplayer kümmert sich um all die harte Arbeit für uns. Es legt ein Belastung(… ) Funktion, mit der wir die Sounds laden können, und drei Event-Handler, mit denen wir den Ladungsfortschritt verfolgen können.

audioPlayer.onloadstart = function () … audioPlayer.onloaderror = function () … audioPlayer.onloadcomplete = function () … audioPlayer.load ("sound-01.ogg") audioPlayer.load ("sound-02.) .ogg ") audioPlayer.load (" sound-03.ogg ")

Die unterstützten Soundformate sind vom Browser abhängig. Zum Beispiel unterstützen Chrome und Firefox OGG Vorbis, Internet Explorer jedoch nicht. Alle drei Browser unterstützen MP3, was praktisch ist, aber das Problem bei MP3 ist das Fehlen von nahtlosem Sound-Looping. Das MP3-Format ist einfach nicht dafür ausgelegt. OGG Vorbis ist jedoch und kann Sounds perfekt schleifen.

Beim Anrufen der Belastung(… ) Funktion mehrmals, Musikplayer Die Anforderungen werden in eine Warteschlange verschoben und nacheinander geladen. Wenn alle in der Warteschlange befindlichen Sounds geladen (und decodiert) wurden, wird der onloadcomplete Eventhandler wird aufgerufen.

Hinter den Kulissen, Musikplayer verwendet eine einzelne XMLHttpRequest Objekt zum Laden der Sounds. Das responseType der Anfrage ist auf gesetzt "arraybuffer", und wenn die Datei geladen ist, wird der Array-Puffer gesendet m_context zum Dekodieren.

// vereinfachtes Beispiel m_loader = new XMLHttpRequest () m_queue = [] Funktion load () m_loader.open ("GET", m_queue [0]) m_loader.responseType = "arraybuffer" m_loader.onload = onLoad m_loader.send () Funktion onLoad (Ereignis) var data = m_loader.response var status = m_loader.status m_loader.abort () // setzt den Loader if (status < 400)  m_context.decodeAudioData(data, onDecode)  

Wenn das Laden und Dekodieren einer Datei erfolgreich ist, Musikplayer wird entweder die nächste Datei in die Warteschlange laden (wenn die Warteschlange nicht leer ist) oder uns mitteilen, dass alle Dateien geladen wurden.

Sounds erstellen

Nachdem wir nun einige Sounddateien geladen haben, können wir unsere Sounds erstellen und abspielen. Wir müssen zuerst erzählen Musikplayer um die Sounds zu erzeugen, und dies geschieht mit der erstellen(… ) Funktion ausgesetzt durch Musikplayer.

var sound1 = audioPlayer.create ("sound-01.ogg") var sound2 = audioPlayer.create ("sound-02.ogg") var sound3 = audioPlayer.create ("sound-03.ogg")

Wir können beliebig viele Sounds erstellen, auch wenn wir nur eine einzige Sounddatei geladen haben.

var a = audioPlayer.create ("beep.ogg") var b = audioPlayer.create ("beep.ogg") var c = audioPlayer.create ("beep.ogg")

Der Sounddateipfad, der an den übertragen wurde erstellen(… ) Funktion erzählt einfach Musikplayer welche Datei der erstellte Sound verwenden soll. Wenn die angegebene Audiodatei beim Laden nicht geladen wurde erstellen(… ) Funktion aufgerufen wird, wird ein Laufzeitfehler ausgelöst.

Sounds abspielen

Wenn wir einen oder mehrere Sounds erstellt haben, können wir diese Sounds jederzeit wiedergeben. Um einen Sound abzuspielen, verwenden wir den passend benannten abspielen(… ) Funktion ausgesetzt durch Musikplayer.

audioPlayer.play (sound1)

Um zu bestimmen, ob Sie ein spielen möchten geschlungen Sound, wir können auch einen Boolean an den übergeben abspielen(… ) Funktion. Wenn der Boolean ist wahr, Der Ton wird so lange wiederholt, bis er gestoppt wird.

audioPlayer.play (sound1, true)

Um einen Ton zu stoppen, können wir die verwenden halt(… ) Funktion.

audioPlayer.stop (sound1)

Das spielt(… ) Mit dieser Funktion können Sie wissen, ob gerade ein Sound abgespielt wird.

if (audioPlayer.isPlaying (sound1)) …

Hinter den Kulissen der Musikplayer Es muss erstaunlich viel Arbeit geleistet werden, um einen Sound zu erzeugen, da Web Audio modular aufgebaut ist. Wann immer ein Ton abgespielt werden muss,Musikplayer muss neu schaffen AudioSourceBufferNode und PannerNode Objekte, konfigurieren und verbinden sie und verbinden Sie den Sound mit dem m_gain Knoten. Glücklicherweise ist Web Audio stark optimiert, sodass die Erstellung und Konfiguration neuer Audio-Nodes selten einen spürbaren Aufwand verursacht.

sound.source = m_context.createBufferSource () sound.panner = m_context.createPanner () sound.source.buffer = sound.buffer sound.source.loop = loop sound.source.onended = onSoundEnded // Dies ist ein bisschen Hack Wir müssen jedoch das // Sound-Objekt im onSoundEnded-Ereignishandler referenzieren, und dies tun // ist auf diese Weise optimaler als das Binden des Handlers. sound.source.sound = sound sound.panner.panningModel = "HRTF" sound.panner.distanceModel = "linear" sound.panner.setPosition (sound.x, sound.y, sound.z) sound.source.connect (sound .panner) sound.panner.connect (m_gain) sound.source.start ()

Klänge zu spielen ist offensichtlich nützlich, aber der Zweck von Musikplayer ist es, Sounds innerhalb eines 3D-Koordinatensystems abzuspielen, daher sollten wir die Klangpositionen wahrscheinlich vor dem Abspielen einstellen. Musikplayer macht einige Funktionen verfügbar, mit denen wir genau das tun können.

Sounds positionieren

  • Das setX (…) und getX (…) Funktionen ausgesetzt durch Musikplayer kann verwendet werden, um die Position eines Sounds entlang des Koordinatensystems festzulegen und abzurufen x Achse.
  • Das setY (…) und getY (…) Funktionen können verwendet werden, um die Position eines Sounds entlang des Koordinatensystems festzulegen und abzurufen y Achse.
  • Das setZ (…) und getZ (…) Funktionen können verwendet werden, um die Position eines Sounds entlang des Koordinatensystems festzulegen und abzurufen z Achse.
  • Zum Schluss das Hilfsmittel Position setzen(… ) Mit dieser Funktion können Sie die Position eines Sounds entlang des Koordinatensystems einstellen x, y, und z Achsen.
audioPlayer.setX (sound1, 100) audioPlayer.setZ (sound1, 200) console.log (audioPlayer.getX (sound1)) // 100 console.log (audioPlayer.getZ (sound1)) // 200 audioPlayer.setPosition (sound1, 300, 0, 400) console.log (audioPlayer.getX (sound1)) // 300 console.log (audioPlayer.getZ (sound1)) // 400

Je weiter ein Klang von der Mitte des Koordinatensystems entfernt ist, desto leiser ist der Klang. In einer Entfernung von 10000 (Standardeinstellung für Web-Audio) Ein Ton ist völlig stumm.

Volumen

Wir können die globale (Master-) Lautstärke der Sounds mit Hilfe von steuern setVolume (…) und getVolume (…) Funktionen ausgesetzt durch Musikplayer.

audioPlayer.setVolume (0.5) // 50% console.log (audioPlayer.getVolume ()) // 0.5

Das setVolume (…) Funktion hat auch einen zweiten Parameter, mit dem die Lautstärke über einen bestimmten Zeitraum ausgeblendet werden kann. Um beispielsweise das Volumen über einen Zeitraum von zwei Sekunden auf null zu bringen, können Sie Folgendes tun:

audioPlayer.setVolume (0.0, 2.0)

Die Tutorial-Demo nutzt dies, um die Sounds sanft einzublenden.

Hinter den Kulissen der Musikplayer sagt einfach das m_gain Knoten, um den Verstärkungswert linear zu ändern, wenn die Lautstärke geändert werden muss.

var currentTime = m_context.currentTime var currentVolume = m_gain.gain.value m_gain.gain.cancelScheduledValues ​​(0.0) m_gain.gain.setValueTime (currentVolume, currentTime)

Musikplayer erzwingt eine minimale Überblendzeit von 0,01 Sekunden, um sicherzustellen, dass starke Lautstärkeänderungen keine hörbaren Klicks oder Knacks verursachen.

Fazit

In diesem Lernprogramm haben wir einen Blick auf eine Möglichkeit zum Einschließen von Web Audio in eine einfache API gerichtet, die sich auf das Spielen von Sounds innerhalb eines 3D-Koordinatenraums für die Verwendung in (neben anderen Anwendungen) 3D-Spielen konzentriert.

Aufgrund des modularen Charakters von Web Audio können Programme, die Web Audio verwenden, sehr schnell komplex werden. Daher hoffe ich, dass dieses Tutorial für Sie von Nutzen war. Wenn Sie verstehen, wie Web Audio funktioniert und wie mächtig es ist, werden Sie sicher viel Spaß daran haben.

Vergessen Sie nicht, dass die AudioPlayer- und Demo-Quelldateien auf GitHub zur Verfügung stehen und zum Download bereitstehen. Der Quellcode ist ziemlich gut kommentiert, daher lohnt es sich, sich die Zeit zu nehmen, um einen kurzen Blick darauf zu werfen.

Wenn Sie Feedback oder Fragen haben, können Sie untenstehend einen Kommentar posten.

Ressourcen

  • W3C Web-Audio-Spezifikation
  • MDN-Web-Audio-Dokumentation