Java MIDI Sequence.getTracks() wrong number

173 Views Asked by At

I'm trying to get the number of Tracks of a MIDI sequence:

File file = new File(strSource);
Sequence sequence = MidiSystem.getSequence(file);
int numTracks = sequence.getTracks().length;

... where strSource is the full path+file name of my .mid file. numTracks is 1, but the .mid file has 16 tracks (as i can see when i open it in another MIDI editor). The file type is 0.

I read somewhere that type-0 files can't have multiple tracks for the same channel. In this case all tracks are forced into a single track. Is that correct? How can I avoid that?

3

There are 3 best solutions below

3
On

It seems you're right, type-0 files hold multiple tracks in just one. Here you have some info.

Isn't possible to extract each separate track from a type 0 file.

Check MIDI file type, if an external MIDI editor can detect multiple tracks, it can be a type 1 or type 2 file, even if extension doesn't match.

0
On

I looked at the file with a hex tool ... It actually has only one track.

The other editor creates the multiple Tracks by itself. It seems to search for program change messages and then put the events into new tracks.

0
On

I have programmed a small function that converts a Type # 0 sequence to a Type # 1 sequence

/**
 * Make multiple tracks from file0 track
 * @param in : Sequence with single track
 * @return Multiple track sequence
 */
private Sequence extractFile0Tracks (Sequence in) throws InvalidMidiDataException
{
    Track inTrack = in.getTracks()[0];
    HashMap<Integer, ArrayList<MidiEvent>> msgMap = new HashMap<>();

    // Distribute events per channel to ArrayList map
    for (int i = 0; i < inTrack.size(); i++)
    {
        MidiEvent event = inTrack.get(i);
        MidiMessage message = event.getMessage();
        if (message instanceof ShortMessage)
        {
            ShortMessage sm = (ShortMessage) message;
            int channel = sm.getChannel() + 1;
            ArrayList<MidiEvent> msgList = msgMap.computeIfAbsent(channel, k -> new ArrayList<>());
            msgList.add(event);
        }
    }

    // Create sequence with multiple tracks
    Sequence newSeq = new Sequence(in.getDivisionType(), in.getResolution());
    for (ArrayList<MidiEvent> msgList : msgMap.values())
    {
        Track tr = newSeq.createTrack();
        for (MidiEvent m1 : msgList)
            tr.add(m1);
    }

    return newSeq;
}