Web Audio og 3D Soundscapes Introduksjon

I denne opplæringen vil vi ta en nærmere titt på de grunnleggende Web Audio-elementene som brukes til å konstruere 3D lydbilder for immersive interaktive applikasjoner, inkludert, men ikke begrenset til, 3D-spill.

Web Audio API og terminologien den bruker kan noen ganger være forvirrende, men denne opplæringen tar sikte på å fjerne kompleksiteten og gi en enklere forklaring på Web Audio-elementene og hvordan de samarbeider for å danne et 3D-lydbilde.

Demonstrasjon

Denne demonstrasjonen inneholder tre lyder som roterer rundt a lytteren, Lyttens retning er indikert med pilen. Hvis du tenker deg å se på et spilltegn (lytteren), kan de roterende lydene enkelt representere venner eller fiender som sirkler karakteren.

Demonstrasjonskilden og ressursene er vedlagt denne opplæringen.

AudioContext

De AudioContext grensesnittet er hjertet og sjelen til Web Audio, den gir de funksjonene som kreves for å lage ulike Web Audio-elementer, samt gi en måte å sende all lyden til maskinvare og videre til noens høyttalere eller hodetelefoner.

var audioContext = null hvis (window.AudioContext! == undefined) audioContext = new AudioContext ()

Det er viktig å sørge for at AudioContext Grensesnittet er tilgjengelig fordi Web Audio fortsatt er ganske nytt, og det kan ikke være tilgjengelig i noen nettlesere.

I tillegg til å gi de funksjonene som kreves for å opprette ulike Web Audio-elementer, vil AudioContext grensesnittet har to viktige egenskaper; mål og lytteren som begge er skrivebeskyttet. De mål eiendom kan betraktes som en forbindelse til lydmaskinvare, det er der all den genererte lyden til slutt vil ende opp. De lytteren eiendom (vi vil se nærmere på dette senere) representerer ting som hører på all lyden, f.eks. et tegn, eller mer presist et kamera, i et spill.

buffere

De AudioBuffer og AudioBufferSourceNode grensesnitt tillater oss å spille av lyd. AudioBuffer objekter inneholder de rå lydene (lydprøver) som er tweaked, knust og knust når de gjør veien gjennom Web Audio før de når noens høyttalere eller hodetelefoner. AudioBufferSourceNode Objekter brukes til å starte og stoppe lyden som finnes i AudioBuffer objekter.

Den vanlige måten å laste lyd til en AudioBuffer objektet er å bruke a XMLHttpRequest objekt med sin responseType satt til arraybuffer. Når lydfilen er lastet, sendes arraybufferen deretter til AudioContext objekt for dekoding, og hvis dekoding er vellykket, vil vi bli forsynt med en AudioBuffer gjenstand.

var loader = ny XMLHttpRequest () loader.open ("GET", "massiv eksplosjon.ogg") loader.responseType = "arraybuffer" loader.onload = nårLaddet loader.send () funksjon whenLoaded (event) var data = loader .response if (data === null) // Det oppsto et problem med å laste filen. return // Dekode dataene. audioContext.decodeAudioData (data, whenDecoded) funksjon whenDecoded (audioBuffer) // "audioBuffer" er et AudioBuffer-objekt. 

De decodeAudioData () funksjonen har også en tredje parameter som aksepterer en tilbakeringing, at tilbakeringingen kalles når den lastede lydfilen ikke kan dekodes.

dekodeAudioData (data, nårDekodet, nårFailed)

Ikke alle nettlesere støtter de samme lydformatene, et godt bord med støttede formater finner du her, så du vil kanskje bruke den andre tilbakeringingen til nedfall til et alternativt lydformat hvis nødvendig. For eksempel støtter Internet Explorer ikke OGG Vorbis, men det støtter MP3. Det eneste virkelige problemet med MP3 er at det ikke tillater sømløst loopet lyd som OGG Vorbis gjør.

Når du har en AudioBuffer objekt tilgjengelig du kan spille det med en AudioBufferSourceNode gjenstand.

var kilde = audioContext.createBufferSource () // Fest et AudioBuffer-objekt. source.buffer = audioBuffer // Koble "kilde" -objektet til "destinasjons" -objektet. source.connect (audioContext.destination) // Eventuelt, fortell "kilde" for å sløyfe lyden kontinuerlig. source.loop = false // Start lyden. source.start ()

Det er viktig å huske AudioBufferSourceNode Objekter er single-shot lydspillere, med andre ord kan du bare bruke start() fungere en gang. Du må opprette en AudioBufferSourceNode objekt og koble den (direkte eller indirekte) til mål objekt utsatt av AudioContext objekt når du vil spille av lyd fra en AudioBuffer gjenstand.

Du kan gjøre livet litt enklere ved å lage en liten verktøyfunksjon som lager, kobler til og starter en AudioBufferSourceNode objekt for deg.

(audioBuffer01, audioContext) -spille (audioBuffer02, audioContext) -spille (audioBuffer02, audioContext) -spille (audioBuffer02, audioContext) -spille (audioBuffer02, audioContext) -spille (audioBuffer02, audioContext) -spille (audioBuffer02, audioContext) , audioContext)

Når en AudioBufferSourceCode objektet er ferdig med å spille, og hvis du ikke har noen referanser til objektet hvor som helst (for eksempel du ikke har dem lagret i en matrise), kobler Web Audio automatisk objektet til deg. Dette er ekstremt praktisk når du bare trenger å brann-og-glem kort lydeffekter mv.

Hvis du bestemmer deg for å sløyfe lyden, bruker du AudioBufferSourceNode sløyfe eiendom, må du ha en referanse til AudioBufferSourceNode objekt et sted slik du kan Stoppe() lydspillet.

source.stop ()

Så på dette punktet bruker vi buffere til å spille av lyd, men lyden blir spilt direkte uten at panning eller spatialisering blir brukt på den. Dette er hvor PannerNode objekter kommer inn i spill.

  • W3C AudioBuffer spesifikasjon.
  • W3C AudioBufferSourceNode spesifikasjon.

panners

PannerNode Objekter gir oss mulighet til å plassere lyd i 3D-rom, innenfor et kartesisk koordinatsystem. Det er her hvor det meste av 3D-magien skjer.

EN PannerNode objektet har ganske mange egenskaper som tillater oss å finjustere lydens oppførsel, men for denne opplæringen er vi kun interessert i to av dem; maxDistance og panningModel. De maxDistance Eiendommen er avstanden fra lytteren på hvilket tidspunkt vil lydvolumet være null. Dette er en vilkårlig verdi og vil bare ha betydning i søknaden din, men den er som standard 10000. Den panningModel forteller Web Audio hvordan du behandler lyden som går gjennom en PannerNode gjenstand. For 3D lydbilder vil du sannsynligvis ønske å sette verdien til HRTF (hovedrelatert overføringsfunksjon).

For å angi posisjonen til en AudioBufferSourceNode vi bruker setPosition () funksjon utsatt av a PannerNode gjenstand.

var panner = audioContext.createPanner () panner.panningModel = "HRTF" // Sett 3D-posisjonen (x, y, z). panner.setPosition (1, 2, 3) // Koble "kilde" -objektet til "panner" -objektet. source.connect (panner) // Koble "panner" -objektet til "destinasjon" -objektet. panner.connect (audioContext.destination) // Start lyden. source.start ()

For å gjøre ting litt klarere, la oss oppdatere verktøyfunksjonen vi opprettet tidligere.

Funksjonsspill (audioBuffer, x, y, z, audioContext) var kilde = audioContext.createSourceBuffer () source.buffer = audioBuffer var panner = audioContext.createPanner () panner.panningModel = "HRTF" panner.setPosisjon (x, y, z) source.connect (panner) panner.connect (audioContext.destination) source.start () avspilling (audioBuffer01, 1, 2, 3, audioContext) avspilling (audioBuffer02, 4, 5, 6, audioContext) avspilling (audioBuffer03, 7, 8, 9, audioContext)

På dette punktet spiller vi lyd og plasserer det i 3D-plass, men det er et viktig element vi må se på; lydlytteren.

  • W3C PannerNode spesifikasjon.

Lydlytteren

Hver AudioContext objektet avslører a lytteren objekt som representerer posisjon og orientering av ting det lytter til lyden. Vanligvis den ting ville være et virtuelt kamera som er festet til et spillkarakterhodet, støtfangeren til en bil, halen på et fly, eller noe annet som gir mening til seeren fra deres perspektiv.

De lytteren objektet har a setPosition () funksjon og a setOrientation () funksjon. De setPosition () funksjonen plasserer lytteren et sted innenfor 3D-plassen, og setOrientation () roterer lytteren (forestill deg et panorering av kameraet og vippe).

De setPosition () Funksjonen fungerer på akkurat samme måte som PannerNode setPosition () funksjon og aksepterer tre koordinater.

audioContext.listener.setPosisjon (x, y, z)

De setOrientation () funksjonen er litt mer kompleks, den aksepterer to enhetvektorer. Den første vektoren representerer lytterens rotasjon (retningen kameraet peker på), og den andre vektoren representerer lytterens opp retning (det peker ut av toppen av kameraet).

audioContext.listener.setOrientation (x1, y1, z1, x2, y2, z2)

Hvis du bare trenger å rotere lytteren rundt en akse, er vektorberegningene relativt enkle. For eksempel, hvis du bruker det samme koordinatsystemet som WebGL bruker hvor positivt x peker til høyre for skjermen, positiv y peker til toppen av skjermen, og positiv z peker ut av skjermen, så kan du rotere lytteren rundt y akse (panorere kameraet) med en cos () funksjonsanrop og en synd() funksjonsanrop.

// Lytterens posisjon (kan være noe). var x = 50 var y = 100 var z = 0 audioContext.listener.setPosisjon (x, y, z) // Beregn rotasjonsvektoren. // rad = rotasjon, i radianer var rad = 0.10 var v1 = Math.cos (rad) // x var v2 = 0 // y var v3 = Math.sin (rad) // z // Den "opp" vektoren var v4 = 0 // x var v5 = 1 // y var v6 = 0 // z audioContext.listener.setOrientation (v1, v2, v3, v4, v5, v6)

Demonstrasjonen for denne opplæringen (kildekoden er vedlagt) gjør en lignende ting og roterer PannerNode objekter rundt en enkelt akse.

  • W3C AudioListener spesifikasjon.

Konklusjon

I denne opplæringen tok vi en titt på de grunnleggende Web Audio-elementene som brukes til å konstruere 3D-lydbilder for immersive interaktive applikasjoner, inkludert, men ikke begrenset til, 3D-spill. Forhåpentligvis har denne opplæringen vært nyttig for deg og har gitt nok informasjon for at du skal kunne forstå hvordan lydbuffere, pannere og lyttere jobber sammen for å produsere 3D-lydbilder.

Hvis du har tilbakemelding eller spørsmål, vær så snill å poste en kommentar nedenfor.

ressurser

  • W3C Web Audio Specification
  • MDN Web Audio Documentation
  • 3D (Euklidiske) vektorer

Neste trinn: Implementering

I neste opplæring, Web Audio og 3D Soundscapes: Implementering, vil vi ta alle de ovennevnte (og mer) og pakke det inn i en forenklet API. Hovedfokuset i neste opplæring vil være 3D-spill, men API-en vil være generisk nok til bruk i ulike immersive interaktive applikasjoner.