Du son dans vos pages web avec SoundManager 2 !

Du son dans vos pages web avec SoundManager 2 !

Mis à jour le jeudi 31 octobre 2013

Vous avez peut-être entendu dire qu'il était difficile de mettre du son dans les pages web. En combinant Javascript et les balises <object> ... ça devient vite compliqué.
Alors beaucoup se rabattent sur Flash.

Mais voilà ! SoundManager 2 est une bibliothèque Javascript qui, utilisant Flash, permet de lire des sons très facilement en Javascript ! :)

Dans ce mini-tuto, vous allez donc découvrir les possibilités offertes par SoundManager 2.

La base pour bien démarrer

Installation de SoundManager 2

Bon, la première étape pour utiliser SoundManager2, c'est de le télécharger ! :)
Rendez-vous donc sur la page de téléchargement du site officiel et cliquez sur le bouton Download pour récupérer la toute dernière version.

Première étape une fois téléchargé, dézippez le fichier !
Ouvrez ensuite le dossier qui contient normalement un certain nombre de choses :

  • Un dossier "demo"

  • Un dossier "doc"

  • Un dossier "script"

  • Un dossier "src"

  • Un dossier "swf"

  • Un fichier "index.html"

  • Et enfin un fichier "license.txt"

(Remarquez en passant le dossier "doc", qui contient la documentation de SoundManager 2 hors-ligne.)

Ici, les dossiers qui nous intéressent sont les dossiers "script", "src" et "swf". Vous pouvez par exemple les déplacer dans un dossier qui servira de dossier test pour ce mini-tuto.

Voilà, c'est tout ce qu'il y a besoin de faire pour utiliser SoundManager 2 ! :) On va pouvoir, sans plus attendre, passer à la pratique. :pirate:

Initialisation

Ca y est, on y est ! On va pouvoir mettre du son dans nos pages web !

Mais pour que la bibliothèque fonctionne bien, il faut l'initialiser. Voici comment ça marche.

Prenons un fichier XHTML de base :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Premiers pas avec SoundManager 2</title>


</head>
<body>


</body>
</html>

La première étape consiste à inclure le script principal de SoundManager.

<script type="text/javascript" src="script/soundmanager2.js"></script>

Et en dessous, on va mettre ceci :

<script type="text/javascript">
soundManager.url = 'swf/';
</script>

Cette première ligne sert à définir l'emplacement du répertoire "swf" dont on a parlé précédemment. Mettez donc l'emplacement qu'il a chez vous.

Ceci peut suffire pour démarrer, mais on va quand même ajouter une deuxième ligne, pour contrôler les éventuelles erreurs :

<script type="text/javascript">
soundManager.url = 'swf/';
soundManager.debugMode = true;
</script>

Voilà. :p On peut commencer pour de bon.

Premiers sons

Lire un son (de façon simple et directe...)

Voici donc notre page actuelle :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Mes premiers pas avec SoundManager 2</title>
<script type="text/javascript" src="script/soundmanager2.js"></script>
<script type="text/javascript">
soundManager.url = 'swf/';
soundManager.debugMode = true;
</script>
</head>
<body>

</body>
</html>

Bon, je ne vous fais pas attendre plus longtemps : pour lire un son, il suffit d'écrire ça :

soundManager.play('premier_son','musique/son.mp3');

Le premier paramètre sera l'id du son créé. Mettez ce que vous voulez.
Le deuxième paramètre, c'est le lien relatif vers le son. Tout simplement.

Mais attendez ! Pour que ça marche, il faut attendre que SoundManager soit chargé. On met donc :

soundManager.onload = function() {
	soundManager.play("premier_son","musique/son.mp3");
}

Notre code complet est :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Mes premiers pas avec SoundManager 2</title>
<script type="text/javascript" src="script/soundmanager2.js"></script>
<script type="text/javascript">
soundManager.url = 'swf/';
soundManager.debugMode = true;
soundManager.onload = function() {
	soundManager.play("premier_son","musique/son.mp3");
}
</script>
</head>
<body>
</body>
</html>

Tester le code

Si vous ouvrez maintenant votre page dans un navigateur (avec le plugin Flash version 8 minimum), le son devrait démarrer.
En local, il arrive que Flash pose problème : allez sur le site de Flash et ajoutez le dossier actuel à la liste des dossiers de confiance.

Maintenant ça doit marcher. Sinon, c'est que vous avez fait une faute de frappe quelque part. ^^

"Ca marche, mais c'est quoi ce texte moche qui remplit ma page ?"

Vous vous souvenez de la ligne de debugMode ?

soundManager.debugMode = true;

Et bien voilà, ce texte nous dira tout ce qu'il se passe. Pratique pour détecter les erreurs. (D'ailleurs celle de Flash était normalement signalée.)

Il vous dérange ce texte ? Pour l'afficher de manière un peu plus jolie et un peu moins encombrante, ajoutez ce code CSS :

#soundmanager-debug {
 position:fixed;
 _position:absolute; /* IE <7 */
 bottom:1em;
 right:1em;
 width:40em;
 height:30em;
 overflow:auto;
 border:1px solid #ccc;
 padding:1em;
 margin:1em;
 font-family:monaco,"VT-100",terminal,"lucida console",courier,system;
 font-size:x-small;
 background:#f6f6f6;
 opacity:0.9;
 color:#333;
}
#soundmanager-debug code {
 font-size:1.1em;
 *font-size:1em;
}
#soundmanager-debug div {
 margin-top:0.5em;
}

Et voilà la "boîte de Debug" ! :) (Remarquez le petit bouton "-" en bas à droite, qui permet de masquer la boîte si nécessaire.)

Et puisqu'elle affiche les erreurs, jetez-y un coup d'oeil approfondi. Que voyez-vous ?

Citation

"premier_son" is an invalid sound ID.

Cette erreur apparaît parce que le son a été lancé de la manière la plus simple qui soit... mais pas la plus correcte. (Et le debug, il n'a pas trop aimé... >_ )

Lire un son (dans les règles de l'Art)

Pour faire bien, il faut d'abord créer le son. Et seulement ensuite, le démarrer.
Pour ça on utilisera :

soundManager.createSound(Obj);

Cette méthode permet en plus d'ajouter pas mal de fonctions à notre lecture de son. On verra ça un peu plus tard, mais retenez une chose : faire comme ça, c'est mieux ! :)

Donc, voici ce qu'il faut écrire pour faire... la même chose qu'avant :

soundManager.onload = function() {
	soundManager.createSound(
	{
		id : "premier_son",
		url : "musique/son.mp3" // Attention pas de virgule ici !
	});
	soundManager.play("premier_son");
}

Remarquez que l'erreur du debug a disparu ! :)
Vous voulez mieux ? Encore mieux ? Voici la façon parfaite de créer un son avec SoundManager : on va utiliser l'objet SMSound retourné par la méthode createSound()...

var premier_son; // On le déclare avant, histoire qu'il soit une variable globale.
soundManager.onload = function() {
	premier_son = soundManager.createSound(
	{
		id : "premier_son",
		url : "musique/son.mp3" // Attention pas de virgule ici !
	});
	premier_son.play();
}

Voilà pour la lecture d'un son. Je vous mets le code complet actuel (j'ai mis le CSS de la "boîte du Debug" dans un fichier externe pour ne pas encombrer le code) :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Mes premiers pas avec SoundManager 2</title>
<link rel="stylesheet" type="text/css" href="debug.css" />
<script type="text/javascript" src="script/soundmanager2.js"></script>
<script type="text/javascript">
soundManager.url = 'swf/';
soundManager.debugMode = true;
var premier_son;
soundManager.onload = function() {
	premier_son = soundManager.createSound(
	{
		id : "premier_son",
		url : "musique/son.mp3" // Attention pas de virgule ici !
	});
	premier_son.play();
}

</script>
</head>
<body>
</body>
</html>

Tester le code

Et on va maintenant pouvoir s'attaquer aux nombreuses fonctionnalités supplémentaires offertes par SoundManager. :soleil:

L'objet SMSound en détail

Méthodes

Voilà, vous savez lancer un son. Mais ne nous arrêtons en si bon chemin.

L'objet SMSound, que nous avons créé précédemment, vous réserve encore quelques surprises.

play() et stop()

Et oui ! Les méthodes, vous en avez déjà utilisé une : la méthode play(). Dans le même ordre d'idée, il existe bien entendu la méthode stop().

pause(), resume() et togglePause()

Voici trois méthodes qui nous permettent facilement de mettre en pause et de relancer le son. La troisième méthode réunit les deux premières en stoppant le son s'il était en lecture et en le relançant s'il était en pause.

On peut donc facilement imaginer un code qui offrirait la possibilité de lire un son, avec en plus l'option de le mettre en pause.

Le code HTML, très simple, peut se composer de trois boutons :

<button onclick="premier_son.play();">Lire</button>
<button onclick="premier_son.pause();">Pause</button>
<button onclick="premier_son.resume();">Reprise</button>

Tester le code

(Pour offrir la possibilité de démarrer le son, il faut bien sûr supprimer la ligne premier_son.play() du code Javascript.)

mute() et unmute()

Ces deux propriétés vont permettre de couper le son (mode "muet") et de le réactiver. De même que précédemment, on peut créer des boutons offrant cette possibilité à l'utilisateur.

<button onclick="premier_son.play();">Lire</button>
<button onclick="premier_son.mute();">Passer en mode "muet"</button>
<button onclick="premier_son.unmute();">Sortir du mode "muet"</button>

Tester le code

setVolume(integer), setPan(integer) et setPosition(integer)

Nous avons ici trois propriétés permettant de modifier respectivement le volume, la balance (gauche/droite) et la position du son. Elles prennent chacune en paramètre un "integer", c'est-à-dire un nombre entier.

  • setVolume : prend en paramètre un entier entre 0 et 100.

  • setPan : prend en paramètre un entier entre -100 (son à gauche) et 100 (son à droite).

  • setPosition : prend en paramètre un entier indiquant à combien de millisecondes du début le son doit être lu.

Voyons maintenant les événements, qui nous seront très utiles par la suite.

Evénements

Les événements de l'objet SMSound vont pouvoir être placés à la création de l'objet.

onload()

L'événement onload() se produit dès que le son a fini de charger. Pratique pour tenir l'utilisateur au courant du chargement.

On pourrait par exemple mettre un petit message dans le code HTML :

<span id="loading">Chargement en cours...</span>

Et dans le javascript, lors de la création du son, on aurait ceci :

premier_son = soundManager.createSound(
	{
		id : "premier_son",
		url : "musique/son.mp3",
		onload : function() {
			document.getElementById("loading").innerHTML = "Chargement terminé !";
		} // Attention pas de virgule ici !
	});
	premier_son.play();

Tester le code

onplay(), onstop(), onpause() et onresume()

Ces événements vont avec les méthodes que nous avons vu juste avant. Je ne pense pas avoir besoin de les détailler plus. On les utilise de la même manière que onload().

onbeforefinish(), onjustbeforefinish(), onfinish() et onbeforefinishcomplete()

On a là quatre événements assez similaires, qui auront lieu vers la fin de la lecture du son.

  • onbeforefinish : a lieu environ 5000 millisecondes (= 5 secondes) avant la fin de la lecture.

  • onjustbeforefinish : a lieu environ 200 millisecondes (= 0.2 seconde) avant la fin de la lecture.

  • onfinish : a lieu à la fin de la lecture.

  • onbeforefinishcomplete : a lieu encore après onfinish(), juste avant que les données du son ne soient réinitialisées.

On peut rapidement trouver une utilité à ces événements. Par exemple pour répéter le même son indéfiniment.

premier_son = soundManager.createSound(
	{
		id : "premier_son",
		url : "musique/son.mp3",
		onfinish : function() {
			this.play();
		} // Attention pas de virgule ici !
	});
	premier_son.play();

Tester le code

onid3()

L'événement onid3() se produit dès que les tags ID3 du son sont lus. On pourra alors les afficher en utilisant la propriété id3 : je détaillerai ça plus loin.

whileloading(), whileplaying()

Ces deux événements vont nous être utiles par la suite. Ils se produisent respectivement pendant le chargement et la lecture du son. On s'en servira par exemple pour afficher l'avancement du son.

Voilà pour les événements. Il se peut que certains soient encore un peu confus ; j'essaierai d'en utiliser le plus possible dans les exemples qui suivent.

Propriétés

Les propriétés nous donnent des informations sur l'objet son créé.

sID

sID fait tout simplement référence à l'id du son créé. Testez par vous-même en ajoutant cette ligne à la fin de votre javascript actuel :

alert(premier_son.sID);

Alors ? On retrouve normalement l'id du son qui est ... "premier_son". Bah oui, on a donné le même nom à la variable SMSound et à son id.
Si vous restez sceptiques, modifiez l'id du son, et réessayez ! :)

url

Pas besoin de m'étendre longtemps sur cette propriété. Vous avez déjà deviné à quoi elle sert. La ligne suivante affichera donc l'url du fichier son.

alert(premier_son.url);

volume

Ici aussi le nom de la propriété est explicite. Il est possible de régler le volume du son. Comme le montre le code ci-dessous, le volume par défaut est 100 (le maximum).

alert(premier_son.volume);

Vous pouvez modifier cette propriété lors de la création du son :

var premier_son = soundManager.createSound(
	{
		id : "premier_son",
		url : "musique/son.mp3",
		volume : 50 // Attention pas de virgule ici !
	});

loaded

Cette propriété est un booléen, indiquant si le son est chargé ou pas.

paused

Avec la propriété paused, on peut tester si le son a été mis en pause ou pas.

readyState

Cette valeur bien pratique donne la situation actuelle du chargement du son. Elle peut prendre quatre valeurs :

  • 0 : Non initialisé

  • 1 : Chargement en cours

  • 2 : Echec/Erreur

  • 3 : Chargé/Succès

duration et durationEstimate

Là, on arrive dans les propriétés réellement intéressantes ! La propriété duration indique la durée du son. Cette durée n'est précise qu'une fois le son entièrement chargé.
durationEstimate, comme son nom l'indique, tente d'estimer la durée du son avant la fin du chargement.
Dans les deux cas, cette durée est donnée en millisecondes.

Entraînez-vous en faisant afficher simplement la durée du son. Utilisez par exemple durationEstimate pendant l'événement whileloading(), puis duration lors de l'événement onload().

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Mes premiers pas avec SoundManager 2</title>
<link rel="stylesheet" type="text/css" href="debug.css" />
<script type="text/javascript" src="script/soundmanager2.js"></script>
<script type="text/javascript">
soundManager.url = 'swf/';
soundManager.debugMode = true;
var premier_son;
soundManager.onload = function() {
	premier_son = soundManager.createSound(
	{
		id : "premier_son",
		url : "musique/piste01.mp3",
		whileloading : function() {
			var nb_sec_est = parseInt(this.durationEstimate/1000,10);
			document.getElementById("duree").innerHTML = "Durée estimée : "+parseInt(nb_sec_est/60,10)+":"+nb_sec_est%60;
		},
		onload : function() {
			var nb_secondes = parseInt(this.duration/1000,10);
			document.getElementById("duree").innerHTML = "Durée : "+parseInt(nb_secondes/60,10)+":"+nb_secondes%60;
		} // Attention pas de virgule ici !
	});
	premier_son.play();
}
</script>
</head>
<body>
<span id="duree">Durée : </span>
</body>
</html>

Tester le code

position

La propriété position indique l'avancement du son en millisecondes. On va donc pouvoir l'utiliser, à l'aide de la méthode whileplaying(), pour créer un compteur d'avancement (comme sur tout lecteur qui se respecte) :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Mes premiers pas avec SoundManager 2</title>
<link rel="stylesheet" type="text/css" href="debug.css" />
<script type="text/javascript" src="script/soundmanager2.js"></script>
<script type="text/javascript">
soundManager.url = 'swf/';
soundManager.debugMode = true;
var premier_son;
soundManager.onload = function() {
	premier_son = soundManager.createSound(
	{
		id : "premier_son",
		url : "musique/son.mp3",
		whileplaying : function() {
			var duree_secondes = parseInt(this.duration/1000,10);
			var duree = parseInt(duree_secondes/60,10)+":"+duree_secondes%60;
			var position_secondes = parseInt(this.position/1000,10);
			var position = parseInt(position_secondes/60,10)+":"+position_secondes%60;
			document.getElementById("cpt").innerHTML = position+" / "+duree;
		} // Attention pas de virgule ici !
	});
	premier_son.play();
}
</script>
</head>
<body>
<span id="cpt"></span>
</body>
</html>

Tester le code

Plutôt facile non ?

id3

Je l'avais mentionnée précédemment, la propriété id3 va permettre de récupérer les tags ID3 du son joué. On pourra alors afficher le titre de la chanson, l'artiste, etc.

Pour accéder aux différents tags, on utilisera cette syntaxe : id3["le_tag"]
Les tags ne sont accessibles que s'ils sont définis. Mieux vaut peut-être vérifier leur existence avant de les afficher... sinon, on risque de voir apparaître des "undefined" un peu partout. ^^
Chaque tag a deux écritures.
Les tags possibles sont :

Tag ID3

Correspondance

id3["COMM"]
id3["comment"]

Commentaire

id3["TALB"]
id3["album"]

Titre de l'album

id3["TCON"]
id3["genre"]

Genre

id3["TIT2"]
id3["songname"]

Titre de la piste

id3["TPE1"]
id3["artist"]

Artiste

id3["TRCK"]
id3["track"]

Numéro de la piste

id3["TYER"]
id3["year"]

Année

Voici un exemple de code qui affiche l'artiste et la chanson :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Mes premiers pas avec SoundManager 2</title>
<link rel="stylesheet" type="text/css" href="debug.css" />
<script type="text/javascript" src="script/soundmanager2.js"></script>
<script type="text/javascript">
soundManager.url = 'swf/';
soundManager.debugMode = true;
var premier_son;
soundManager.onload = function() {
	premier_son = soundManager.createSound(
	{
		id : "premier_son",
		url : "musique/son.mp3",
		onid3 : function() {
			chaine_tag = "";
			if(this.id3["artist"]) {
				chaine_tag += "<strong>Artiste :</strong> "+this.id3["artist"]+"<br />";
			}
			if(this.id3["songname"]) {
				chaine_tag += "<strong>Titre :</strong> "+this.id3["songname"]+"<br />";
			}
			document.getElementById("tag").innerHTML = chaine_tag;
		} // Attention pas de virgule ici !
	});
	premier_son.play();
}
</script>
</head>
<body>
<div id="tag"></div>
</body>
</html>

Tester le code

bytesLoaded et bytesTotal

Voici les deux dernières propriétés que je présenterai. Elles permettent d'obtenir le nombre d'octets chargés et le nombre d'octets total.
Pourquoi ne pas faire alors un petit compteur de chargement ? On utilisera cette fois la méthode whileloading().

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Mes premiers pas avec SoundManager 2</title>
<link rel="stylesheet" type="text/css" href="debug.css" />
<script type="text/javascript" src="script/soundmanager2.js"></script>
<script type="text/javascript">
soundManager.url = 'swf/';
soundManager.debugMode = true;
var premier_son;
soundManager.onload = function() {
	premier_son = soundManager.createSound(
	{
		id : "premier_son",
		url : "musique/son.mp3",
		whileloading : function() {
			taille_totale = parseInt(this.bytesTotal/1048576*100)/100+" Mo";
			taille_chargee = parseInt(this.bytesLoaded/1048576*100)/100+" Mo";
			document.getElementById("cpt").innerHTML = taille_chargee+" / "+taille_totale;
		} // Attention pas de virgule ici !
	});
	premier_son.play();
}
</script>
</head>
<body>
<span id="cpt"></span>
</body>
</html>

Tester le code

Voili voilou. On a fait le tour des principales possibilités offertes par les objets SMSound. Bien entendu, je n'ai pas parlé de tout (ça prendrait bien trop de temps). Le reste est présenté dans la documentation de SoundManager 2 (sur le site de SoundManager ou dans le dossier doc que vous avez téléchargé au début).

On approche de la fin de ce tuto. Je vais à présent vous parler assez brièvement des méthodes, événements et propriétés de l'objet soundManager.

SoundManager en détail

Dès le début de ce tuto, vous avez utilisé l'objet soundManager avec son événement onload() et sa méthode createSound().

On va voir qu'il en existe d'autres qui valent la peine d'être présentées. ^^

Méthodes

createSound(objet) et destroySound(sID)

La méthode createSound(), c'est la seule que nous ayons utilisé jusqu'à présent. Elle permet de créer un objet SMSound et d'y indiquer un certain nombre de paramètres et d'actions événementielles.
La méthode destroySound(), comme son nom l'indique permet de détruire un objet SMSound créé. Le son sera stoppé, puis détruit. destroySound() prend en paramètre l'id (propriété sID) du son à détruire.

Exemple où l'on détruit le son à la fin de sa lecture :

premier_son = soundManager.createSound(
	{
		id : "premier_son",
		url : "musique/son.mp3",
		onfinish : function() {
			soundManager.destroySound(this.sID);
		} // Attention pas de virgule ici !
	});
	premier_son.play();

getSoundById(sID) et sounds{}

Ces méthodes sont bien pratiques pour retrouver un son par son sID (par exemple si on ne l'a pas enregistré dans un variable...).

  • getSoundById : prend en paramètre l'id du son recherché. La méthode renvoie null en cas d'erreur.

  • sounds : c'est un objet littéral.

soundManager.getSoundById("premier_son");
// est équivalent à
soundManager.sounds.premier_son;
// ou encore à
soundManager.sounds["premier_son"];

load(sID) et unload(sID)

Nous avons deux méthodes qui permettent de charger en mémoire un son ou le décharger. Depuis le début de ce mini-tuto, on faisait directement play() et le son se chargeait alors.
Ca peut être utile de précharger les sons pour éviter un temps de latence entre play() et le début de la lecture.

play(sID), stop(sID), pause(sID), resume(sID) et togglePause(sID)

Ces méthodes ont la même utilité que celles du même nom de l'objet SMSound. Ce sont ici des méthodes de soundManager, qui prennent donc en paramètre l'id du son.

mute(sID) et unmute(sID)

On retrouve ici aussi des méthodes que possédait l'objet SMSound. Comme précédemment, ces méthodes prennent en paramètre l'id du son.
Si aucun id n'est spécifié, tous les sons seront affectés.

pauseAll(), resumeAll() et stopAll()

Ces trois méthodes propres à soundManager permettent respectivement de mettre en pause, relancer et stopper tous les sons d'un coup. Elles ne prennent pas de paramètres.

setVolume(sID, integer), setPan(sID, integer) et setPosition(sID, integer)

Encore une fois des méthodes que l'on a déjà rencontrées. Elles prennent en paramètres l'id du son et un entier. (Voir les méthodes de l'objet SMSound pour plus de précision sur les valeurs possibles)

canPlayURL(url)

Nous avons ici une méthode qui permet de vérifier si une url est lisible par soundManager. La vérification est basée principalement sur l'extension, et non pas sur l'existence du fichier.
Cette méthode prend en paramètre l'url d'un son.

loadFromXML(url)

Cette méthode particulière permet de charger des sons directement à partir d'un fichier XML. Voici un exemple de fichier XML :

<items baseHref="musique/"> // baseHref est optionnel. C'est le dossier de référence des sons.
                            // Si vous l'utilisez, n'oubliez pas le slash final
     <sound id="premier_son" href="son1.mp3" />
     <sound id="deuxieme_son" href="son2.mp3" />
</items>

Ce système peut s'avérer pratique pour automatiser le chargement de sons. Pour utiliser le fichier XML créé, c'est très simple :

soundManager.onload = function() {
	soundManager.loadFromXML("nom_du_fichier.xml");
}

Evénements

soundManager ne possède que deux événements.

onload()

On l'utilise depuis le début de ce mini-tuto, afin de détecter le chargement de soundManager. Je ne reviendrai pas dessus, je pense que vous avez compris son utilité.

onerror()

L'événement onerror() permet de détecter si soundManager ne se charge pas correctement.

Voilà, cette fois, je crois qu'on a réellement fait le tour des principales possibilités de gestion des sons offertes par soundManager 2.
Sachez néanmoins que soundManager 2 propose quelques autres options, notamment les spectres sonores, les waveform et même la lecture de formats vidéo. N'hésitez pas à consulter le site officiel et bien entendu la documentation de soundManager 2. :)

TP : Un lecteur audio

TP : Un lecteur audio

Pour terminer ce mini-tuto, je vous propose un petit TP.

L'objectif de ce TP est de réaliser un petit lecteur audio avec une playlist prédéfinie de quelques titres.
Il faudra donc créer un compteur d'avancement, ainsi que les boutons habituels d'un lecteur (play, pause, stop, suivant, précédent, etc.).

Je vous laisse vous débrouiller avec tout ce qu'on a vu. N'hésitez pas à aller consulter les exemples donnés sur le site pour vous aider.

Voici ma version du lecteur.

Et les codes qui vont avec :

Fichier player.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Lecteur audio avec Sound Manager 2</title>
<link rel="stylesheet" type="text/css" href="debug.css" />
<link rel="stylesheet" type="text/css" href="player.css" />
<script type="text/javascript" src="script/soundmanager2.js"></script>
<script type="text/javascript" src="player.js"></script>
</script>
</head>
<body>

<div id="lecteur">
<div id="controls">
<!-- BOUTONS D'INTERACTION -->

<img id="play" src="images/play.png" alt="play" title="Lecture" onclick="bouton_play();" />
<img id="stop" src="images/stop.png" alt="stop" title="Stop" onclick="bouton_stop();" />
<img id="previous" src="images/previous.png" alt="précédent" title="Titre précédent" onclick="bouton_previous();" />
<!-- Pour rewind et forward, on utilise onmouseup pour cesser de répéter en boucle la fonction -->
<img id="rewind" src="images/rewind.png" alt="retour arrière" title="Retour arrière" onmousedown="bouton_rewind();" onmouseup="if(timer) { clearTimeout(timer); }" />
<img id="forward" src="images/forward.png" alt="avance rapide" title="Avance rapide" onmousedown="bouton_forward();" onmouseup="if(timer) { clearTimeout(timer); }" />
<img id="next" src="images/next.png" alt="suivant" title="Titre suivant" onclick="bouton_next();" />
<img id="loop" src="images/none.png" alt="répéter" title="Répéter le titre" onclick="bouton_loop();" />
<img id="mute" src="images/sound.png" alt="muet" title="Muet" onclick="bouton_toggleMute();" style="margin-left:20px;" />
<!-- De même ici pour volume moins et volume plus -->
<img id="moins" src="images/moins.png" alt="moins" title="Volume -" onmousedown="bouton_volume(false);" onmouseup="if(timer) { clearTimeout(timer); }" />
<!-- Pour la barre de volume, on détecte le clic avec onmousedown, et le déplacement avec onmousemove. -->
<img id="volume" src="images/volume.png" alt="volume" title="100" onmousedown="clic('vol', event);" onmousemove="move('vol', event);" />
<img id="plus" src="images/plus.png" alt="plus" title="Volume +" onmousedown="bouton_volume(true);" onmouseup="if(timer) { clearTimeout(timer); }" />
</div>
<div id="avancement">
<!-- Pour la barre d'avancement, on détecte le clic avec onmousedown, et le déplacement avec onmousemove. -->

<div id="test"><img id="barre" src="images/barre.png" onmousedown="clic('barre', event);" onmousemove="move('barre', event);" /><br />
<img id="chargement" src="images/none.png" />
<span id="load" style="float:right;">0 / 0</span>
<span id="cpt">0:00 / 0:00</span>
</div>
</div>
</div>
<div id="tagid3"></div>

<!-- PLAYLIST -->
<!-- C'est la playlist qui définit les sons à créer. Il suffit donc de la modifier pour changer de playlist ! :) -->
<div id="playlist">
<a href="musique/piste01.mp3">Piste 01</a><br />

<a href="musique/piste02.mp3">Piste 02</a><br />
<a href="musique/piste03.mp3">Piste 03</a><br />
<a href="musique/piste04.mp3">Piste 04</a><br />
<a href="musique/piste05.mp3">Piste 05</a><br />
<a href="musique/piste06.mp3">Piste 06</a><br />
<a href="musique/piste07.mp3">Piste 07</a><br />
<a href="musique/piste08.mp3">Piste 08</a><br />
<a href="musique/piste09.mp3">Piste 09</a><br />
<a href="musique/piste10.mp3">Piste 10</a><br />

<a href="musique/piste11.mp3">Piste 11</a>
</div>
</body>
</html>

Fichier player.css

#lecteur {
width:450px;
float:left;
margin-bottom:20px;
}
#controls {
text-align:center;
}
#controls img {
cursor:pointer;
}
#controls #loop {
width:32px;
height:32px;
background-image:url("images/repeat.png");
background-position:50% 50%;
}
#controls #volume {
cursor:pointer;
background-image:url("images/arr_volume.png");
background-position:0 50%;
}
#avancement {
text-align:center;
position:relative;
}
#test {
text-align:left;
width:420px;
margin:auto;
}
#chargement {
width:420px;
height:10px;
background-image:url("images/arr_charg2.png");
background-position:-420px 50%;
background-repeat:no-repeat;
margin-top:10px;"
}
#barre {
position:absolute;
margin-top:29px;
background-image:url("images/arr_barre2.png");
background-position:-420px 50%;
background-repeat:no-repeat;
height:12px;
width:420px;
cursor:pointer;
}
#tagid3 {
float:left;
margin-left:20px;
padding:5px;
width:225px;
}
#playlist {
width:350px;
float:left;
padding-left:20px;
border:1px solid black;
line-height:30px;
}
#playlist a {
color:black;
text-decoration:none;
}
#playlist a:hover {
text-decoration:underline;
}
#playlist img {
border:0;
vertical-align:middle;
}

Fichier player.js

soundManager.url = 'swf/'; // Chemin du dossier "swf"
soundManager.debugMode = false; // DebugMode désactivé
soundManager.waitForWindowLoad = true; // Attendre le chargement de la page pour charger soundManager
soundManager.onerror = function() { // En cas d'erreur ...
	alert("SoundManager 2 a rencontré une erreur."); // ... on affiche un message à l'utilisateur
}
var playlist = []; // Tableau pour contenir la playlist
var current = 0; // Indice du son courant (dans playlist[]);
var act_vol = soundManager.defaultOptions.volume; // Variable pour le volume actuel, initialisée au volume par défaut de SoundManager
var loop = "none"; // Mode de répétition séléctionné
var next = false; // Indicateurs booléens du clic sur Previous et Next
var prev = false;

soundManager.onload = function() { // On attend tout d'abord le chargement...
	var barre = document.getElementById("barre"); // On récupère la barre d'avancement,
	var chargement = document.getElementById("chargement"); // la barre de chargement,
	var cpt = document.getElementById("cpt"); // le compteur de secondes,
	var vol = document.getElementById("volume"); // la barre de volume,
	var list = document.getElementById("playlist").getElementsByTagName("a"); // et les différents liens <a> de la playlist (les titres).
	for (var i=0;i<list.length;i++) { // On parcourt la liste
		list[i].rel = i; // On renseigne un indice arbitraire dans l'attribut rel de chaque <a>
		var sp = document.createElement("span"); // On crée un élément span
		list[i].parentNode.insertBefore(sp,list[i]); // qu'on ajoute avant chaque <a> de la liste
		list[i].onclick = function() { // On crée une fonction onclick sur chaque lien :
			soundManager.stopAll(); // On stoppe tous les sons
			current = this.rel; // On mets en "son courant" celui cliqué (grâce à l'indice du rel)
			lire_current(); // On appelle la fonction lire_current() pour lancer la lecture
			return false; // On renvoie faux pour empêcher les liens de rediriger (ils ne servent qu'aux sans-js)
		};
		(function(titre) {
			playlist[i] = soundManager.createSound( // On crée un son pour chaque lien de la playlist
			{
				id : "piste"+i, // Id arbitraire : piste0, piste1, etc.
				url : list[i].href, // L'url de chaque son est le href de chaque lien
				whileloading : function() { // Pendant le chargement :
					chargement.style.backgroundPosition = -420+(this.bytesLoaded/this.bytesTotal * 420)+"px 50%"; // On ajuste le background de la barre de chargement
					if(this.bytesTotal>= 1048576) { // Si taille totale >= 1 Mo
						taille_totale = parseInt(this.bytesTotal/1048576*100)/100+" Mo";
						taille_chargee = parseInt(this.bytesLoaded/1048576*100)/100+" Mo";
					} else if(this.bytesTotal >= 1024) { // Sinon si taille totale >= 1 Ko
						taille_totale = parseInt(this.bytesTotal/1024*100)/100+" Ko";
						taille_chargee = parseInt(this.bytesLoaded/1024*100)/100+" Ko";
					} else { // Sinon si < 1 Ko
						taille_totale = this.bytesTotal+" o";
						taille_chargee = this.bytesLoaded+" o";
					}
					document.getElementById("load").innerHTML = taille_chargee+" / "+taille_totale; // On insère dans le span de chargement.
				},
				whileplaying : function() { // Pendant la lecture :
					barre.style.backgroundPosition = -420+(this.position/this.duration * 420)+"px 50%"; // On ajuste le background de la barre d'avancement
					act_sec = parseInt(this.position/1000 % 60,10); // Calcul du nb de secondes écoulées
					if(act_sec<10) { act_sec = "0"+act_sec; } // (Ajout d'un 0 si <10)
					act_min = parseInt(this.position/1000/60,10); // Calcul du nb de minutes écoulées
					tot_sec = parseInt(this.duration/1000 % 60,10); // Calcul du nb de secondes total du son
					if(tot_sec<10) { tot_sec = "0"+tot_sec; } // (Ajout d'un 0 si <10)
					tot_min = parseInt(this.duration/1000/60,10); // Calcul du nb de minutes total du son
					cpt.innerHTML = act_min+":"+act_sec+" / "+tot_min+":"+tot_sec; // On affiche ces valeurs dans le div "cpt"
					vol.style.backgroundPosition = -100+act_vol+"px 50%"; // On ajuste le background de la barre de son, en fonction du son actuel
					vol.title = "Volume : "+act_vol; // On ajuste aussi le title du volume
				},
				onresume : // Quand on enlève "pause" :
					function() {
					titre.previousSibling.innerHTML = "<img src='images/played.png' alt='lecture' /> "; // On insère une image "play" dans le span créé
					},
				onplay : // Quand on fait "play" :
					function() {
					titre.previousSibling.innerHTML = "<img src='images/played.png' alt='lecture' /> "; // On insère une image "play" dans le span créé
					},
				onstop : // Quand on fait "stop" :
					function() {
					playlist[current].unload(); // On "décharge" le son, histoire de pas occuper trop de mémoire
					titre.previousSibling.innerHTML = ""; // On enlève l'image du span
					},
				onfinish : // A la fin d'un son
					function() {
					playlist[current].unload(); // On "décharge" le son, histoire de pas occuper trop de mémoire
					titre.previousSibling.innerHTML = ""; // On enlève l'image du span
					if(!prev && !next) { // Si la fin du son n'est pas due à un clic sur Previous ou Next, on regarde le mode de répétition choisi
						if(loop=="one") { // Si "Répéter un titre"
							lire_current(); // On (re)lance la lecture du son actuel
						} else if(loop=="all") { // Si "Répéter la playlist"
							bouton_next(); // On appelle bouton_next() (On passe au titre suivante)
						} else { // Si "Ne pas répéter"
							if(current<playlist.length-1) { // Si on n'est pas encore à la fin de la playlist
								bouton_next(); // On passe au titre suivant
							} else { // Sinon
								current = 0; // On réinitialise juste le titre courant.
							}
						}
					}
					},
				onpause : // Quand on fait "pause"
					function() {
					titre.previousSibling.innerHTML = "<img src='images/paused.png' alt='pause' /> "; // On insère une image "pause" dans le span créé
					},
				onid3 : function() { // A l'arrivée des Tag ID3
					var chaine_tag = ""; // On crée une chaîne vide
					if(this.id3["artist"]) { // Et on y insère les différents tag en vérifiant leur existence au préalable.
						chaine_tag += "<strong>Artiste : </strong>"+this.id3["artist"]+"<br />";
					}
					if(this.id3["album"]) {
						chaine_tag += "<strong>Album : </strong>"+this.id3["album"]+"<br />";
					}
					if(this.id3["songname"]) {
						chaine_tag += "<strong>Titre : </strong>"+this.id3["songname"];
					}
					document.getElementById("tagid3").innerHTML = chaine_tag; // On insère finalement la chaîne dans la page
				}
			});
		})(list[i]);
	}
}

function lire_current() { // Fonction de démarrage de la lecture
	soundManager.stopAll(); // On stoppe tous les sons (pour éviter le multi-shot
	playlist[current].setPosition(0); // On réinitialise la position du son courant
	playlist[current].setVolume(act_vol); // On applique le volume actuel
	playlist[current].play(); // On lance la lecture
	document.getElementById("play").src = "images/pause.png"; // Le bouton "play" devient "pause"
	document.getElementById("play").title = "Pause"; // On change le title également.
}
function bouton_play() { // Appui sur le bouton "play"
	if(playlist[current].playState) { // On teste si un titre est en cours de lecture/pause. Si oui
		b_play = document.getElementById("play"); // On récupère le bouton "play"
		if(playlist[current].paused) { // S'il est en pause
			playlist[current].resume(); // On le relance
			b_play.src = "images/pause.png"; // Le bouton "play" devient "pause"
			b_play.title = "Pause"; // On change le title également
		} else { // S'il est en lecture
			playlist[current].pause(); // On le met en pause
			b_play.src = "images/play.png"; // Le bouton "pause" devient "play"
			b_play.title = "Lecture"; // On change le title également
		}
	} else { // Si le son est stoppé
		lire_current(); // On démarre la lecture
	}
}
function bouton_stop() { // Appui sur le bouton "stop"
	playlist[current].stop(); // On stoppe le son courant
	document.getElementById("play").src = "images/play.png"; // Le bouton "pause" devient "play"
	document.getElementById("play").title = "Lecture"; // On change le title également
	document.getElementById("barre").style.backgroundPosition = "-420px 50%"; // On réinitialise la position du background de la barre d'avancement
	document.getElementById("cpt").innerHTML = "0:00 / 0:00"; // On réinitialise le compteur de temps
	document.getElementById("chargement").style.backgroundPosition = "-420px 50%"; // On réinitialise la position du background de la barre de chargement
	document.getElementById("load").innerHTML = "0 / 0"; // On réinitialise le compteur de chargement
}
function bouton_previous() { // Appui sur le bouton "précédent"
	prev = true; // On "actionne" le booléen prev
	current--; // On recule d'un titre
	if(current<0) { current = playlist.length - 1; } // Si on a trop reculé, on prend le dernier titre
	lire_current(); // On lance la lecture
	prev = false; // On "désactionne" le booléen
}
function bouton_next() { // Appui sur le bouton "suivant"
	next = true; // On "actionne" le booléen next
	current++; // On avance d'un titre
	if(current>=playlist.length) { current = 0; } // Si on a trop avancé, on prend le premier titre
	lire_current(); // On lance la lecture
	next = false; // On "désactionne" le booléen
}
function bouton_rewind() { // Appui sur le bouton "Retour arrière"
	playlist[current].setPosition(playlist[current].position - 1000); // On recule d'une seconde
	timer = setTimeout(bouton_rewind,50); // On relance la fonction
}
function bouton_forward() { // Appui sur le bouton "Avance rapide"
	playlist[current].setPosition(playlist[current].position + 1000); // On avance d'une seconde
	timer = setTimeout(bouton_forward,50); // On relance la fonction
}
function bouton_loop() { // Appui sur le bouton "Répéter"
	var b_loop = document.getElementById("loop"); // On récupère le bouton
	if(loop=="one") { // Si il est sur "Répéter un titre"
		loop = "all"; // on passe à "Répéter la playlist"
		b_loop.src = "images/all.png"; // On change l'image du bouton et le title en fonction
		b_loop.title = "Ne pas répéter";
	} else if(loop=="all") { // S'il est sur "Répéter la playlist"
		loop = "none"; // On passe à "Ne pas répéter"
		b_loop.src = "images/none.png"; // Et on change l'image et le title
		b_loop.title = "Répéter le titre";
	} else { // Et enfin s'il est sur "Ne pas répéter"
		loop = "one"; // On passe à "Répéter un titre"
		b_loop.src = "images/one.png"; // Et on change l'image et le title
		b_loop.title = "Répéter la playlist";
	}
}
function bouton_toggleMute() { // Appui sur le bouton "Muet"
	var bouton_muet = document.getElementById("mute"); // On récupère le bouton
	if(bouton_muet.alt == "muet") { // S'il est en sonore
		soundManager.mute(); // On coupe le son
		bouton_muet.alt = "son"; // On change les attributs alt, title et src
		bouton_muet.title = "Son";
		bouton_muet.src = "images/mute.png";
	} else { // S'il est en muet
		soundManager.unmute(); // On remet le son
		bouton_muet.alt = "muet"; // On change les attributs alt, title et src
		bouton_muet.title = "Muet";
		bouton_muet.src = "images/sound.png";
	}
}
function bouton_volume(aug) { // Appui sur les boutons du volume
	if(aug) { // Si appui sur "+"
		if(act_vol<100) { // Si on peut encore augmenter
		act_vol++; // On augmente
		timer = setTimeout(bouton_volume,50,true); // Et on relance la fonction
		}
	} else { // Si appui sur "-"
		if(act_vol>0) { // Si on peut encore diminuer
		act_vol--; // On diminue
		timer = setTimeout(bouton_volume,50,false); // Et on relance la fonction
		}
	}
	playlist[current].setVolume(act_vol); // On applique le volume au titre courant
	var vol = document.getElementById("volume"); // On récupère la barre de volume
	vol.style.backgroundPosition = -100+act_vol+"px 50%"; // On ajuste son background
	vol.title = "Volume : "+act_vol; // et son title
}
var v_clic = false; // Indicateur booléen du clic sur la barre de volume
var b_clic = false; // Indicateur booléen du clic sur la barre d'avancement
var v_x; // Variable de position absolue en x de la barre de volume
var b_x; // Variable de position absolue en x de la barre d'avancement
function clic(obj, event) { // Clic sur une des deux barres
	if (event.preventDefault){ // Code pour éviter que la souris embarque les images...
	event.preventDefault();
	}
	event.returnValue = false;
	if(obj=="vol") { // Si on clique sur la barre de volume
		v_clic = true; // On active le booléen
		var vol = document.getElementById("volume"); // On récupère la barre de volume
		v_x = coord(vol); // On calcule sa position absolue en x
		act_vol = event.clientX - v_x; // Une simple soustraction donne le volume
		playlist[current].setVolume(act_vol); // On applique le volume au titre courant
		vol.style.backgroundPosition = -100+act_vol+"px 50%"; // On ajuste son background
		vol.title = "Volume : "+act_vol; // et son title
	} else { // Si on clique sur la barre d'avancement
		b_clic = true; // On active le booléen
		var barre = document.getElementById("barre"); // On récupère la barre d'avancement
		b_x = coord(barre); // On calcule sa position absolue en x
		playlist[current].setPosition(parseInt((event.clientX - b_x)/420 * playlist[current].duration,10)); // On change la position du titre en cours en fonction
	}
}
function move(obj, event) { // Cliquer-glisser sur une des deux barres
	if(obj=="vol" && v_clic) { // Si on est sur la barre de volume
		act_vol = event.clientX - v_x; // On calcul le volume choisi
		playlist[current].setVolume(act_vol); // On applique le volume au titre courant
		var vol = document.getElementById("volume"); // On récupère la barre de volume
		vol.style.backgroundPosition = -100+act_vol+"px 50%"; // On ajuste son background
		vol.title = "Volume : "+act_vol; // et son title
	} else if(obj=="barre" && b_clic) { // Si on est sur la barre d'avancement
		playlist[current].setPosition(parseInt((event.clientX - b_x)/420 * playlist[current].duration,10)); // On change la position du titre en cours en fonction
	}
}
function coord(element) { // Fonction pour calculer la position absolue en x d'un élement
	var eX = 0; // Initialisation de la valeur
	do{
		eX += element.offsetLeft; // On ajoute l'offsetLeft
		element = element.offsetParent; // On remonte à l'objet parent
	} while( element && element.style.position != 'absolute'); // Et on recommence
	return eX; // On renvoit la position absolue en x de l'élément
}
document.onmouseup = function() { // Quand on relâche le clic
	v_clic = false; // On "désactionne" les deux indicateurs de clic.
	b_clic = false;
}

Ce TP devrait vous avoir permis de réutiliser une bonne partie des connaissances acquises pendant ce tuto. J'espère que vous ne vous êtes pas trop ennuyés. :)

Voilà, c'est fini. SoundManager n'a (presque) plus de secrets pour vous.

J'aimerais faire remarquer, avant que l'on se quitte, que le son sur les pages web n'est pas toujours très apprécié de l'utilisateur. Essayez donc de ne pas être trop intrusif, et proposez une fonction "muet", au minimum.

Sur ce, amusez-vous bien, et peut-être à une prochaine fois ! ;)

déroulement d'un cours

  • 1

    Dès aujourd'hui, vous avez accès au contenu pédagogique et aux exercices du cours.

  • 2

    Vous progressez dans le cours semaine par semaine. Une partie du cours correspond à une semaine de travail de votre part.

  • !

    Les exercices doivent être réalisés en une semaine. La date limite vous sera annoncée au démarrage de chaque nouvelle partie. Les exercices sont indispensables pour obtenir votre certification.

  • 3

    À l'issue du cours, vous recevrez vos résultats par e-mail. Votre certificat de réussite vous sera également transmis si vous êtes membre Premium et que vous avez au moins 70% de bonnes réponses.

L'auteur

Exemple de certificat de réussite
Exemple de certificat de réussite