Search code examples
javamidijavasound

How to get Note On/Off messages from a MIDI sequence?


I am hoping to get notifications of note on/off events in a playing MIDI sequence to show the notes on a screen based (piano) keyboard.

The code below adds a MetaEventListener and a ControllerEventListener when playing a MIDI file, but only shows a few messages at the start and end of the track.

How can we listen for note on & note off MIDI events?

import java.io.File;
import javax.sound.midi.*;
import javax.swing.JOptionPane;

class PlayMidi {

    public static void main(String[] args) throws Exception {
        /* This MIDI file can be found at..
        https://drive.google.com/open?id=0B5B9wDXIGw9lR2dGX005anJsT2M&authuser=0
        */
        File path = new File("I:\\projects\\EverLove.mid");

        Sequence sequence = MidiSystem.getSequence(path);
        Sequencer sequencer = MidiSystem.getSequencer();

        sequencer.open();

        MetaEventListener mel = new MetaEventListener() {

            @Override
            public void meta(MetaMessage meta) {
                final int type = meta.getType();
                System.out.println("MEL - type: " + type);
            }
        };
        sequencer.addMetaEventListener(mel);

        int[] types = new int[128];
        for (int ii = 0; ii < 128; ii++) {
            types[ii] = ii;
        }
        ControllerEventListener cel = new ControllerEventListener() {

            @Override
            public void controlChange(ShortMessage event) {
                int command = event.getCommand();
                if (command == ShortMessage.NOTE_ON) {
                    System.out.println("CEL - note on!");
                } else if (command == ShortMessage.NOTE_OFF) {
                    System.out.println("CEL - note off!");
                } else {
                    System.out.println("CEL - unknown: " + command);
                }
            }
        };
        int[] listeningTo = sequencer.addControllerEventListener(cel, types);
        for (int ii : listeningTo) {
            System.out.println("Listening To: " + ii);
        }

        sequencer.setSequence(sequence);
        sequencer.start();
        JOptionPane.showMessageDialog(null, "Exit this dialog to end");
        sequencer.stop();
        sequencer.close();
    }
}

Solution

  • I'll be watching to see if there is a better answer than either of the two suggestions that I have, which are clearly less than ideal.

    1. edit the midi file to include meta events that match the existing key on/off
    2. write you own event system

    I don't do a lot yet with MIDI, myself. I only occasionally import MIDI scores and strip out most of the info, converting it to use with an event-system I wrote for my own audio needs (triggering an FM synthesizer I wrote).