Prima dell'API Web Audio, HTML5 ci ha dato il elemento. Potrebbe sembrare difficile da ricordare ora, ma prima del
elemento, la nostra migliore opzione per il suono in un browser era un plugin!
Il l'elemento era davvero eccitante, ma aveva un focus piuttosto singolare. Era essenzialmente un video player senza video, buono per un audio lungo come la musica o un podcast, ma non adatto alle esigenze dei giochi. Abbiamo sopportato (o trovato soluzioni alternative) problemi di loop, limiti di suono simultanei, problemi tecnici e totale mancanza di accesso ai dati audio stessi.
Fortunatamente, la nostra pazienza ha dato i suoi frutti. Dove il potrebbe mancare un elemento, l'API Web Audio fornisce. Ci dà un controllo senza precedenti sul suono, ed è perfetto per tutto, dal gioco al montaggio audio sofisticato. Tutto questo con un'API pulita che è davvero divertente da usare e ben supportata.
Siamo un po 'più specifici: Web Audio ti dà accesso ai dati della forma d'onda grezza di un suono e ti consente di manipolarli, analizzarli, distorcere o altrimenti modificarli. È audio quello che l'API canvas è per i pixel. Hai un accesso profondo e per lo più libero ai dati audio. È davvero potente!
Questo tutorial è il secondo di una serie su Flight Arcade, creato per dimostrare ciò che è possibile sulla piattaforma web e nel nuovo motore di rendering Edge Edge e EdgeHTML. Il codice interattivo e gli esempi per questo articolo si trovano anche in Flight Arcade / Learn.
Anche le prime versioni di Flight Simulator hanno fatto sforzi per ricreare la sensazione del volo usando il suono. Uno dei suoni più importanti è il passo dinamico del motore che cambia l'intonazione con l'acceleratore. Sapevamo che, come abbiamo reimmaginato il gioco per il web, un rumore statico del motore sarebbe sembrato piatto, quindi il tono dinamico del rumore del motore era un ovvio candidato per Web Audio.
Meno ovvio (ma forse più interessante) era la voce del nostro istruttore di volo. Nelle prime iterazioni di Flight Arcade, abbiamo suonato la voce dell'istruttore proprio come era stata registrata, e sembrava come se uscisse da una cabina audio! Abbiamo notato che abbiamo iniziato a parlare della voce come "narratore" anziché "istruttore".
In qualche modo quel suono incontaminato ha spezzato l'illusione del gioco. Non sembrava giusto che un audio così perfetto arrivasse oltre i suoni rumorosi del cockpit. Quindi, in questo caso, abbiamo utilizzato Web Audio per applicare alcune semplici distorsioni alle istruzioni vocali e migliorare il realismo dell'apprendimento del volo!
Nelle sezioni seguenti, ti darò una visione abbastanza dettagliata di come abbiamo usato l'API Web Audio per creare questi suoni.
Il primo passo in qualsiasi progetto Web Audio è creare un AudioContext
oggetto. Alcuni browser (incluso Chrome) richiedono ancora questa prefisso API, quindi il codice è simile al seguente:
var AudioContext = window.AudioContext || window.webkitAudioContext; var audioCtx = new AudioContext ();
Allora hai bisogno di un suono. Puoi effettivamente generare suoni da zero con l'API Web Audio, ma per i nostri scopi volevamo caricare una sorgente audio preregistrata. Se hai già un HTML elemento, potresti usarlo, ma molte volte non lo farai. Dopo tutto, chi ha bisogno di un
elemento se hai Web Audio? Più comunemente, devi solo scaricare l'audio direttamente in un buffer con una richiesta HTTP:
var request = new XMLHttpRequest (); request.open ("GET", url, true); request.responseType = "arraybuffer"; var loader = this; request.onload = function () loader.context.decodeAudioData (request.response, function (buffer) if (! buffer) console.log ('error decoding file data:' + url); return; loader.bufferList [indice] = buffer; if (++ loader.loadCount === loader.urlList.length) loader.onload (loader.bufferList);, funzione (errore) console.error ('errore decodeAudioData', errore );); ;
Ora abbiamo un AudioContext e alcuni dati audio. Il prossimo passo è far funzionare queste cose insieme. Per questo, abbiamo bisogno ...
Quasi tutto ciò che fai con Web Audio avviene tramite una sorta di AudioNode, e sono disponibili in molti gusti diversi: alcuni nodi sono usati come sorgenti audio, alcuni come uscite audio e altri come processori audio o analizzatori. Puoi incatenarli insieme per fare cose interessanti.
Potresti pensare all'AudioContext come a una sorta di palcoscenico sonoro. I vari strumenti, amplificatori e altoparlanti che contiene sarebbero tutti diversi tipi di AudioNode. Lavorare con l'API Web Audio è come collegare tutte queste cose insieme (strumenti, ad esempio, pedali e pedale effetti in un amplificatore e poi altoparlanti, ecc.).
Bene, per fare qualcosa di interessante con le nostre sorgenti audio AudioContext appena acquisite, dobbiamo prima incapsulare i dati audio come sorgente AudioNode.
var sourceNode = audioContext.createBufferSource ();
Questo è tutto. Abbiamo una fonte. Ma prima di poterlo riprodurre, dobbiamo collegarlo a un nodo di destinazione. Per comodità, AudioContext espone un nodo di destinazione predefinito (in genere cuffie o altoparlanti). Una volta connesso, è solo questione di chiamare inizio
e Stop
.
sourceNode.connect (audioContext.destination); sourceNode.start (0); sourceNode.stop ();
Vale la pena notare che puoi solo chiamare inizio()
una volta su ciascun nodo di origine. Ciò significa che "pausa" non è direttamente supportata. Una volta che una fonte viene arrestata, è scaduta. Fortunatamente, i nodi sorgente sono oggetti economici, progettati per essere creati facilmente (i dati audio stessi, ricorda, si trovano in un buffer separato). Pertanto, se si desidera riprendere un suono sospeso, è sufficiente creare un nuovo nodo di origine e chiamare inizio()
con un parametro timestamp. AudioContext ha un orologio interno che puoi usare per gestire i timestamp.
Questo è tutto per le basi, ma tutto quello che abbiamo fatto finora (semplice riproduzione audio) avrebbe potuto essere fatto con il vecchio elemento. Per Flight Arcade, dovevamo fare qualcosa di più dinamico. Volevamo che il pitch cambiasse con la velocità del motore.
In realtà è piuttosto semplice con Web Audio (e sarebbe stato quasi impossibile senza di esso)! Il nodo sorgente ha una proprietà rate che influenza la velocità di riproduzione. Per aumentare il tono, aumentiamo la velocità di riproduzione:
throttleSlider.onMove = function (val) sourceNode.source.playbackRate.value = val; ;
Anche il suono del motore deve essere ripetuto. Anche questo è molto semplice (c'è anche una proprietà per questo):
sourceNode.source.loop = true;
Ma c'è un problema. Molti formati audio (in particolare l'audio compresso) memorizzano i dati audio in frame di dimensioni fisse e, il più delle volte, i dati audio non "riempiono" il frame finale. Questo può lasciare un piccolo spazio alla fine del file audio e causare clic o glitch quando questi file audio vengono riprodotti in loop. Gli elementi audio HTML standard non offrono alcun tipo di controllo su questa lacuna, e può essere una grande sfida per i giochi web che si basano sull'audio in loop.
Fortunatamente, la riproduzione audio senza pause con l'API Web Audio è davvero semplice. Si tratta semplicemente di impostare un timestamp per l'inizio e la fine della porzione di loop dell'audio (si noti che questi valori sono relativi alla sorgente audio stessa e non all'orologio di AudioContext).
engineAudioSource.source.loopStart = 0.5; engineAudioSource.source.loopEnd = 1.5;
Finora, tutto ciò che abbiamo fatto è stato con un nodo sorgente (il nostro file audio) e un nodo di uscita (la destinazione del suono che abbiamo impostato in anticipo, probabilmente i tuoi altoparlanti), ma gli AudioNodes possono essere usati molto di più, inclusa la manipolazione del suono o analisi. In Flight Arcade, abbiamo usato due tipi di nodi (un ConvolverNode e un WaveShaperNode) per far suonare la voce dell'istruttore come se attraversasse un altoparlante.
Dalla specifica W3C:
La convoluzione è un processo matematico che può essere applicato a un segnale audio per ottenere molti effetti lineari di alta qualità interessanti. Molto spesso, l'effetto viene utilizzato per simulare uno spazio acustico come una sala da concerto, una cattedrale o un anfiteatro all'aperto. Può anche essere usato per effetti di filtro complessi, come un suono attutito proveniente da un armadio, suono sott'acqua, suono proveniente da un telefono o riproduzione attraverso un cabinet vintage. Questa tecnica è molto comunemente utilizzata nelle principali produzioni cinematografiche e musicali ed è considerata estremamente versatile e di alta qualità.
Convolution combina fondamentalmente due suoni: un suono da elaborare (la voce dell'istruttore) e un suono chiamato risposta all'impulso. La risposta all'impulso è, infatti, un file audio, ma è davvero utile solo per questo tipo di processo di convoluzione. Si può pensare ad esso come a un filtro audio di sorta, progettato per produrre un effetto specifico quando è convoluto con un altro suono. Il risultato è in genere molto più realistico della semplice manipolazione matematica dell'audio.
Per usarlo, creiamo un nodo di convoluzione, carichiamo l'audio contenente la risposta all'impulso e quindi colleghiamo i nodi.
// crea il convolver var convolverNode = audioContext.createConvolver (); // supponiamo di aver già scaricato il suono del telefono in un buffer convolver.buffer = telephponeBuffer; // collega i nodi sourceNode.connect (convolverNode); convolverNode.connect (audioContext.destination);
Per aumentare la distorsione, abbiamo anche utilizzato un nodo WaveShaper. Questo tipo di nodo consente di applicare una distorsione matematica al segnale audio per ottenere effetti davvero drammatici. La distorsione è definita come una funzione curva. Queste funzioni possono richiedere una matematica complessa. Per l'esempio qui sotto, abbiamo preso in prestito uno buono dai nostri amici di MDN.
// crea il wavehade var waveShaper = audioContext.createWaveShaper (); // la nostra funzione di funzione curva di distorsione makeDistortionCurve (importo) var k = tipo di importo === 'numero'? amount: 50, n_samples = 44100, curve = new Float32Array (n_samples), deg = Math.PI / 180, i = 0, x; per (; i < 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); ;
Notare la netta differenza tra la forma d'onda originale e la forma d'onda con WaveShaper applicato ad essa.
L'esempio sopra è una rappresentazione drammatica di quanto si possa fare con l'API Web Audio. Non solo stiamo apportando alcune modifiche al suono drasticamente dal browser, ma stiamo anche analizzando la forma d'onda e rendendola in un elemento canvas! L'API Web Audio è incredibilmente potente e versatile e, francamente, molto divertente!
Microsoft ha un sacco di apprendimento gratuito su molti argomenti JavaScript open source, e siamo in missione per creare molto di più con Microsoft Edge. Ecco alcuni da verificare:
E alcuni strumenti gratuiti per iniziare: Visual Studio Code, Azure Trial e strumenti di test cross-browser, tutti disponibili per Mac, Linux o Windows.
Questo articolo fa parte della serie di web dev tech di Microsoft. Siamo entusiasti di condividere Microsoft Edge e il nuovo Motore di rendering EdgeHTML con te. Ottieni macchine virtuali gratuite o test in remoto sul tuo dispositivo Mac, iOS, Android o Windows @ http://dev.modern.ie/.