O Pacote Java MIDI
Roteiro

Principais Classes e Interfaces do Pacote MIDI

Acessando Recursos MIDI

Carregando Seqüências MIDI

Transmitindo e Recebendo Mensagens MIDI

Gravando e Editando Seqüências MIDI

Recursos Avançados de Sequencer

Sintetizando Som
Principais Classes e
Interfaces do Pacote MIDI
Classe MidiMessage

MidiMessage


classe abstrata que representa uma mensagem MIDI pura
3 subclasses:



ShortMessages : tipo mais comum, possui um byte de
status e no máximo dois de dados (Ex.: Note On)
SysexMessages: podem possuir muito bytes e contém
instruções especificas do fabricante
MetaMessages: ocorre apenas em SMF, contem, por
exemplo, letra da música
Classe MidiEvent

MidiEvent


Mensagens MIDI + momento em que
ocorre
Métodos para especificar e também
obter informação de tempo:


long getTick ()
void setTick (long tick)
Classe Sequence

Sequence


Composição musical que pode ser lida de um arquivo ou
criada em tempo real
É composto por uma coleção de Tracks onde estão
armazenados os MidiEvents
Sequence
Tracks
MidiEvents
Interface MidiDevice




São capazes de enviar e receber mensagens
MIDI
Métodos para reservar (open) e liberar (close)
o uso do dispositivo
MidiDevice.Info
 fornece uma descrição textual do dispositivo;
Objetos transmissores implementam a
interface Transmitter e objetos receptores
implementam a interface Receiver
Interface Sequencer

Dispositivo para captura e execução de
seqüências de eventos MIDI



Responsável por manter os dados
sincronizados
Possui transmissores e receptores
Sequencer é uma subinterface de
MidiDevice
Interface Synthesizer



Representa o dispositivo que
efetivamente produz a onda sonora
Subinterface de MidiDevice
Um sintetizador possui canais


Interface MidiChannel
Possui apenas receptores
Acessando Recursos MIDI
Classe MidiSystem


Similar ao AudioSystem do pacote sampled
Permite obter os seguintes recursos:






Sequenciadores
Sintetizadores
Transmissores
Receptores
Dados a partir de arquivos MIDI
Dados a partir de arquivos de soundbank
Obtendo Dispositivos Padrões


Uma aplicação típica inicia obtendo os
dispositivos necessários
(sequenciadores, sintetizadores, etc.)
Métodos para obter dispositivos padrão:




static
static
static
static
Sequencer getSequencer ();
Synthesizer getSynthesizer ();
Receiver getReceiver ();
Transmitter getTransmitter ();
Exemplo 1


Obtendo informações sobre os MidiDevices
Exercício 1: Listar apenas os Sintetizadores
Carregando Seqüências MIDI
Criando e Carregando um Objeto
Sequence
try {
File midiFile = new File (“seq1.mid”);
Sequence seq = MidiSystem.getSequence (midiFile);
sequencer.setSequence (seq);
} catch (Exception e) {
// tratar ou throw a exceção
}
Transmitindo e Recebendo
Mensagens MIDI
Dispositivos, Receptores e
Transmissores



Diferentes MidiDevice podem ser
interconectados
Um MidiDevice possui um ou mais
objetos com interface Transmitter
e/ou Receiver;
Cada transmissor só pode ser conectado a
um receptor e vice-versa;
Conectando-se a um Dispositivo

Interface Transmitter


void setReceiver (Receiver
receiver)
Após terminada a conexão deve-se
invocar o método close() de
Transmitter e Receiver para que os
mesmos sejam liberados;
Exercício 2

Abrir e tocar um arquivo MIDI
Como enviar a mesma mensagem
para diferentes dispositivos ?


Usando mais de um transmissor e mais de um
receptor
MidiDevice possui métodos para descobrir quantos
transmissores e receptores um dispositivo suporta:


int getMaxTransmitters ()
int getMaxReceivers ()
Exemplo 2: Conectando uma Porta de Entrada a
um Sequenciador e a um Sintetizador
Sequencer seq;
Synthesizer synth;
MidiDevice inputPort;
// Obter e abrir os três dispositivos
Transmitter inPortTrans1, inPortTrans2;
Receiver synthRcvr, seqReceiver;
try {
inPortTrans = inputPort.getTransmitter ();
synthRcvr = synth.getReceiver ();
inPortTrans1.setReceiver (synthRcvr);
inPortTrans2 = inputPort.getTransmitter ();
seqRcvr = seq.getReceiver ();
inPortTrans2.setReceiver (seqRcvr);
} catch (MidiUnavailableException e) {
// tratar ou throw a exceção
}
Enviando Mensagem para um
Receptor sem Usar um Transmissor

Receiver contém um método que envia
mensagens para o receptor


void send (MidiMessage message, long
timeStamp)
Criar um objeto ShortMessage e usar o
método

void setMessage (int command, int
channel, int data1, int data2)
Exemplo 3:


Enviando uma Mensagem sem Usar um
Transmissor
Exercício 3

FileToMIDI : Lê arquivo qualquer e toca seus bytes
como Notas



Monofônico
Para cada note ON, existe um note OFF correspondente
As notas tem a mesma duração
Roteiro

Principais Classes e Interfaces do Pacote MIDI

Acessando Recursos MIDI

Carregando Seqüências MIDI

Transmitindo e Recebendo Mensagens MIDI

Gravando e Editando Seqüências MIDI

Recursos Avançados de Sequencer

Sintetizando Som
Gravando e Editando
Seqüências MIDI
Tracks


Arquivos MIDI são organizados em tracks
Normalmente, cada track agrupa informações
que possuem forte relação entre si


Notas de determinado instrumento
Arquivos MIDI são organizados em uma
hierarquia de três níveis:



Sequence
Track
MidiEvents
Sequence
Tracks
MidiEvents
MidiEvents e Ticks


Em um MidiEvent o tempo é expresso em ticks,
que é o menor intervalo de tempo em um SMF
O tamanho de um tick é um valor relativo pode ser
dado em duas unidades:




Pulsos por semínima (PPQ)
Ticks por frame (SMPTE)
O valor absoluto do tick é calculado no momento do
sequenciamento
Na API Java os valores de tick medem tempo
cumulativo;
Gravando e Salvando
Sequences (1/2)
1.
2.
3.
Obtenha um Sequencer através de MidiSystem;
Estabeleça a conexão entre o Sequencer e o
objeto que transmitirá as mensagens MIDI;
Crie um novo objeto Sequence:
Sequence (float divisionType, int resolution )
Sequence (float divisionType, int resolution,
int numTracks )
4.
Crie um objeto Track caso isso não seja feito no
construtor:
Sequence.createTrack();
Gravando e Salvando
Sequences (2/2)
5.
Relacione Sequence com o Sequencer usando:
Sequencer.setSequence(Sequence sequence)
6.
7.
8.
9.
Chame o método Sequencer.recordEnable ();
Chame o método Sequence.startRecording ();
Quando terminar, chame Sequencer.stop () ou
Sequencer.stopRecording ();
Salve o objeto Sequence gravado usando
MididSystem.write();
Editando uma Seqüência

Objetos do tipo Sequence permitem que sejam
adicionados ou removidos Tracks:



Track createTrack ()
Boolean deleteTrack (Track track)
As Tracks são armazenadas em um objeto Sequence
através de um Vector;
Editando uma Seqüência


Os MidiEvents contidos em uma Track também são
armazenados em um Vector
Métodos de Track





boolean add (MidiEvent event)
MidiEvent get (int index)
boolean remove (MidiEvent event)
int size ()
long ticks ()
Exercício 4

Gravar Exercício 3 em arquivo



Formato 1
120 PPQ
Tick é acumulativo
Recursos Avançados de
Sequencer
Posição de uma Sequence

Obtendo a posição corrente do Sequencer em um
Sequence:



Long getTickPosition ()
Long getMicrosecondPosition ()
Movendo para um ponto arbitrário em um objeto
Sequence:


void setTickPosition (long Tick)
void setMicrosecondPosition (long
microsecond)
Mudando a Velocidade de Execução


A velocidade de uma seqüência é indicada pelo
seu andamento (tempo)
Pode-se mudar o andamento de uma seqüência
através de eventos MIDI ou através da chamada
de métodos de Sequencer:



void setTempoInBPM (float bpm)
void setTempoInMPQ (float mpq)
void setTempoFactor (float factor)
Mute e Solo em Tracks

Pode-se escolher que Tracks irão contribuir para
o stream de mensagens MIDI gerados pelo
Sequencer;
void setTrackMute (int track, boolean
mute)
void setTrackSolo (int track, boolean
solo)

Para verificar o status de uma Track:


boolean getTrackMute (int track)
boolean getTrackSolo (int track)
Exercício 5

Adicionar código ausente no MidiPlayer



Pause e Parar
Acelerar 2x
Aplicar Mute e Solo em alguma track
Sintetizando Som
A Síntese de Sons em Java

A arquitetura para síntese de sons em Java é
composta de três interfaces




Synthesizer
MidiChannel
Soundbank
E quatro classes:




Instrument
Patch
SoundbankResource
VoiceStatus
Verificando Quais Instrumentos
Estão Carregados


Soundbank é um repositório de Instruments
Instruments são classes responsáveis pela síntese do som


O Patch tem dois componentes: o Bank e o Program que
funcionam como índices (2 dimensões) na memória do
sintetizador


Além de determinar seu Patch (posição na memória do
Sintetizador)
Cada bank possui até 128 programs
Para carregar o Soundbank padrão deve-se usar o seguinte
método de Synthesizer:
Soundbank getDefaultSoundbank ()

Para descobrir quais instrumentos estão atualmente carregados
deve-se usar o seguinte método de Synthesizer:
Instrument[] getLoadedInstruments()
Carregando Instrumentos

Para descobrir quais instrumentos pertencem ao
Sintetizador:
Instrument[] getAvailableInstruments ()

Um instrumento pode ser carregado usando:
boolean loadInstrument (Intrument instrument)

O instrumento será carregado na posição
especificada pelo seu objeto Patch;
Carregando Instrumentos



Cada objeto do tipo Instrument possui um objeto Patch que
especifica onde o instrumento deverá ser carregado;
Esse local é definido pelo número do banco e número do programa;
É possível carregar o instrumento em um outro local através do
seguinte método de Synthesizer:
boolean remapIntrument (Intrument from, Instrument to)
Descarregando Instrumentos

Existem três métodos para descarregar instrumentos:



void unloadAllInstruments (Soundbank soundbank)
void unloadInstrument(Instrument instrument)
void unloadInstruments(Soundbank soundbank,
Patch[] patchList)
Acessando Canais



Existem 2 maneiras para controlar o sintetizador sem
usar um sequenciador:
Através do seu Receiver
Interagir direta com objetos MidiChannel
Alterando o Instrumento
de um Canal


Para descobrir qual o instrumento atualmente alocado a um
canal deve-se usar:
int getProgram ()
Para modificar o instrumento associado:
void programChange (int program)
void programChange(int bank,int program)
OBS.: Instrumento deve estar carregado no sintetizador !
Exercício 6

Adicionar código ao programa TocaNotas para enviar
mensagens Note On e Note Off diretamente para o
canal de um sintetizador (sem usar MidiMessages).
Permitir também a mudança de Instrumentos;
Download

jsmidi