电脑音乐论坛(MIDI音乐、录音缩混技术交流)'s Archiver

点击查看相关商品

Thinking 发表于 2007-5-6 16:01

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                  停止一个队列
下表列出的是与音符相对应的命令标记。
八度音阶&brvbar;&brvbar;                    音符号
  #  &brvbar;&brvbar;
      &brvbar;&brvbar; C  &brvbar; C#  &brvbar; D  &brvbar; D#  &brvbar; E  &brvbar; F  &brvbar; F#  &brvbar; G  &brvbar; G#  &brvbar; A  &brvbar; A#  &brvbar; B
-----------------------------------------------------------------------------
  0  &brvbar;&brvbar;  0 &brvbar;  1 &brvbar;  2 &brvbar;  3 &brvbar;  4 &brvbar;  5 &brvbar;  6 &brvbar;  7 &brvbar;  8 &brvbar;  9 &brvbar;  10 &brvbar; 11
  1  &brvbar;&brvbar;  12 &brvbar;  13 &brvbar;  14 &brvbar;  15 &brvbar;  16 &brvbar;  17 &brvbar;  18 &brvbar;  19 &brvbar;  20 &brvbar;  21 &brvbar;  22 &brvbar; 23
  2  &brvbar;&brvbar;  24 &brvbar;  25 &brvbar;  26 &brvbar;  27 &brvbar;  28 &brvbar;  29 &brvbar;  30 &brvbar;  31 &brvbar;  32 &brvbar;  33 &brvbar;  34 &brvbar; 35
  3  &brvbar;&brvbar;  36 &brvbar;  37 &brvbar;  38 &brvbar;  39 &brvbar;  40 &brvbar;  41 &brvbar;  42 &brvbar;  43 &brvbar;  44 &brvbar;  45 &brvbar;  46 &brvbar; 47
  4  &brvbar;&brvbar;  48 &brvbar;  49 &brvbar;  50 &brvbar;  51 &brvbar;  52 &brvbar;  53 &brvbar;  54 &brvbar;  55 &brvbar;  56 &brvbar;  57 &brvbar;  58 &brvbar; 59
  5  &brvbar;&brvbar;  60 &brvbar;  61 &brvbar;  62 &brvbar;  63 &brvbar;  64 &brvbar;  65 &brvbar;  66 &brvbar;  67 &brvbar;  68 &brvbar;  69 &brvbar;  70 &brvbar; 71
  6  &brvbar;&brvbar;  72 &brvbar;  73 &brvbar;  74 &brvbar;  75 &brvbar;  76 &brvbar;  77 &brvbar;  78 &brvbar;  79 &brvbar;  80 &brvbar;  81 &brvbar;  82 &brvbar; 83
  7  &brvbar;&brvbar;  84 &brvbar;  85 &brvbar;  86 &brvbar;  87 &brvbar;  88 &brvbar;  89 &brvbar;  90 &brvbar;  91 &brvbar;  92 &brvbar;  93 &brvbar;  94 &brvbar; 95
  8  &brvbar;&brvbar;  96 &brvbar;  97 &brvbar;  98 &brvbar;  99 &brvbar; 100 &brvbar; 101 &brvbar; 102 &brvbar; 103 &brvbar; 104 &brvbar; 105 &brvbar; 106 &brvbar; 107
  9  &brvbar;&brvbar; 108 &brvbar; 109 &brvbar; 110 &brvbar; 111 &brvbar; 112 &brvbar; 113 &brvbar; 114 &brvbar; 115 &brvbar; 116 &brvbar; 117 &brvbar; 118 &brvbar; 119
  10  &brvbar;&brvbar; 120 &brvbar; 121 &brvbar; 122 &brvbar; 123 &brvbar; 124 &brvbar; 125 &brvbar; 126 &brvbar; 127 &brvbar;
参考资料:
"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]

Powered by Discuz! Archiver 7.0.0  © 2001-2009 Comsenz Inc.