I'm trying to create a sort of automatic sheet music viewer just for fun which I will eventually try to integrate in my digital piano with a raspberry pi or something, but that's another story. Let's focus on my current problem.
In order to make this work, I have to compare MIDI input coming from my piano, with a MIDI file, representing the sheet music that I'm playing.
As I want to compare the two MIDI in realtime, I found really difficult to get live MIDI directly from my piano.
I've already tried to read 10 seconds of MIDI and write everything on a file and it works flawlessly, but I can't find any way to receive a sort of callback whenever a message is sent from my piano.
This is my current TEST code (it's horrible, I know, but I'm just testing right now) where I basically write to a .mid file 10 seconds of MIDI coming from my piano, and I also try to use a ControllerEventListener, but it doesn't seem to work.
import java.io.File;
import java.io.IOException;
import javax.sound.midi.ControllerEventListener;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiDevice.Info;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Receiver;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Track;
import javax.sound.midi.Transmitter;
import javax.swing.Timer;
public class Main {
public static void main(String[] args) throws Exception {
Info[] infos = MidiSystem.getMidiDeviceInfo();
for(int i = 0; i < infos.length; i++) {
System.out.println(infos[i].getName() + " - " + infos[i].getDescription());
}
MidiDevice inputDevice = MidiSystem.getMidiDevice(infos[1]);
Sequencer sequencer = MidiSystem.getSequencer();
Receiver receiver;
Transmitter transmitter;
inputDevice.open();
sequencer.open();
transmitter = inputDevice.getTransmitter();
receiver = sequencer.getReceiver();
transmitter.setReceiver(receiver);
Sequence seq = new Sequence(Sequence.PPQ, 24);
Track currentTrack = seq.createTrack();
sequencer.setSequence(seq);
sequencer.setTickPosition(0);
sequencer.addControllerEventListener(new ControllerEventListener() {
@Override
public void controlChange(ShortMessage event) {
System.out.println("listener works");
}
}, new int[] {127});
sequencer.recordEnable(currentTrack, -1);
sequencer.startRecording();
new Timer(10000, e -> {
Sequence tmp = sequencer.getSequence();
sequencer.stopRecording();
try {
MidiSystem.write(tmp, 0, new File("midi.mid"));
} catch (IOException e1) {
e1.printStackTrace();
}
System.exit(0);
}).start();
}
}
As you can see, I tried to add a ControllerEventListener to the Sequencer, but it doesn't seems to work when listening events while recording:
sequencer.addControllerEventListener(new ControllerEventListener() {
@Override
public void controlChange(ShortMessage event) {
System.out.println("listener works");
}
}, new int[] {127});
No matter how hard I tried, but I couldn't find anything that could help me... Any way to receive events on live MIDI instruments?
If you want to be notified in real time when a Note ON MidiMessage arrived from your piano, use a custom Receiver.
If you want that the Sequencer records the MidiMessages in parallel to create a Sequence, get a second transmitter from inputDevice and connect it to the Sequencer's receiver.