Search code examples
python-3.xmidifile-type

how do multi-track midi files work?


I'm working on a project that analyses MIDI files and calculates the scale but i've hit a wall.

I can find all the notes of a single track song (i.e only one instrument is playing) but i get a weird number with multi-track MIDIs.

I made a MIDI with: 88 C notes, 32 C#, 16 D, 68 G and 36 E. When i put that MIDI file through my analyser i get: 2 C notes, 2 C# and 1 G

Here's how the MIDI file looks like when i put it into ableton: https://i.sstatic.net/wRGPX.jpg

And here's my code in it's entirety (sorry if its really ugly / bad i'm fairly new): http://pastebin.com/r7YkgqMB

It's really hard to find information about how the MIDI files are build but here are my main two sources (Maybe it's them that are wrong?): Source 1, Source 2

Relevant bit:

for i in range(0, len(midi_bytes) - 3): # iterates through the midi (without head chunk)
    # Looks for start of track chunk (MTrk)
    if midi_bytes[i][1:3] + \
       midi_bytes[i + 1][1:3] + \
       midi_bytes[i + 2][1:3] + \
       midi_bytes[i + 3][1:3] == "4D54726B":
        # Found a track chunk

        # How long is the chunk?
        len_of_chunk = int(midi_bytes[i + 4][1:3] +
                           midi_bytes[i + 5][1:3] +
                           midi_bytes[i + 6][1:3] +
                           midi_bytes[i + 7][1:3], 16)

        # iterates through that chunk (from 8 bytes after chunk start to length of chunk + 8 (from the 8 after))
        for j in range(9, len_of_chunk + 8):
            # Looks for keys

            bit = int(midi_bytes[j][1:3], 16)

            if midi_bytes[j - 1][1] == "8" and bit <= 127: 

Then it checks what the byte following the 8 (which should be the stop note command) mod 12 is (if = 0 then its a c, = 1 is c# etc.)


Solution

  • You cannot simply search for bytes with 8 in the upper nibble. A note-off message can be encoded as a note-on message with a velocity of zero, and status bytes can be omitted in certain circumstances (running status). Furthermore, bytes that encode delta times also can have such a value.

    You have to correctly parse the MIDI file. (And read the official Standard MIDI Files (SMF) Specification.)