I'm working on a simple MIDI parser that converts MIDI files to a different format, and one issue I'm facing is that occasionally I'll get some tracks in the MIDI file that don't have any assigned instrument to them (no program change events)
Here's the truncated section of the code that looks for program change events specifically. Forgive me for the messy formatting, I'm new to this and had some trouble getting code pasted, but hopefully the general idea is still clear.
private static final int PROGRAM_CHANGE = 0xC0;
ArrayList<Note> noteSequence = new ArrayList<Note>();
int trackNumber = 0;
for (Track track : sequence.getTracks()) {
trackNumber++;
for (int i = 0; i < track.size(); i++) {
MidiEvent event = track.get(i);
MidiMessage message = event.getMessage();
currentTick = event.getTick();
ShortMessage sm = (ShortMessage) message;
if (sm.getCommand() == PROGRAM_CHANGE) {
noteSequence.add(new Note(currentTick+1,sm.getData1(),0,trackNumber,0,"PROGRAM_CHANGE",0,0,0, 2));
}}
One of the main issues I might be facing is just grabbing program change events the wrong way. They don't seem to have a tick associated with them so I've just been giving them the timing event of the previous tick + 1. I'm not sure if this is the proper way to do it, so this might be causing some issues.
For example, one MIDI file I ran through it had 23 tracks. Every track except for track #8 had an assigned instrument, and I'm at a loss at why #8 would not have an instrument assigned to it. I presume it's meant to inherit it's instrument based on another track, but I'm not too knowledgable on how that would work.
Other events such as NOTE_ON events are being captured correctly from these tracks however. I know this is a bit of a niche issue, but does anyone have any insights into this?
Yes, this can happen. The Midi specification does not enforce the use of Program Changes. It really depends for what purpose the Midi files were designed. For maximum portability it's normally better to add GM Program Changes for each used Midi channel. Note that for non-GM Midi devices you usually specify an instrument using Bank Select and Program Changes messages.
Also, you might find Midi files on the web designed for a specified synth, or VST, which uses synth-specific SysEx messages to select the instrument.
Yes they do. Though tick is often 0 because Program Changes are usually at the start of the song. But it happens that some songs change the instrument in the middle of the song, so with a tick position > 0.
If you want an example of a complete open-source Midi file parser: https://github.com/jjazzboss/JJazzLab-X/tree/master/Midi/src/org/jjazz/midi/api/parser