MID Format

From ModdingWiki

Jump to: navigation, search

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.

Contents

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 typeNameDescription
BYTE[4]cSignature"MThd" (not NULL-terminated)
UINT32BEiLengthLength of MThd block (usually 6)
UINT16BEiType0, 1 or 2 (for format-0, 1 or 2)
UINT16BEiNumTracksNumber of tracks (will be 1 for format-0)
UINT16BEiTicksPerQuarterNoteNumber 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 typeNameDescription
BYTE[4]cSignature"MTrk" (not NULL-terminated)
UINT32BEiLengthLength of block
BYTE[iLength]cDataMIDI 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) >> 1) | (0x50 & 0x7F)

Here is some C code to read these values:

C code
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 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 valueEvent numberData sizePurpose
0x8002Note off
0x9012Note on
0xA022Polyphonic key pressure
0xB032Controller
0xC041Instrument change
0xD051Channel pressure
0xE062Pitch bend
0xF07AnySysex
0xFFN/AAnyMeta-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.

Running-status

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 bytesPurpose
UINT8 iNoteMIDI note number to key-off (0-127)
UINT8 iVelocityHow 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 bytesPurpose
UINT8 iNoteMIDI note number to key-on (0-127)
UINT8 iVelocityHow hard to press the note (0-127)
0xA0: Polyphonic key pressure
Data bytesPurpose
UINT8 iPressurePressure value (0-127)
UINT8 iNoteMIDI note number to affect (0-127)
0xB0: Controller

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

Data bytesPurpose
UINT8 iControllerController index (0-127)
UINT8 iValueValue to set (0-127)
0xC0: Instrument change

Set the channel to the specified instrument.

Data bytesPurpose
UINT8 iInstrumentInstrument number (0-127)
0xD0: Channel pressure
Data bytesPurpose
UINT8 iPressurePressure value (0-127)
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 bytesPurpose
UINT8 iLSBLeast significant byte (0-127)
UINT8 iMSBMost 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 bytesPurpose
MIDILEN iLengthLength 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 typePurpose
0xF0Start system exclusive event
0xF1MIDI time code
0xF2Song position pointer
0xF3Song select
0xF4(Unused)
0xF5(Unused)
0xF6Tune request
0xF7End system exclusive event (EOX)
0xF8Timing clock
0xF9(Unused)
0xFAStart playback
0xFBContinue playback
0xFCStop playback
0xFD(Unused)
0xFEActive sensing
0xFFSystem 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 bytesPurpose
UINT8 iTypeMeta-event type
MIDILEN iLengthLength 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 typeText use
0x01Generic text event. Often the first text event in a song is used as its title.
0x02Copyright notice
0x03Track name. Often the first event (format-0) or the first track (format-1) is the song title.
0x04Instrument name
0x05Lyric
0x06Marker
0x07Cue 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.

Additional meta-events

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

Tools

  • DRO2MIDI - converts .dro files into .mid files

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

Personal tools
programming