Lezione 22 Dati MIDI in Java Programmazione MIDI (Prof. Luca A. Ludovico) Introduzione • Obiettivi conseguiti: – Ripasso/acquisizione delle basi sintattiche di Java – Rudimenti della programmazione a oggetti – Esempi orientati al MIDI (senza usare e usando il package javax.sound.midi) • Nuovo obiettivo: comprendere la logica di descrizione di dati e dispositivi MIDI da parte del package • Un tutorial completo si trova nella documentazione ufficiale in lingua inglese: http://docs.oracle.com/javase/tutorial/sound/overvi ew-MIDI.html Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Strutture dati dinamiche VECTOR Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Strutture dati dinamiche • I tipi primitivi (int, char, …) e i tipi strutturati (array) visti finora hanno dimensioni predefinite • Nel caso degli array, nella dichiarazione è necessario: – stabilire il tipo base per gli elementi del vettore – stabilire il numero di elementi complessivi Una volta fissati questi aspetti, non possono più essere modificati Esistono invece strutture dati dinamiche, le cui dimensioni possono variare «dinamicamente» a seconda delle esigenze Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java La classe public class Vector<E> • La classe Vector<E> implementa un array di dimensioni variabili. Ai suoi elementi si accede tramite indice, come negli array non ridimensionabili • Richiede: import java.util.Vector; • Costruttori: – Vector() – Vector(Collection<? extends E> c) costruisce un vettore che contiene gli elementi della collezione specificata, nel loro ordine originario – Vector(int initialCapacity) – Vector(int initialCapacity, int capacityIncrement) Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Aggiunta, inserimento e ricerca di elementi • public boolean add(E e) aggiunge l’elemento e in coda al vettore • public E set(int index, E element) rimpiazza l’elemento all’indice specificato con element • public E get(int index) public E elementAt(int index) restituiscono l’elemento alla posizione specificata • public int indexOf(Object o) public int indexOf(Object o, int index) public int lastIndexOf(Object o) restituiscono l’indice corrispondente rispettivamente alla prima occorrenza, alla prima occorrenza a partire da un dato indice e all’ultima occorrenza dell’oggetto o, oppure -1 se l’oggetto non viene trovato Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Rimozione di elementi • public void clear() public void removeAllElements() rimuovono tutti gli elementi del vettore e ne impostano la dimensione a 0 • public E remove(int index) public void removeElementAt(int index) rimuovono l’elemento all’indice dato • public boolean remove(Object o) public boolean removeElement(Object o) rimuove la prima occorrenza dell’oggetto o • protected void removeRange(int fromIndex, int toIndex) rimuove tutti gli elementi il cui indice sta tra fromIndex (incluso) e toIndex (escluso) Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Metodi per il dimensionamento di un Vector • public void trimToSize() riduce la capacità del vettore a quella corrente, minimizzando l’occupazione di spazio in memoria • public void ensureCapacity(int minCapacity) incrementa se necessario la capacità per supportare il numero minimo di elementi specificato • public void setSize(int newSize) imposta le dimensioni del vettore: se superiori a quelle attuali il vettore viene riempito alla fine di elementi null, se inferiori si scartano gli elementi in eccesso • public int capacity() restituisce la capacità corrente del vettore (cioè la lunghezza dell’array di dati, indipendentemente dal suo effettivo riempimento) • public int size() restituisce il numero di elementi del vettore • public boolean isEmpty() verifica se il vettore non abbia elementi Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Size e capacity • Istanza di un nuovo Vector size = 0, capacity = 10 • Dopo due operazioni di add size = 2, capacity = 10 Ab Ki • Dopo un’operazione di trimToSize size = 2, capacity = 2 Ab Ki EsempioVector.java MIDIPitchArray2.java Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Rappresentazione dei DATI MIDI Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Messaggi MIDI • La classe MidiMessage è astratta e fornisce una descrizione grezza dei messaggi MIDI. Ha tre sottoclassi: – ShortMessage (vedi lezione precedente) – SysexMessage per i System Exclusive – MetaMessage per i metaeventi, ossia eventi generalmente utili per i sequencer ma insignificanti per i sintetizzatori • Le tre sottoclassi ereditano da (e rendono concreta) la classe MidiMessage Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java MetaMessage • Costruttori public MetaMessage() public MetaMessage(int type, byte[] data, int length) throws InvalidMidiDataException • I contenuti del messaggio si possono impostare anche con il metodo setMessage • Parametri: – type – il tipo di metamessaggio (deve essere < 128) – data – i byte di dati – length – il numero di byte nell’array di dati (deve essere non negativo e <= data.length) Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Eventi MIDI • Gli standard MIDI file contengono eventi temporizzati. La classe MidiEvent rappresenta questo tipo di informazione, cioè un messaggio nella forma in cui sarebbe memorizzato in uno standard MIDI file • La classe presenta metodi per impostare e leggere il valore della temporizzazione dell’evento • E’ inoltre possibile ottenere il messaggio MIDI “grezzo”, istanza di una delle sottoclassi di MidiMessage Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Sequenze e tracce • Negli standard MIDI file gli eventi sono disposti in tracce • La strutturazione Java prevede: – – – Sequence Track MidiEvent ove una traccia Track è una collezione di MidiEvent e una sequenza Sequence è una collezione di Track Attenzione: non si tratta di una gerarchia tra classi! Difatti le tre classi ereditano direttamente da java.lang.Object. Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Sequenze e tracce Livello 1 Sequence Livello 2 Livello 3 Track MidiEvent MidiEvent Track MidiEvent MidiEvent MidiEvent Ogni evento MidiEvent è {ShortMessage | SysExMessage | MetaMessage} + temporizzazione Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Sequenze e tracce • Le sequenze, ossia le istanze della classe Sequence, possono essere: – lette dai file MIDI – create da zero – editate aggiungendo o rimuovendo tracce • Le tracce rappresentano il livello intermedio della gerarchia a 3 livelli, posizionandosi tra le sequenze che un sequencer può gestire e gli eventi MIDI • Analogamente gli eventi MIDI, ossia le istanze della classe MidiEvent, possono essere aggiunti o rimossi dalle tracce di una data sequenza Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Istanziare una sequenza • Come si istanzia una sequenza? • Costruttori: public Sequence(float divisionType, int resolution) Public Sequence(float divisionType, int resolution, int numTracks) • Possibili valori per divisionType: PPQ,SMPTE_24, SMPTE_25, SMPTE_30, SMPTE_30DROP • La risoluzione temporale esprime i tick per beat – Per conoscere la temporizzazione assoluta, è necessario il BPM (default = 120) Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Istanziare una traccia • Come si istanzia una traccia? Track miaTraccia = new Track(); dà errore!!! • Non è possibile definirla al di fuori di una sequenza, in quanto questa ne determina la temporizzazione e la risoluzione temporale • E’ dunque necessario invocare il metodo Sequence.createTrack() Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Aggiunta e rimozione di eventi MIDI public class Track extends Object • boolean add(MidiEvent event) • MidiEvent get(int index) • boolean remove(MidiEvent event) • int size() restituisce il numero di eventi nella traccia • long ticks() restituisce la lunghezza della traccia in MIDI ticks EsempioSequenze.java Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java Far suonare le sequenze • La prossima lezione sarà dedicata alla rappresentazione dei dispositivi MIDI, tra cui sequencer e sintetizzatori • Al momento: Sequencer mioSeq = MidiSystem.getSequencer(); mioSeq.open(); mioSeq.setSequence(sequence); mioSeq.start(); … mioSeq.stop(); CreateSequence.java Programmazione MIDI (Prof. Luca A. Ludovico) 22. Dati MIDI in Java