本文主要参考自Official MIDI Specifications
Chunks
每个MIDI文件由一系列chunk组成,每个chunk的前四个字节为魔数(magic number),是由四个ASCII字符所组成的类型标识。目前标准格式中已定义的chunk类型只有header和track两种,其魔数分别为"MThd"
和"MTrk"
,对于类型未被定义的chunk则应该被忽略。
每个chunk在其四字符类型之后紧跟一个32位无符号整数,意味这一chunk后续将要读入的字节个数,每个chunk已经读入的这八个字节不包含在内。
通常来说,一个MIDI文件中首先要存在一个header chunk,然后一系列track chunk紧随其后,格式大致如下:
MThd
MTrk
MTrk
...
Header Chunks
在目前的标准中,header chunk长度固定为14,其由五个部分所组成:
=
其中type固定为"MThd"
,format、ntrks、division均为16位,因此length固定为0x00000006
。
format指定了整个文件的组织结构,在当前的标准下,仅支持0x0000
、0x0001
、0x0002
这三种可能的值。
0 the file contains a single multi-channel track
1 the file contains one or more simultaneous tracks (or MIDI outputs) of a
sequence2 the file contains one or more sequentially independent single-track patterns
ntrks表示整个文件中track chunk的总个数,对于format为零的文件来说ntrks的值总是0x0001
。
最后的division表示了delta-times的含义,有metrical time和time-code-based time这两种形式,这取决于其最高位是否为零。
假如division最高位为零,那么就属于metrical time形式,这个16位无符号整数的意义为每个四分音符的ticks个数。否则属于time-code-based time形式,其低8位表示每帧的ticks个数,高8位为一个8位负数补码,有-24
、-25
、-29
、-30
这四种可能的值,其意义与SMPTE有关,以下内容摘抄自维基百科:
Sub-second timecode time values are expressed in terms of frames. Common supported frame rates include:
24 frame/sec (film, ATSC, 2K, 4K, 6K)
25 frame/sec (PAL (Europe, Uruguay, Argentina, Australia), SECAM, DVB, ATSC)
29.97 (30 ÷ 1.001) frame/sec (NTSC American System (US, Canada, Mexico, Colombia, etc.), ATSC, PAL-M (Brazil))
30 frame/sec (ATSC)
在这里可以发现,凭借division是完全不足以描述每个时间间隔的实际长度的。在规范中对此有所说明,在默认情况下,乐曲的节奏为4/4拍,速度为每分钟120拍。这类元数据应该在MIDI文件中被指定,对于format为0x0000
的文件应处于其track chunk
的开始,对于format为0x0001
的文件应包含在第一个track chunk
之内,对于format为0x0002
的文件应包含在每个track chunk
之中。
值得一提的是,未来的标准有可能会定义更多种类的format和chunk,甚至有可能为header chunk添加更多的参数从而使其length不再为0x00000006
,因此对于程序的实现者来说,遵守标准是十分必要的。
Track Chunks
无论format的取值是什么,Track Chunks的结构都是一致的:
在length后是一串连续的MTrk event,每个MTrk event由两部分组成:
=
这里的delta-time是一种variable-length quantity,其每个字节仅有7个有效位,最高位若非零则说明后面还有下一字节,最多可占据四个字节,因此其最大值为0x0fffffff
。以下为参考示例:
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 |
001FFFFF | FF FF 7F |
00200000 | 81 80 80 00 |
08000000 | C0 80 80 00 |
0FFFFFFF | FF FF FF 7F |
delta-time后紧跟的event有三种不同的类型:
= | |
MIDI event的第一个字节通常表示running status
,其最高位必须非零,对于sysex event和meta-event来说,这个字节分别为0xf0
或0xff
。
MIDI event
在每个track chunk中出现的第一个MIDI event必须指定running status,而对于后续的MIDI event,假如其紧跟在一个MIDI event后面,并且与前一个MIDI event有着同样的running status,那么这一个MIDI event的running status可以被省略。
每个MIDI event根据其running status高4位的不同而存在一个或两个单字节参数,这些参数的最高位均为零,running status的低4位表示channel的编号,每个MIDI event只会在对应的channel上造成影响。举几个例子,以16进制表示:高4位为C
意为Program Change,其跟随一个单字节参数,表示修改乐器音色;高4位为9
意为Note On,高4位为8
意为Note Off,这两者都跟随两个单字节参数,分别表示音高与力度。
中央C在MIDI event中的值为0x3c
,每升高半音则加一,每降低半音则减一,通过这种规律可以推断出标准音为0x45
。
channel最多有16个,每个channel之间是独立的,也就是说不同的channel可以通过Program Change同时使用不同的音色,而又由于Note On和Note Off也是独立的,因此同一个channel中也可以同时播放不止一个音符。不过打击乐通常位于第10号channel。
音色对照表见文章末尾。
sysex event
这是一种结构稍显复杂的事件信息,它可以包含一连串的sysex event
,其基本结构如下:
F0
这里length为bytes的长度,如果bytes不以0xf7
结尾,那么其后就要跟随一个变长的delta-time,然后在跟随下一个sysex event,就像这样:
F7
除第一个sysex event之外,后续跟随的sysex event首字节应为0xf7
,且最后一个sysex event的最后一字节应为0xf7
。以下是一串合法的sysex event示例:
F0 03 43 12 00
81 48
F7 06 43 12 00 43 12 00
64
F7 04 43 12 00 F7
以上部分的0x8148
和0x64
分别表示200-tick delta-time和100-tick delta-time。
meta-event
这一部分的格式是比较固定的:
FF
所有meta-event以0xff
起始,然后紧跟一个字节的type,再然后跟随一个变长的length,length的值即为bytes的长度。
在Standard MIDI Files 1.0中已经预定义了一部分meta-event,其中Copyright Notice应作为第一个track的第一个event,Sequence Number和Sequence/Track Name若存在则必须在任何delta-times非零的event前出现,End of Track必须作为每个track的最后一个event。
FF |
meta-event |
---|---|
FF 00 02 ssss | Sequence Number |
FF 01 len text | Text Event |
FF 02 len text | Copyright Notice |
FF 03 len text | Sequence/Track Name |
FF 04 len text | Instrument Name |
FF 05 len text | Lyric |
FF 06 len text | Marker |
FF 07 len text | Cue Point |
FF 20 01 cc | MIDI Channel Prefix |
FF 2F 00 | End of Track |
FF 51 03 tttttt | Set Tempo |
FF 54 05 hr mn se fr ff | SMPTE Offset |
FF 58 04 nn dd cc bb | Time Signature |
FF 59 02 sf mi | Key Signature |
FF 7F len data | Sequencer-Specific Meta-Event |
Set Tempo参数的意义为每个四分音符的微秒数。
Time Signature参数的意义分别为节奏的分子、以二为底取得节奏分母的对数、节拍器每响一次的MIDI clocks个数、每个四分音符所包含的三十二分音符个数(最后这个我也不理解有什么意义),比如以下示例:
Therefore, the complete event for 6/8 time, where the metronome clicks every three eighth-notes, but there are 24 clocks per quarter-note, 72 to the bar, would be (in hex):
FF 58 04 06 03 24 08
That is, 6/8 time (8 is 2 to the 3rd power, so this is 06 03), 36 MIDI clocks per dotted-quarter (24 hex!), and eight notated 32nd-notes per MIDI quarter note.
Key Signature的第一个参数表示乐曲经过了移调所添加的升降号个数,第二个参数取0x00
或0x01
意为大调或小调。
附
以下音色对照表引用自General MIDI System Level 1
General MIDI Sound Set Groupings(all channels except 10)
Prog # | Instrument Group | Prog # | Instrument Group |
---|---|---|---|
1-8 | Piano | 65-72 | Reed |
9-16 | Chromatic Percussion | 73-80 | Pipe |
17-24 | Organ | 81-88 | Synth Lead |
25-32 | Guitar | 89-96 | Synth Pad |
33-40 | Bass | 97-104 | Synth Effects |
41-48 | Strings | 105-112 | Ethnic |
49-56 | Ensemble | 113-120 | Percussive |
57-64 | Brass | 121-128 | Sound Effects |
General MIDI Percussion Map(Channel 10)
MIDI Key | Drum Sound | MIDI Key | Drum Sound | MIDI Key | Drum Sound |
---|---|---|---|---|---|
35 | Acoustic Bass Drum | 51 | Ride Cymbal 1 | 67 | High Agogo |
36 | Bass Drum 1 | 52 | Chinese Cymbal | 68 | Low Agogo |
37 | Side Stick | 53 | Ride Bell | 69 | Cabasa |
38 | Acoustic Snare | 54 | Tambourine | 70 | Maracas |
39 | Hand Clap | 55 | Splash Cymbal | 71 | Short Whistle |
40 | Electric Snare | 56 | Cowbell | 72 | Long Whistle |
41 | Low Floor Tom | 57 | Crash Cymbal 2 | 73 | Short Guiro |
42 | Closed Hi Hat | 58 | Vibraslap | 74 | Long Guiro |
43 | High Floor Tom | 59 | Ride Cymbal 2 | 75 | Claves |
44 | Pedal Hi-Hat | 60 | Hi Bongo | 76 | Hi Wood Block |
45 | Low Tom | 61 | Low Bongo | 77 | Low Wood Block |
46 | Open Hi-Hat | 62 | Mute Hi Conga | 78 | Mute Cuica |
47 | Low-Mid Tom | 63 | Open Hi Conga | 79 | Open Cuica |
48 | Hi Mid Tom | 64 | Low Conga | 80 | Mute Triangle |
49 | Crash Cymbal 1 | 65 | High Timbale | 81 | Open Triangle |
50 | High Tom | 66 | Low Timbale |