Reversed MIDI Chunk Length

• Aug 19, 2022 - 02:58

Hello, I don't know if this is the right place to ask this question. If not, I apologize and please kindly refer me to the right place.

I'm developing a MIDI decoder and I use MIDI files generated by Musescore to test it. I'm following MIDI format guidelines from here (https://www.personal.kent.edu/~sbirch/Music_Production/MP-II/MIDI/midi_…) and here (https://www.music.mcgill.ca/~ich/classes/mumt306/StandardMIDIfileformat…). Both of them specify that the length of a MIDI chunk should be 32 bits long, most significant bit first.

However, I found out that MIDI files generated by Musescore have their chunk sizes reversed. Is this intentional or an oversight? Am I understanding the guidelines correctly?

I also attached the source code and MIDI files I used to test this if that helps.

Any help will be appreciated. Thank you in advance.

C++ source code:

#include <iostream>
#include <fstream>
 
int main(int argc, char* argv[]) {
    char type[4];
    unsigned int length;
    char dummy;
 
    //Opens test.mid
    std::ifstream midi("test.mid", std::ios::binary);
 
    midi.read(type, 4 * sizeof(char)); //Should be MThd
    std::cout << type[0] << type[1] << type[2] << type[3] << '\n'; //Outputs MThd
 
    midi.read((char*)&length, sizeof(unsigned int)); //Should be 6
    std::cout << length << '\n'; //Outputs 100663296
 
    //Skip the next 6 bytes
    for (int i = 0; i < 6; i++) midi.read(&dummy, sizeof(char));
 
    midi.read(type, 4 * sizeof(char)); //Should be MTrk
    std::cout << type[0] << type[1] << type[2] << type[3] << '\n'; //Outputs MTrk
 
    midi.read((char*)&length, sizeof(unsigned int)); //Should be track chunk size of 49355
    std::cout << length << '\n'; //Outputs 3540189184
 
    //Skip the next 49355 bytes
    for (int i = 0; i < 49355; i++) midi.read(&dummy, sizeof(char));
 
    midi.read(type, 4 * sizeof(char)); //Should be MTrk
    std::cout << type[0] << type[1] << type[2] << type[3] << '\n'; //Outputs MTrk
 
    // Opens test2.mid
    midi.close();
    midi.open("test2.mid", std::ios::binary);
    std::cout << '\n';
 
    midi.read(type, 4 * sizeof(char)); //Should be MThd
    std::cout << type[0] << type[1] << type[2] << type[3] << '\n'; //Outputs MThd
 
    midi.read((char*)&length, sizeof(unsigned int)); //Should be 6
    std::cout << length << '\n'; //Outputs 100663296
 
    //Skip the next 6 bytes
    for (int i = 0; i < 6; i++) midi.read(&dummy, sizeof(char));
 
    midi.read(type, 4 * sizeof(char)); //Should be MTrk
    std::cout << type[0] << type[1] << type[2] << type[3] << '\n'; //Outputs MTrk
 
    midi.read((char*)&length, sizeof(unsigned int)); //Should be track chunk size of 16501
    std::cout << length << '\n'; //Outputs 1577189376
 
    //Skip the next 16501 bytes
    for (int i = 0; i < 16501; i++) midi.read(&dummy, sizeof(char));
 
    midi.read(type, 4 * sizeof(char)); //Should be MTrk
    std::cout << type[0] << type[1] << type[2] << type[3] << '\n'; //Outputs MTrk
}
Attachment Size
test2.mid 1.01 KB
test.mid 13.46 KB

Comments

Both your files correctly contain the length encoded as 00 00 00 06 - see the attachments, where I simply opened them with a text editor capable of showing hexadecimal.
So, the problem is your program: You assume that

midi.read((char*)&amp;length, sizeof(unsigned int)); //Should be 6

uses the bytes in "big-endian byte order", but, as Ira Gershwin told us, "this aint necessarily so". I dont know on which platform you compile and run your program, but you might want to check how to read number types from that byte stream.

Edit: The WP article linked above says:
...little-endianness is the dominant ordering for processor architectures (x86, most ARM implementations, base RISC-V implementations) and their associated memory.
So this might be the basic problem ... You might want to consult stackoverflow or the like to find out how to read an integer from the stream.

H.M.

Attachment Size
Test2.mid.jpg 40 KB
Test.mid.jpg 33.28 KB

Do you still have an unanswered question? Please log in first to post your question.