Skip to content

javax.sound.midi porting for Android

Kaoru Shoji edited this page Jan 28, 2015 · 4 revisions

Now, this porting is moving into javax.sound.midi for Android repository!

  • Provides USB MIDI driver as the same interface as javax.sound.midi package.
  • Android applications can not include the package name starts with javax.. So, this project uses jp.kshoji.javax.sound.midi instead of the javax.sound.midi.

Supporting APIs

  • javax.sound.midi.MidiSystem
  • javax.sound.midi.Receiver
  • javax.sound.midi.Transmitter
  • javax.sound.midi.MidiEvent
  • javax.sound.midi.MidiMessage
    • MetaMessage, ShortMessage, SysexMessage
  • javax.sound.midi.Sequencer
    • Sequence, Track, MidiFileFormat
  • javax.sound.midi.Soundbank
    • interface only, no implementation class included.
  • javax.sound.midi.Synthesizer
    • interface only, no implementation class included.

Unsupported APIs

Time-stamping for real-time events is not supported.

  • Receiver#send(MidiMessage message, long timeStamp) method's timeStamp argument is always ignored. (When called by the library, timeStamp will be set as -1).

How to use

Almost same as using the original javax.sound.midi except below.

  • Application need to call...
    • MidiSystem.initialize(Context) on starting to use MIDI.
    • MidiSystem.terminate() on finishing to use MIDI.
  • MidiSystem can attach OnMidiSystemEventListener to detect new device connections.

Usage examples

Initialize library

  • MidiSystem.initialize(Context) may called at Activity#onCreate() , or somewhere.
  • Then, application starts device polling.
@Override
protected void onCreate() {
    super.onCreate();

    MidiSystem.initialize(MyActivity.this);
}

Finish using library

  • MidiSystem.terminate() may called at Activity#onDestroy();
  • This method closes all unclosed devices, and the application ends device polling.
@Override
protected void onDestroy() {
    super.onDestroy();

    MidiSystem.terminate();
}

Using MidiDevice (Receiver, Transmitter)

  • Get MidiDevice.Info instances from MidiSystem.
  • Get MidiDevice instance from MidiSystem.
  • Open the device.
MidiDeviceInfo[] informations = MidiSystem.getMidiDeviceInfo();

if (informations != null && informations.length > 0) {
    MidiDevice device = MidiSystem.getMidiDevice(informations[0]);

    try {
        device.open();
    } catch (MidiUnavailableException mue) {
        // TODO some treatment for mue
    }
}
  • Get Receiver / Transmitter instance from MidiDevice
  • Receiver can send MidiMessage.
// get the receiver
Receiver receiver = device.getReceiver();

// send something..
receiver.send(new ShortMessage());
  • Transmitter can attach a Receiver instance, and can receive MidiMessage with send(MidiMessage) method.
// get the transmitter
Transmitter transmitter = device.getTransmitter();
// start to receive
transmitter.setReceiver(new Receiver() {
    void send(MidiMessage message, long timeStamp) {
        // handling the event
        Log.i("MIDI", "received:" + Arrays.toString(message.getMessage()));
    }

    void close() {
        // do nothing
    }
});
  • clean up MidiDevice instance
device.close();

Playing Sequence

// get and open sequencer
sequencer = MidiSystem.getSequencer();
sequencer.open();

// read SMF
FileInputStream inputStream = new FileInputStream(new File(root, "example.mid"));
Sequence sequence = MidiSystem.getSequence(inputStream);
inputStream.close();

// play
sequencer.setSequence(sequence);
sequencer.start();

Recording Sequence

  • Start a recording
// get and open sequencer
sequencer = MidiSystem.getSequencer();
sequencer.open();

// record
sequencer.setSequence(new Sequence(Sequence.PPQ, 24));
sequencer.setTickPosition(0);
sequencer.startRecording();
  • Finish the recording
sequencer.stop();

// save to SMF file
StandardMidiFileWriter writer = new StandardMidiFileWriter();
FileOutputStream outputStream = new FileOutputStream(new File(path, "saved.mid"));
writer.write(sequencer.getSequence(), 1, outputStream);
fos.flush();
fos.close();

Additional Function

  • UsbMidiReceiver
    • setCableId(int) / getCableId() to set the cable ID. The default cable ID is 0.
  • MidiSystem.MidiSystemUtils
    • getReceivers() / getTransmitters() can get all of the connected devices.