jbrown
jbrown

Reputation: 7986

Java MIDI sequencer never ends

I'm running some MIDI code from a tutorial, but the program never terminates. It seems the MIDI sequencer never stops running, even though it reports that the length is 0.625s.

Do I need to do something else to make the sequencer stop?

import javax.sound.midi.*;

public class MyMidiPlayer {
    public static void main(String[] args)
    {
        MyMidiPlayer player = new MyMidiPlayer();
        player.setUpPlayer(4);
    }

    public void setUpPlayer(int numOfNotes)
    {
        try {
            Sequencer sequencer = MidiSystem.getSequencer();
            sequencer.open();
            Sequence sequence = new Sequence(Sequence.PPQ, 4);
            Track track = sequence.createTrack();

            for (int i = 0; i < numOfNotes; i++)
            {
                track.add(makeEvent(144, 1, i+48, 100, i));
                track.add(makeEvent(128, 1, i+48, 100, i + 2));
            }

            sequencer.setSequence(sequence);
            sequencer.setTempoInBPM(88);
            System.out.println("Playing (length=" + sequencer.getMicrosecondLength()/1000000f + "s)...");
            sequencer.start();

            while (true) {
                // Never returns false, so the program never quits
                if (!sequencer.isRunning()) {
                    sequencer.close();
                    System.exit(1);
                }
            }
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public MidiEvent makeEvent(int command, int channel, int note, int velocity, int tick)
    {
        MidiEvent event = null;
        try {
            ShortMessage a = new ShortMessage();
            a.setMessage(command, channel, note, velocity);
            event = new MidiEvent(a, tick);
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
        return event;
    }
}

Upvotes: 0

Views: 221

Answers (1)

jbrown
jbrown

Reputation: 7986

I was going to delete this, but I'll leave it up and post the answer. It seems you need to call sequencer.getMicrosecondPosition() in the while loop. Presumably this updates some variable in the sequencer class which then makes isRunning correctly return false when the position matches the value returned by getMicrosecondLength.

So specifically:

while (true) {
    if (!sequencer.isRunning()) {
        sequencer.close();
        System.exit(1);
    }
    sequencer.getMicrosecondPosition();
}

Upvotes: 2

Related Questions