Thread with 7 posts

jump to expanded post

today i have been writing a program that reads a midi file. as is typical for me, i decided to write my own parser.

so i've been consulting the “standard midi files specification” and “midi 1.0 detailed specification”, neither of which i had ever read before. it's been pretty fun! they're written in a refreshingly informal and thoughtful style that makes the purpose and form of everything clear. the protocol and file format are remarkably well-designed… very efficient encodings for example

Open thread at this post

things i appreciate about standard midi files (smf)

• it's a riff variant, like all good file formats!
• it doesn't waste space on optional or redundant info. the header chunk contains just three 16-bit integers: the format, track count and an elegantly bit-packed field that specifies the timing unit. the only other chunks are the tracks, and they contain nothing but events with attached time deltas. all optional data is specified using events; only one event (“end of track”) is mandatory.

Open thread at this post

some neat tricks standard midi files (smf) do to minimise the overhead versus raw midi data:

• delta times and event lengths use variable-length encoding. every event begins with a time delta, but it's usually a single byte!
• smf meta events steal their prefix encoding from midi system messages that ought not to be present in a midi file, so that the most common midi messages (e.g. note on/off) need no extra prefix
• common midi messages don't need a length prefix because they are fixed length

Open thread at this post

a typical midi message might be “on channel 15, depress key A4 with velocity 80”

midi can express this in three bytes:

9F 45 50

it packs the kind of message (9 = note on) and the channel number into the two nibbles of the first byte. the note number (decimal 69) and velocity are the second and third bytes respectively. efficient, right?

but if we depress two keys:

9F 45 50 46 50

2.5 bytes per message! the kind and channel number can be skipped, because they are unchanged :3

Open thread at this post