La riproduzione di audio può costituire un requisito essenziale per alcune pagine Web; ad esempio, il sito di una band non può fare a meno di una sezione in cui riprodurre le tracce musicali del gruppo, mentre i giochi online non possono essere altrettanto godibili se privi di un tema di sottofondo o, a maggior ragione, di effetti sonori.
Farebbe quindi molto comodo avere una libreria, una API, che fornisca la possibilità di riprodurre il suono su qualsiasi client e piattaforma, facendosi carico delle incompatibilità: questo è proprio l'obiettivo di SoundManager2.
Le caratteristiche in breve
Queste sono le caratteristiche principali della libreria SoundManager2 (SM2):
- funzioni base di gestione dei suoni, tra cui caricamento, riproduzione (play) di suoni e arresto (stop), ricerca (seek), silenzio (mute), pan (bilanciamento) e controllo del volume tramite JavaScript;
- supporto di eventi per intercettare il caricamento (in corso o terminato), la riproduzione (in corso o terminata) dei suoni;
- supporto dei tag ID3V1 e ID3V2 per i file MP3 (titolo, artista, genere, ecc.).
Le qualità della libreria vengono espletate a livello base tramite l'interfacciamento a un filmato Flash (versione 8) nascosto; utilizzando il filmato per Flash versione 9, è possibile accedere ad altre caratteristiche avanzate (streaming video, supporto MPEG-4, riproduzione "multishot" con effetti di sovrapposizione e coro, accesso ai dati di forme d'onda e frequenza, buffering e altro).
Le funzioni di base sono accessibili anche tramite l'interfaccia Audio() di HTML5 dove disponibile, indispensabile sui device che non supportano Flash (come Apple iPhone e iPad), con possibilità di ripiegare su Flash nel caso in cui non sia disponibile.
La libreria è gratuita e distribuita con licenza BSD.
Primi passi con SoundManager2
SoundManager2 è una libreria scritta in linguaggio JavaScript che fornisce una API unificata per la riproduzione di file audio in grado di funzionare su (quasi) qualsiasi browser, utilizzando l'oggetto Audio di HTML5 o il plugin Flash "dietro le quinte" in modo del tutto trasparente, sia allo sviluppatore sia all'utente finale.
Possiamo scaricare la libreria dalla pagina dedicata. Il pacchetto che otteniamo include tutto l'occorrente: lo script in differenti versioni (per il debug, oppure ottimizzata e compressa per l'uso in produzione), le risorse necessarie (ad esempio, le animazioni Flash sfruttate per alcune funzionalità avanzate), la documentazione completa e gli esempi del sito ufficiale per la consultazione offline.
Vediamo ora quali sono le prime mosse da compiere per iniziare a utilizzare la libreria.
Caricamento e inizializzazione della libreria
Per poter sfruttare le funzionalità di SM2, innanzitutto occorre copiare nella directory del proprio progetto i file che si trovano nelle directory /script
e /swf
, che contengono rispettivamente i file JavaScript del "core" e le animazioni Flash di supporto (.swf
).
Per importare la libreria nella propria applicazione, basta inserire il tag <script>
nella pagina, sostituendo /path/to/
con il percorso del file, in base alla sua collocazione:
<script src="/path/to/soundmanager2.js"></script>
Prima di poter utilizzare le funzioni dell'API, occorre inizializzare la libreria tramite un'apposita funzione setup()
dell'oggetto globale SoundManager:
<script>
soundManager.setup({
url: '/path/to/swf-files/',
flashVersion: 9,
preferFlash: false,
debugMode: false,
onready: function() {
var mySound = soundManager.createSound({
id: 'aSound',
url: '/path/to/an.mp3'
});
mySound.play();
},
ontimeout: function() {
// Non è stato possibile avviare SM2: mancano i file SWF? Flash è bloccato? Altri errori?
}
});
</script>
Analizziamo le proprietà principali dell'oggetto passato alla funzione per scoprirne il significato:
Opzione | Descrizione |
---|---|
url | Definisce il percorso relativo della directory che contiene i file SWF; la libreria accoda autonomamente il nome del file, in base alla configurazione scelta; è importante che il valore termini con uno slash ("/") |
flashVersion | Indica la versione di Flash del filmato da utilizzare; è possibile indicare 8 (il default) oppure 9 |
preferFlash | Se impostato a false, viene privilegiato l'uso di HTML5, dove disponibile, altrimenti la libreria avvia il filmato Flash nascosto, a cui demanda le operazioni multimediali interfacciandole con il mondo JavaScript |
debugMode | Se impostato a true, abilita l'output delle informazioni di debug nella console JavaScript; quando la libreria viene usata in ambiente di produzione, normalmente va impostato a false |
onready | Consente di definire una funzione di callback che viene richiamata quando l'inizializzazione dell'API è andara a buon fine ed è possibile iniziare a riprodurre suoni |
ontimeout | Consente di definire una funzione che viene eseguita quando è trascorso il tempo massimo consentito per inizializzare la libreria o si è verificato un errore durante questo processo |
È possibile specificare molteplici altre opzioni per tarare a proprio piacimento la libreria a seconda degli usi e dei dispositivi del proprio sito o applicazione.
Riproduzione semplice di un suono
Nel codice di esempio visto in precedenza, che mostra come inizializzare la libreria, abbiamo inserito il codice seguente per caricare un suono e riprodurlo. Andiamolo a vedere più in dettaglio:
var mySound = soundManager.createSound({
id: 'aSound',
url: '/path/to/an.mp3'
});
mySound.play();
La funzione createSound()
restituisce un oggetto di tipo SMSound attraverso il quale è possibile controllare il suono, che viene inizializzato in base ai parametri specificati; il parametro url
, che indica la locazione della risorsa, ed è obbligatorio. Il metodo play()
dell'oggetto consente di riprodurre il suono appena caricato.
Controllo avanzato del playback
L'oggetto SMSound è uno degli elementi fondamentali della libreria SM2: oltre al semplice "play" di un suono, permette di specificare una gamma estesa di opzioni che consentono di controllare ogni aspetto del processo.
Riporto qui di seguito alcuni degli attributi maggiormente utilizzati e compatibili con la maggior parte dei dispositivi:
Opzione | Descrizione |
---|---|
autoLoad | Se impostata a false , consente di inibire il caricamento iniziale del suono, posticipandolo al momento del "play" |
autoPlay | Se impostato a true , suggerisce di riprodurre il suono il prima possibile, al termine del caricamento o addirittura durante (se il flag "stream" è attivato) |
from | Consente di impostare la posizione di inizio della riproduzione; è espresso in millisecondi |
loops | Indica il numero di volte che il suono deve essere riprodotto al momento del "play"; il valore predefinito è 1 |
multiShot | Se impostato a true , sovrappone il suono a quello già udibile nel caso venga riprodotto più volte; se false , il suono udibile si arresta e riparte |
pan | Imposta il bilanciamento degli altoparlanti da sinistra (-100) a destra (+100); il valore predefinito è 0 (zero) |
stream | Consente di riprodurre un suono prima che questo sia stato caricato interamente in memoria |
to | Consente di impostare la posizione di fine della parte di suono da riprodurre; è espresso in millisecondi come "from" |
volume | Imposta il livello del volume del suono, da un minimo di 0 (zero) a un massimo di 100 |
Oltre a proprietà che possono essere valorizzate per impostare posizioni di inizio e fine, livelli e bilanciamenti, si possono definire una serie di funzioni di callback richiamate dalla libreria in momenti topici della riproduzione:
Callback | Descrizione |
---|---|
onload | Chiamata quando il caricamento del suono è terminato |
onplay | Chiamata quando ha inizio la riproduzione del suono, avviata tramite il metodo play() o in automatico |
onstop | Chiamata quando viene richiesta l'interruzione della riproduzione del suono |
onpause | Chiamata quando viene richiesta la pausa della riproduzione |
onresume | Chiamata quando il suono, in pausa, riprende la riproduzione |
onfinish | Chiamata quando la riproduzione del suono è terminata |
whileloading | Chiamata nel corso del caricamento del suono: consente di determinare quanti byte sono stati trasferiti sul totale |
whileplaying | Chiamata nel corso del playback: consente di determinare la posizione attuale della riproduzione |
Come noterete, sono presenti sia callback chiamate dalla libreria al verificarsi di determinati eventi chiave (come "onplay", "onstop", ecc.), sia callback che vengono invece invocati ripetutamente nel corso del playback (come "whileloading" e "whileplaying"): questo consente allo sviluppatore la libera scelta nella collocazione della propria logica, con la possibilità di seguire interamente la riproduzione o ricevere avvisi solo al verificarsi di determinate condizioni, ottimizzando l'efficienza della propria applicazione.
L'effettivo playback è possibile utilizzando i metodi dell'oggetto SMSound, di cui riportiamo quelli principali:
Opzione | Descrizione |
---|---|
play() | Avvia la riproduzione del suono associato all'oggetto SMSound con le opzioni già analizzate |
pause() | Mette in pausa la riproduzione del suono associato |
resume() | Riprende la riproduzione del suono associato |
mute() | Silenzia l'audio durante la riproduzione |
unmute() | Rimuove il silenziamento dell'audio attivato con il metodo mute() |
togglePause() | Commuta lo stato di pausa/ripresa della riproduzione |
toggleMute() | Commuta lo stato di silenziamento dell'audio |
setPosition() | Modifica dinamicamente la posizione corrente; è espresso in millisecondi |
setVolume() | Modifica dinamicamente il volume di uscita del suono |
setPan() | Modifica il bilanciamento sinistra-destra degli altoparlanti |
stop() | Arresta il playback del suono |
Molti dei metodi dell'oggetto SMSound restituiscono un riferimento all'istanza stessa, consentendo il "method chaining".
L'oggetto globale SoundManager implementa anch'esso metodi con lo stesso nome di quelli appena descritti, accettando come primo parametro una stringa che contiene l'identificativo (ID) del suono a cui deve essere applicato il metodo che stiamo invocando.
Alcuni esempi di utilizzo
Abbiamo già visto come riprodurre semplicemente un suono. Ora vediamo alcuni esempi di codice per capire come utilizzare la libreria per sfruttare le sue caratteristiche più avanzate.
Caricamento e riproduzione di un file con monitoraggio
soundManager.createSound({
url: 'res/music.mp3',
autoLoad: true,
autoPlay: true,
whileloading: function() {
console.log(this.id + ': caricamento ' + this.bytesLoaded + ' / ' + this.bytesTotal);
},
whileplaying: function() {
console.log(this.id + ': posizione playback ' + this.position);
}
});
Nell'esempio utilizziamo il flag autoLoad
per indicare a SM2 di caricare automaticamente il brano musicale specificato nel parametro url
. Durante il caricamento, la callback whileloading()
mostra nella console JavaScript i byte scaricati in relazione ai totali previsti. Quando il caricamento è terminato, il flag autoPlay
fa sì che il brano venga riprodotto subito. La callback whileplaying()
mostra nella console la posizione (in millisecondi) del "lettore virtuale" durante il playback.
Riproduzione di un file con posizione di inizio e fine
var spliceDemo = soundManager.createSound({
id: 'spliceSound',
url: 'res/sound.mp3'
});
spliceDemo.play({
// Posizione di inizio
from: 500,
// Posizione finale
to: 1200,
onstop: function() {
console.log('Il suono si è fermato alla posizione ' + this.position);
}
});
Nell'esempio vediamo l'uso dei parametri from
e to
per specificare rispettivamente le posizioni di inizio e fine da riprodurre, passati come parametro al metodo play()
dell'oggetto SMSound
ottenuto da createSound()
, assieme a una funzione di callback da invocare quando la riproduzione del suono si arresta.
Va precisato che la libreria usa una tecnica di "polling" per determinare se è stata raggiunta la posizione finale. Tuttavia, il timer di controllo ha una bassa precisione per garantire comunque performance ottimali di esecuzione, motivo per cui è probabile che il suono si arresti qualche decina di millisecondi dopo la fine impostata. Se è fondamentale garantire la precisione in questo tipo di operazione, è possibile abilitare il flag useHighPerformance impostandolo a true
nella chiamata al metodo soundManager.setup()
e, in aggiunta, ridurre il tempo di polling settando useFastPolling a true
.
Loop infinito di un suono
Nella chiamata al metodo play()
abbiamo a disposizione il parametro loop per specificare il numero di volte che SM2 deve ripetere il suono; se vogliamo creare un loop che ripeta il suono un numero indefinito di volte, possiamo agire come segue:
var s = soundManager.createSound({
url: 'res/effect.mp3'
});
function loopSound(sound) {
sound.play({
onfinish: function() {
loopSound(sound);
}
});
}
loopSound(s);
Nella pratica, abbiamo creato una funzione che avvia la riproduzione del suono e alla sua conclusione, intercettata tramite la callback onfinish
, invochiamo nuovamente la funzione per ripetere l'operazione.
Altri esempi, demo interattive e documentazione
Il sito di SM2 mette a disposizione una ricca serie di demo interattivi che consentono di avere un'idea delle capacità della libreria (come l'interessante Drum Machine) e anche testare le performance di esecuzione (vedi il demo Christmas Lights); uno di questi presenta numerosi esempi di codice da cui prendere spunto per acquisire dimestichezza con le funzionalità supportate; infine, di estrema utilità la documentazione in linea affiancata al codice sorgente originale corredato da commenti.
Conclusioni
Abbiamo visto come aggiungere facilmente suoni alle nostre pagine Web incorporando la libreria SM2 e utilizzando le funzioni, gli oggetti e i metodi che mette a disposizione.
Questo semplifica estremamente lo sviluppo di quei siti particolarmente votati al multimediale, evitando di dover scrivere codice specifico per gestire il playback di brani e/o effetti sonori, a maggior ragione quando ciò richiede di addentrarsi nei meandri delle particolarità e soprattutto delle incompatibilità tra diversi browser, client, dispositivi e piattaforme.
Possiamo basarci quindi su una solida e potente astrazione che ci consente di concentrarci sulla logica di business nella realizzazione di un player "fatto in casa", di un gioco, di un'app HTML5 per Windows 8 o per Chrome, di un sito dinamico o di qualsiasi altro programma che stiamo realizzando.