Opprette dynamisk lyd med Web Audio API

Før Web Audio API, ga HTML5 oss element. Det kan virke vanskelig å huske nå, men før element, vårt beste alternativ for lyd i en nettleser var et plugin! 

De elementet var virkelig spennende, men det hadde en ganske enestående fokus. Det var i hovedsak en videospiller uten videoen, bra for lang lyd som musikk eller podcast, men dårlig tilpasset spillkravene. Vi satte opp (eller fant løsninger for) looping problemer, samtidige lydgrenser, glitches og total mangel på tilgang til lyddataene selv.

Heldigvis har vår tålmodighet lønnet seg. Hvor i elementet kan ha manglet, leverer Web Audio API. Det gir oss enestående kontroll over lyd, og det er perfekt for alt fra spill til sofistikert lydredigering. Alt dette med en ryddig API som er veldig morsomt å bruke og godt støttet.

La oss være litt mer spesifikke: Web Audio gir deg tilgang til de rå bølgeformdataene i en lyd og lar deg manipulere, analysere, forvride eller på annen måte endre det. Det er å lyde hva lerret-APIen er å piksler. Du har dyp og for det meste uhindret tilgang til lyddataene. Det er veldig kraftig!

Denne opplæringen er den andre i en serie på Flight Arcade-bygget for å demonstrere hva som er mulig på webplattformen og i den nye Microsoft Edge-nettleseren og EdgeHTML-gjengemotoren. Interaktiv kode og eksempler for denne artikkelen finnes også på Flight Arcade / Learn.

Flight Sounds

Selv de tidligste versjonene av Flight Simulator gjorde anstrengelser for å gjenskape følelsen av fly med lyd. En av de viktigste lydene er dynamisk tonehøyde på motoren som endrer tonehøyde med gasspjeldet. Vi visste at, da vi reimagined spillet for nettet, ville en statisk motorstøy virkelig virke flatt, så den dynamiske banen på motorstøyen var en åpenbar kandidat for Web Audio.

Mindre åpenbare (men muligens mer interessant) var stemmen til vår flyinstruktør. I tidlig iterasjoner av Flight Arcade spilte vi instruktørens stemme akkurat som det hadde blitt registrert, og det hørtes ut som om det kom ut av en lydboks! Vi la merke til at vi begynte å henvise til stemmen som "fortelleren" i stedet for "instruktøren". 

På en eller annen måte brøt den uberørte lyden illusjonen av spillet. Det virket ikke riktig å ha så perfekt lyd som kommer over de støyende lydene av cockpiten. Så, i dette tilfellet, brukte vi Web Audio til å bruke noen enkle forvrengninger til stemmeinstruksjonen og øke realismen ved å lære å fly!

I avsnittene nedenfor gir jeg deg en ganske detaljert oversikt over hvordan vi brukte Web Audio API for å lage disse lydene.

Bruk av API: AudioContext og lydkilder

Det første trinnet i et hvilket som helst Web Audio-prosjekt er å opprette en AudioContext gjenstand. Enkelte nettlesere (inkludert Chrome) krever at denne API-en skal prefikses, slik at koden ser slik ut:

var AudioContext = window.AudioContext || window.webkitAudioContext; var audioCtx = ny AudioContext ();

Deretter trenger du en lyd. Du kan faktisk generere lyder fra grunnen av med Web Audio API, men for våre formål ønsket vi å laste inn en forhåndsinnspilt lydkilde. Hvis du allerede hadde en HTML element, du kan bruke det, men mange ganger vil du ikke. Tross alt, hvem trenger en element hvis du har Web Audio? Mest vanlig vil du bare laste ned lyden direkte til en buffer med en HTTP-forespørsel:

var request = ny XMLHttpRequest (); request.open ("GET", url, true); request.responseType = "arraybuffer"; var loader = dette; request.onload = function () loader.context.decodeAudioData (request.response, funksjon (buffer) if (! buffer) console.log ('feildekoding fildata:' + url); return; loader.bufferList [index] = buffer; hvis (++ loader.loadCount === loader.urlList.length) loader.onload (loader.bufferList);, funksjon (feil) console.error ('decodeAudioData error' );); ;

Nå har vi en AudioContext og noen lyddata. Neste trinn er å få disse tingene til å fungere sammen. For det trenger vi ...

AudioNodes

Omtrent alt du gjør med Web Audio skjer via en slags AudioNode, og de kommer i mange forskjellige smaker: Noen noder brukes som lydkilder, noen som lydutganger, og noen som lydprosessorer eller analysatorer. Du kan kjede dem sammen for å gjøre interessante ting.

Du kan kanskje tenke på AudioContext som et slags lydstadium. De forskjellige instrumentene, forsterkerne og høyttalerne som den inneholder, vil alle være forskjellige typer AudioNodes. Å arbeide med Web Audio API er som å plugge alle disse tingene sammen (instrumenter inn, si, effekter pedaler og pedal inn i en forsterker og deretter høyttalere, etc.).

Vel, for å gjøre noe interessant med våre nyoppkjøpte AudioContext lydkilder, må vi først innkapslere lyddataene som en kilde AudioNode.

var sourceNode = audioContext.createBufferSource ();

avspilling

Det er det. Vi har en kilde. Men før vi kan spille det, må vi koble det til en destinasjonskode. For enkelhets skyld utsetter AudioContext en standard destinasjonskode (vanligvis hodetelefoner eller høyttalere). Når det er koblet, handler det bare om å ringe start og Stoppe.

sourceNode.connect (audioContext.destination); sourceNode.start (0); sourceNode.stop ();

Det er verdt å merke seg at du bare kan ringe start() en gang på hver kildeknute. Det betyr at "pause" ikke støttes direkte. Når en kilde er stoppet, er den utløpt. Heldigvis er kilde noder billige gjenstander, designet for å bli opprettet enkelt (selve lyddataene, husk, er i en separat buffer). Så, hvis du vil gjenoppta en midlertidig lyd, kan du bare opprette en ny kildekode og ringe start() med en tidsstempel parameter. AudioContext har en intern klokke som du kan bruke til å administrere tidsstempler. 

Motorlyden

Det er det for det grunnleggende, men alt vi har gjort så langt (enkel lydavspilling) kunne ha blitt gjort med den gamle element. For Flight Arcade måtte vi gjøre noe mer dynamisk. Vi ønsket at banen skulle endres med motorens hastighet.

Det er faktisk ganske enkelt med Web Audio (og ville ha vært nesten umulig uten det)! Kildenoden har en hastighetsegenskap som påvirker avspillingshastigheten. For å øke tonehøyde øker vi bare avspillingshastigheten:

throttleSlider.onMove = funksjon (val) sourceNode.source.playbackRate.value = val; ;

Motoren lyden må også sløyfe. Det er også veldig enkelt (det er en eiendom for det også):

sourceNode.source.loop = true;

Men det er en fangst. Mange lydformater (spesielt komprimert lyd) lagrer lyddataene i faste størrelsesrammer, og oftest vil ikke lyddataene "fylle" den endelige rammen. Dette kan etterlate et lite mellomrom på slutten av lydfilen og resultere i klikk eller feil når lydfilene blir sløyfe. Standard HTML-lydelementer gir ikke noen form for kontroll over dette gapet, og det kan være en stor utfordring for nettspill som stole på loopinglyd.

Heldigvis er gapløs lydavspilling med Web Audio API veldig grei. Det er bare et spørsmål om å sette en tidsstempel for begynnelsen og slutten av looping-delen av lyden (merk at disse verdiene er i forhold til selve lydkilden og ikke AudioContext-klokken).

engineAudioSource.source.loopStart = 0.5; engineAudioSource.source.loopEnd = 1.5;

Instruktørens stemme

Hittil har alt vi har gjort vært med en kildekode (lydfilen) og en utgangskode (lyddestinasjonen vi setter tidlig, sannsynligvis høyttalere), men AudioNodes kan brukes til mye mer, inkludert lydmanipulering eller analyse. I Flight Arcade brukte vi to node typer (en ConvolverNode og WaveShaperNode) for å gjøre instruktørens stemme lyd som om den kommer gjennom en høyttaler.

konvolusjon

Fra W3C-spesifikasjonen:

Konvolusjon er en matematisk prosess som kan brukes på et lydsignal for å oppnå mange interessante, høykvalitets lineære effekter. Svært ofte brukes effekten til å simulere en akustisk plass som konserthus, katedral eller utendørs amfiteater. Den kan også brukes til komplekse filtereffekter, som en dimmet lyd som kommer fra et skap, lyd under vann, lyd som kommer gjennom en telefon eller spiller gjennom et høyttalerskap. Denne teknikken er svært vanlig brukt i større film og musikkproduksjon og anses å være ekstremt allsidig og av høy kvalitet.

Konvolusjon kombinerer i utgangspunktet to lyder: en lyd som skal behandles (instruktørens stemme) og en lyd som kalles en impulsrespons. Impulsresponsen er faktisk en lydfil, men det er egentlig bare nyttig for denne typen convolution-prosess. Du kan tenke på det som et lydfilter av forskjellige slag, designet for å produsere en bestemt effekt når det er forbundet med en annen lyd. Resultatet er vanligvis langt mer realistisk enn enkel matematisk manipulering av lyden.

For å bruke det, oppretter vi en konvolverknut, laster lyden som inneholder impulsresponsen, og kobler deretter knutepunktene.

// opprett konvolveren var convolverNode = audioContext.createConvolver (); // antar at vi allerede har lastet ned telefonlyden til en buffer-convolver.buffer = telephponeBuffer; // koble nodene sourceNode.connect (convolverNode); convolverNode.connect (audioContext.destination);

Bølgeforming

For å øke forvrengningen brukte vi også en WaveShaper-node. Denne typen node lar deg bruke matematisk forvrengning til lydsignalet for å oppnå noen virkelig dramatiske effekter. Forvrengningen er definert som en kurvefunksjon. Disse funksjonene kan kreve litt komplisert matte. For eksemplet nedenfor lånte vi en god en fra våre venner på MDN.

// lage waveshaper var waveShaper = audioContext.createWaveShaper (); // vår forvrengningskurvefunksjon funksjon makeDistortionCurve (mengde) var k = typeof mengde === 'tall'? mengde: 50, n_samples = 44100, kurve = ny Float32Array (n_samples), deg = Math.PI / 180, i = 0, x; for (; < n_samples; ++i )  x = i * 2 / n_samples - 1; curve[i] = ( 3 + k ) * x * 20 * deg / (Math.PI + k * Math.abs(x));  return curve;  // connect the nodes sourceNode.connect(convolver); convolver.connectwaveShaper); waveShaper.connect(audioContext.destination); // vary the amount of distortion with the slider distortionSlider.onMove = function(val) waveShaper.curve = makeDistortionCurve(val); ;

Legg merke til den sterke forskjellen mellom den opprinnelige bølgeformen og bølgeformen med WaveShaper anvendt på den.

Eksemplet ovenfor er en dramatisk fremstilling av hvor mye du kan gjøre med Web Audio API. Ikke bare gjør vi noen ganske dramatiske endringer i lyden rett fra nettleseren, men vi analyserer også bølgeformen og gjør det til et lerretelement! Web Audio API er utrolig kraftig og allsidig og, ærlig, mye moro!

Flere hands-on med JavaScript

Microsoft har en mengde gratis læring på mange JavaScript-temaer med åpen kildekode, og vi har et oppdrag å skape mye mer med Microsoft Edge. Her er noen å sjekke ut:

  • Microsoft Edge Web Summit 2015 (en komplett serie av hva du kan forvente med den nye nettleseren, nye webplattformfunksjoner og gjestens høyttalere fra samfunnet)
  • Best of // BUILD / og Windows 10 (inkludert den nye JavaScript-motoren for nettsteder og apper)
  • Forbedre JavaScript uten å bryte på nettet (Christian Heilmanns siste nybegynnelse)
  • Hosted Web Apps og Web Platform Innovations (et dypt dykk på emner som manifold.JS)
  • Praktiske ytelsestips for å gjøre HTML / JavaScript raskere (en syvdelte serie fra lydhør design til uformelle spill til ytelsesoptimalisering)
  • Den moderne webplattformen Jump Start (grunnleggende for HTML, CSS og JavaScript)

Og noen gratis verktøy for å komme i gang: Visual Studio Code, Azure Trial og testverktøy for kryss-leser-alt tilgjengelig for Mac, Linux eller Windows.

Denne artikkelen er en del av web dev-teknologiserien fra Microsoft. Vi er glade for å dele Microsoft Edge og den nye EdgeHTML rendering motor med deg. Få gratis virtuelle maskiner eller test eksternt på Mac, IOS, Android eller Windows-enheten @ http://dev.modern.ie/.