Search code examples
cmidi

Generating MIDI-files in C


I'm trying to generate MIDI files in C but I'm having bit trouble with the header chunk of the file.

So the MIDI header is in form of:

chunk type-length-format-ntrks-division

The chunk type is the four ASCII characters 'MThd'; length is a 32-bit representation of the number 6 (high byte first). The rest are 16 bits.

So I created a Struct for the Header which is the following:

struct headerStruct {
    char chunktype[4]; //MThd
    long length; //32bit length
    int format;//16bit format
    int ntraks;//16bit number of tracks
    int division;//16bit division
};

Then I'm creating the struct in the code:

struct headerStruct *mthd = malloc(sizeof(struct headerStruct));
strncpy(mthd->chunktype, "MThd",4);
mthd->length = 6;
mthd->format = 0;
mthd->ntraks = 1;
mthd->division = 96;

And then I write the file (also with additional stuff not presented here) with fwrite, I'll leave that part of the code out. But if I look at the binary/hex with xxd and compare it to a correct midi file created with let's say ableton I see that they are different and mine is incorrect.

Correct midi header in hex:

4d54 6864 0000 0006 0000 0001 0060

My incorrect midi header in hex:

4d54 6864 0000 0000 0600 0000 0000 0000 0000 0100 6000 0000

What causes this? Is it an endianness issue or am I using wrong data types. I'm on 64bit os X 10.10.5. Because if I understood correctly 16 bit parts in the header should be ints and the length(32bit) long and so on. If it is an endianness thing how can I correct this. I read some endianness topics here but didn't really understand them.

Here's a link to pdf for more information on MIDI: https://www.cs.cmu.edu/~music/cmsip/readings/Standard-MIDI-file-format-updated.pdf


Solution

  • MIDI files require that the values be written in big-endian byte order, aka "network order"; you may find htnol(3) and htons(3) to be useful:

    #include <arpa/inet.h>
    ...
    mthd->length = htonl(6);
    mthd->ntraks = htons(1);
    ...