În acest tutorial vom examina cu atenție elementele fundamentale de Web Audio care sunt folosite pentru a construi sunete 3D pentru aplicații interactive imersive, inclusiv, dar fără a se limita la, jocuri 3D.
Aplicația Web Audio API și terminologia pe care o folosesc pot fi uneori confuze, dar acest tutorial are scopul de a elimina complexitatea și de a oferi o explicație mai simplă a elementelor Web Audio și modul în care acestea lucrează împreună pentru a forma un sunet 3D.
Această demonstrație conține trei sunete care se rotesc în jurul a ascultător, direcția ascultătorului este indicată de săgeată. Dacă vă imaginați că vă uitați în jos pe un personaj de joc (ascultător), sunetele rotative ar putea reprezenta cu ușurință prieteni sau dușmani care înconjoară personajul.
Codul sursă demonstrativ și resursele sunt atașate acestui tutorial.
AudioContext
interfața este inima și sufletul aplicației Web Audio, furnizează funcțiile necesare pentru a crea diverse elemente de Web Audio, precum și pentru a oferi o modalitate de a trimite toate materialele audio la hardware și la difuzoare sau căști ale cuiva.
var audioContext = null dacă (window.AudioContext! == undefined) audioContext = nou AudioContext ()
Este important să vă asigurați că AudioContext
interfața este disponibilă deoarece Web Audio este încă destul de nouă și este posibil să nu fie disponibilă în anumite browsere web.
Pe lângă furnizarea funcțiilor necesare pentru crearea diferitelor elemente de Web Audio, AudioContext
interfața are două proprietăți importante; destinaţie
și ascultător
care sunt atât pentru citire. destinaţie
proprietatea poate fi considerată ca fiind conexiunea cu hardware-ul audio, în cazul în care toate audio generat va ajunge în cele din urmă. ascultător
proprietate (vom arăta mai mult în detaliu mai târziu) reprezintă lucru care ascultă toate audio-urile, de ex. un personaj, sau mai precis o cameră, într-un joc.
AudioBuffer
și AudioBufferSourceNode
interfețele ne permit să jucăm audio. AudioBuffer
obiectele conțin semnalele brute (eșantioane de sunet) care sunt modificate, cruncate și zdrobite în timp ce își fac drumul prin Web Audio înainte de a ajunge la difuzoare sau căști ale cuiva. AudioBufferSourceNode
obiectele sunt utilizate pentru a porni și a opri audio-ul conținut în AudioBuffer
obiecte.
Modul standard de a încărca un sunet într-un AudioBuffer
obiect este de a utiliza a XMLHttpRequest
obiect cu ei responseType
setat la arraybuffer
. Când fișierul audio a fost încărcat, tamponul de array este trimis apoi la AudioContext
obiect pentru decodare și, în cazul în care decodificarea este de succes, vom primi un AudioBuffer
obiect.
var loader = new XMLHttpRequest () loader.open ("GET", "masiv-exploion.ogg") loader.responseType = "arraybuffer" loader.onload = atunci când funcția loader.send ()Loaded (event) var data = loader .response if (data === null) // A apărut o problemă la încărcarea fișierului. returnați // Decodați datele. audioContext.decodeAudioData (data, atunciDecodata) atunci cândDecodat (audioBuffer) // "audioBuffer" este un obiect AudioBuffer.
decodeAudioData ()
funcția are de asemenea un al treilea parametru care acceptă un al doilea apel invers, că apelul este apelat când fișierul audio încărcat nu poate fi decodificat.
decodeAudioData (date, cândDecodate, cândFailed)
Nu toate browserele web acceptă aceleași formate audio, poate fi găsită o bună tabelă de formate acceptate, deci este posibil să doriți să utilizați al doilea apel invers pentru a reveni la un format audio alternativ, dacă este necesar. De exemplu, Internet Explorer nu acceptă OGG Vorbis, dar suportă MP3. Singura problemă reală cu MP3-ul este că nu permite o audio perfectă, cum ar fi OGG Vorbis.
Când ai un AudioBuffer
obiect disponibil, îl puteți juca folosind un AudioBufferSourceNode
obiect.
var source = audioContext.createBufferSource () // Atașați un obiect AudioBuffer. source.buffer = audioBuffer // Conectați obiectul "sursă" la obiectul "destinație". source.connect (audioContext.destination) // Opțional, spuneți "sursă" pentru a bifa audio continuu. source.loop = false // Porniți audio. source.start ()
Este important să vă amintiți AudioBufferSourceNode
obiectele sunt playere audio single-shot, cu alte cuvinte puteți utiliza doar start()
o dată. Va trebui să creați un AudioBufferSourceNode
obiect și conectați-l (direct sau indirect) la destinaţie
obiect expus de AudioContext
obiect ori de câte ori doriți să redați audio de la AudioBuffer
obiect.
Ați putea face viața un pic mai simplă prin crearea unei funcții de utilitate mică care creează, conectează și pornește un proces AudioBufferSourceNode
obiect pentru tine.
(audioBuffer01, audioContext) play (audioBuffer01, audioContext) play (audioBuffer01, audioContext) play (audioBuffer02, audioContext) , audioContext)
Când o AudioBufferSourceCode
obiectul finalizează redarea și dacă nu aveți referințe la obiect oriunde (de exemplu, nu le aveți stocate într-o matrice), atunci Web Audio va deconecta automat obiectul pentru dvs. Acest lucru este extrem de util când trebuie doar să focalizați și să uitați efecte sonore scurte etc.
Dacă vă decideți să faceți buclă audio, folosiți butonul AudioBufferSourceNode
buclă
proprietate, va trebui să păstrați o referință la AudioBufferSourceNode
obiect undeva pentru a putea Stop()
redarea audio.
source.stop ()
Deci, în acest moment, folosim tampoane pentru a reda audio, dar sunetul este redat direct fără a fi aplicat niciun panning sau spațializare. Aici e locul PannerNode
obiectele intră în joc.
PannerNode
obiectele ne permit să poziționăm sunetul în spațiul 3D, într-un sistem cartesian de coordonate. Aici se întâmplă cea mai mare parte a magiei 3D.
A PannerNode
obiectul are câteva proprietăți care ne permit să ajustăm comportamentul audio, dar pentru acest tutorial suntem interesați numai de două dintre ele; maxDistance
și panningModel
. maxDistance
proprietatea este distanța de la ascultător moment în care volumul audio va fi zero. Aceasta este o valoare arbitrară și va avea doar înțeles în cadrul aplicației dvs., dar va fi implicită la 10000 panningModel
spune Web Audio cum să proceseze sunetul care trece prin a PannerNode
obiect. Pentru sunete de sunet 3D, probabil că doriți să setați valoarea la HRTF
(funcție de transfer legate de cap).
Pentru a seta poziția unui AudioBufferSourceNode
noi folosim setPosition ()
funcție expusă de a PannerNode
obiect.
var panner = audioContext.createPanner () panner.panningModel = "HRTF" // Setați poziția 3D (x, y, z). panner.setPosition (1, 2, 3) // Conectați obiectul "sursă" la obiectul "panner". source.connect (panner) // Conectați obiectul "panner" la obiectul "destination". panner.connect (audioContext.destination) // Porniți audio. source.start ()
Pentru a face lucrurile puțin mai clare, lăsați să actualizeze funcția de utilitate creată anterior.
(x, y, y, z, audioContext) var sursa = audioContext.createSourceBuffer () source.buffer = audioBuffer var panner = audioContext.createPanner () panner.panningModel = "HRTF" (audioBuffer01, 1, 2, 3, audioContext) redare (audioBuffer02, 4, 5, 6, audioContext) redare (audioBuffer03, 7, 8, 9, audioContext)
În acest moment, suntem joacă audio și poziționăm-o în spațiu 3D, dar există un element mai important pe care trebuie să-l privim; ascultătorul audio.
Fiecare AudioContext
obiect expune a ascultător
obiect care reprezintă poziția și orientarea lucru care ascultă sunetul. De obicei lucru ar fi o cameră virtuală atașată capului unui personaj, bara de protecție a unei mașini, coada unei aeronave sau orice altceva care are sens din partea spectatorului.
ascultător
obiect are un setPosition ()
funcția și a setOrientation ()
funcţie. setPosition ()
funcția plasează ascultătorul undeva în spațiul 3D și setOrientation ()
rotește ascultătorul (imaginați o panoramare a camerei și o înclinare).
setPosition ()
funcția funcționează exact în același mod ca și PannerNode
setPosition ()
funcționează și acceptă trei coordonate.
audioContext.listener.setPoziția (x, y, z)
setOrientation ()
funcția este un pic mai complexă, acceptă două vectori unitate. Primul vector reprezintă rotația ascultătorului (direcția pe care o indică camera), iar al doilea vector reprezintă funcția ascultătorului sus direcție (arată din partea de sus a camerei).
audioContext.listener.setOrientare (x1, y1, z1, x2, y2, z2)
Dacă trebuie doar să rotiți ascultătorul în jurul unei axe, calculele vectoriale sunt relativ simple. De exemplu, dacă utilizați același sistem de coordonate pe care WebGL îl folosește acolo unde este pozitiv X
puncte în partea dreaptă a ecranului, pozitiv y
arată în partea de sus a ecranului și pozitiv z
scoate afară din ecran, apoi puteți roti ascultătorul în jurul valorii de y
axa (pan camera) folosind una cos ()
apel și una păcat()
funcția de apel.
// Poziția ascultătorului (ar putea fi orice). var x = 50 var y = 100 var z = 0 audioContext.listener.setPosition (x, y, z) // Calculați vectorul rotației. // rad = rotație, în radiani var rad = 0.10 var v1 = Math.cos (rad) // x var v2 = 0 // y var v3 = Math.sin (rad) // z // Vectorul "sus" var v4 = 0 // x var v5 = 1 // y var v6 = 0 // z audioContext.listener.setOrientation (v1, v2, v3, v4, v5, v6)
Demonstrația pentru acest tutorial (codul sursă este atașat) face un lucru similar și îl rotește PannerNode
obiecte în jurul unei singure axe.
În acest tutorial am aruncat o privire asupra elementelor Web Audio fundamentale care sunt folosite pentru a construi sunete 3D pentru aplicații interactive imersive, inclusiv, dar fără a se limita la, jocuri 3D. Sperăm că acest tutorial a fost de folos pentru dvs. și a furnizat suficiente informații pentru ca dvs. să aveți o înțelegere a modului în care tampoanele audio, pannerele și ascultătorii lucrează împreună pentru a produce sunete 3D.
Dacă aveți orice feedback sau orice alte întrebări, vă rugăm să postați un comentariu de mai jos.
În următorul tutorial, sunetele Web Audio și 3D: Implementare, vom lua toate cele de mai sus (și mai mult) și îl vom împacheta într-un API simplificat. Principalul obiectiv al tutorialului următor va fi jocurile 3D, dar API-ul va fi suficient de generic pentru a fi utilizat în diverse aplicații interactive imersive.