Interpolation

Mise en place

Le premier objectif de ce TP est d'utiliser l'interpolation pour animer plusieurs propriétés d'un objet avec des tweens. Le second est de créer un petit instrument utilisable sur smartphone, avec plusieurs doigts simultanément.

Notre instrument sera composé de cinq tranches verticales colorées. Chaque tranche jouera une note tant qu'un doigt reste posé dessus. Un cercle apparaîtra à l'endroit du contact et son rayon oscillera pendant le maintien. Au relâchement, le son s'arrêtera progressivement et le cercle grandira en disparaissant.

Setup HTML CSS

Le HTML et le CSS sont fournis : téléchargez la page de départ et ajoutez-y votre programme JavaScript.

Les cinq touches sont des éléments HTML colorés. Le canvas, transparent et placé au-dessus, servira à afficher les cercles et à recevoir les interactions.

API WebAudio

Afin de simplifier l'utilisation de la Web Audio API, nous allons utiliser WebAudio TinySynth. Cette bibliothèque génère les sons et gère leur attaque et leur extinction. Les tweens de notre programme serviront aux animations visuelles.

Chargez la bibliothèque depuis le CDN, avant le script de votre programme principal :

<script src="https://g200kg.github.io/webaudio-tinysynth/webaudio-tinysynth.js"></script>

Créez une seule instance du synthétiseur dans votre programme :

const synth = new WebAudioTinySynth({ quality: 1, useReverb: 1 });
const audio = synth.getAudioContext();
synth.setMasterVol(0.35);
synth.setProgram(0, 89);

Le programme 89 correspond à l'instrument Pad 2 (warm). Le premier paramètre de setProgram désigne le canal MIDI : nous utiliserons le canal 0 pour tout le TP.

Pour jouer une note, utilisez synth.noteOn(0, midi, 90), où midi est son numéro MIDI. La valeur 90 est la vélocité de la note, qui contrôle son intensité sonore ; nous la garderons constante. Pour relâcher cette note, appelez synth.noteOff(0, midi). TinySynth se charge de son extinction progressive.

Avant de lancer la note dans l'écouteur du contact, appelez audio.resume(). Le navigateur peut en effet suspendre le contexte audio jusqu'à un geste de l'utilisateur.

Commencez par tester une seule note, par exemple le Do de numéro MIDI 60, en la lançant au contact et en la relâchant lorsque le doigt se retire.

Interpolation des paramètres audio

L'interpolation sert aussi à faire évoluer un son. La Web Audio API permet de programmer des transitions sur ses paramètres, par exemple le gain (qui contrôle le volume) ou la fréquence. Une variation progressive du gain permet d'adoucir le début et la fin d'une note et d'éviter les clics liés aux changements brusques.

À titre d'exemple, voici comment programmer une montée linéaire du gain de 0 à 0.3 en un dixième de seconde :

const gain = audio.createGain();
const now = audio.currentTime;
gain.gain.setValueAtTime(0, now);
gain.gain.linearRampToValueAtTime(0.3, now + 0.1);

Le principe ressemble à celui d'un tween : une valeur évolue au cours d'une durée. Ici, le moteur audio calcule cette évolution indépendamment de la boucle d'animation, avec des temps exprimés en secondes. La documentation AudioParam présente les différentes transitions disponibles.

TinySynth utilise ces mécanismes pour gérer les enveloppes sonores. Vous n'avez donc pas à ajouter ce code à votre instrument : la bibliothèque s'en charge, tandis que votre classe Tweens animera les cercles.

Gamme pentatonique

Une gamme pentatonique contient cinq notes par octave. Nous utiliserons Do, Ré, Mi, Sol, La, de gauche à droite. Leurs numéros MIDI sont respectivement 60, 62, 64, 67 et 69.

Représentez ces notes dans votre programme. Chaque tranche doit permettre de jouer la note correspondante.

Utilisez les événements pointerdown et pointerup. Les Pointer Events permettent de gérer les contacts tactiles et la souris avec les mêmes écouteurs.

Le canvas occupant tout le viewport depuis son origine, vous pouvez utiliser directement les coordonnées event.clientX et event.clientY. Comme il y a cinq tranches de même largeur, il est aisé de déterminer quelle note correspond à la position du contact.

Gestion multi touch

Votre instrument doit permettre de maintenir plusieurs notes simultanément et de les relâcher indépendamment. Chaque contact possède un identifiant, accessible avec event.pointerId : utilisez-le pour retrouver la note à arrêter au relâchement.

Prévoyez une structure pour mémoriser les contacts en cours. Une Map peut être pratique. Le support Gestion des pointeurs présente un exemple de suivi de plusieurs contacts. Limitez chaque tranche à un seul contact actif : les contacts supplémentaires sur une tranche déjà occupée doivent être ignorés.

Feedback visuel

Reprenez votre classe Circle du premier TP et ajoutez un paramètre pour l'opacité.

Dans le contexte 2D du canvas, la propriété globalAlpha permet de définir l'opacité des dessins. Sa valeur va de 0 (transparent) à 1 (opaque) et s'applique aux dessins suivants. Consultez la documentation pour l'utiliser dans votre méthode de dessin.

Chaque contact doit faire apparaître un cercle à sa position. Prévoyez un mécanisme pour stocker les cercles et retrouver celui associé au doigt qui se relève : il faudra ensuite pouvoir le supprimer.

Reprenez votre boucle d'animation pour afficher les cercles.

Les bandes HTML restent visibles derrière le canvas, sans avoir besoin de les redessiner dans votre programme.

Animation

Utilisez la classe Tweens.js fournie pour gérer les animations, comme vu en cours. Intégrez sa mise à jour à votre boucle d'animation.

Pulsation pendant le maintien

Animez le rayon du cercle pour le faire pulser tant que le doigt reste posé. Les options loop et yoyo pourront vous être utiles.

Choisissez librement les rayons, la durée et l'easing. Expérimentez pour obtenir une pulsation qui vous plaît.

Relâchement

Lorsque le doigt se relève, arrêtez la note et la pulsation. Faites ensuite grandir le cercle tout en le rendant progressivement transparent. La transition doit démarrer depuis son état actuel pour éviter une rupture visuelle.

Le cercle doit être supprimé une fois sa disparition terminée. Le callback onComplete de la classe Tweens pourra vous être utile. Choisissez librement les durées et les easings de cette animation.

Comparez plusieurs easings pour la pulsation et l'agrandissement au relâchement. Observez comment le ressenti change sans modifier les valeurs de départ et d'arrivée.

Optionnel : ajoutez un second cercle en contour qui se propage au relâchement, ou faites varier la couleur des cercles avec un tween. Vous pouvez aussi explorer les autres instruments avec setProgram(0, programme), en consultant la démo de TinySynth.