Skip to content

How to work with SMF

Kaoru Shoji edited this page Jul 23, 2014 · 1 revision

The javax.sound.midi porting has a UsbMidiSequencer class, this class can read and write the SMF(Standard MIDI File).

Setup the MidiSystem

To use the MidiSystem, the application must call MidiSystem.initialize(Context) and MidiSystem.terminate() method.

Initialization

Call MidiSystem.initialize(Context) method at onCreate in the Activity or Fragment.

@Override
public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    
    MidiSystem.initialize(this);
}

Termination

Call MidiSystem.terminate() method at onDestroy in the Activity or Fragment.

@Override
protected void onDestroy() {
    super.onDestroy();
    
    MidiSystem.terminate();
}

Play a SMF

Load, and play the SMF

  • Obtain Sequencer from MidiSystem.getSequencer().
  • Open Sequencer with Sequencer.open() method, and set a Sequence from SMF file.
    • The asset file in app, or normal file path can be read.
  • Start the sequencer with calling Sequencer.start() method, then the sequencer thread starts playing the SMF data.
Sequencer sequencer = null;

public void onPlayButtonClick() {
    try {
        sequencer = MidiSystem.getSequencer();
        sequencer.open();
        sequencer.setSequence(getAssets().open("example.mid"));
        sequencer.start();
    } catch (MidiUnavailableException e) {
        e.printStackTrace();
    } catch (InvalidMidiDataException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Stop playing SMF

  • Just call Suquencer.stop() method.
  • Sequencer.close() can be used if the application don't need the Sequencer.
    • The another Sequencer instance can be obtained by calling MidiSystem.getSequencer() method again.
public void onStopPlayingButtonClick() {
    if (sequencer != null && sequencer.isOpen()) {
        sequencer.stop();
        sequencer.close(); // if the application don't need the Sequencer anymore.
    }
}

Record MIDI data as a SMF

Record a MIDI sequence

  • Obtain Sequencer from MidiSystem.getSequencer().
  • Open Sequencer with Sequencer.open() method, and set a new Sequence.
  • Start the sequencer with calling Sequencer.startRecording() method, then the sequencer thread starts recording the Sequence data.
Sequencer sequencer = null;

public void onRecordButtonClick() {
    try {
        sequencer = MidiSystem.getSequencer();
        sequencer.open();
        sequencer.setSequence(new Sequence(Sequence.PPQ, 480));
        sequencer.startRecording();
    } catch (MidiUnavailableException e) {
        e.printStackTrace();
    } catch (InvalidMidiDataException e) {
        e.printStackTrace();
    }
}

Stop recording and save sequence as SMF

  • Just call Sequencer.stopRecording() method.
  • Sequencer.close() can be used if the application don't need the Sequencer.
    • The another Sequencer instance can be obtained by calling MidiSystem.getSequencer() method again.
public void onStopPlayingButtonClick() {
    if (sequencer != null && sequencer.isOpen()) {
        sequencer.stopRecording();
        try {
            MidiSystem.write(sequencer.getSequence(), 0, 
                new File(Environment.getExternalStorageDirectory().getPath(), "recording.mid"));
            // Note: this requires the 'WRITE_EXTERNAL_STORAGE' permission
        } catch (IOException e) {
            e.printStackTrace();
        }

        sequencer.close(); // if the application don't need the Sequencer anymore.
    }
}