Lezione 16 Web MIDI API Programmazione MIDI (Prof. Luca A. Ludovico)
Prerequisiti Competenze Rudimenti di programmazione per il Web HTML + CSS + JavaScript Catena MIDI: sintetizzatore MIDI hardware o software (virtuale) collegato alla macchina Esempi: CoolSoft VirtualMIDISynth (Windows), SimpleSynth (Mac), FluidSynth (multipiattaforma) Browser compatibili (fine 2018): Chrome, Opera, Chrome for Android, Android Browser, Samsung Internet Fonte: https://caniuse.bitsofco.de/embed/index.html?feat=midi&periods=future_1,current,past_1,past_2 Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
Web MIDI API La Web MIDI API è una specifica del W3C per il supporto al protocollo MIDI. Consente alle applicazioni Web di elencare e selezionare i dispositivi MIDI di input e output rilevati sul client, e di mandare e ricevere messaggi MIDI. Al momento, si tratta di una bozza dell’Audio Group destinata a diventare una W3C Recommendation. Versione corrente: W3C Editor's Draft 18 October 2018 Link: https://webaudio.github.io/web-midi-api/ Versione precedente: Working Draft 17 March 2015 Link: https://www.w3.org/TR/webmidi/ Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
Obiettivi Enumerare, manipolare e accedere ai dispositivi MIDI (non solo collegati su porta MIDI, ma anche via USB se compatibili con le specifiche USB-MIDI) Fornire accesso diretto e a basso livello ai dispositivi compatibili con MIDI presenti nel sistema dell’utente (controller, sintetizzatori esterni o software, sistemi di illuminazione, altri dispositivi meccanici, …) Permettere la progettazione di una nuova classe di applicazioni Web in grado di rispondere a input provenienti da controller MIDI, anche al di là delle finalità musicali. Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
Non-obiettivi Fornire descrizioni semantiche della musica e dei dispositivi MIDI. Ci si concentra su invio e ricezione di messaggi, non sul significato semantico. E’ la differenza che sussiste tra generare un accordo G#7 e inviare i messaggi di NoteOn corrispondenti; o tra modulare il vibrato di 20 Hz e cambiare il valore di un controller. Gestire e mandare in esecuzione SMF. Questo viene demandato all’estensione dei formati audio supportati dall’elemento <audio> in HTML5; né, più in generale, implementare concetti di alto livello come il sequencing. Lo scopo è consentire di sviluppare applicazioni Web usando la API. Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
Porte MIDI virtuali La Web MIDI API permette di scrivere browser app che comunicano con dispositivi su catene MIDI a monte e a valle. Tali dispositivi possono essere fisici o virtuali. Ma come creare porte MIDI virtuali? sotto Windows, esistono software appositi. Es.: LoopBe1 è un software gratuito residente in memoria che emula una porta MIDI dotata di 1 MIDI In e 1 MIDI Out; Sotto MacOS X, è possibile creare nativamente porte MIDI virtuali tramite: Configurazione MIDI Audio > Finestra > Mostra Studio MIDI > doppio clic su Driver IAC > + Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
DISPOSITIVI MIDI Accesso ai Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
Codice JavaScript nelle pagine Web E’ possibile scrivere codice JavaScript all’interno di una pagina HTML includendolo tra i seguenti tag: <script language="javascript" type="application/javascript"> // codice javascript </script> In alternativa, è possibile collegare un file esterno, convenzionalmente con estensione .js, tramite la seguente sintassi: <script language="javascript" type="application/javascript" src="miofile.js"></script> Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
Snippet di codice per accedere alle risorse Il codice JavaScript sotto riportato è quanto richiesto per ottenere (o meglio, cercare di ottenere) accesso alle risorse di sistema MIDI: var midi = null; // global MIDIAccess object function onMIDISuccess(midiAccess) { console.log("MIDI ready!"); midi = midiAccess; } function onMIDIFailure(msg) { console.log("Failed to get MIDI access - " + msg); navigator.requestMIDIAccess().then(onMIDISuccess, onMIDIFailure); Nelle prossime slide tale codice verrà commentato. Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
Metodo requestMIDIAccess() navigator.requestMIDIAccess().then(onMIDISuccess, onMIDIFailure); Quando questo metodo viene invocato, restituisce un oggetto Promise che rappresenta una richiesta di accesso ai dispositivi MIDI rilevati nel sistema dell’utente. Il metodo then di una Promise – non solo nel caso di Web MIDI API - prende due argomenti, che sono le funzioni di callback da richiamare rispettivamente in caso di successo e di fallimento della Promise. Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
Funzioni di callback Una funzione di callback («richiamo») è, in generale, un blocco di codice che viene passato come parametro ad un'altra funzione. La callback viene passata come parametro alla funzione chiamante. In questo modo la funzione chiamante può realizzare un compito specifico (quello svolto dalla callback) che non è noto al momento della scrittura del codice, ma dipende dal verificarsi o meno di determinate condizioni: nel caso specifico, la disponibilità o meno di risorse MIDI. Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
Analisi delle funzioni di callback Il punto saliente sta nell’assegnazione all’oggetto globale midi del MIDIAccess eventualmente recuperato in caso di successo (in rosso). var midi = null; // variabile (o meglio oggetto) globale function onMIDISuccess(midiAccess) { console.log("MIDI ready!"); // non necessario midi = midiAccess; } function onMIDIFailure(msg) { console.log("Failed to get MIDI access - " + msg); // arbitrario navigator.requestMIDIAccess().then(onMIDISuccess, onMIDIFailure); La callback in caso di fallimento è del tutto arbitraria. Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
Elencare le porte MIDI disponibili Disponendo di un oggetto midiAccess, è possibile elencare le porte di input e output tramite la seguente sintassi: function listInputsAndOutputs(midiAccess) { for (var input in midiAccess.inputs) { console.log("Input port [type:'" + input.type + "'] id:'" + input.id + "' manufacturer:'" + input.manufacturer + "' name:'" + input.name + "' version:'" + input.version + "'"); } for (var output in midiAccess.outputs) { console.log("Output port [type:'" + output.type + "'] id:'" + output.id + "' manufacturer:'" + output.manufacturer + "' name:'" + output.name + "' version:'" + output.version + "'"); midiAccess si può passare al richiamo della funzione, oppure si usa il valore della variabile globale. elenco_porte_MIDI.html Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
Elencare le porte MIDI disponibili Disponendo di un oggetto midiAccess, è possibile elencare le porte di input e output tramite la seguente sintassi: function listInputsAndOutputs(midiAccess) { for (var input in midiAccess.inputs) { console.log("Input port [type:'" + input.type + "'] id:'" + input.id + "' manufacturer:'" + input.manufacturer + "' name:'" + input.name + "' version:'" + input.version + "'"); } for (var output in midiAccess.outputs) { console.log("Output port [type:'" + output.type + "'] id:'" + output.id + "' manufacturer:'" + output.manufacturer + "' name:'" + output.name + "' version:'" + output.version + "'"); midiAccess si può passare al richiamo della funzione, oppure si usa il valore della variabile globale. elenco_porte_MIDI.html Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
Invio di messaggi MIDI a un output Guadagnato il midiAccess e scelta una porta di output, è possibile inviare messaggi MIDI al dispositivo di output selezionato. function sendMiddleC( midiAccess, portID ) { var noteOnMessage = [0x90, 60, 0x7f]; // note on, do centrale, velocity massima var output = midiAccess.outputs.get(portID); output.send(noteOnMessage); // senza timestamp output.send([0x80, 60, 0x40], window.performance.now() + 1000.0 ); // note off, do centrale, release velocity = 64, timestamp = now + 1000ms. } Questo esempio mostra: come selezionare un dispositivo di output come inviargli messaggi MIDI diversi (un note on e un note off) come preparare messaggi MIDI con status e data byte come introdurre un delay programmatico (in questo caso 1 secondo) suona_do.html Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
Altro esempio Nell’esempio vengono introdotti due elementi cliccabili che consentono all’utente di stabilire quando accendere e quando spegnere una nota. Per farlo si è scelto il timbro di tromba, che non presenta un decadimento naturale del suono come invece avviene ad esempio per le corde pizzicate o percosse. E’ stata introdotta una parametrizzazione sulla velocity. accendi_spegni.html Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API
Osservazione: selezione della OutPort Negli esempi mostrati, le porte vengono lette attraverso un costrutto foreach, e si sceglie come porta di output l’ultima dell’elenco tramite iterazioni di riassegnamento dell’id corrente. Questo metodo non è concettualmente corretto (anche se spesso funziona): l’utente dovrebbe avere la possibilità di configurare la porta di output desiderata, in particolare quando più di un dispositivo di output è disponibile nella catena. In questo modo, è possibile ad esempio scegliere il synth con cui renderizzare la melodia. Il problema verrà affrontato e risolto nella prossima lezione. Programmazione MIDI (Prof. Luca A. Ludovico) 16. Web MIDI API