Standard MIDI FIle (SMF) Format 1.0
Header Chunk |
Track Chunk |
[Track Chunk] |
• • • |
SMF = <header_chunk> + <track_chunk> [+ <track_chunk> ...]
type | length | Data | ||
---|---|---|---|---|
MThd | 6 | <format> | <tracks> | <division> |
MTrk | <length> | <delta_time> <event> ... | ||
: | ||||
MTrk | <length> | <delta_time> <event> ... |
header_chunk = "MThd" + <header_length> + <format> + <n> + <division>
Chunk header |
"MThd"
(4bytes) |
the literal string MThd, or 0x4d546864. These four characters
at the start of the MIDI file indicate that this is a MIDI file. |
Header length |
4 bytes |
length of the header chunk in bytes (always 6--the size
of the next three fields). |
Format/type |
2 bytes |
0 = single track file format
1 = multiple track file format
2 = multiple song file format (i.e., a series of type
0 files) |
Number of tracks |
2 bytes |
number of track chunks that follow the header chunk (always
1 for type 0) |
Division |
2bytes |
Unit of time for delta timing. If the positive, it
represents the units per beat, e.g, +64 would mean 64 ticks per beat.
If negative, delta times are in SMPTE compatible units. |
TRack header Chunk
Chunk header |
"MTrk" (4bytes) |
the literal string MTrk, or 0x4d546864.
These four characters at the start of each MIDI track. |
Data length |
4 bytes |
length of the track data |
MTrk events |
n bytes |
<delta-time> <event>, • • •
|
[MTrk events] • • • |
n bytes |
<delta-time> <event>, • • • |
A track may contain up to 16 MIDI channels
<Track Chunk> = <chunk type> <length> <MTrk event>+<MTrk
event>+...
<MTrk event> = <delta-time> <event>
<delta-time> is stored as a variable-length quantity. It represents the
amount of time before the following event.
<event> = <MIDI event> | <sysex event> | <meta-event>
<meta-event>
http://ourworld.compuserve.com/homepages/mark_clay/midi.htmSome numbers in MIDI Files are represented in a form called a variable-length quantity, e.g. <delta-time>. These numbers are represented 7 bits per byte, most significant bits first. All bytes except the last have bit 7 set, and the last byte has bit 7 clear. If the number is between 0 and 127, it is thus represented exactly as one byte.
Here are some examples of numbers represented as variable-length quantities:
Number (hex) |
Representation (hex) |
00000000 | 00 |
00000040 | 40 |
0000007F | 7F |
00000080 | 81 00 |
00002000 | C0 00 |
00003FFF | FF 7F |
00004000 | 81 80 00 |
00100000 | C0 80 00 |
00lFFFFF | FF FF 7F |
00200000 | 81 80 80 00 |
08000000 | C0 80 80 00 |
0FFFFFFF | FF FF FF 7F |
// Take the input 'value' and prepare for output in 'buffer'. // Go from the least significant byte in 'value' (the rightmost byte) and // build 'buffer' in reverse byte order, i.e. the least significant // byte to the left. WriteVarLen (long value) { long buffer; // the encoded format in reverse order buffer = value & 0x7f; while ((value >>= 7) > 0) // build buffer { buffer <<= 8; // shift to left by 8 bits (one byte) buffer |= 0x80; // set the leftmost bit buffer += (value & 0x7f); // strip the leftmost bit then add } while (1) // output section { putc(buffer, outfile); // ouput rightmost byte if (buffer & 0x80) // if not the last byte (leftmost bit is zero) buffer >>= 8; // get the next byte else break; } } unsigned long ReadVarLen (void) { unsigned long value; char c; if ((value = getc(infile)) & 0x80) // if more than one byte { value &= 0x7F; // strip the lefmost bit do // shift left 7 bits and add the next byte { // without the leftmost bit value = (value << 7) + ((c = getc(infile)) & 0x7F); } while (c & 0x80); // while not the last byte } return value; }