Reversed MIDI Chunk Length
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 }
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
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.
In reply to Both your files correctly… by hmmueller
Huh. You're right. When reading as char and shift them one by one, it shows the correct length.
I've never heard of endianness before this. I'll check it out.
Posting this problem in Musescore forum now feels awkward, but thanks for the help.
In reply to Huh. You're right. When… by ViNata
Check https://manpages.ubuntu.com/manpages/trusty/man3/byteorder.3.html