MIDI文件结构分析及生成方法
一、MIDI文件结构分析 MIDI文件包含首部块(Header Chunk)和音轨块(Track Chunk)两部分。其格式一般如下:MThd <数据长度> <Header数据> //首部块
.......
Mtrk <数据长度> <Track数据> //音轨块
Header Chunk 结构为:
char MidiId[4];
long length;
int foarmt;
int TrackNum;
int division;
其中:
MidiId称为MIDI文件头标志,一般将其设置为MThd;
length为文件首部数据长度(除它本身和文件头标志占用的字节以外),通常它设置为6,即format,TrackNum和division共占用的字节数据长度;
format表示MIDI文件存放的格式,当前只有3种格式:
0 表示MIDI文件只有一个Track Chunk;
1 表示MIDI文件只有一个或多个Track Chunk;
2 表示MIDI文件只有一个或多个各处独立的Track Chunk。
division指定计数的方法,一种随时间计数(最高位设置为0时),另一种使用制式的时间码(最高位设置为1时)。这里,主要介绍随时间计数的一种格式。其各位意义如下:
┌─┬─────────┐
│0 │ 每一拍的计数值 │
└─┴─────────┘
b15 b14  ̄ b0
其最高位一定要设置为0,其它的15位表示每一拍的计数值。如该数据为96(以八分音符为一拍),则表示一个四分音符延时数应该为192。
另外,在MIDI文件中,long和int型数据均将高字节值存放入低地址上,如一个long型数据为0x45678,则在文件中,存放的结果为:0x00,0x04,0x56,0x78。而在内存中,int,long的变量值通常将崐高字节值存放高地址上。因此,存放数据时,应该作一下调整。
Track Chunk为用来播放歌曲的数据信息。每一个Track Chunk是一组简单的MIDI码(包括一些非MIDI码)的集合。它又由头部信息和崐若干个Mtrk event组合而成。
头部结构和意义为:
char TrackChunkId[4]; //Track Chunk标志MTrk
long TrackChunkMsgLength; //该Track Chunk信息长度
而Mtrk event是由时间计数值(dela-time)和event(MIDI码信崐息)组合成的。即:
<Mtrk event>=<dela-time> <event>
<dela-time>使用可变长度的形式存储数据,它代表处理event之前要计数时间值。 它在音乐中,即表示拍数。通常音乐开始演奏时,总是将计数时间值设置为0。为了能连续处理两个event,我们可以将deta-time设置为0。如:3和5同时演奏2拍(每一拍计数值为24),可以设置如下:
deta-time event
0 开始演奏3
0 开始演奏5
48 停止3演奏
0 停止5演奏
event表示MIDI码信息集,如0x9n表示开始发音,0x8n表示关闭发音等等(下有说明)。
上述的dela-time使用可变长度的形式表示数据值。可变长度形崐式是MIDI文件中对于大于8位的数据打用的一种存储方式,它把每一个数据定义为7位,剩下的最高位作为数据长度的识别。当这一位为0时,表示数据是最后一个,若为1,则表示还有下一个。
如:数值0x3fff,可变长度形式便为0xff,0x7f;0x4000则应该为0x81,0x80,0x00。此数据的转换可以参阅WriteLenghtToBuf()函数。
二、常见MIDI码说明
MIDI码是制定音乐交换的信息码,它使用串行非同步传送,因此数据码是用多码形式。第一个MIDI码是状态码,剩余的都是数据码,其长度视状态而定。
以下是一些常见的MIDI码。
1、开始发音(0x9n)
格式为:0x9n note speed
它一共占用3个字节,n表示通道号,取值0-15。MIDI可以同时演奏16个通道,用此指定在哪一个通道上发音(以下n相同)。
note表示音高数值,即音阶码值。如C4(中音1)为60,它的取值在0xc和0x6c之间(具体码值,可参考「参考书籍1」)。
speed表示按键时的速度,用此表示音的力度。若没有力度感,可以将其设置为64,若为0,表示关闭发音。
如:在第2通道上开始演奏3,则MIDI码便为0x91,63,40。
MIDI规范还规定,若连续向同一通道上发送多个音,则可以不指出状态码。如上述同时演奏3,5,MIDI码便为:0x91,63,40,65,40。
2、关闭发音(0x8n)。
格式:0x8n note speed
说明同上。通常它用0x9n,note,0来代替。
3、切换音色(0xcn)。
格式:0xcn,program
program表示音色代码,0 ̄255之间,如Acou Piano 1(电钢1值为0),Synth Bass 1(电贝司1值为64)等(详见「参考书籍1」)。
4、设置音量大小
格式:0xbn ,07,size
0xbn,39,size
7,表示设置主音量的高字节值;39表示设置主音量的低字节值。
5、设置时间记号
格式:0xff 0x58 04 nn dd cc bb
nn和dd直接对应到谱号的数字,dd使用2的指数。如3/8,则nn=3,dd=3。cc是代表第次节拍器打后的时间是几个MIDI clock。bb通常设置为8表示多少个MIDI clock等于1/4 拍。
6、设置演奏速度
格式:0xff 0x51 03 tt tt tt
tt tt tt 表示第一拍定义多少个Miscro Seconds。它即是用来崐变演奏的速度。
7、写歌词
格式:0xff 0x05 len text
len表示歌词的长度,text表示歌词文本码。
8、磁道结束
格式:0xff,0x2f,00
它表示结束点。每外track chunk后都应该有此MIDI码。
三、MIDI信息文本文件制作
为了能制成符合规范的MIDI文件,我们在此规定MIDI信息文本制作格式如下:
[MIDI]
<调号>,<节拍>,<每分钟节拍数>,<音轨个数>
[1]
.....
[n]
....
说明:
1、调号,占用一个字符,必须为A、B、C、D、E、F、G,否则视为C调;
2、节拍,取值如下:2/4,3/4,4/4,3/8,6/8....等。
3、每分钟节拍数:表示每分钟演奏的节拍总数,取值在40-200崐之间,否则视为120。
4、音轨个数表示此歌曲声部数。如三声部,可将其设置为3。
5、[n]后表示此音轨的音乐信息。有如下说明字符组合而成。
音高:
高音 C D E F G A B
中音 1 2 3 4 5 6 7
低音 c d e f g a b
若某音升半音,则在其后加#号;降半音,在其后加b字符。
音长: -(延长四分音符的一拍)、_(8分音符,后可带符点)、=(16分音符,后可带符点)、.(附点音符,后不可带符点)、:(32分音符,后可带符点)、;(64分音符,后不可带符点)。
说明:在书写时,请先写完整的音高,再写音长,如简谱中的"3-",则应该为"3#-"。
Pn:表示设置音色,取值1-256之间。
{}:歌词或注释。
|: 表示小节分隔符。
\: 后继音均降八度
/: 后继音均升八度
Sn:音量大小,n数值越大,音量越大。
其它的字符,视为非法字符。
一个MIDI文件基本上由两个部分组成,头块和轨道块。第二节讲述头块,第三节讲述轨道块。一个MIDI文件有一个头块用来描述文件的格式、许多的轨道块等内容。一个轨道可以想象为像一个大型多音轨录音机那样,你可以为某种声音、某种乐谱、某种乐器或者你需要的任何东西分配一个轨道。
2.头块:
头块出现在文件的开头,有三种方式来描述文件。头块看起来一直是这样的:
4D 54 68 64 00 00 00 06 ff ff nn nn dd dd
前4个字节等同于ASCII码MThd,接着MThd之后的4个字节是头的大小。它将一直是00 00 00 00 06,因为现行的头信息将一直是6字节。
ff ff是文件的格式,有3种格式:
0-单轨
1-多规,同步
2-多规,异步
单轨,很显然就只有一个轨道。同步多轨意味着所有轨道都是垂直同步的,或者其他的措辞为他们都在同一时间开始,并且可以表现一首歌的不同部分。异步多轨没有必要同时开始,而且可以完全的不同步。
nn nn 是MIDI文件中的轨道数。
dd dd 是每个4分音符delta-time节奏数(这之后将做详细介绍)。
3.轨道块:
头块之后剩下的文件部分是轨道块。每一个轨道包含一个头,并且可以包含你所希望的许多MIDI命令。轨道头与文件头及其相似:
4D 54 72 6B xx xx xx xx
与头一致,前4个字节是ASCII吗,这个是MTrk,紧跟MTrk的4个字节给出了以字节为单位的轨道的长度(不包括轨道头)。
在头之下是MIDI事件,这些事件同现行的可以被带有累加的MIDI合成器端口接受和发送的数据是相同的。一个MIDI 事件先于一个delta-time。一个delta-time是一个MIDI事件被执行后的节奏数,每个四分之一音符的节奏数先前已经定义在了文件的头块中。这个delta-time是一个可变长度的编码值。这种格式虽然混乱,可是允许根据需要利用多位表示较大的数值,这不会因为需求小的数值情况下以添零的方式浪费掉一些字节!数值被转换为7位的字节,并且除了最后一个字节以最高有效位是0外,各个字节最有意义的一位是1,。这就允许一个数值被一次一个字节地读取,你如果发现最高有效位是0,则这就是这个数值的最后一位(意义比较小)。依照MIDI说明,全部delta-time的长度最多超过4字节。
delta-time 之后就是MIDI事件,每个MIDI事件(除了正在运行的事件外)带有一个最高有效位总是1的命令字节(值将>128)。大部分命令的列表在附录A中。每个命令都有不同的参数和长度,但是接下来的数据将是最高有效位为零(值将<128)。这里有个例外就是meta-event,最高有效位可以是1。然而,meta-events需要一个长的参数以区分。
微小失误就可以导致混乱的是运行模式,这是现行MIDI命令所忽略的地方,并且最终发行的MIDI命令是假定的。这就意味这如果包含了命令,那么MIDI事件就是由delta-time与参数组成而转换的。
1.MIDI事件命令
每个命令字节有两部分,左nybble(4位)包含现行的命令,右nybble包含将被执行的命令的通道号,这里有16各MIDI通道8个MIDI命令(命令nybble必须最高有效位是1的)。在下表中,X表示MIDI通道号。所有的音符即数据字节都<128(最高有效位是0)。
十六进制 二进制 数据 描述
8x 1000xxxx nn vv 音符关闭 (释放键盘)
nn=音符号
vv=速度
9x 1001xxxx nn vv 音符打开 (按下键盘)
nn=音符号
vv=速度
Ax 1010xxxx nn vv 触摸键盘以后
nn=音符号
vv=速度
Bx 1011xxxx cc vv 调换控制
cc=控制号
vv=新值
Cx 1100xxxx pp 改变程序(片断)
pp=新的程序号
Dx 1101xxxx cc 在通道后接触
cc=管道号
Ex 1110xxxx bb tt 改变互相咬和的齿轮 (2000H 表明缺省或没有改变)(什么意思搞不懂:)
bb=值的低7位(least sig)
tt=值的高7位 (most sig)
下表是没有通道的 meta-events列表 ,他们的格式是:
FF xx nn dd
所有的 meta-events 是以 FF 开头的命令 (xx),长度,或者含在数据的字节数(nn),现行的数据(dd)
十六进制 二进制 数据 描述
00 00000000 nn ssss 设定轨道的序号
nn=02 (两字节长度的序号)
ssss=序号
01 00000001 nn tt .. 你需要的所有文本事件
nn=以字节为单位的文本长度
tt=文本字符
02 00000010 nn tt .. 同文本的事件, 但是用于版权信息
nn tt=同文本事件
03 00000011 nn tt .. 序列或者轨道名
nn tt=同文本事件
04 00000100 nn tt .. 轨道乐器名
nn tt=同文本事件
05 00000101 nn tt .. 歌词
nn tt=同文本事件
06 00000110 nn tt .. 标签
nn tt=同文本事件
07 00000111 nn tt .. 浮点音符
nn tt=同文本事件
2F 00101111 00 这个事件一定在每个轨道的结尾出现
51 01010001 03 tttttt 设定拍子
tttttt=微秒/四分音符
58 01011000 04 nn dd cc bb 拍子记号
nn=拍子记号分子
dd=拍子记号分母2=四分之一
3=8分拍, 等等.
cc=节拍器的节奏
bb=对四分之一音符标注的第32号数字
59 01011001 02 sf mi 音调符号
sf=升调/降调(-7=7 降调, 0=基准C调,7=7 升调)
mi=大调/小调(0=大调, 1=小调)
7F 01111111 xx dd .. 音序器的详细信息
xx=被发送的字节数
dd=数据
下表列出了控制整个系统的系统消息。这里没有MIDI通道数 (这些一般仅应用于MIDI键盘等.)
十六进制 二进制 数据 描述
F8 11111000 同步所必须的计时器
FA 11111010 开始当前的队列
FB 11111011 从停止的地方继续一个队列
FC 11111100 停止一个队列
下表列出的是与音符相对应的命令标记。
八度音阶¦¦ 音符号
# ¦¦
¦¦ C ¦ C# ¦ D ¦ D# ¦ E ¦ F ¦ F# ¦ G ¦ G# ¦ A ¦ A# ¦ B
-----------------------------------------------------------------------------
0 ¦¦ 0 ¦ 1 ¦ 2 ¦ 3 ¦ 4 ¦ 5 ¦ 6 ¦ 7 ¦ 8 ¦ 9 ¦ 10 ¦ 11
1 ¦¦ 12 ¦ 13 ¦ 14 ¦ 15 ¦ 16 ¦ 17 ¦ 18 ¦ 19 ¦ 20 ¦ 21 ¦ 22 ¦ 23
2 ¦¦ 24 ¦ 25 ¦ 26 ¦ 27 ¦ 28 ¦ 29 ¦ 30 ¦ 31 ¦ 32 ¦ 33 ¦ 34 ¦ 35
3 ¦¦ 36 ¦ 37 ¦ 38 ¦ 39 ¦ 40 ¦ 41 ¦ 42 ¦ 43 ¦ 44 ¦ 45 ¦ 46 ¦ 47
4 ¦¦ 48 ¦ 49 ¦ 50 ¦ 51 ¦ 52 ¦ 53 ¦ 54 ¦ 55 ¦ 56 ¦ 57 ¦ 58 ¦ 59
5 ¦¦ 60 ¦ 61 ¦ 62 ¦ 63 ¦ 64 ¦ 65 ¦ 66 ¦ 67 ¦ 68 ¦ 69 ¦ 70 ¦ 71
6 ¦¦ 72 ¦ 73 ¦ 74 ¦ 75 ¦ 76 ¦ 77 ¦ 78 ¦ 79 ¦ 80 ¦ 81 ¦ 82 ¦ 83
7 ¦¦ 84 ¦ 85 ¦ 86 ¦ 87 ¦ 88 ¦ 89 ¦ 90 ¦ 91 ¦ 92 ¦ 93 ¦ 94 ¦ 95
8 ¦¦ 96 ¦ 97 ¦ 98 ¦ 99 ¦ 100 ¦ 101 ¦ 102 ¦ 103 ¦ 104 ¦ 105 ¦ 106 ¦ 107
9 ¦¦ 108 ¦ 109 ¦ 110 ¦ 111 ¦ 112 ¦ 113 ¦ 114 ¦ 115 ¦ 116 ¦ 117 ¦ 118 ¦ 119
10 ¦¦ 120 ¦ 121 ¦ 122 ¦ 123 ¦ 124 ¦ 125 ¦ 126 ¦ 127 ¦
参考资料:
"MIDI Systems and Control" Francis Rumsey 1990 Focal Press
"MIDI and Sound Book for the Atari ST" Bernd Enders and Wolfgang Klem 1989 M&T Publishing, Inc.
MIDI file specs and general MIDI specs were also obtained by sending e-mail to LISTSERV@AUVM.AMERICAN.EDU with the phrase GET MIDISPEC PACKAGE in the message.
页:
[1]
