Web Sound and 3D Soundscapes implementazione

In questo tutorial avvolgeremo Web Audio in una semplice API che si concentra sulla riproduzione di suoni all'interno di uno spazio di coordinate 3D e può essere utilizzato per applicazioni interattive coinvolgenti inclusi, a titolo esemplificativo, giochi 3D.

Questo tutorial è il secondo di una serie in due parti. Se non hai letto il primo tutorial della serie, dovresti farlo prima di leggere questo tutorial perché ti introduce ai vari elementi del Web Audio che useremo qui.

Dimostrazione

Prima di iniziare, ecco una piccola dimostrazione che utilizza l'API semplificata che tratteremo in questo tutorial. I suoni (rappresentati dai quadrati bianchi) vengono posizionati in modo casuale e riprodotti in uno spazio di coordinate 3D utilizzando la funzione di trasferimento relativa alla testa (HRTF) che Web Audio fornisce per noi.

I file di origine per la dimostrazione sono allegati a questo tutorial.

Panoramica

Poiché l'API semplificata (AudioPlayer) è già stata creata per questo tutorial ed è disponibile per il download, ciò che faremo qui è dare un'occhiata all'API AudioPlayer e al codice che la alimenta.

Prima di continuare questo tutorial, leggi il precedente tutorial di questa serie se non lo hai già fatto e sei nuovo nel mondo di Web Audio.

Lettore audio

Il Lettore audio class contiene la nostra API semplificata ed è esposta su finestra oggetto a fianco delle classi standard Web Audio se, e solo se, Web Audio è supportato dal browser web. Ciò significa che dovremmo verificare l'esistenza della classe prima di tentare di usarla.

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

(Avremmo potuto provare a crearne uno nuovo Lettore audio oggetto all'interno di a prova a prendere dichiarazione, ma un semplice controllo condizionale funziona perfettamente.)

Dietro le quinte, il lettore audio crea un nuovo AudioContext oggetto e un nuovo AudioGainNode oggetto per noi, e collega il GainNode oggetto al destinazione nodo esposto dal AudioContext oggetto.

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

Quando i suoni vengono creati e riprodotti saranno collegati al m_gain nodo, questo ci permette di controllare facilmente il volume (ampiezza) di tutti i suoni.

Il lettore audio configura anche l'audio ascoltatore, esposto da m_context, quindi corrisponde al comune sistema di coordinate 3D utilizzato con WebGL. Il positivo z punti dell'asse al visore (in altre parole, indica lo schermo 2D), il positivo y l'asse punta verso l'alto e il positivo X l'asse punta a destra.

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

La posizione del ascoltatore è sempre zero; si trova al centro del sistema di coordinate audio.

Caricamento dei suoni

Prima di poter creare o riprodurre suoni, è necessario caricare i file audio; per fortuna lettore audio si prende cura di tutto il duro lavoro per noi. Espone a caricare(… ) funzione che possiamo usare per caricare i suoni e tre gestori di eventi che ci permettono di tenere traccia dell'avanzamento del carico.

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

Il set di formati audio supportati dipende dal browser. Ad esempio, Chrome e Firefox supportano OGG Vorbis ma Internet Explorer no. Tutti e tre i browser supportano l'MP3, il che è comodo, ma il problema con l'MP3 è la mancanza di loop audio continuo, il formato MP3 semplicemente non è progettato per questo. Tuttavia, OGG Vorbis è, e può riprodurre perfettamente i suoni.

Quando si chiama il caricare(… ) funzione più volte, lettore audio spingerà le richieste in una coda e le caricherà in sequenza. Quando tutti i suoni in coda sono stati caricati (e decodificati) onLoadComplete verrà chiamato il gestore dell'evento.

Dietro le quinte, lettore audio usa un singolo XMLHttpRequest oggetto di caricare i suoni. Il responseType della richiesta è impostata su "ArrayBuffer", e quando il file ha caricato il buffer dell'array viene inviato a m_context per la decodifica.

// esempio semplificato m_loader = new XMLHttpRequest () m_queue = [] function load () m_loader.open ("GET", m_queue [0]) m_loader.responseType = "arraybuffer" m_loader.onload = onLoad m_loader.send () function onLoad (event) var data = m_loader.response var status = m_loader.status m_loader.abort () // ripristina il loader if (status < 400)  m_context.decodeAudioData(data, onDecode)  

Se il caricamento e la decodifica di un file hanno successo, lettore audio caricherà il file successivo nella coda (se la coda non è vuota) o comunicaci che tutti i file sono stati caricati.

Creare suoni

Ora che abbiamo caricato alcuni file audio, possiamo creare e suonare i nostri suoni. Dobbiamo prima dirlo lettore audio per creare i suoni, e questo viene fatto usando il creare(… ) funzione esposta da lettore audio.

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

Siamo liberi di creare tutti i suoni di cui abbiamo bisogno anche se abbiamo caricato solo un singolo file audio.

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

Il percorso del file audio passato al creare(… ) la funzione dice semplicemente lettore audio quale file dovrebbe usare il suono creato. Se il file audio specificato non è stato caricato quando il file creare(… ) viene chiamata la funzione, verrà generato un errore di runtime.

Suoni

Quando abbiamo creato uno o più suoni, siamo liberi di suonare quei suoni ogni volta che ne abbiamo bisogno. Per riprodurre un suono, usiamo il nome appropriato giocare(… ) funzione esposta da lettore audio.

audioPlayer.play (SOUND1)

Per determinare se giocare a loop suono, possiamo anche passare un booleano al giocare(… ) funzione. Se il booleano è vero, il suono si interrompe continuamente finché non viene arrestato.

audioPlayer.play (audio1, vero)

Per fermare un suono, possiamo usare il Stop(… ) funzione.

audioPlayer.stop (SOUND1)

Il sta giocando(… ) funzione ci consente di sapere se un suono è attualmente in riproduzione.

if (audioPlayer.isPlaying (sound1)) ...

Dietro le quinte, il lettore audio deve fare una quantità sorprendente di lavoro per far suonare un suono, a causa della natura modulare di Web Audio. Ogni volta che è necessario suonare un suono,lettore audio deve creare nuovo AudioSourceBufferNode e PannerNode oggetti, configurarli e collegarli, quindi collegare il suono al m_gain nodo. Fortunatamente, Web Audio è altamente ottimizzato, quindi la creazione e la configurazione di nuovi nodi audio raramente causa un notevole sovraccarico.

sound.source = m_context.createBufferSource () sound.panner = m_context.createPanner () sound.source.buffer = sound.buffer sound.source.loop = loop sound.source.onended = onSoundEnded // Questo è un po 'un hack ma dobbiamo fare riferimento all'oggetto // suono nel gestore di eventi onSoundEnded, e fare cose // in questo modo è più ottimale rispetto al binding del gestore. sound.source.sound = sound sound.panner.panningModel = "HRTF" sound.panner.distanceModel = "linear" sound.panner.setPosition (sound.x, sound.y, sound.z) sound.source.connect (audio .panner) sound.panner.connect (m_gain) sound.source.start ()

La riproduzione dei suoni è ovviamente utile, ma lo scopo di lettore audio è quello di riprodurre suoni all'interno di un sistema di coordinate 3D, quindi dovremmo probabilmente impostare le posizioni del suono prima di riprodurle. lettore audio espone alcune funzioni che ci permettono di fare proprio questo.

Posizionamento dei suoni

  • Il setX (...) e getX (...) funzioni esposte da lettore audio può essere usato per impostare e ottenere la posizione di un suono lungo il sistema di coordinate X asse.
  • Il setY (...) e getY (...) le funzioni possono essere utilizzate per impostare e ottenere la posizione di un suono lungo il sistema di coordinate y asse.
  • Il setZ (...) e getZ (...) le funzioni possono essere utilizzate per impostare e ottenere la posizione di un suono lungo il sistema di coordinate z asse.
  • Infine, l'utile setPosition (...) la funzione può essere utilizzata per impostare la posizione di un suono lungo il sistema di coordinate X, y, e z assi rispettivamente.
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

Più il suono è lontano dal centro del sistema di coordinate, più silenzioso sarà il suono. A una distanza di 10000 (l'impostazione predefinita Audio Web) un suono sarà completamente silenzioso.

Volume

Possiamo controllare il volume globale (principale) dei suoni usando il setVolume (...) e getVolume (...) funzioni esposte da lettore audio.

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

Il setVolume (...) la funzione ha anche un secondo parametro che può essere usato per sfumare il volume per un periodo di tempo. Ad esempio, per sfumare il volume a zero per un periodo di due secondi, potremmo fare quanto segue:

audioPlayer.setVolume (0.0, 2.0)

La demo del tutorial sfrutta questo per sfumare gradualmente i suoni.

Dietro le quinte, il lettore audio dice semplicemente il m_gain nodo per cambiare linearmente il valore del guadagno ogni volta che è necessario modificare il volume.

var currentTime = m_context.currentTime var currentVolume = m_gain.gain.value m_gain.gain.cancelScheduledValues ​​(0.0) m_gain.gain.setValueAtTime (currentVolume, currentTime) m_gain.gain.linearRampToValueAtTime (volume, currentTime + time)

lettore audio applica un tempo minimo di dissolvenza di 0.01 secondi, per garantire che le forti variazioni di volume non causino clic o pop udibili.

Conclusione

In questo tutorial, abbiamo preso in considerazione un modo per avvolgere Web Audio in una semplice API che si concentra sulla riproduzione di suoni all'interno di uno spazio di coordinate 3D da utilizzare in (tra le altre applicazioni) giochi 3D.

A causa della natura modulare di Web Audio, i programmi che utilizzano Web Audio possono diventare complessi abbastanza rapidamente, quindi spero che questo tutorial sia stato di qualche utilità per voi. Quando capirai come funziona Web Audio e quanto sia potente, sono sicuro che ti divertirai molto.

Non dimenticare l'AudioPlayer ei file sorgente dimostrativi sono disponibili su GitHub e pronti per il download. Il codice sorgente è commentato abbastanza bene, quindi vale la pena prendersi il tempo per dargli una rapida occhiata.

Se avete commenti o domande, non esitate a postare un commento qui sotto.

risorse

  • W3C Web Audio Specification
  • MDN Web Audio Documentation