MIDI file format
MIDI files contain MIDI messages, along with timing information.
This page describes MIDI files, but the MIDI messages themselves are out-of-scope.
- See the MIDI messages page to learn more about them.
- See the MIDI hardware interface page for what happens inside a physical MIDI cable.
Extension | .mid | |
MIME type | audio/midi |
Example MIDI file
Bytes | Δt | Message |
---|---|---|
4D546864 00000006 | Header chunk start : length = 6 | |
0001 | → track_format = .simultaneous_tracks | |
0003 | → num_tracks = 3 | |
0180 | → time_config = { .ticks_per_quarter_note, 384 } | |
4D54726B 00000050 | Track chunk start : length = 80 | |
00 FF03 09 | 0 | .sequence_or_track_name (9 bytes) : "SomeTitle" |
536F6D655469746C65 | ||
00 FF01 09 | 0 | .text (9 bytes) : "creator: " |
63726561746F723A20 | ||
00 FF01 1E | 0 | .text (30 bytes) : "LilyPond 2.24.2 " |
4C696C79506F6E6420322E32342E32 | ||
202020202020202020202020202020 | ||
00 FF5804 04 02 18 08 | 0 | .time_signature |
00 FF5103 0F 42 40 98 | 0 | .set_tempo |
00 FF2F 00 | 0 | .end_of_track |
4D54726B 0000005A | Track chunk start : length = 90 | |
00 FF03 06 | 0 | .sequence_or_track_name (6 bytes) : "upper:" |
75707065723A | ||
00 C0 0C | 0 | .program_change : SoundSet.marimba (0C ) |
00 C0 0C | 0 | .program_change : SoundSet.marimba (0C ) |
00 FF04 07 | 0 | .instrument_name (7 bytes) : "marimba" |
6D6172696D6261 | ||
00 FF59 020000 | 0 | .key_signature : TODO |
00 903C5A | 0 | NoteOn(C4, v=90) |
8300 903C00 | 384 | NoteOn(C4, v=0) |
00 90405A | 0 | NoteOn(E4, v=90) |
8300 904000 | 384 | NoteOn(E4, v=0) |
00 90435A | 0 | NoteOn(G4, v=90) |
8300 904300 | 384 | NoteOn(G4, v=0) |
8300 903C5A | 384 | NoteOn(C4, v=90) |
00 90405A | 0 | NoteOn(E4, v=90) |
00 90435A | 0 | NoteOn(G4, v=90) |
8C00 903C00 | TODO | NoteOn(C4, v=0) |
00 904000 | 0 | NoteOn(E4, v=0) |
00 904300 | 0 | NoteOn(G4, v=0) |
00 FF2F00 | 0 | .end_of_track |
4D54726B 00000052 | Track chunk start : length = 82 | |
00 FF03 06 | 0 | .sequence_or_track_name (6 bytes) : "lower:" |
6C6F7765723A | ||
00 C1 0C | 0 | .program_change : SoundSet.marimba (0C ) on channel 2 |
00 C1 0C | 0 | .program_change : SoundSet.marimba (0C ) on channel 2 |
00 FF04 07 | 0 | .instrument_name (7 bytes) : "marimba" |
6D6172696D6261 | ||
00 FF59020000 | 0 | .key_signature : TODO |
00 91305A | 0 | NoteOn(C3, v=90, channel=2) |
8300 913000 | 384 | NoteOn(C3, v=0, channel=2) |
00 91305A | 0 | NoteOn(C3, v=90, channel=2) |
8300 913000 | 384 | NoteOn(C3, v=0, channel=2) |
00 91305A | 0 | NoteOn(C3, v=90, channel=2) |
8300 913000 | 384 | NoteOn(C3, v=0, channel=2) |
00 91305A | 0 | NoteOn(C3, v=90, channel=2) |
8300 913000 | 384 | NoteOn(C3, v=0, channel=2) |
00 91305A | 0 | NoteOn(C3, v=90, channel=2) |
8C00 913000 | TODO | NoteOn(C3, v=0, channel=2) |
00 FF2F00 | 0 | .end_of_track |
Format details
A MIDI file consists of one header chunk ("MThd") followed by one or more track chunks ("MTrk").
Track chunks ("MTrk")
A track chunk starts with "MTrk" + length:
4D54726B "MTrk"
0000ABCD u32 -> length of the remainder of this chunk
...which is followed by one or more events.
Each event consists of a time delta (in ticks) plus the raw bytes of a MIDI message.
The last event must be an .end_of_track
MIDI message (FF2F00
).
Header chunk ("MThd")
Header chunks contain three things:
pub const Header = struct {
track_format: TrackFormat,
num_tracks: u16,
time_config: TimeConfig,
};
Example
4D546864 "MThd" (chunk type)
00000006 u32 -> len = 6
0001 u16 -> track_format = TrackFormat.SimultaneousTracks
0003 u16 -> num_tracks = 3
E728 u16 -> time_config = TimeConfig.withMillisecondTicks()
TrackFormat
u16 | Enum | JSON | Description |
---|---|---|---|
0 | .one_track | "one_track" | |
1 | .simultaneous_tracks | "simultaneous_tracks" | |
2 | .independent_tracks | "independent_tracks" |