Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

22
Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Transcript of Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Page 1: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Dispositivi MIDI in Java

Lezione 23

Programmazione MIDI (Prof. Luca A. Ludovico)

Page 2: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Introduzione

• Nella lezione precedente è stata introdotta la logica di descrizione di dati MIDI da parte del package

• Tipicamente i dati vengono scambiati tra dispositivi– Ad esempio, un programma può generare messaggi MIDI da

zero, ma spesso invece questi vengono creati da un sequencer o ricevuti su una porta MIDI In

– Di solito poi i messaggi vengono inviati a un altro dispositivo, quale un sintetizzatore o una porta MIDI Out

• In Java si creano allo scopo oggetti software che implementano l’interfaccia MidiDevice

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 3: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Interfaccia MidiDevice

• Usata per definire oggetti software in grado di inviare o ricevere messaggi MIDI

• Può presentare un’implementazione software pura o fungere come interfaccia per le porte MIDI di una scheda audio (hardware)

• Cos’è un’interfaccia Java? Un’interfaccia (interface) ha una struttura simile a una classe, ma può contenere solo metodi d'istanza astratti e costanti (quindi non può contenere costruttori, variabili statiche, variabili di istanza e metodi statici).

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 4: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Interfaccia MidiDevice

• Di base l’interfaccia MidiDevice fornisce tutte le funzionalità genericamente richieste da dispositivi di sequencing, sintetizzatori, porte MIDI di ingresso e uscita – Esistono delle sotto-interfacce più specifiche di MidiDevice:

Synthesizer e Sequencer

• L’interfaccia MidiDevice include metodi per “aprire” e “chiudere” un dispositivo

• Include inoltre la classe interna MidiDevice.Info che fornisce descrizioni testuali del dispositivo, tra cui il nome del modello, il produttore e la versione

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 5: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Trasmettitori e ricevitori

• Un MidiDevice può essere un trasmettitore di eventi MIDI, un ricevitore o entrambe le cose. Dunque MidiDevice deve mettere a disposizione istanze delle interfacce Transmitter o Receiver o entrambe.

• Tipicamente:– le porte MIDI IN presentano trasmettitori– le porte MIDI OUT e i sintetizzatori presentano ricevitori – i sequencer mettono a disposizione trasmettitori per il

playback e ricevitori per le operazioni di registrazione

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

DeviceInfo.java

Page 6: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Paradigma di ricezione e trasmissione

• In che modo un dispositivo invia i dati MIDI? Tramite uno o più trasmettitori

• In che modo un dispositivo riceve i dati MIDI? Tramite uno o più ricevitori

• Ogni trasmettitore può essere connesso a un solo ricevitore alla volta, ma non viceversa– Se un dispositivo deve inviare messaggi MIDI a più dispositivi

contemporaneamente, deve avere più trasmettitori– Se un dispositivo deve poter ricevere messaggi MIDI da più

mittenti simultaneamente, può (non deve avere) più ricevitori

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 7: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

SynthPorta MIDI In

Esempi

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Trasmettitore Messaggio MIDI Ricevitore

Midi Out 1Sequencer

Trasmettitore 1 Messaggio MIDI Ricevitore Midi Out 2

Trasmettitore 2 Messaggio MIDI Ricevitore

Page 8: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Esempio

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

da mittente

1

da mittente 3

da mittente 2

da mittente 1

da mittente 3

da mittente 2

Page 9: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Sequencer

public interface Sequencer extends MidiDevice

•Un sequencer è un dispositivo che cattura ed esegue sequenze di eventi MIDI.

– Può ad esempio caricare una sequenza da un file MIDI, interrogarne e impostarne il tempo e sincronizzare altri dispositivi

•Possiede trasmettitori, in quanto è in grado di inviare i messaggi salvati in una sequenza ad altri dispositivi (synth, MIDI OUT). Possiede ricevitori in quanto è in grado di catturare messaggi MIDI e salvarli in una sequenza

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 10: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Sintetizzatori

public interface Synthesizer extends MidiDevice

•I sintetizzatori sono gli unici oggetti nel package javax.sound.midi in grado di produrre audio

•Ogni sintetizzatore controlla un insieme di 16 oggetti “canale MIDI”, ciascuno istanza dell’interfaccia MidiChannel

•Un’applicazione può generare suono invocando direttamente i metodi degli oggetti “canale MIDI” di un sintetizzatore. Il caso più comune però è che un sintetizzatore generi suono in risposta ai messaggi inviati ai suoi ricevitori

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 11: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Strumenti

• Il sintetizzatore valuta i messaggi che giungono ai suoi ricevitori e quindi invia i comandi corrispondenti (ad es. Note On o Control Change) a uno dei propri oggetti MidiChannel sulla base del numero di canale specificato nell’evento

• Per generare audio però serve informazione aggiuntiva: lo strumento associato al canale. Lo si fa tramite la classe astratta Instrument

• Il sintetizzatore deve caricare uno strumento e associarlo a uno o più canali tramite un comando di Program Change. Da quel momento le note inviate a quei canali verranno sintetizzate con lo strumento

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 12: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

SINTESI DEL SUONO IN JAVA

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 13: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Introduzione

• La maggior parte dei software in Java che si avvalgono del package hanno l’obiettivo di generare suonoL’apparato fin qui descritto, composto da:– messaggi– eventi (messaggi temporizzati)– tracce (insiemi di eventi)– sequenze (inziemi di tracce)– sequencer (oggetti che manipolano tracce)

quasi sempre ha lo scopo di inviare dati musicali a un sintetizzatore che li tradurrà in segnali audio

• Esistono eccezioni: ad esempio, programmi che visualizzano dati MIDI in formato testuale, o software che li convertono in notazione musicale, o che li inviano a dispositivi esterni tramite porte MIDI

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 14: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

L’interfaccia Synthesizer

• In questa parte della lezione si mostrerà come manipolare un sintetizzatore per far suonare eventi MIDI

• Esistono vari approcci:1. Utilizzare un sequencer per inviare dati MIDI al sintetizzatore,

eventualmente caricandoli da un file MIDI o generando direttamente la sequenza (vedi lezione precedente)

2. Controllare il sintetizzatore in modo diretto, senza passare attraverso sequencer

3. Usare direttamente oggetti MidiMessage

• I diversi approcci verranno trattati separatamente

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 15: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

L’architettura per la sintesi del suono

• L’architettura include tre interfacce:1. Synthesizer2. MidiChannel3. Soundbank: concetto introdotto dall’API Java come ulteriore livello gerarchico.

I soundbank possono contenere fino a 128 bank, ciascuno contenente fino a 128 strumenti 

e quattro classi:1. Instrument: una specifica per sintetizzare un certo tipo di suono. In GM si

definiscono 128 strumenti standard

2. Patch3. SoundbankResource4. VoiceStatus: dà informazioni sullo stato corrente (attivo o inattivo) della voce,

sul canale MIDI, sul numero di bank e di programma associati, sul numero di nota MIDI e sul volume

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 16: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Synthesizer e sequencer di default

Sequencer sequencer = MidiSystem.getSequencer();

Synthesizer synthesizer = MidiSystem.getSynthesizer();

Per considerare tutti i dispositivi installati:

devices = MidiSystem.getMidiDeviceInfo();

for (MidiDevice.Info info: devices)

{...

}

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 17: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Caricamento di strumenti

• Per conoscere gli strumenti attualmente caricati nel sintetizzatore si può invocare il metodo di SynthesizerInstrument[] getLoadedInstruments()

• Per conoscere gli strumenti caricabili dal soundbank correnteInstrument[] getAvailableInstruments()

• Per conoscere il nome dei singoli strumenti, si utilizza il metodo getName() di Instrument

• Il metodo di Synthesizer che restituisce il soundbank di default èSoundbank getDefaultSoundbank()

• Anche in questo caso, l’interfaccia Soundbank includes metodi per recuperare il nome, il produttore, il numero di versione, ecc.

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

SynthInfo.java

Page 18: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Approccio 1: uso di sequencer

• In molti casi, un programma può utilizzare un oggetto Synthesizer quasi senza invocare metodi per la sintesi– E’ possibile creare una sequenza manualmente o

caricarla da un file MIDI all’interno di un oggetto Sequence. Tale oggetto viene poi caricato da un sequencer, che manda i dati al sintetizzatore di default.

• Come ottenere il sequencer di default? Usando un metodo statico di MidiSystem:

static Sequencer getSequencer()

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 19: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Approccio 1: uso di sequencer

• Ottenere il sequencer di default, acquisire le risorse di sistema richieste e renderlo operativo:

Sequencer mioSequencer;

mioSequencer = MidiSystem.getSequencer();

if (mioSequencer == null) {

// Errore - dispositivo sequencer non supportato }

else

{

mioSequencer.open();

}

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 20: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Approccio 1: uso di sequencer

• Leggere una sequenza da file: si usa il metodo getSequence di MidiSystem, in grado (tramite overload) di caricare una sequenza da InputStream, File, o URL. Il metodo restituisce un oggetto Sequence che può essere caricato in un Sequencer 

try

{

File mioMidiFile = new File("seq1.mid");

Sequence miaSeq = MidiSystem.getSequence(mioMidiFile); mioSequencer.setSequence(miaSeq);

}

catch (Exception e)

{

// Gestione dell’errore

}

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

CaricaSequenzaDaFile.java

CaricaSequenzaDaUrl.java

Page 21: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Playback di una sequenza

• Metodi principali invocabili su oggetti Sequencer:void start() avvia l’esecuzionevoid stop() mette in pausa l’esecuzione

• Il metodo setSequence inizializza la posizione corrente del sequencer all’inizio della sequenza

• Tra i metodi per il riposizionamento:void setMicrosecondPosition(long microseconds)void setTickPosition(long tick)

• Descrizione completa della classe Sequencer:http://docs.oracle.com/javase/7/docs/api/javax/sound/midi/Sequencer.html

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java

Page 22: Dispositivi MIDI in Java Lezione 23 Programmazione MIDI (Prof. Luca A. Ludovico)

Ulteriori esempi

• Nel file ZIP della lezione corrente sono state incluse delle varianti agli esercizi sopra commentati

• SynthInfo2.java dà informazioni su tutti i sintetizzatori trovati nel sistema, non solo su quello di default– Per farlo, si cicla su tutti i MidiDevice e si filtrano i risultati tramite

l’istruzione if (device instanceof Synthesizer)

• CaricaSequenzaDaFile2.java permette di scegliere quale traccia ascoltare tra quelle di un MIDI file– Se il file è di tipo 1, di solito la 1a traccia è riservata ai metadati e

non contiene informazione audio– Per farlo si accede alla struttura dati

Track[] tracks = miaSeq.getTracks(); e si eliminano tutte le tracce diverse da quella scelta

Programmazione MIDI (Prof. Luca A. Ludovico)23. Dispositivi MIDI in Java