Get MIDI file format


#1

How can I extract MIDI file format with JUCE? 
I've searched in MIDI Message and MIDI File classes but couldn't find this exact thing. 
Should I extract a value from header chunk by myself, or is there a function for that I'm overlooking? 


#2

Do you mean: How to get a list of MIDI events from a MIDI-file?

If so, e.g.:

File F = ...;   FileInputStream S(F);
MidiFile midifile;
midifile.readFrom(S);
midifile.convertTimestampTicksToSeconds();
  
MidiMessageSequence seq;
seq.clear();
for (int t = 0; t < midifile.getNumTracks(); t++)
    seq.addSequence(* midifile.getTrack(t), 0.0 /*timeAdjustmentDelta*/);
seq.updateMatchedPairs();

That example flattens all tracks into a single sequence.

Then you can do e.g.

seq.getEventPointer(42)->message.getNoteNumber()

To play as audio, you'll probably want to manually create a MidiBuffer from the sequence.

π

PS It would be nice to have an iterator, to allow:

for (auto& track : midifile.getTracks()) ...

#3

I think he means Type 0/1/2 midi files.  however, your code suggest that JUCE internally doesn't care what kind of midi file it receives when you load it into a MidiMessageSequence object.  

https://www.csie.ntu.edu.tw/~r92092/ref/midi/

Type 0

Format 0 MIDI files consist of a header-chunk and a single track-chunk.
The single track chunk will contain all the note and tempo information.

Type 1

Format 1 MIDI files consist of a header-chunk and one or more track-chunks, with all tracks being played simultaneously.

The first track of a Format 1 file is special, and is also known as the 'Tempo Map'. It should contain all meta-events of the types Time Signature, and Set Tempo. The meta-events Sequence/Track Name, Sequence Number, Marker, and SMTPE Offset. should also be on the first track of a Format 1 file.

Type 2

Format 2 MIDI files consist of a header-chunk and one or more track-chunks, where each track represents an independant sequence.

 

Juce internally cares about the file type as shown here: 

JUCE/modules/juce_audio_basics/midi/juce_MidiFile.cpp line 260

But externally the MidiFile class doesn't.   And neither should you!


#4

Thanks, that's an answer I needed.


#5

I have a followup in this question. Why is there not a getFileType() method on class MidiFile. There is for example a method for getTimeFormat(). In juce_MidiFile.cpp line 266 the file type is read but assigned to a local variable.

I made fileType a class property defined:

short MidiFile::getFileType() const noexcept
{
return fileType;
}

And it seems to return correct types for type 0 and1 midi files. (I didn’t have a type 2 to test).

So should it be supported, or is there a reason why it isn’t?


#6

If the MIDI file is format 0, does the JUCE MidiFile class break the events into different tracks based on the MIDI channel number of the event? If so, I agree that you don’t need to know whether you have a format 0 or format 1.

However, if it’s a format 0 file and the data is not split, then you definitely care whether it’s a format 0 or format 1 file because on a multi-track file, you often won’t care about the actual MIDI channel of an internal event and you’ll want to assign instruments based on the track number, not the MIDI channel number.


#7

And a quick test shows that MidiFile class does not in fact break up different channels into tracks so in fact you do need to know the format.


#8

Sounds like a good request.

Rail