Java MIDI - obtenção de dados de piano?
Pergunta
Eu herdei um projeto Java que utilizou um velho C ++ dll para receber dados MIDI de um de piano conectado ao computador.
Agora que Java tem suporte embutido para dispositivos MIDI, eu quero me livrar do legado C ++ dll e usar apenas puro Java. Suporte Does Java receber dados de um piano conectado ao computador? Eu procurei Google para exemplos sem sucesso.
Solução
Sim, a API JavaSound pode ser usada para ler dados MIDI de um dispositivo MIDI.
JFugue é uma API Java para programação de música que usa a API JavaSound, e pode ajudar a simplificar sua interação com JavaSound. Em JFugue 5.x, código de exemplo para captura 10 segundos de dados MIDI de um dispositivo MIDI é a seguinte:
MidiDevice device = /* specify a MIDI device */
MusicTransmitterToSequence transmitter = new MusicTransmitterToSequence(device);
transmitter.listenForMillis(10000);
Sequence music = transmitter.getSequence();
Você também pode iniciar e parar de ouvir um dispositivo:
MidiDevice device = /* specify a MIDI device */
MusicTransmitterToSequence transmitter = new MusicTransmitterToSequence(device);
transmitter.startListening();
// Do stuff
transmitter.stopListening();
Sequence music = transmitter.getSequence();
Outras dicas
Se você quiser gravar apenas com a api MIDI por Java (javax.sound.midi. *) Isso é feito com muita facilidade. Este não é o código para copiar e colar, mas deve ajudá-lo a começar a programar o seu próprio gravador de MIDI, que é bastante fácil, na verdade.
O primeiro passo é definir a sua entrada e MidiDevice saída. Então, primeiro você terá que encontrar uma lista de possibilidades de IO e fazer uma GUI em que você pode selecionar o dispositivo de entrada e saída para a sua gravação e reprodução MIDI.
Info[] infos = MidiSystem.getMidiDeviceInfo();
for(int i=0;i<infos.length;i++)
{
System.out.println(infos[i].getName() + " - " + infos[i].getDescription());
}
Portanto, há uma lista de seus dispositivos MIDI. Em seguida, você quer selecionar um dispositivo MIDI, por exemplo, você começa a escolher os índices na matriz infos.
MidiDevice inputDevice = MidiSystem.getMidiDevice(infos[x]);
MidiDevice outputDevice = MidiSystem.getMidiDevice(infos[y]);
Você também vai querer especificar algumas globals:. Sequenciador, transmissor e receptor
Sequencer sequencer = MidiSystem.getSequencer();
Transmitter transmitter;
Receiver receiver;
Agora, há um botão de gravação que você deseja usar.
// Open a connection to your input device
inputDevice.open();
// Open a connection to the default sequencer (as specified by MidiSystem)
sequencer.open();
// Get the transmitter class from your input device
transmitter = inputDevice.getTransmitter();
// Get the receiver class from your sequencer
receiver = sequencer.getReceiver();
// Bind the transmitter to the receiver so the receiver gets input from the transmitter
transmitter.setReceiver(receiver);
// Create a new sequence
Sequence seq = new Sequence(Sequence.PPQ, 24);
// And of course a track to record the input on
Track currentTrack = seq.createTrack();
// Do some sequencer settings
sequencer.setSequence(seq);
sequencer.setTickPosition(0);
sequencer.recordEnable(currentTrack, -1);
// And start recording
sequencer.startRecording();
Cuidado , este código pode jogar MidiUnavailableExceptions e você deve chamar os métodos próximos sobre todas as coisas que você abriu em um finally.
Mas este é apenas o núcleo do que o código deve ser semelhante. Ele registra tudo para o seq
Sequence assim que você ligue para o sequencer.startRecording()
método.
Em seguida, você quer parar a gravação, e ser capaz de salvar a seqüência como MIDI para um arquivo, ou fazer uma reprodução. Por exemplo, este poderia ser um código quando você pressiona o botão de gravação Parar ou algo assim.
// Stop recording
if(sequencer.isRecording())
{
// Tell sequencer to stop recording
sequencer.stopRecording();
// Retrieve the sequence containing the stuff you played on the MIDI instrument
Sequence tmp = sequencer.getSequence();
// Save to file
MidiSystem.write(tmp, 0, new File("MyMidiFile.mid"));
}
Além disso, a classe Track (uma seqüência pode ter várias faixas) contém os dados de entrada reais, que você pode acessar facilmente por um método get. A classe trilha consiste em MidiEvents. Por exemplo, a faixa é:
MidiEvent 0: The C key is pressed
MidiEvent 1: The D key is pressed
MidiEvent 2: The C key of MidiEvent 0 is released
MidiEvent 3: The sustain pedal is pressed
etc...
E cada MIDIEVENT tem uma certa timestamp, que é expressa em Carrapatos MIDI, assim você pode facilmente mudar o tempo, aumentando ou diminuindo o número de tiques por segundo.
O problema mais difícil aqui é que MidiEvents são expressos em código de bytes, assim você terá que usar uma folha de código byte de referência que lhe diz o que byte representa o que ação. Isso deve começar com isso: http://www.onicos.com /staff/iz/formats/midi-event.html