Introduction au Web MIDI

“Un tutoriel sur le Web MIDI? En 2016? Tu plaisante, n'Est-ce pas?"

Non! Ce n'est pas ce que tu penses! Pour ceux d'entre nous qui utilisent le Web depuis les années 1990, la phrase «Web MIDI» induit généralement des retours en arrière à une époque où les sites Web jouaient automatiquement une version bloopy de The Final Countdown pendant que vous signiez le livre d'or du webmaster. Cependant, en 2016, Web MIDI - et plus particulièrement l’API Web MIDI - a beaucoup plus de potentiel..

Normes MIDI pour l’interface numérique des instruments de musique. C'est un protocole qui permet aux instruments de musique électroniques, ordinateurs et autres appareils de se parler. Cela fonctionne en envoyant de petits messages d'un appareil à l'autre en disant, par exemple, que "la note 12 vient d'être appuyée" ou que "la note 62 n'est plus appuyée", mais en sténographie numérique..

L’API Web MIDI utilise ce protocole et vous permet de prendre un instrument compatible MIDI, tel qu’un clavier, de le connecter à votre ordinateur et d’envoyer des informations du clavier à votre navigateur..

Actuellement, l’API Web MIDI n’est prise en charge que par Chrome et Opera, mais vous pouvez suivre sa progression dans Firefox en visitant ce bogue.. 

Alors, pourquoi voudrions-nous connecter un clavier à un navigateur Web? Eh bien, peu de musiciens connaissent autant le clavier QWERTY que le clavier musical. En outre, la gamme de périphériques musicaux prenant en charge le MIDI est énorme. En connectant un périphérique d'entrée compatible MIDI à notre navigateur et en utilisant l'API Web Audio, nous pouvons créer des instruments de musique sur le Web.. 

Voulez-vous jouer du piano? Il suffit de connecter votre clavier et de visiter une page Web utilisant ces technologies pour reproduire le son d’un piano. Vous voulez un son différent? Il suffit de visiter un site différent.

J'espère que vous pourrez voir les avantages de cette API, mais comment ça marche réellement?

Accéder à un périphérique MIDI

Nous voulons d’abord vérifier si notre navigateur prend en charge l’API Web MIDI. Nous faisons cela en vérifiant si le navigator.requestMIDIAccess méthode existe. Cette méthode n'est implémentée que dans les navigateurs prenant en charge l'API..

if (navigator.requestMIDIAccess) console.log ('Le navigateur prend en charge MIDI!'); 

Maintenant que nous savons que la méthode existe, appelons-la pour demander l'accès à toute entrée MIDI fournie par le navigateur..

if (navigator.requestMIDIAccess) navigator.requestMIDIAccess () .then (succès, échec); 

navigator.requestMIDIAccess () renvoie une promesse, ce qui signifie qu’elle appellera une fonction de succès ou une fonction d’échec en fonction du résultat de la demande d’accès MIDI. Ici, nous lui avons donné le nom de deux fonctions que nous allons créer ensuite.

succès de la fonction (midi) console.log ('Got midi!', midi);  function failure () console.error ('Aucun accès à vos périphériques MIDI.')

Comme vous pouvez le constater, notre fonction success prend un paramètre MIDI sous la forme d’un objet MIDIAccess. L'objet MIDIAccess est la clé pour recevoir des données MIDI. L'objet lui-même fournit une interface à tous les périphériques MIDI que vous avez connectés. Les entrées représentent tous les périphériques MIDI que vous avez connectés à votre ordinateur. J'ai un seul clavier MIDI connecté, donc si je me connecte midi.inputs.size, il produirait "1".

Afin d’obtenir les données d’entrée de notre appareil, nous créons d’abord une variable et nous l’attribuons. midi.inputs.values ​​() ainsi.

var input = midi.inputs.values ​​();

Une chose importante à noter est que la valeur attribuée à contributions est un itérateur. Un itérateur est un objet qui sait comment accéder à ses propriétés, une par une, tout en gardant une trace de la position actuelle dans la séquence d'itérations. Il fournit un suivant() méthode pour vous permettre d’obtenir le prochain élément de la séquence. Il a aussi un terminé propriété pour nous faire savoir si nous avons itéré sur toutes les propriétés de l'objet. Cela signifie que nous pouvons écrire pour des boucles fantaisie comme ceci:

for (var input = inputs.next (); input &&! input.done; input = inputs.next ()) // chaque fois qu'un message MIDI est appelé, la fonction onMIDIMessage input.value.onmidimessage = onMIDIMessage; 

Ce que cette boucle dit, c'est:

  1. Créez une variable appelée contribution et lui assigner la prochaine entrée. Parce que nous n'avons pas encore parcouru d'intrants, cela retournera le premier de nos intrants.
  2. Si nous avons une entrée et que la valeur done de l'itérateur d'entrée n'est pas égale à true, continuez avec la boucle.
  3. Ensemble contribution à la prochaine entrée dans notre objet itérateur.

Vous remarquerez également qu'à l'intérieur de cette boucle, nous affectons une fonction à l'entrée sur la moyenne auditeur. Cette fonction sera appelée chaque fois qu'un événement MIDI est reçu de l'appareil représenté par cette entrée. Créons cette fonction:

function onMIDIMessage (message) console.log (message.data); 

Décodage des données MIDI

La partie du message MIDI qui nous intéresse est ses données; quel type d'événement MIDI a été envoyé? Quelle touche du clavier a été enfoncée? 

Si vous suivez ce didacticiel, vous constaterez que lorsque vous appuyez sur une touche de votre clavier, le navigateur enregistre quelque chose comme: [144, 61, 95] à la console. Et lorsque vous retirez votre doigt de la clé, le navigateur enregistre à nouveau quelque chose de légèrement différent, comme [128, 61, 0].

Ce tableau peut être décomposé comme tel. Le premier élément est le type d'événement MIDI. Les messages MIDI peuvent contenir un assez petit nombre d’événements, et chaque événement a un numéro correspondant. Dans notre cas, 144 cartes sur un noteOn message indiquant qu'une touche a été enfoncée, 128 étant un note off message, nous indiquant que la touche n'est plus enfoncée. Pour une liste complète des types d'événements MIDI possibles, consultez la liste des messages dans les spécifications MIDI..

La deuxième valeur du tableau représente la touche sur laquelle vous avez appuyé. Chaque note sur un clavier se voit attribuer un numéro compris entre 0 et 127. Dans l'exemple ci-dessus, j'ai appuyé sur la touche 61 qui, en utilisant cette table de correspondance, permet de voir qu'il s'agit d'un C #..

La troisième et dernière valeur du tableau représente la vélocité, essentiellement la vitesse à laquelle la touche a été frappée. Cela peut être utilisé pour imiter jouer un piano où les touches peuvent être jouées doucement ou frappées rapidement et fort.

Maintenant que nous savons quel numéro de touche est pressé ou relâché, changeons-le en quelque chose d’utile. Connectons l'API Web MIDI à l'API Web Audio. Si vous n'êtes pas familier avec l'API Web Audio, consultez ma série de tutoriels sur ce sujet.

Création d'un instrument Web

Passons notre navigateur dans un mini synthétiseur. Nous voudrons créer un oscillateur qui générera la fréquence de la note appuyée. Nous devrons donc convertir le numéro de note MIDI en fréquence appropriée. Heureusement, notre bon ami Wikipedia nous donne un petit algorithme pour le faire. Voici à quoi cela ressemble sous forme JavaScript:

fonction midiNoteToFrequency (note) return Math.pow (2, ((note - 69) / 12)) * 440; 

Donnez-lui une note et récupérez la fréquence. Utilisons cela dans notre onMIDIMessage une fonction.

fonction onMIDIMessage (message) var fréquence = midiNoteToFrequency (message.data [1]); 

Ensuite, nous voulons jouer une note de cette fréquence si le message MIDI est un message. noteOn message.

if (message.data [0] === 144 && message.data [2]> 0) playNote (fréquence); 

Vous comprendrez probablement la première partie de cette si déclaration assez facilement. Nous vérifions que le type de message est 144, qui est le noteOn message.

Mais qu'en est-il de la deuxième partie? Eh bien, certains périphériques MIDI, au lieu d’envoyer un note off message, enverra un noteOn message avec une vitesse nulle, donc nous vérifions que le message a une vitesse supérieure à zéro. 

Maintenant que nous avons noteOn couvert, nous écrirons quelque chose de similaire pour note offNoteOffLa valeur du message est 128, nous devons donc vérifier non seulement cette valeur, mais aussi si sa vitesse est nulle afin de couvrir la situation que je viens de mentionner.

if (message.data [0] === 128 || message.data [2] === 0) stopNote (fréquence); 

Il ne nous reste plus qu'à remplir le startNote et stopNote les fonctions. C’est le travail de l’API Web Audio, et sort donc malheureusement du cadre de ce tutoriel, mais si vous connaissez l’API, le code complet ci-dessous devrait s’expliquer assez bien.. 

Sinon, consultez ma série sur l'API Web Audio, qui explique comment construire un synthétiseur. Le code de ce tutoriel est similaire à ce que j'ai fait ici, ce serait donc l'endroit idéal pour appliquer ce que vous avez appris ici..

var contexte = new AudioContext (), oscillators = ; if (navigator.requestMIDIAccess) navigator.requestMIDIAccess () .then (succès, échec);  succès de la fonction (midi) var entrées = midi.inputs.values ​​(); // input est un itérateur pour (var input = inputs.next (); input &&! input.done; input = inputs.next ()) // chaque fois qu'un message MIDI est appelé, la fonction onMIDIMessage input.value. onmidimessage = onMIDIMessage;  function failure () console.error ('Aucun accès à vos périphériques MIDI.') function onMIDIMessage (message) var frequency = midiNoteToFrequency (message.data [1]); if (message.data [0] === 144 && message.data [2]> 0) playNote (fréquence);  if (message.data [0] === 128 || message.data [2] === 0) stopNote (fréquence);  fonction midiNoteToFrequency (note) return Math.pow (2, ((note - 69) / 12)) * 440;  function playNote (fréquence) oscillateurs [fréquence] = context.createOscillator (); oscillateurs [fréquence] .fréquence.valeur = fréquence; oscillateurs [fréquence] .connect (contexte.destination); oscillateurs [fréquence] .start (context.currentTime);  function stopNote (fréquence) oscillateurs [fréquence] .stop (context.currentTime); oscillateurs [fréquence] .disconnect (); 

Quoi ensuite?

Rappelles toi, noteOn et note off ne sont que deux des types de message disponibles et un clavier MIDI n’est que l’un des nombreux types de périphériques MIDI. Vous n'avez même pas besoin d'utiliser le MIDI pour créer quelque chose de musical. Un jeu HTML5 auquel vous jouez avec une trompette MIDI? On dirait juste mon truc.