MID Format

From ModdingWiki
Jump to navigation Jump to search
MID Format
Format typeMusic
Notation typeMIDI
Max channel count16
Max track count65535
Max pattern count1
Max order count0
Tags?Text events

The Musical Instrument Digital Interface (MIDI) file format is used for storing the notes required to accurately reproduce a song. Commercial instruments are available that "speak" the MIDI protocol, and a MIDI file (.mid) simply stores the data sent over the wire, with a few headers on the front.

File format

A MIDI file starts with an overall MThd header, followed by one or more MTrk headers for each "track" (a track is normally created for each instrument, for simplicity when the song is being composed.)

MThd Header

The file begins with a header:

Data type Name Description
BYTE[4] cSignature "MThd" (not NULL-terminated)
UINT32BE iLength Length of MThd block (usually 6)
UINT16BE iType 0, 1 or 2 (for format-0, 1 or 2)
UINT16BE iNumTracks Number of tracks (will be 1 for format-0)
UINT16BE iTicksPerQuarterNote Number of MIDI delay ticks in a quarter-note

If the high bit in iTicksPerQuarterNote is set (0x8000) then the file uses SMPTE timing instead, which is rare and not covered here.

MTrk block

The MTrk block is repeated once for each track in the song (the iNumTracks field in the MThd header.)

Data type Name Description
BYTE[4] cSignature "MTrk" (not NULL-terminated)
UINT32BE iLength Length of block
BYTE[iLength] cData MIDI data

MIDI data

The MIDI data consists of a delay value (in MIDI variable-length integer notation), followed by a MIDI event byte (see #MIDI events below.) The event data follows, and will be different depending on the event. It then starts again with the delay value for the next event.

MIDI lengths

MIDI lengths are stored as variable length integers, between one and four bytes long. Each byte only uses the lower 7-bits, with the MSB set if there is another length byte following. The bytes are in big endian order. Some examples of these length bytes are:

 50      // Hex value 0x50
 81 50   // Hex value 0xD0 ((0x81 & 0x7F) << 7) | (0x50 & 0x7F)

Here is some C code to read these values:

const char *midi_data = "\x81\x50";
unsigned long val = 0;

for (int i = 0; i < 4; i++) {

	// Include the lower 7-bits of this byte into the value
	val |= midi_data[i] & 0x7F;

	// If the high bit is set, shift the value up
	// seven bits to make room for the next value
	if (midi_data[i] & 0x80) val <<= 7;
	else break; // High bit unset means end of value

printf("Value is %lu\n", val);

Generally variable-length integers are defined to be unsigned numbers. However, some MIDI files in the wild assume that delays are measured as signed 32-bit integers, which is used to shift some MIDI events at the start of the file into the negative range. For this reason, if the first delay value on a channel is 2,147,483,648 or greater, it should be treated as a signed number instead.

Generally speaking, MIDI data that can be sent over the wire uses these values (e.g. delays), whereas data only used to write .mid files on disk (e.g. MTrk lengths in bytes) use normal big-endian fixed-length values.

MIDI events

This table lists the different MIDI events that can occur in a song. The events are listed as channel zero (e.g. 0x80, which would become 0x85 for channel five.) Removing the high bit ((byte & 0x7F) >> 4) will give the 'event number'.

Register value Event number Data size Purpose
0x80 0 2 Note off
0x90 1 2 Note on
0xA0 2 2 Polyphonic key pressure
0xB0 3 2 Controller
0xC0 4 1 Instrument change
0xD0 5 1 Channel pressure
0xE0 6 2 Pitch bend
0xF0 7 Any Sysex
0xFF N/A Any Meta-event

The data bytes for each event are described in the sections below.

Each event is preceded by a delay (as a MIDILEN variable-length integer, see #MIDI lengths above) which specifies the number of MIDI ticks until the event should be actioned.

To convert the number of MIDI ticks into a usable time value, the iTicksPerQuarterNote field from the header will allow the tick count to be converted into a fractional number of quarter notes, then the song's tempo (in microseconds per quarter note) will allow this fractional number of quarter notes to be converted into microseconds.

The default tempo of 500,000 microseconds per quarter note applies until overridden by a set-tempo event.


Any event values without the high-bit set (i.e. less than 0x80) are so-called "running status" values. If one of these bytes is encountered as a MIDI event, it is actually the first data byte of the event instead. The actual event is the same as the previous one. For example, these two lines are equivalent: (delay bytes omitted for clarity)

90 40 7F   91 44 7F   91 47 7F   81 44 7F  (full syntax)
90 40 7F   91 44 7F      47 7F      44 00  (with running status)

This means:

  • 90 40 7F: Turn note 0x40 on channel 0 at maximum velocity
  • 91 44 7F: Then turn note 0x44 on channel 1 at maximum velocity
  • 47 7F: Turn note 0x47 on the same channel (running status means use event 0x91 from before)
  • 44 00: Turn note 0x44 off on the same channel (running status uses event 0x91 again, and takes advantage of note-on at zero velocity being the same as note-off)

Meta-events do not affect running status, so any event from 0xF0 to 0xFF can appear in the middle of data without affecting the running status. For example the following line is equivalent to the two lines above:

90 40 7F   91 44 7F   FF 01 02 AA BB   47 7F   F0 02 AA F7   44 00
0x80: Note off

Stops the specified note from sounding on this channel. Does not affect any other notes currently being played on the same channel. A note-on event with a velocity of zero is the same as a note-off event.

Data bytes Purpose
UINT8 iNote MIDI note number to key-off (0-127)
UINT8 iVelocity How hard to release the note (0-127)
0x90: Note on

Plays the specified note on the given channel. Multiple notes can be sounding at the same time on the same channel. A velocity of zero is the same as a note-off event (this is often used with running status to minimise the amount of data used.)

Data bytes Purpose
UINT8 iNote MIDI note number to key-on (0-127)
UINT8 iVelocity How hard to press the note (0-127)
0xA0: Polyphonic key pressure
Data bytes Purpose
UINT8 iPressure Pressure value (0-127)
UINT8 iNote MIDI note number to affect (0-127)

Like channel pressure, but applies to individual notes on the channel.

0xB0: Controller

Set a MIDI controller to the specified value. TODO: List of standard controllers

Data bytes Purpose
UINT8 iController Controller index (0-127)
UINT8 iValue Value to set (0-127)
0xC0: Instrument change

Set the channel to the specified instrument.

Data bytes Purpose
UINT8 iInstrument Instrument number (0-127)
0xD0: Channel pressure
Data bytes Purpose
UINT8 iPressure Pressure value (0-127)

Also known as "channel aftertouch", it is designed for instruments that can have their volume/intensity changed after the initial velocity set in the note-on event, such as woodwind instruments where a note can start softly and then become louder. The exact meaning is implementation-defined. For example, this event may set the volume of the notes currently playing on the channel in a similar way as velocity in a note-on event, but other possibilites include applying a filter change or vibrato to the notes.

0xE0: Pitch bend

Bend all notes on the channel up or down by the specified amount. The value is between 0 and 16384. The value 8192 is in the middle and means no bend, thus 8192 can be subtracted from this the value to create a signed integer between -8192 and +8191, with zero meaning "no bend." The actual pitch resulting from the bend depends on the range, which is set (usually at the start of the song) by a MIDI controller message.

Data bytes Purpose
UINT8 iLSB Least significant byte (0-127)
UINT8 iMSB Most significant byte (0-127)

The value is calculated by combining the lower seven bits from each of the two bytes into a single 14-bit value: value = (iMSB << 7) | iLSB

0xF0: System exclusive

These messages are used to send proprietary commands to various MIDI devices. They are essentially a list of raw bytes to send. The channel is not used, so 0xF0 through 0xFF are different "sysex" messages. Since 0xFF is used as a reset it would have no use in a .mid file on disk, so this event is used for meta-events described below.

The event type (0xF0 to 0xFE) is followed by this structure:

Data bytes Purpose
MIDILEN iLength Length of data
UINT8 cData[iLength] Block of data, iLength bytes long

Event 0xFF has a different structure and is covered below. The event types are defined as follows:

Event type Purpose
0xF0 Start system exclusive event
0xF1 MIDI time code
0xF2 Song position pointer
0xF3 Song select
0xF4 (Unused)
0xF5 (Unused)
0xF6 Tune request
0xF7 End system exclusive event (EOX)
0xF8 Timing clock
0xF9 (Unused)
0xFA Start playback
0xFB Continue playback
0xFC Stop playback
0xFD (Unused)
0xFE Active sensing
0xFF System reset (used for meta-event in a MIDI file)

Meta events

Meta events are events specific to MIDI files themselves. They are not transmitted to MIDI devices. A meta event is signalled by the 0xFF system exclusive event. The following table lists the format of the bytes following the 0xFF.

Data bytes Purpose
UINT8 iType Meta-event type
MIDILEN iLength Length of event data
UINT8 cData[iLength] Event data

The following section lists the meaning of various values of iType.

0x01 - 0x0F: Text

These events set various types of text. The event data is the text to set.

Event type Text use
0x01 Generic text event. Often the first text event in a song is used as its title.
0x02 Copyright notice
0x03 Track name. Often the first event (format-0) or the first track (format-1) is the song title.
0x04 Instrument name
0x05 Lyric
0x06 Marker
0x07 Cue point (e.g. stage instructions)
0x2F: End of track

Mandatory event at the end of each MTrk track. The length field is always zero, so there are no bytes of event data.

0x51: Set tempo

This event should always have a length of three. The event data is a big-endian integer (not in MIDI variable-length notation) indicating the number of microseconds in a quarter note. Together with the iTicksPerQuarterNote value from the header, this allows MIDI ticks to be converted into microseconds for correct playback speed of the MIDI file.

Unless overridden by this event, the number of microseconds in a quarter note defaults to 500,000.

0x7F: Manufacturer-specific

The first data byte of this event is a manufacturer ID. If it is 0x00, then the following UINT16BE is the actual manufacturer ID. This means either one or three bytes total will be read to obtain the manufacturer ID.

If the manufacturer ID is 0x3F then it is an Ad Lib, Inc. event, and the file format is technically .mdi (an Ad Lib MIDI file with embedded OPL instruments), see MDI Format for details.

Additional meta-events

Other meta-events (not so important for playing back game music) are listed on various web sites:


Some extensions to the format are in use, which work by defining custom controllers, meta events, and so on - but otherwise leave the format unchanged and the files are still readable/playable by normal programs.

  • Apogee Expanded MIDI defines MIDI controllers for muting tracks depending on the sound card in use as well as for looping parts of tracks, co-designed by Lee Jackson.
  • MDI files provide a method for storing OPL register settings for instruments. In this respect the format is functionally equivalent to CMF, but where CMF uses a custom wrapper around the MIDI data, MDI is entirely standard MIDI.


Similar formats

  • CMF files store their song data in MIDI format.
  • MUS files are single-track MIDI files made by id Software.
  • XMI files are Extended MIDI files.

External links