Introduzione al Web MIDI

"Un tutorial su Web MIDI? Nel 2016? Stai scherzando, vero?"

No! Non è quello che pensi! Per quelli di noi che hanno usato il web dagli anni '90, la frase "Web MIDI" di solito induce i flashback a un tempo in cui i siti web riproducevano automaticamente una versione lo-fi bloopy di The Final Countdown mentre firmava il guestbook del webmaster. Tuttavia, nel 2016, il Web MIDI, e in particolare l'API Web MIDI, ha molto più potenziale.

Standard MIDI per l'interfaccia digitale di strumenti musicali. È un protocollo che consente a strumenti musicali elettronici, computer e altri dispositivi di comunicare tra loro. Funziona inviando piccoli messaggi da dispositivo a dispositivo dicendo cose come "la nota 12 è stata appena premuta" o "la nota 62 non viene più premuta", ma in una abbreviazione digitale.

L'API Web MIDI utilizza questo protocollo e ti permette di prendere uno strumento abilitato MIDI come una tastiera, collegarlo al tuo computer e avere informazioni inviate dalla tastiera al tuo browser.

Attualmente, l'API Web MIDI è supportata solo in Chrome e Opera, ma puoi seguire i suoi progressi in Firefox visitando questo bug. 

Quindi, perché dovremmo collegare una tastiera a un browser web? Beh, non molti musicisti conoscono la tastiera QWERTY tanto quanto ne fanno uno musicale. Inoltre, la gamma di dispositivi musicali che supportano il MIDI è enorme. Collegando un dispositivo di input abilitato MIDI al nostro browser, insieme all'utilizzo dell'API Web Audio, siamo in grado di creare strumenti musicali sul web. 

Vuoi suonare un pianoforte? Basta collegare la tastiera e visitare una pagina Web che utilizza queste tecnologie per replicare il suono di un pianoforte. Vuoi un suono diverso? Basta visitare un altro sito.

Spero che tu possa vedere il vantaggio di questa API, ma come funziona effettivamente?

Accesso a un dispositivo MIDI

Per prima cosa vogliamo verificare se il nostro browser supporta l'API Web MIDI. Lo facciamo vedendo se il navigator.requestMIDIAccess esiste il metodo Questo metodo è implementato solo nei browser che supportano l'API.

if (navigator.requestMIDIAccess) console.log ('Browser supporta il MIDI!'); 

Ora che sappiamo che il metodo esiste, chiamiamolo per richiedere l'accesso a qualsiasi input MIDI che provenga dal browser.

if (navigator.requestMIDIAccess) navigator.requestMIDIAccess () .then (successo, fallimento); 

navigator.requestMIDIAccess () restituisce una promessa, il che significa che chiamerà una funzione di successo o una funzione di errore a seconda dell'esito della richiesta di accesso MIDI. Qui abbiamo dato i nomi di due funzioni che creeremo in seguito.

function success (midi) console.log ('Got midi!', midi);  function failure () console.error ('Nessun accesso ai dispositivi midi.')

Come puoi vedere, la nostra funzione success prende un parametro MIDI sotto forma di un oggetto MIDIAccess. L'oggetto MIDIAccess è la chiave per ricevere dati midi. L'oggetto stesso fornisce un'interfaccia per tutti i dispositivi MIDI collegati. Gli ingressi rappresentano tutti i dispositivi MIDI collegati al computer. Ho una singola tastiera MIDI collegata, quindi se dovessi registrarmi midi.inputs.size, produrrebbe "1".

Per ottenere i dati di input dal nostro dispositivo, prima creiamo una variabile e la assegniamo midi.inputs.values ​​() così.

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

Una cosa importante da notare è che il valore assegnato a ingressi è un iteratore. Un iteratore è un oggetto che sa come accedere alle sue proprietà uno alla volta, mentre tiene traccia della posizione corrente nella sequenza di iterazione. Fornisce a Il prossimo() metodo per consentire di ottenere l'elemento successivo nella sequenza. Ha anche un fatto proprietà per farci sapere se abbiamo iterato su tutte le proprietà dell'oggetto. Questo significa che possiamo scrivere fantasia per loop come questo:

per (var input = inputs.next (); input &&! input.done; input = inputs.next ()) // ogni volta che c'è un messaggio midi chiama la funzione onMIDIMessage input.value.onmidimessage = onMIDIMessage; 

Ciò che questo ciclo dice è:

  1. Crea una variabile chiamata ingresso e assegnare il prossimo input ad esso. Perché non abbiamo ancora iterato su nessun input, questo restituirà il primo dei nostri input.
  2. Se abbiamo un input e il valore fatto dall'iter iter di input non è uguale a true, prosegui con il ciclo.
  3. Impostato ingresso al prossimo input nel nostro oggetto iteratore.

Noterai anche che all'interno di questo ciclo for stiamo assegnando una funzione agli input onmidimessage ascoltatore. Questa funzione sarà chiamata ogni volta che viene ricevuto un evento MIDI dal dispositivo rappresentato da quell'input. Creiamo questa funzione:

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

Decodifica dati MIDI

La parte del messaggio MIDI a cui siamo interessati è i suoi dati; che tipo di evento MIDI è stato inviato? Quale tasto della tastiera è stato premuto? 

Se segui questo tutorial, vedrai che quando premi un tasto sulla tastiera, il browser registrerà qualcosa di simile [144, 61, 95] alla console. E quando togli il dito dalla chiave, il browser registrerà di nuovo qualcosa di leggermente diverso, come [128, 61, 0].

Questo array può essere suddiviso in questo modo. Il primo elemento è il tipo di evento MIDI. I messaggi MIDI possono contenere un numero piuttosto piccolo di eventi e ogni evento ha un numero corrispondente. Nel nostro caso, 144 mappe per a noteon messaggio, indicando che è stato premuto un tasto, mentre 128 è a noteoff messaggio, dicendoci che la chiave non viene più premuta. Per un elenco completo dei possibili tipi di eventi MIDI, controlla l'elenco dei messaggi nelle specifiche MIDI.

Il secondo valore nell'array rappresenta il tasto premuto sulla tastiera. Ad ogni nota di una tastiera viene assegnato un numero compreso tra 0 e 127. Nell'esempio precedente, ho premuto il tasto 61, che utilizzando questa tabella di ricerca è possibile vedere un C #.

Il terzo e ultimo valore dell'array rappresenta la velocità, in pratica la velocità con cui il tasto è stato colpito. Questo può essere usato per imitare suonare un piano in cui i tasti possono essere suonati delicatamente o colpiti rapidamente e duramente.

Ora che sappiamo quale tasto viene premuto o rilasciato, trasformiamolo in qualcosa di utile. Colleghiamo l'API Web MIDI all'API Web Audio. Se non hai familiarità con l'API Web Audio, controlla la mia serie di tutorial su questo argomento.

Creazione di uno strumento Web

Trasformiamo il nostro browser in un mini sintetizzatore. Vogliamo creare un oscillatore che generi la frequenza della nota, quindi dovremo convertire il numero di nota MIDI nella relativa frequenza. Fortunatamente il nostro buon amico Wikipedia ci dà un piccolo algoritmo per fare proprio questo. Ecco come appare in forma JavaScript:

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

Dagli un appunto e riprendi la frequenza. Usiamo questo nel nostro onMIDIMessage funzione.

function onMIDIMessage (message) var frequency = midiNoteToFrequency (message.data [1]); 

Quindi vogliamo suonare una nota di questa frequenza se il messaggio MIDI è a noteon Messaggio.

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

Probabilmente capirai la prima parte di questo Se dichiarazione abbastanza facilmente. Stiamo verificando che il tipo di messaggio sia 144 che è il noteon Messaggio.

Ma per quanto riguarda la seconda parte? Bene, alcuni dispositivi MIDI, invece di inviare un noteoff messaggio, invierà a noteon messaggio con velocità zero, quindi stiamo verificando che il messaggio abbia una velocità maggiore di zero. 

Ora che abbiamo noteon coperto, scriveremo qualcosa di simile per noteoffnoteoffIl valore del messaggio è 128, quindi dobbiamo controllare non solo per quel valore ma anche se la sua velocità è zero per coprire la situazione che ho appena citato.

if (message.data [0] === 128 || message.data [2] === 0) stopNote (frequenza); 

Tutto quello che dobbiamo fare ora è compilare il startNote e stopNote funzioni. Questo è il lavoro dell'API Web Audio ed è quindi tristemente al di fuori dello scopo di questo tutorial, ma se conosci l'API allora il codice completo sotto dovrebbe essere abbastanza auto-esplicativo. 

In caso contrario, controlla le mie serie sull'API Web Audio, che include come creare un sintetizzatore. Il codice in questo tutorial è simile a quello che ho fatto qui, quindi sarebbe il posto perfetto per applicare ciò che hai imparato qui.

var context = new AudioContext (), oscillators = ; if (navigator.requestMIDIAccess) navigator.requestMIDIAccess () .then (successo, fallimento);  function success (midi) var inputs = midi.inputs.values ​​(); // input è un Iterator per (var input = inputs.next (); input &&! input.done; input = inputs.next ()) // ogni volta che c'è un messaggio midi chiama la funzione onMIDIMessage input.value. onmidimessage = onMIDIMessage;  function failure () console.error ('Nessun accesso ai dispositivi midi.') function onMIDIMessage (message) var frequency = midiNoteToFrequency (message.data [1]); if (message.data [0] === 144 && message.data [2]> 0) playNote (frequenza);  if (message.data [0] === 128 || message.data [2] === 0) stopNote (frequenza);  function midiNoteToFrequency (note) return Math.pow (2, ((note - 69) / 12)) * 440;  function playNote (frequency) oscillators [frequency] = context.createOscillator (); oscillatori [frequenza] .frequenza.valore = frequenza; oscillatori [frequenza] .connect (context.destination); oscillatori [frequenza] .start (context.currentTime);  function stopNote (frequency) oscillators [frequency] .stop (context.currentTime); oscillatori [frequenza] .disconnect (); 

Cosa Avanti?

Ricorda, noteon e noteoff sono solo due dei tipi di messaggi disponibili e una tastiera MIDI è solo uno dei tanti, molti tipi di dispositivi MIDI. Non devi nemmeno usare il MIDI per creare qualcosa di musicale. Un gioco HTML5 che giochi utilizzando una tromba MIDI? Sembra solo la mia cosa.