Introduction
Lors de la dernière séance vous avez pris contact avec la librairie Web Audio de HTML5, et vous avez été invités à vous inspirer d'une application, heu, pardon, une preuve de concept, d'un lecteur audio multipistes. Ce code est très mal écrit, en vrac, et à été codé en deux soirs.
Quelques explications à propos de trucs qui ont pu vous paraitre bizarres:
- Mesurer le temps courant. Il n'existe pas de propriété "current time" sur une chanson, d'ailleurs il n'y a pas de type correspondant à une chanson, dans Web Audio ! Vous bénéficiez néanmoins d'une propriété
currentTime
dans l'audio context, qui vous donne un temps précis au milliardième de seconde. A vous de le mesurer régulièrement et de sommer les deltas! Pour cela utilisez une boucle qui s'exécute très rapidement, soixante fois par seconde, avec requestAnimationFrame (cf dans le MOOC HTML5 la Week4 du MOOC partie 1 ou la Week 2 sur les jeux dans la MOOC partie 2).
- Les échantillons sonores possèdent une propriété
duration
qui permet de connaitre la durée totale d'un échantillon. Avec les morceaux de musique fournis, tous ont la même durée. Ca permet de connaitre la durée totale d'une chanson.
- Pour faire pause/resume, il faut arrêter la lecture. Et un arrêt par un appel à stop() sur un noeud correspondant à un éhantillon source, détruit le noeud!
Il faut donc, pour pauser un morceau, arrêter la chanson, conserver le temps courant, reconstruire le graphe (au moins recréer les noeuds sources, pas la peine de recréer les autres noeuds) et appeler start(0)
sur chaque noeud source de chaque piste. Dans la FAQ Web Audio il est expliqué que cette manoeuvre a l'air compliquée mais l'API est optimisée pour cette pattern.
Travail à faire pendant cette session
Nous vous proposons de continuer à implémenter votre lecteur, mais en pensant déja à refactorer votre code.
Déjà, on peut isoler des éléments dans ce logiciel :
- On a une chanson, composée de pistes, la chanson a des propriétés (nom, liste des pistes, le temps courant, son volume, des booléens pour donner son état : en pause, etc.). La chanson a des méthodes : play(), stop(), pause(), loadDecodedBuffers(), buildGraph(), etc... Faites donc une belle fonction constructeur Song() dans un fichier song.js
- On a des pistes qui elles aussi peuvent être vues comme des objets : nom, url, l'échantillon décodé correspondant à la piste, son image (qui va devenir facultative dans les prochains TPs, on dessinera directement le sample sans avoir besoin de l'image), son volume, son état (muté, en mode solo, etc.). Idem, créez une fonction constructeur Track() que vous mettrez dans track.js
- On essaiera de penser à isoler aussi la partie "interface graphique et controleur". Par exemple l'écouteur du bouton play appellera une méthode
play()
dans un code controleur Web, qui va changer l'état de certains éléments de l'interface (par exemple, enabler les boutons pause et stop), puis appelera la méthode song.play()
de l'objet corerspondant à une chanson. Ainsi, on isole la partie GUI de la partie métier. Ne jamais mettre d'écouteurs dans des fonction constructeur, conseil d'ami! Sinon ce sera la guerre du this
! - Etc.
Vous pourrez également commencer à consulter les ressources suivantes qui pourront vous être utilises:
- waveformDrawer.js : un exemple de code source qui dessine la forme d'onde d'un échantillon (en vert dans l'exemple donné), dans un canvas HTML5.
- ecrire un analyseur de spectre sonore qui danse en musique, il y a des leçons sur cela dans le MOOC partie 2, semaine 1
- etc.
Vous pouvez aller tester une version élaborée d'un lecteur multipistes pour vous aider
- Lecteur multipistes écrit par M.Buffa et Amine Halili: http://mainline.i3s.unice.fr, lien vers les sources et la documentation dans l'onglet help du logiciel.
- Au final dans le projet on voudrait un logiciel comme celui ci mais avec un traitement du son par piste bien plus complet (stéréo, égalizeur, compresseur, gain, etc), on voudrait plus une table de mixage qu'un lecteur multi-pistes.