1. MIDI基础
1.1. 概念
MIDI(Musical Instrument Digital Interface)乐器数字接口 ,是20 世纪80 年代初为解决电声乐器之间的通信问题而提出的。MIDI是编曲界最广泛的音乐标准格式,可称为“计算机能理解的乐谱”。它用音符的数字控制信号来记录音乐。一首完整的MIDI音乐只有几十KB大,而能包含数十条音乐轨道。几乎所有的现代音乐都是用MIDI加上音色库来制作合成的。MIDI 传输的不是声音信号, 而是音符、控制参数等指令, 它指示MIDI 设备要做什么,怎么做, 如演奏哪个音符、多大音量等。它们被统一表示成MIDI 消息(MIDI Message) 。传输时采用异步串行通信, 标准通信波特率为31.25×( 1±0.01) KBaud。
1.2. MIDI结构
MIDI格式的歌曲自产生以来,得到迅速的扩展以及广泛的应用,大概有以下原因:
①MIDI文件结构在网络传送中,通常采用7位数据传送方式(不考虑字节的最高位),大大提高了传输速度;
②MIDI文件的歌曲体积很小,便于传送;
③有利于创作音乐,是很多作曲家在创作初期的首选。
缺点是:由于MIDI文件的结构相当于一个文本文档,记录了音乐该如何进行(相当于歌曲的乐谱),所以它的回放音色效果完全取决于MIDI乐器的硬件设施。
MIDI文件由大量的数据块组成,可以从附件1中观察到,一行也即一块,共有4个字节,32位长度,它的具体构成如表1所示:
类型 | 长度 | 数据 |
---|---|---|
4个字节 | 4个字节 | 4个字节 |
其中类型是ASCII码"MThd"或"MTrk",长度是除去类型和长度两部分外,其它数据占的字节数,表(1)的块结构是MIDI文件以12个字节为一行存储的,不同于下表的MIDI文件结构:
头块(Header Chunk) | 头块标记(MThd chunk type) | 头块数据长度6<length of header data> | 6字节的数据<header data> |
---|---|---|---|
音轨块1 | 块标记(MTrk)(MTrk chunk type) | 音轨数据长度 <length of track data> | 音轨数据(一连串按时间顺序排列的事件)<track data> |
…… | …… | …… | …… |
音轨块n | 块标记(MTrk)(MTrk chunk type) | 音轨数据长度<length of track data> | 音轨数据<track data> |
其中<track data> = <MTrk event>+<MTrk event>….. = <delta-time> <event>
<音轨数据> = <MTrk 事件>+<MTrk 事件>….. = <时间差> <事件>
其中<event> = <MIDI event> | <sysex event> | <meta-event> <事件> = <MIDI 事件> | <系统码事件> | <元-事件>
表(2)定义了MIDI文件的两种类型:文件头块和音轨块,MIDI文件通常以文件头块开始,接着是一个或多个音轨块。
文件头块描述了整个MIDI文件的信息;
音轨块由一系列事件组成,具体内容是:歌曲名字、音轨名字、序列、音轨结构,拍子、调号、乐器、音符等。音轨数据块是实际歌曲数据存放的地方,本质上是一系列MIDI事件和非MIDI事件,并且每个事件前面都带有时间差(delta-time)。
MIDI文件使用单条或多条音轨格式记录事件,只要时间差设置的合适,不同格式间还可以相互转化。
1.3. MIDI文件头块
MIDI文件的头块的具体构成,包含的信息:头块类型、头块长度和数据部分。头块长度是可变常量,每个字节的最高位为标志位;数据部分包括:格式、音轨数、分区,总共有3个16bit字节,需要先存储高位。以下是头块的语法和格式(16进制):
<头块类型> <头块长度> <格式> <音轨数> <分区>
<Header chunk type> <length> <format> <ntrks> <division>
<4d 54 68 64 ><00 00 00 06>< ff ff>< nn nn> < dd dd>
前4个字节是头块类型,表示“MThd”的ASCII码,每个MIDI文件都以这四个字符为开头;
“00 00 00 06”是头块长度,表明文件头块描述信息的字节数,对于目前的MIDI标准这个值是固定的,只能是6;
“ff ff”定义了整个文件的组织结构,表明MIDI文件的格式,一共有三种情况;
“nn nn”是音轨块的块的个数;“dd dd”是一个四分音符的tick数。
例1:4D 54 68 64 00 00 00 06 00 01 00 0A 01 E0
00 01同步多音轨
00 0A文件中总共有10个音轨块,其中包括1块总音轨,9块分音轨
01 E0 分区,是16进制,最高位不是标志位,换算为10进制是480=28+27+26+25
1.3.1. 格式
MIDI文件有三种格式,在MIDI文件中存储的形式是16进制,具体作用如下表:
ff ff | 格式 | 指定midi的格式 |
---|---|---|
00 00 | 格式0 | 单音轨:头块的后面只有一个音轨块 。 |
00 01 | 格式1 | 多音轨,且同步:头块的后面有2个或者以上的音轨块,所有音轨块垂直同步,也就是说所有的音轨块开始演奏的时间相同;或者是其他的措辞都在同一时间开始,并且可以表现一首歌的不同部分。 |
00 02 | 格式2 | 多音轨,但不同步:头块的后面有多个音轨块,所有音轨块不同步,音轨块播放时间指令由开始时间决定,这种格式的MIDI文件有很大的复杂度,所以这种格式比较少见。 |
格式0,是一个多通道音轨块,存储了不同的音轨块的信息。从附件3里可以看到事件前需要添加通道状态标志,以便播放歌曲时能区别出来事件发生在那一通道,这是最简单的格式,但也使文件体积增大。
格式1,是一个垂直一维表,不同通道的信息垂直分布。这种格式最为常用。
格式2,是一个水平一维表,支持多个独立模式的程序要能够保存和读取格式2的数据。
MIDI文件格式不同,内部的复杂度会有较大差别,三种格式的复杂度是递增的,而且前一种格式总可以近似的看作后一种格式的特例,所以只要面向最复杂的类型2做好各种处理,相对简单的类型0和1只要稍作修改即可支持,也即不同格式间可以互相转换。
1.3.2. 音轨数
“nn nn”表明轨道块数,等于实际音轨块数加上一个全局的音轨块。
在解析MIDI文件时,通常根据音轨块数,就可以判断MIDI歌曲总共含有多少个音轨块,特别是对于格式1、2,这对程序的编写是非常有利的。
注意:自己编写MIDI文件的歌曲时,多加一个音轨,就要更改”nn nn”的数目。
1.3.3. 分区
“dd dd”也即分区,是把一个四分音符长度的时间平均分成DTT“delta-time ticks”(DTT微小时间事件片)份,DTT是MIDI文件中的时间计量单位,一个DTT比1秒短的多。在MIDI文件中是以16进制存储的,是可变常量,但是高位字节的最高位设置为0。具体作用如下表:
dd dd | 指定基本时间格式类型 | 类型1:定义一个四分音符的tick数,tick是MIDI中的最小时间单位类型2:定义每秒中SMTPE帧的数量及每个SMTPE帧的tick |
---|
在MIDI文件中,通常设置分区为120,但MIDI文件也支持更改这个值。由于这种情况在实际应用中比较少见,因此可以通过统一转换为120的方式,在不影响正确性的前提条件下,降低解析的复杂度。本文的附件中的分区都是变化的,不是120。
如果division是负数,则表示delta-time的一秒钟的分割量,因此音轨事件发生可以用精确时间代替韵律时间来表示。表示如下:第一字节是-24,-25,-29,-30四个值之一,相对应4种标准的SMPTE和MIDI事件码,和表示每秒的帧数。第二字节(保存正数)是帧的解析度:通常值可能是4(MIDI时间码解析度), 8, 10, 80 (比特解析度)或100。 系统允许定义额外的基于时间码的音轨,也允许25帧每秒和40个单位每帧解析度的基于毫秒的音轨。) 例2:01 E0
可以写成0000 0001 1110 0000所以换算为10进制是480=2^8+2^7+2^6+2^5
1.4. MIDI音轨块
音轨块的语法:
<Track data> = <MTrk event>+<MTrk event>…… = <delta-time> <event>
<音轨数据>= <MTrk 事件>+<MTrk 事件>…… = <时间差> <事件>
<event> = <MIDI event> | <sysex event> | <meta-event>
<事件> = <MIDI 事件> | <系统码事件> | <元数据-事件>
MIDI文件的音轨块包括:全局音轨和分音轨。
首先是全局音轨块,主要包括:歌曲的附加信息(比如标题和版权),歌曲速度和系统码(sysex)等。
接着是分音轨块,主要包括:MIDI事件、非MIDI事件和系统码事件,每个事件前面都有时间差。事件的基本格式为:种类+参数。
不管是全局音轨还是含有音符的分音轨,都以“4D 54 72 68”开头,它其实是ASCII字符“MTrk”,其后跟着一个4字节的整数,它标志了该轨道的字节数,这不包括前面的4个字节和本身的4个字节。
通过简单的计算得出一个音轨块的长度最多是(2^32+8)个字节,由于音轨块长度是可变常量,最小为1个字节,最大是4个字节,字节的最高位没有标志位,完全采用10进制转为16进制的计算方法,从这种意义上来讲,音轨块中MIDI事件个数也是有限制的。
1.4.1.时间差(Delta-Time)
时间差是可变常量(variable length quantity),含义是将要发生的事件与前一事件之间的时间差值。如果音轨第一个事件发生在开头,或者两个事件同时发生,<delta-time>设为零。
注意:时间差区别于文件头块的DTT,两者的具体含义是不同的,只是都是长度变量。时间差的10进制在转为16进制时,字节的最高位是标志位。具体方如下:
对于0-127tick, 标志位为0,用一个字节(8位表示);对于大于127tick,标志位为1,用多个字节表示,也即除了最后一个字节的最高有效位是0外,其它字节最高位是1。
优点:这种记录方法允许一个数值被一次一个字节地读取,如果发现某个字节的最高有效位是0,那么它就是这个数值的最后一个字节。
依照MIDI说明,全部delta-time的长度最多不超过4字节,并且最大值为0FFFFFFF。
例1: 65535tick(10进制)=83 FF 7F(16进制)
65535tick=1282*3+1281127+128^0127
1000 0011=83 由于远远大于127,所以标志位为1(3的16进制0000 0011把最高位0改为1,也即1000 0011)
1111 1111=FF由于大于127,所以标志位为1(127的16进制0111 1111把最高位0改为1,也即1111 1111)
0111 1111=7F由于小于127,所以标志位为0(127的16进制0111 1111)
1.4.2.MIDI事件(MIDIEvent)
通过把MIDI的不同通道分配给各种音色,就能产生乐器合奏的效果,音源最大的特点是可以根据需要调整音色的参数,以编辑新的,甚至是本来不存在的音色。
MIDI事件也叫MIDI events,常见的有音符事件、控制器事件和系统信息事件等。
事件组成:种类+参数。
种类用状态字节来区分,总是大于等于80H。
参数用数据字节来区分,总是小于80H。
因此可以很容易区分状态字节和数据字节。在状态字节中,用数据的低4为表示通道号,高4位表示不同的命令。
这里有个例外就是meta-event,状态字节是FF,需要一个长的参数区分不同事件,3.3 章节给出了此类事件的规范。如何参照下表读取MIDI事件,第5章将给出详细介绍。下表中的x是音轨通道,总共有16个(0是第一通道)。
1.4.3.Meta事件(MetaEvent)
非MIDI事件。非MIDI事件也叫meta-event(元事件),是MIDI文件中的非MIDI信息,语法规定如下:
FF<种类><字节数><数据>
FF <type> <length> <bytes>
所有的meta-event都以0xFF开头,接着是事件种类(总小于128)、数据的长度值length(用长度变量表示,无标志位)、数据。如果没有数据,那么长度为0。元事件的规范如下表:
下表详细的列出了FF的详细情况,对于字节数由数据决定的情况,表中以 “--”表示
种类 字节数 数据
字节 含义
00 设置轨道音序 02 音序号 00 00-FF FF
01 歌曲备注 -- 文本信息
音轨文本 文本信息
02 歌曲版权 -- 版权信息
03 歌曲标题 -- 歌曲标题:用于全局音轨,第一次使用表示主标题,第二次表示副标题
音轨名称 -- 音轨名
04 乐器名称 -- 音轨文本(同01/2)
05 歌词 -- 歌词
06 标记 -- 用文本标记(marker)
07 开始点 -- 用文本记录开始点(同01/2)
08 Program name -- 歌曲文件的名字
09 设备名字 DeviceName -- MIDI设备的名字
20 MIDI通道 01 MIDI通道,0通常为第一通道
21 MIDI接口 01 接口号码
2F 音轨结束标志 00 无
51 速度 03 3字节整数,1个4分音符的微妙数
54 SMPTE时间 05 SMPTE的开始时间(时,分,秒,帧,复帧)
58 节拍 04 分子
分母:00(1),01(2),02(4),03(8)等
节拍器时钟
一个4分音符包括的32分音符的个数
59 调号 02 升降号数:-7-1(降号),0(c),17(升号)
大小调:0(大调),1(小调)
7F 音符特定信息 -- 音符特定信息
1.4.4.系统事件(SYSEvent)
系统码,又叫MIDI专有信息是跟音源(音色库)交流最精确的语言,专门用来调整MIDI设备内部参数设置的指令,由十六进制数构成。
系统码分三个部分
<1>固定的开头 F0 4X 10 4X
F0: 系统码开头
4X: 厂商代码YAMAHA为43 ROLAND为41 KORG 为42
10: 音源设备编号
4X: 当前音源格式的选择….XG为4C….GS为42
<2>核心部分
例如: F0 43 10 4C 00 00 04 7F F7
后面的00 0X 04 表示工作在主控音量上,其中0X表示设置的通道,7F 代表取值范围
1. 复位码
一. GS F0 41 10 42 12 40 00 7F 00 41 F7
二. XG F0 43 10 4C 00 00 7E 00 F7
三. GM F0 7E 7F 09 01 F7
Msb( most singnificant bit) 、Lsb (least singnificant bit ),都是两位的十六进制数, 因为XG格式的音源系统码是开放的,所以就以XG标准的音源来讲,如果你只有GS标准的音源…那可以把YAMAHA格式的设置成GS在YAMAHA音源下的TG300B模式
系统码:F0 43 71 7E 09 01 F7或者 F0 41 10 42 12 40 00 7F 00 41 F7
重要:若想让MIDI乐器正确响应系统码,在开始先用复位码把它设置成相应的模式
用于传输大量的数据给一个MIDI设备,例如patch寄存器、音序器、waveform数据;
也有可能传送特别的信息给一个模型设备,例如在一个Roland Physical Modeling Synth中,可能被用来为一个操作员设置反馈水平。
状态描述:0xF0-0xF7 其中低字节代表使用的MIDI的不同音轨
数据描述:在0xF0-0xF7之间,可能有任意的数据bytes,最重要的是头一个数据bytes(紧跟在0xF0后),应该是制造商的ID值。
对每一个MIDI设备定义它自己的sysex event,并且所有的MIDI sysex event必须是以0xF0开始,以0xF7(结束标志)结束,没有0xF0状态标志是不可能发生的,虽然0xF7作为结束标志的,但是事实上,任何的状态都有可能引起系统信息终止,若一个系统码事件未传达,这种情况就没必要以一个F7作为标志来结束事件。
系统码可以写在任何音轨,不过通常写在全局音轨中,时间差设成00。
对于制造商的ID,MMA已经针对多种多样的制造商的ID设定了特殊的值,以便设备确定信息是否来自传送的制造商。例如,Roland设备的IDbytes是0x41,如果MIDI设备收到的ID不是0x41,设备将忽略剩余的bytes值,包括0xF7。
例2:传输信息F0 43 12 00 07 F7
F0 05 43 12 00 07 F7。
F0是标志位,05是5个字节,内容是43 12 00 07 F7。
F7结束标志,使得在读MIDI文件时知道已经读取整个系统信息。
注意:若单个系统码事件被分割成几部分,每一部分在不同时段传输,每一部分(除了第一个)的系统码事件必须以F7开头,不以F7结尾(除了最后一个,因为它必须要以F7结尾),而且各部分事件之间不能含有其它可传输的MIDI事件。
例3:假设发送字节F0 43 12 00,接着延时200-tick,又接着字节43 12 00 43 12 00,延时100-tick,字节43 12 00 F7,在MIDI文件里头是:
F0 03 43 12 00
81 48 200-tick 时间差
F7 06 43 12 00 43 12 00
64 100-tick 时间差
F7 04 43 12 00 F7
1.5. MIDI事件
1.5.1. 音符
当你在MIDI键盘上按下一个琴键,你不是在制造一个声音而是发出一条MIDI指令,至于这个信息能发什么声音,完全取决于电缆另一端的MIDI乐器(如果有的话)。MIDI电缆里完全没有音频数据。
给出音符的符号,如何找到相对应的16进制数,本节给出了2种方法:
(1)针对熟识音乐的人来讲,代入公式就可以得到,快速有效;
(2)对于普通人来讲,查询表格就可以得到。
音符标号,也就是音高,MIDI规格有128个音符标号,中央C的音符标号被定义为60。音符标号值越小音高就越低,值越大音高就越高。
1.5.1.1. 运算查找法
已经知道音符的16进制数,求音符的符号。假设音符是N0,其中音名N,音阶为0
公式:N=B mod 12 ;0=B div 12-1 (1)
其中B表示音符的字节的10进制数,N的10进制数值参照下表:
音名 C #C D #D E F #F G #G A #A B
10进制数值 0 1 2 3 4 5 6 7 8 9 10 11
例1:已经知道某一音符的16进制为45,求对应的音符为A4
45(16进制)=69(10进制)
根据公式(1)得出69 mod 12 = 9 =N; 4= 69 div 12-1
参照N的10进制数得出音符为A,音阶为4
已经知道音符的符号,求对应的16进制数。假设音符是N0,其中音名为N,音阶为0
公式:10进制公式:(0+1)12+N (2)
例2:计算音符G2的16进制为2B
代入公式(2)为(2+1)12+7=43,16进制为2B
4.5.1.2.图标查找法
音符的有效范围是0-127,16进制是00-7FH,可以直接参照下表查找。
MIDI音符代码表
1.5.1.3. 音符力度表
音符的力度,也称为按键的速度,范围是1-127,也即01-FF,当按下或松开音符的力度为0时,表示松开音符。
力度的值越小越弱,越大越强[3]。可以参照下表查找力度值的具体含义:
1.5.2. MIDI文件中音符的使用
音符具有三个属性:音高,力度,时值(由按下时间和松开时间决定)。
MIDI文件中有一个特殊的通道10,也即0x09,是节奏乐器的专用通道,因为节奏乐器是没有音高的,一般如各种鼓等,所以音符在通道10中表示的是各种节奏乐器,而其它通道中的音符表示各种音高。在附件4中看到同时在通道10中演奏几种节奏乐器,并且不同的节奏乐器分布在不同的音轨块里。
1.5.3. 松开音符
松开音符。松开音符也叫noteoff,可以理解为:需要松开一个特殊的音符,但是松开某些音符需要一定的时间和力度,同时由于按下音符是通过MIDI的轨道传输信息的,所以状态描述需要考虑到音轨,下面是松开音符的表达方法:
状态描述:0x80-0x8F 其中低字节代表使用的MIDI文件的不同音轨,高位字节代表松开音符
数据描述:nnff
其中nn 表示按下的音符的名称,范围为00-7FH,这样总共有128个音符,足以覆盖整个音域,可以参照4.1.2章节的GM音符代码表查找;ff表明松开键盘的速度,又称力度,也即表示需要多大的速度松开音符,范围也是00-7FH,在很多MIDI设备中,该指令中的速度数据ff常被忽略。下面以例子说明如何在MIDI文件中描述松开音符。
例3: 松开音符 6C 80 5B 40
时间差为6C,查表可得:松开音符G,音阶是6,力度40,中等偏强的力度
表示:隔了时间差6C,以中等偏强的力度松开音符G。
例4:按下中音A 00 91 45 30
松开中音A 3C 81 45 00
时间差为3C
45表示中音A(是音符)
00力度为0
注意:如果一个音符的力度为0,则MIDI文件认为用户松开这个键,由于松开中音A前面已经按下中音A,那么以00力度的同一音符松开就可以计算中音A的时值为3C。
1.5.4. 按下音符
按下音符也叫noteon,可以理解为:在某一时间,用一定的力度按下一个特殊的音符,并且通过MIDI器件的通道传输信息,所以描述noteon状态时需要考虑力度和音轨。下面是松开音符的表达方法:
状态描述:0x90-0x9F 其中低字节代表使用的MIDI的不同音轨
数据描述:nnff 其中nn 表示按下的音符(16进制表示),范围为00-7FH,这样总共有128个音符,足以覆盖整个音域,可以参照4.1.2章节的GM音色表;ff表示音符的力度(16进制),是速度数据,表明击键的速度,又称力度,范围也是00-7FH。如果速度数据为0,则等同于松开音符命令。下面以例子说明如何在MIDI文件中描述按下音符。
例5:按下中音A 00 96 45 70
时间差为00
9x中的x是6,6表示音轨,是第7个通道
45表示A4,70表示力度为112
例6:按下/松开音符 0E 91 24 00
按下音符,但由于力度是0,在这里等同于0E 81 24 00,也即松开音符。
例子选自附件3
例7:同时按下中音A和附点4分中音D,接着按下#G
00 96 45 70(按下中音A) 00 96 3E 64(同时按下中音D)3C 96 45 00(过了3C时间后松开中音A) 00 96 44 64 78 96 44 00(按下中音#G再松开) 00 96 3E 00松开中音D
分析如下:知道了如何单一的按下和松开音符,但由于音色的音符是不断变化的,所以需要仔细分析如何连续的写入不同音符。
按下中音A的后面按下一个4分音符中音#G
按下4分音符中音#G 00 96 44 64
00表示与松开中音A的事件的时间差为0
松开4分音符中音#G 78 96 44 00
78表示与按下4分音符的时间差为78H
00表示力度
注意:由于松开中音D前已经过了的时间,而中音D的时间差为3个8分音符,所以加上一个音符事件00 96 3E 64表示松开中音D。这里的关键点是时间差的概念:表示前一事件和后一事件的时间差,所以在这里中音D的时间差为:3CH+78H。在解析和编写MIDI文件歌曲时,这一点是极为重要的。
1.5.5. 触后(Aftertouch)
Aftertouch可以理解为:由于演奏传出的音符是随着时间和不同的力度变化而变换,所以当你使用这个事件时,需要考虑停留在键盘的时间和力度,同时Aftertouch是通过MIDI器件的轨道传输信息的,状态描述需要考虑到音轨:
状态描述:0xA0-0xAF 其中低字节代表使用的MIDI的不同音轨
数据描述:nnff 其中nn 表示Aftertouch的音符名称(16进制表示),范围为00-7FH,这样总共有128个音符,足以覆盖整个音域,可以参照4.1.2章节的GM音色表;ff表示音符的力度(16进制),是速度数据,表明击键的速度,又称力度,范围也是00-7FH。
例8:0E A0 0C 00 选自附件3
0E是时间差,在0轨道,音符是C,力度为0。
1.5.6.控制器(Controller)
控制器也叫controller,是用来控制MIDI乐器中的滑音、颤音、渐强、渐弱和声道等功能的编辑管理器,比如转换器,滑动器,把手等等,但又完全不同于按下和松开音符事件,同时使用控制器时,需要MIDI器件的通道传输信息。状态描述如下:
状态描述:0xB0-0xBF 其中低字节代表使用的MIDI的不同音轨
数据描述:nnff 其中nn 表示使用哪一种控制器(16进制表示),控制器的种类有128种,范围为00-7FH,可以参照本章节的控制器表;ff表示使用控制器时需要设置的值(16进制),范围也是00-7FH。
在MIDI歌曲制作中,控制器的运用占有极为重要的地位,可以使原来听起来十分死板、并且电子味很浓的音乐变得具有人性化,还可以实现许多音乐的细节,所以要想制作出高水平的MIDI音乐,控制器的使用特别重要。
MIDI控制器有128种不同的事件控制器,在MIDI的1、0协议中,对这128控制器做了具体的定义。控制器号由0-127号构成,但仅仅用了0-119号,120-127号被划分给了模式信息,做了其它的用途。
MIDI控制器的参数变化范围都为0-127,0为最小值,127是最大值。
对于开关的控制器,控制器的值小于63为关闭,大于64为开启。
每个控制器对应于一种控制事件,但是,并不是每个编号的控制器对音源都有同样效果,要看音色的型号。如71号泛音控制器,在XG音色表中改变音色的亮度,但是,GS和GM音色表格里都没有作出规定。还有80号和81号控制器,在GM、GS和XG音色表格里没有作出定义。
在0-63号控制器里,一般只使用0-31号控制器,32-63号控制器是为了发送提高0-31号控制器精度的LSB数据而准备的,连续可变的0-31号控制器在需要一个字节(7位,这里不考虑最高位标志位)以上的精度时,就可以利用32-63号控制器。
16-19和80-83号控制器定义为通用控制器,16-19号是两个字节,80-83号为一个字节,这些控制器号可以指定为任何控制器,用来控制内部参数。相当于踏板开关类型的控制器分布在64-95号之间。下面是控制器表:
控制器可以在设备控制面板和MIDI键盘实时发送。控制器只作用于自己所在的通道,对其他通道不起作用。
下面针对比较常用的MIDI控制器进行介绍。
0号控制器:音色库的选择。如果你的电脑中安装了创新AWE、LIVE或AUDIGY声卡,而且安装了几个音色库,可以用它进行音色库的变换。
1号控制器:颤音深度控制器。一般的MIDI键盘和合成器都带有一个调制轮,用它进行颤音的操作,一般都用实时录音的方法。当然,也可以在钢琴卷帘窗中用画笔进行绘制,但是,用实时录音的办法制作的颤音效果要更自然些。
2号控制器:呼吸(吹管)控制器。它可以接收一些特殊输入设备发出的信息,对音量进行控制,做出淡出淡入、渐强渐弱的效果来。
5号控制器:滑音时间。65号控制器:滑音开关。这两个控制器不单独使用,要配合使用。当65号打开时,使用5号控制器来设定话音的时间。65号的默认值是关闭状态,将它改为任意一个大于“0”的数字,表示打开这个控制器,然后用5号设定滑音的时间,数值越大,滑音时间越长,反之则越小。5号的可取范围是0-127,一般将它设置在20-30之间。5号和65号都是用鼠标输入的。
6号控制器:数据输入。它要和98-101号控制器配合使用,与RPN与NRPN有关。为了在规定的120个控制器之外扩展使用,MIDI中规定了RPN和NRPN两套控制器,RPN是注册参数号,NRPN是非注册参数号。前者是MMA的定义,后者可以由厂家自行定义,它们的使用方法相同。不同编号的RPN和NPRN事件对应于一种控制事件,RPN和NPRN的编号由两个字节表示,即MSB和LSB,编号范围是0-16383,比控制器编号成倍地提高了,便于提供更丰富的控制功能。它的取值也是由两个字节表示,取值从0-16383,因此控制的解析度也成倍的提高了。所有音源只要是兼容GM标准的,就能响应RPN表中事件。GM标准规定了三种RPN事件。GM标准对NRPN事件没有作任何定义,但所有GS个XG乐器都能正确响应各自的NRPN事件。
7号控制器:音量控制器。使用它可以协调各个声部的音量比例,一般在音轨窗中直接调节参数,在一般情况下,伴凑声部的音量要小于主旋律声部,持续音声部的音量不要过大。
7号是控制某一轨强弱变化的一个控制器,可取范围是0-127。
10号控制器:声响控制器。可以控制各个音轨的声音在声场中的位置。它的主要原则是模拟乐队在演出时的各个乐器声部的位置,当两种音色比较接近时,不要把它们摆在一起。它的设置可以在音轨窗中设定,这样比较直观。声像的取值范围是0-127,对应于从最左边到最右边。可以制作立体声游移的效果,立体声游移的源素材一般选择琶音乐句或时值较长的持续音。
11号控制器:表情控制器。通常用来作弦乐等的演奏效果,以此做出它的起伏变化。7号和11号都可以改变音量的大小,7号一般用于设置通道的相对音量平衡,11号一般用于实时改变通道的强弱变化,前者设置好后一般不再变化,后者可以随时连续变化。临时改变声音的大小和管乐是一般慢节奏的时候用11号控制器,快的时候或顿音时改变力度就可以了。11号与1号控制器配合使用,长音乐器声部的效果就会更加逼真。11号与2号呼吸控制器的作用相似。可以实时录制,也可以用鼠标画[4]。
64号控制器:保持音踏板(Hold Pedal)。即使音乐家已经松开了音符,这个保持音符仍在演奏。也即只有当音乐家关闭了这个控制器,才意味着停止所有的在使用的音符。注意和123号控制器的区别,这个控制器也延迟了同一轨道的123号控制器的使用。如果是一个Multi Timbral装置,那么每一个部分通常设有自己的保持音踏板。值的范围是0-63是关闭,64-127是开。
66号控制器:持续音控制器。
67号控制器:弱音控制器。
68号控制器:连滑音控制器。
69号控制器:保持音控制器。
71号控制器:泛音控制器。它是XG独有的控制器,通过低通滤波器的谐振参数对音色进行变化。如果71号泛音(harmonic content)控制器与74号亮度(Brightness)控制器结合使用,音色将会有变化。71号控制器是用鼠标输入的,取值范围是0-127,初始值时64,不要变化太多,一般到需要变化的时候只输入一个数值就可以了
72号控制器:释音控制器。它的作用是控制音色的振幅包络的变化,把音尾变长或变短。
73号控制器:起音控制器。它的作用也是控制音色的振幅包络的变化,把音头变硬或软。
74号控制器:亮度控制器。用来控制器的截止频率,初始值是64,大于64音色就越明亮,小于64音色越暗淡,74号与71号控制器配合使用音色会有很大变化。比如将71号设置为90,再使用74号就会听到变化,反之一样。
91号控制器:外部效果器深度控制器。通常用于混响效果器。
92号控制器:颤音深度控制器。
93号控制器:合唱深度控制器。
94号控制器:风琴音栓深度控制器。XG特有。
120号控制器:关闭所有声音(all sound off)。如果使用note on按下的音符还没有使用note off松开音符(音符个数大于等于1),可以用120号关闭所有的音符,但不是使所有的音符静音(通过键盘演奏的音符)。如果不能确定演奏的音符是通过MIDI IN还是键盘,则不能使用120号控制器。注意:不同于123号控制器,120号控制器立即使所有的声音静音,包括使用的64号控制器的设备。120号控制器的值通常不被使用,默认为0。
121号控制器:关闭所有控制器。将该轨道控制设定到GM的初始状态。
122号控制器:本地键盘开关。当你的设备是合成器的时候,值为127是开启状态,键盘弹的时候它本身会发声,当值为0时,为关闭状态,键盘弹时它本身不发声,而是将弹入的信号先输入电脑的音序器软件,然后通过软件再把信号传至键盘,才能使它发声,如果MIDI 的IN和OUT同时接在一台设备上,应该设为关闭状态,否则同时同一个音符会发两个音,听到一个如同合唱的效果。
123号控制器:关闭所有音符。如果使用note on按下的音符还没有使用note off松开音符(音符个数大于等于1),可以用120号关闭所有的音符,但不是使所有的音符静音(通过键盘演奏的音符)。如果不能确定演奏的音符是通过MIDI IN还是键盘,则不能使用123号控制器。注意:不同于120号控制器,123号控制器不能关闭64号控制器的设备。进一步说,如果一个装置处于Omni On的状态时,应该忽略这条信息(虽然这条信息出现在任意轨道上)。这个控制器的值通常不被使用,默认为0。
126号控制器:单音模式。当第一个音符发音后,紧接着的第二个音符不会发音,而是延续发音前的一个音符,但是,音高时第二个音符的音高。
MIDI控制器用处大,但是占用传输空间,信息量很大,过密的控制器会使设备的处理出现很大的问题,播放的速度很受影响,改动也麻烦,所以不要过多滥用MIDI控制器。
例9: 00 B6 0A 6F
00表示时间差
B6控制器Bx, 6是轨道,使用第7轨道
0A相位控制(pan)
6F 是控制器值,是111
1.5.7.音色改变(Program Change)
要使音源(音色)按你的音乐意图发出不同声部的声音(或同时发出),就必须使用MIDI的通道功能。即:将不同的声部交给不同的通道去处理和演奏。可以象理解电视频道一样去理解MIDI通道的概念。
MIDI通道有16个,因为,位置字节中,只能分出4位来区分通道,2的4次方=16。实际上,16个通道来发送MIDI信息,完全不是最多只能有16个声部演奏,它可以演奏更多的声部和发送更多的信息,这取决于音源的质量规格和最大发音数限制。因为MIDI有16个基本通道,所以,一套MIDI系统,最多可以连接16个外部音源设备。
Program Change表达式如下:
状态描述:0xC0-0xCF 其中低字节代表使用的MIDI的不同音轨
数据描述:nn 其中nn 表示使用的乐器音色的号码,范围是0-127,也即00-7FH。可以参照本章的G音色表
Program Change是使MIDI设备换一种音色使用(这些设备可能是patch、乐器、预调设置等)。很多声音装置有大量的乐器声音,例如piano,guitar,trumpet等等,每一种乐器发出的音色都被包括在音色表里。
因此当使用按下音符事件时,Program Change只需要改变MIDI设备弹奏的乐器的音符,Program Change事件只是选择了目前使用的乐器,不过,别的MIDI事件也可以改变当前的音色的声音。
如果设备是MultiTimbral unit,那么它通常可以立即演奏16部分,每一部分可以通过各自的音轨道获得相应的数据。而且每种乐器的音色只能通过各自的音轨道改变。
针对那些乐器没有声音的MIDI设备,例如Reverb unit,它可能存储有一些重置的“room 规则”,那Program Change信息通常被用来选择使用哪一种重置设备。例如:drum box可以用Program Change去选择一个特殊的节奏。
音色库的选择也不是很标准的,大致有3中XG,GS,GM,本文列出了GM的标准库。不同的音色表有不同的乐器。注意:不同的音色库开始时可能是0或1,所以实际描写MIDI数据流时需要特别留意。
例10:选自《passport》第1块音轨
00 C0 03
00表示时间差
C0表示Program Change发生在第一通道
03表示音色,查表知道是Honky-tonk Piano
事实上,音色的选择是由Program Change和相匹配的控制器事件共同完成。所以例10还需要结合2个匹配的控制器号00和20来实现音色Honky-tonk Piano的选择,附件1得到:00 B0 00 05 00 20 57 00 C0 03
例11:取自《克罗地亚狂想曲.mid》第1块音轨
00 C0 00 00 B0 0A 40
在0轨道使用音色00(原声大钢琴),控制器号码是0A(声像调整pan)
1.5.8. 通道压力(Channel Pressure)
Channel pressure描述的是变化的力度(音乐家用一定的力度按下音符时产生的),同时是通过通道传输信息的。状态描述如下:
状态描述:0xC0-0xCF 其中低字节代表使用的MIDI的不同音轨
数据描述:nn 其中nn 表示压力值,范围是0-127,也即00-7FH ,0是没有压力,127是最大的压力值。
Channel pressure不同于AfterTouch,它们的区别是:
(1)Channel pressure是针对按下整个键盘时使用的力度值,即使你按下不同的键的力度值不同,模块将最终把这些不同的力度值平均化,这样表现出来的是你按下所有的键的力度值是一样的,也即最终的结果是一些不同的压力值将平均分布在整个键盘上。
(2)AfterTouch是针对于按下单个键时使用的力度值,力度越大,AfterTouch信息值越大,不同的键产生不同的力度值,也即产生AfterTouch的信息值也是不同的。
控制器一般使用这两个力度值中的一个,但是通常不同时使用。
MIDI控制器很少使用AfterTouch,原因是:AfterTouch要求每个键有相对应的压力感知器,导致器件价格高。channel pressure只要求键盘有一个感知器,所以控制器经常使用这个力度值。
当然,一个设备能够产生这两种信息值,在这种情况下,AfterTouch先产生每个键的力度值,接着把所有的力度值平均化,最终把这个平均值作为channel pressure力度值送出。
1.5.9. 滑音(Pitch Wheel)
滑音也叫pitch wheel,可以理解为:用不同的滑音参数调整MIDI器件来改变音符的值,同时对于不同的MIDI器件的通道,滑音的信息是不同的。所以滑音表达式如下:
状态描述:0xE0-0xEF 其中低字节代表使用的MIDI的不同音轨
数据描述:nnff 这里的nnff组合构成14bit的值(不考虑字节的最高位,总设为0)。其中nn 是0-6bit,ff是7-13bit。总共加起来组成14bit。计算公式nn:pitch mod 128;ff:pitch div 128。0x2000是中间值,它的声调不能调大或调小。滑音的参数值值越大声调越高,值越小,声调越低。
滑音的乐理范围对于不同的MIDI设备是不同的。例如虽然0x2000H也即8192总是中间值,但是对于一个MIDI设备,0x3000可能调升一个音阶,但对应别的设备有可能只调升了半个阶。滑音范围是通过RPN控制器信息来调整的。
GM标准建议MIDI默认的滑音范围的信息值是0x0000-0x3FFF,也即16384个单位,最小时为-8192,最大时为8191,每次调升降是半阶。参数为0 表示没有滑音。但在使用时参数是个正数,比如要设置成0,则应该是0-(-8192)=8192,它才是参数。
如果设备是MultiTimbral unit,那么设备中的每一部分对于不同的滑音的反应是不同的。
例11:00 E6 00 40
00时间差,E6表示滑音,在第7通道使用滑音,设置滑音值为0,代入公式:参数是0-(-8192)=8192,8192的7位双字节表示成8192 mod 128=00H(字节的最高位设置为0),8192 div 128=128*64=40H(字节的最高位设置为0)。
1.6. Meta事件
元事件也叫meta event,是非MIDI事件流。由于MIDI文件含有大量的非MIDI事件,而且功能不同,所以单独列出一章具体阐述每一个元事件的用法。
注意:并不是每个MIDI文件,都必须描述每一个元事件。
元事件开始的状态位都是FF,紧接着是元事件的各种类型,其中范围01-0F的是预留给各种类型的文本使用的,使用的目的各不相同。MIDI文件结构中各种元事件的定义如下:
设置轨道音序在MIDI文件中存储的表达式如下:
FF0002ssss/ FF0000其中ssss是音序器号码,用来指定MIDI提示信息,范围是00 00-FF FFH。
在格式2中使用表达式FF0002ssss,音序器号码主要用来识别不同的状态(例如MTrk),以便一首歌的音序器能用MIDI提示信息找到对应的状态。
如果忽略ssss,使用表达式FF0000,可以用MTrk块的位置起始点作为音序器号码(例如:如果第一个MTrk音轨块的音序器号码是0,则第二个MTrk音轨块的音序器号码是1……)。在格式0或1中,仅仅有一种状态(虽然格式1包含了几个MTrk),在这种情况下,这个事件必须被放置在第一个MTrk音轨块里,位于任何非零时间发生的事件或可传送的MIDI信息事件的前面。所以一组带有不同音序号码的格式0或格式1的文件能组成一个歌的集合。
歌曲备注和音轨文本在MIDI文件中存储的表达式如下:
FF01+字节总数+文本信息(ASCII的16进制)
字节总数指的是文本信息的字节数目总和,是可变长度量,类同于时间差的写法
例:选自附件3的TITANIC.MID
00 FF 01 0F 44 65 72 53 68 69 75 6E 20 53 74 75 64 69 6F 00 FF 01 10 44 65 72 53 68 69 75 6E 20 53 74 75 64 69 6F 0A
0F表示歌曲备注和音轨文本的总长度为15个字节,对应的ASCII码是“DerShiun Studio”
00表示时间差
这个事件经常放在音轨的开头,有助于日后查看,这个事件可以连续发生,可以从附件3的TITANIC.MID中观察到。文本事件也可能发生在其它时间,被用来作为歌词。
歌曲版权在MIDI文件中存储的表达式如下 FF02+字节总数+版本信息(ASCII的16进制)
字节总数指的是版本信息的字节数目总和,是可变长度量,类同于时间差的写法
例:附件3的TITANIC.MID
00 FF 02 21 43 6F 70 79 72 69 67 68 74 20 31 39 39 38 20 62 79 20 44 65 72 53 68 69 75 6E 20 53 74 75 64 69 6F
21表示歌曲版本的总长度为33个字节,对应的ASCII码是“Copyright 1998 by DerShiun Studio”
歌曲版权包括的内容有:字符、版权所有的时间、版权所有者。如果几段音乐同时放在一个MIDI文件中,那么它们的音乐的版权声明应放在一起,并且时间差都为0,放在第一个音轨块里,而且全部放在文件的开头。
歌曲标题/音轨名称在MIDI文件中存储的表达式如下: FF03+字节总数+歌曲标题(ASCII码的16进制)
字节总数指的是歌曲标题的字节数目总和(此时只用于全局音轨,第一次使用表示主标题,第二次使用表示副标题),是可变长度量,类同于时间差的写法;音轨名称通常用在“Mtrk”之后,表示这个音轨的名称
例:选自愛是永恒.mid,表示歌曲标题
00 FF 03 08 B7 52 AC 4F A5 C3 AB ED
时间差为0
08表示歌曲标题的总长度为8个字节,查ASCII码得出
例:选自附件3,表示音轨名称
00 FF 03 14 54 75 62 75 6C 61 72 20 42 65 6C 6C 73 20 20 20 20 20 20 20
时间差为0
14表示音轨名称的总长度为20个字节,查ASCII码得出“Tubular Bells ”
MIDI文件中的每一个音轨块,通常都会用音轨名称来标注字段,不过,这个规范并不是必须的,但只要是标注了字段的音轨块,都能对主旋律音轨的提取提供有益的信息,并且表征旋律音轨的特征量所也都能使用[1]。
乐器名称在MIDI文件中存储的表达式如下:
FF04+字节总数+音轨文本(ASCII码的16进制)
字节总数指的是音轨文本的字节数目总和,是可变长度量,类同于时间差的写法
例:选自附件1
00 FF 04 1B 4D 69 63 72 6F 73 6F 66 74 20 47 53 20 B2 A8 B1 ED C8 ED BC FE BA CF B3 C9 C6
00表示时间差为0
1B表示乐器名称的总长度为27个字节,查ASCII码表可知“Microsoft GS 波表合成软件器”
歌词在MIDI文件中存储的表达式如下: FF05+字节总数+歌词(ASCII码的16进制)
字节总数指的是歌词的字节数目总和,是可变长度量,类同于时间差的写法
例:00 FF 05 05 57 61 74 63 68
00表示时间差为0
05表示歌词的总长度为5个字节,查ASCII码表可知“Watch”
由于每个音节将是一行单独的歌词,应该写清时间。
标记在MIDI文件中存储的表达式如下: FF06+字节总数+文本标记(ASCII码的16进制)
字节总数指的是文本标记的字节数目的总和,是可变长度量,类同于时间差的写法
例: 例子来源于《passport.mid》
00 FF 06 10 43 34 2D 50 39 31 2D 50 4F 4C 59 53 59 4E 54 48
00表示时间差为0
10表示标记的总长度为16个字节,查ASCII码表可知“C4-P91-POLYSYNTH”
通常出现在格式0的音轨,或格式1的第一个音轨,可以连续出现多个标记事件。
开始点在MIDI文件中存储的表达式如下: FF07 len text 其中Len为字节总数,是可变长度量,类同于时间差的写法。text是歌曲文件的名字。
这个事件主要为给定的节拍做标记,可以标记一个歌曲文件的开始。
Program name在MIDI文件中存储的表达式如下: FF08 len text 其中Len为字节总数,是可变长度量,类同于时间差的写法;text是歌曲文件的名字。
例:00 FF 08 0A 47 6F 6E 7A 6F 20 48 61 72 70
0A表示设备名字的总长度为1名字长度为10,查ASCII码得出“Gonzo Harp”
乐器名字不同于音序器和音轨的名字,是用来播放MTrk音轨块块。例如:音序器的名字是“Butterfly”,但由于音轨是在电子piano上演奏的,所以你也要写上乐器名字“ELECTRIC PIANO”。
在前面提到过,乐器的使用是通过MIDI改变乐器事件和MIDI的控制器事件描述的,当MIDI文件使用非MIDI乐器,这个时候就需要使用乐器标题事件来提示MIDI改变乐器事件。
设备名字 Device(Port)Name在MIDI文件中存储的表达式如下:
FF 09 len text
Len为字节总数,是可变长度量,类同于时间差的写法;text是传输音轨事件所用的MIDI设备的名字(ASCII码的16进制),
例:00 FF 09 0A 4D 49 44 49 20 4F 75 74 20 33
0A表示设备名字的总长度为10,通过查ASCII码得出“MIDI Out 3”
这个事件取代了音序器传输MIDI音轨到多种MIDI接口的元事件,主要是为了能够使用超过16个MIDI通道才使用的。例如假设你有一个MIDI接口有4个MIDI输出接口,分别是“MIDI Out 1”,“MIDI Out 2”,“MIDI Out 3”,“MIDI Out 4”。如果你希望一个特殊的MTRk使用“MIDI Out 1”,那么你可以把一个port name元事件放在MTrk的开始,text是“MIDI Out 1”。
格式0中,可以使用多个这个事件来表示多种的接口。
格式1中,使用这个事件用来传输一个特殊的接口。
音轨结束标志 在MIDI文件中存储的表达式如下: FF2F00 每当完成一段音轨块的数据流时,都要加上这个事件作为结束的标志。
设定速度tempo在MIDI文件中存储的表达式如下 FF5103tt tt tt
表示速度的变化,其中03表示总共3个字节,tt tt tt表示每完成1个4分音符用多少时间,并以微妙为单位。给出时间直接换算为16进制即可,没有标志位。
例:27985(十进制)=6D51(十六进制)
27985除以16=1749余1. 1749除以16=109余5. 109除以16=6余13. 6比16小,不能再除了,因此,6就成为十六进制数值的首位,然后从下往上逐一加上余数13,5,1.就得到数值6 13 5 1.转化为十六进制就是6D51.
例:选自附件1 00 FF 51 03 09 A3 1A
如果MIDI文件中没有速度事件,速度可以直接被假设为120BPM。
格式0中,速度的变化贯穿于整个MTrk音轨。
格式1中,为了使一些设备的速度映射起来,第一个MTrk音轨应该只含有速度和拍子记号事件,最好不放其它的MIDI事件。附件2看出总音轨没有放置MIDI事件,都是元事件。
格式2中,每一个MTrk音轨块的开始应该至少放一个速度事件和拍子记号事件。
SMPTE时间同步在MIDI文件中存储的表达式如下 FF5405hrmnsefrff 其中hrmnsefrff 分别是MTrk音轨块的SMPTE的开始时间(时,分,秒,帧,复帧),应放在MTrk音轨的开始,因为使用的是MIDI时间编码,所以不应该用SMPTE的格式对“时”编码/译码(encode)。
例:选自附件2的愛是永恒.mid
00 FF 54 05 60 00 03 00 00
表示(96小时)3秒
格式1中,SMPTEOFFSET应该被存储在速度块里(tempo map)例如第一音轨,在其它的MTrk音轨里没有意义。其中ff域是分数帧的个数,在SMPTE里,MTrk块对时间差阐述了一个不同的帧的分区和MThd里的复帧不一样。
拍子记号(Time Signature)在MIDI文件中存储的表达式如下: FF5804nnddccbb 其中nn和dd分别表示乐谱上的拍子记号的分子与分母,分母是2的指数:2是22=4分音符的指数,3=23是8分音符的指数等;cc表示一个节拍器的MIDI时钟;bb参数表示一个MIDI的4分音符包括的32分音符的个数。
例:例子来源于《passport.mid》
4/4拍号 FF5804 04 02 18 08 4/4拍号(4等于2的二次方,因此,这里是0402),四分音符是32个MIDI时间间隔(24的十六进制是18),四分音符等于8个三十二分音符。
如果MIDI文件里没有拍子记号,那么默认为4/4。
格式0中,速度变化贯穿于整个MTrk音轨。
格式1中,为了使一些MIDI设备的速度映射起来,第一个MTrk音轨应该只含有速度和拍子记号事件,最好不放其它的MIDI事件。附件2看出总音轨没有放置MIDI事件,都是元事件。
格式2中,每一个MTrk音轨块的开始应该至少放一个速度事件和拍子记号事件。
音调符号(Key Signature)在MIDI文件中存储的表达式如下 FF5902sfmi 其中sf=-7
例:FF59020301
sf=03,大调在五线谱上注了三个升号
sf指明乐曲曲调中升号、降号的数目。也就是说,升号数目写成0x,降号数目写成8x mf指出曲调是大调还是小调。大调mf=00,小调mf=01
音符特定信息(Proprietary Event)在MIDI文件中存储的表达式如下 FF7F+字节总数+音符特定信息(16进制)
这个事件被一个乐器存储特定数据,第一个字节应该是一类独特的ID,以便乐器能确定是否属于自己,建议使用ASCII码;字节总数是可变长量,类同于时间差的写法。
例:选自附件3
00 FF 7F 03 00 00 40
MIDI通道(MIDI Channel)在MIDI文件中存储的表达式如下
FF 20 01 cc 其中cc是MIDI通道,0通常作为第一通道
MIDI Channel指定MIDI文件的那个通道是与这些事件(任何随后的元事件和系统码事件)相关的。
MIDI Channel事件是可选的,通常发生在MTrk块的开始,
MIDI文件规定不分配给系统码事件一个MIDI通道。同时元事件也没有一个嵌入(imbedded)的通道。
MIDI Channel使用原因:在格式0中,由于所有的元事件和系统码事件都被放在同一个音轨块里,所以把这些事件和各自的MIDI声音信息联系起来是非常困难。例如:在MIDI,你想要分别为通道1“Flute Solo”和通道2“Trumpet Solo”命名,那么你需要使用2个音轨名字元事件。但是2个事件都放在一个音轨块里。为了使音轨块名字和自己的MIDI通道映射起来,你需要在“Flute Solo”音轨块名字元事件前面放一个带有通道号码的MIDI通道元事件,对“Trumpet Solo”也是一样。
MIDI接口(MIDI port)在MIDI文件中存储的表达式如下
FF 21 01 pp 其中pp是接口的号码,在系统中,0必须放在第一个MIDI文件的母线上。
MIDI port主要用来使一个音序器能够识别MTrk音轨块里的事件是从哪一个MIDI接口输出的。例如第二个MIDI器件接口的通道1通过第一个MIDI器件接口的通道1。
在一个音轨块里可以含有一个以上的这类事件。
MIDI port是可选的,通常发生在MTrk的开始,位于任何非零时间发生的事件或可传送的MIDI信息事件的前面。
MIDI器件的局限性:每个MIDI器件的输入/输出(或用硬件体现MIDI器件的输入/输出的技术)仅仅有16个通道,范围是00-0FH。
MIDI port使用的原因:在MIDI器件的宽带下,为了使MIDI器件能够工作在这个局限性下,很多MIDI接口有很多的MIDI输入/输出母线,所以音乐家才能使用多于16个通道的MIDI器件。一些音序器件支持超过一个MIDI器件的接口(同时用来输入/输出),不幸的是,在多于16个通道的情况下,没有任何方法能够在一个MIDI状态字节下编码,所以用MIDI port来识别将要输出的事件。
例:附件2的阿刺伯跳舞女郎.mid
00 FF 21 01 01
1.7. MIDI的“速度”描述
在MIDI规范中定义的最小时间单位是Tick。重新定义一个新的时间单位来描述音符的时长,是因为现有的一些时间格式都不太适合MIDI的描述与存储。虽然Tick是一种新的时间单位,但它与其他一些相关的音乐时间(比如BPM、SMPTE)都是相互关联的,也是可以相互转换的。事实上,为了在两台MIDI设备之间控制不同的时间格式以保持它们之间的同步,MIDI规范中专门制定了一个名为MTC(MIDI Time Code)的子协议。MIDI中一个音符的时长是通过开音码和对应关音码之间的间隔时间,即德尔塔(delta)时间来描述的,由于MIDI中没有音符的概念,因此要通过将对应的音符开启和关闭事件配对形成一个音符,称之为原始音符,之后还需要将音符开始时间戳和结束时间戳转换成音符开始时间戳和音符持续长度。为了完成上述两个任务,使用一个大数组缓存16个通道里的128个音的状态。在接收到音符打开与关闭消息时进行记录,并同时计算开始时间与持续时间。
Meta事件的读取
MIDI中的Meta事件中描述的信息在五线谱显示中基本上都是有用的,有些信息还起着至关重要的作用。例如很多说明性的文字信息,需要直接添加到五线谱和各音轨的属性中。当这些说明性信息重复出现时,可以把两段信息的文字连起来,作为一条长的信息出现。调号和拍号信息是Meta信息中非常关键的两条。调号决定了每个音符在五线谱上显示的确切位置及其升降号标志,拍号决定了小节的长度还同时影响合成音符组的规则。这些信息都是整合分析器不可缺少的重要信息。 节拍[meter] 是衡量节奏的单位,在音乐中,有一定强弱分别的一系列拍子在每隔一定时间重复出现。如 2 / 4 、 4 / 4 、 3 / 4 拍等。
节拍,乐曲中表示固定单位时值和强弱规律的组织形式。又称拍子。每小节中强拍和弱拍的循环称二拍子;强拍、弱拍 、弱拍的循环称三拍子。表示每小节中基本单位拍的时值和数量的记号,称拍号。拍号的上方数字表示每小节的拍数,下方数字表示每拍的时值。
例如,2/4表示以4分音符为1拍,每小节有 2 拍。拍号中时值的实际时间,应视乐曲所标速度而定。在不同节拍类型中,每小节只有一个强拍的叫做单拍子,如2/4、2/8是单2拍子,3/4、3/8是单3拍子。每小节有一个强拍并有次强拍的叫做复拍子。 如 4/4、6/8是复 2 拍子,9/8、9/16是复3拍子。单位拍时值相同而拍数不同的单拍子组合在一小节内,叫做混合拍子。例如5/4是由2/4+3/4或3/4+2/4组合而成,7/8是2/8+2/8+3/8或3/8+2/8+2/8组合而成。
1.7.1. BPM
在音乐中我们一般用BPM来表述乐曲的速度,BPM(Beat per Minute)的意思是每分钟的拍子数。例如,BPM=100,表示该歌曲的速度是每分钟100拍。注意,对于音乐家来说,BPM中的一拍是指一个四分音符,而不管歌曲的拍号是多少。例如,假设歌曲的拍号是3/8拍(以八分音符为一拍,每小节3拍),BPM=100,那么,音乐家依然会把歌曲的速度认为是以四分音符(非八分音符)为一拍,每分钟100拍。 因此,BPM被称为是“音乐速度(Musical Tempo)”,它与MIDI文件表述的速度(Tempo)是不完全一样的。 MIDI中并没有使用BPM来表示歌曲的速度,取而代之的是Meta Tempo事件,主要是因为Meta Tempo的时间单位比BPM描述更为精确,因为有时需要更精准的拍子时,BPM可能会出现小数,比如BPM=120.5。 因为MIDI文件中并没有定义BPM的信息,因此为了将MIDI中的速度(Meta Tempo)转换为音乐速度(Musical Tempo),需要使用下面的转换公式:
BPM=60000000/microTempo
上式中,MicroTempo是指Meta Tempo事件(FF 51 03 tt tt tt)中的时间tt tt tt。例如,当MicroTempo=07 A1 20=500000(微秒),则乐曲的BPM=60000000/500000=120。
1.7.2. PPNQ Clock
对于相关音乐人士来说,使用微秒作为MIDI事件的delta时间,确实让人很难以理解也很费脑筋。因此,MIDI中定义了另一个比微秒更合适的时间单位:Tick。 对于音乐制作者来说,Tick就是MIDI中定义的最小单位(TimeBase),在MIDI音乐制作中,MIDI事件就可以用这种大家都容易接受的方式来描述——小节:拍:Ticks。 为了产生计数TimeBase的时钟(PPQN Clock, Pulses Per Quarter Note),音序器程序一般需要借助硬件(微秒)定时器来实现。那么,如何确定PPQN Clock的时长呢,也就是说1个Tick到底是多少微秒?其实这是可以算出来的,因为Meta Tempo可以告诉你一个四分音符的微秒数,而division告诉了你一个四分音符的Tick数,因此1个Tick的时间可以通过如下的公式计算出来:
tick=Meta Tempo(微秒)/division
Micro Tempo是指Meta Tempo事件(FF 51 03 tt tt tt)中的时间tt tt tt,例如,MicroTempo=07 A1 20=500000,Division=120,那么1个Tick的时长就是500000/120=4166(微秒)
1.7.3. MIDI clock
在MIDI标准中,定义了只有一个状态字节的F8码,它是为两台设备之间(主设备和从设备)同步而定义的MIDI时钟系统信息(稍微高档一点的MIDI设备一般都具有定时发送F8码的功能,我们可以从诸如midiox这样的应用程序中监测得到),并且该信息发送的速率是根据主设备音乐速度的不同而改变的,因为MIDI规范中指定了一个四分音符为24个MIDI Clock,因此每个MIDI Clock的时长可根据下面的公式计算出来:
MIDI Clock信息的速率=Micro Tempo(微秒)/24
例如,FF 51 Meta Tempo信息中Micro Tempo=500000,则设备发送MIDI Clock信息的频率就是500000/24=20833(微秒)。 当然,我们也可以用PPQN Clock为单位来表述一个MIDI Clock的时长:
MIDI Clock信息的频率=Division/24
例如,MIDI文件头信息中Division=120,则设备发送MIDI Clock信息的频率为120/24=5 PPQN Clocks。
1.7.4. SMPTE
SMPTE是一种基于日常生活基本时间:时、分、秒的时间格式,并且它把秒分为了更小的单位:帧(Frames)。该时间格式最初应用于电影行业,被应用于音乐设备之后,帧又被分为了更小的单位:子帧(SubFrames)。 SMPTE是一种绝对的时间格式,而不是音乐上用于计时的时间,与音乐速度(Musical Tempo)没有直接的关系,也不会随速度的改变而改变。 许多MIDI主设备(Master)通常通过SMPTE来同步与之连接的MIDI从设备(Slave),从设备为了响应这种方式的同步就必须转换SMPTE。即以SMPTE时间为基础,得到并维护自己的PPQN Clock,这样,用户才能通过设置BPM来改变乐器的播放速度。 PPQN Clocks必须通过计算传递的SMPTE时间(时:分:秒:Frames:SubFrames)重新来确定,假设SMPTE的fps为25(每秒钟25帧)并且每帧分为40个子帧(SubFrames),那么每秒钟的子帧数就是25×40=1000,也就是说,每个子帧的时间是1毫秒(ms)=1000微秒。 现在假设Meta Tempo=500000(微秒/四分音符),则每个四分音符子帧数为500000/(25×40)=500,再假设Division=96(Ticks/四分音符),则每个Tick的子帧数为500/96=5.2083。因此,在Meta Tempo=500000,Division=96的条件下,每个Tick(PPQN Clock)的子帧数为5.2083,而每个子帧的时间是1000微秒,可知每个Tick的时间是5208.3微秒。设置速度是51 ,但是在其前面必须是FF,然后需要3个字节作为参数,所以字节数为03
1.8. 实时分类事件(RealTime Category)
实时分类事件也叫realtime category,这类(状态位0xF8-0xFF,仅有一个byte组成)事件只集中于实时功能,也就是说在特定的时间输入输出事件,没有任何的延迟。因此,MIDI文件允许实时分类事件可以在任何时候被传送,即使MIDI文件被插入一些不相关联的MIDI事件。也即任何事件的表达式都必须带有相应的状态位。
1.8.1. 运行状态(Running Status)
运行状态也叫running status,可以理解为:当先前被传送的事件具有相同的状态位时,接下来被传送的同类的MIDI事件可以省略状态位。
原因是:MIDI设备能够存储最后传送进来的MIDI事件的状态位,只要将要传送的事件具有相同的状态位,都可以省略相同的状态位,进行传送一连串的同类事件,最终最大限度的提高了MIDI的传送率。
例1:选自《阿刺伯跳舞女郎》
00 91 2B 78 00 32 78
连续按下音符
特例:选自《阿刺伯跳舞女郎》
88 7F 92 3C 64 00 41 64 00 39 64 81 1C 39 00 04 3C 00 04 41 00 1C 3E 64这个特例的原因是,按下音符时,如果力度是0,将等同于松开音符,所以可以一连串的按下和松开音符,省略状态位。
例2:选自附件3
00 B0 00 05 00 20 57
连续使用控制器
例3:选自附件3
0E A0 0C 00 02 03 00 02 02 00
连续使用aftertouch
例4:选自附件3
00 E0 00 40 00 00 40 00 00 40 连续使用滑音
注意:一旦使用了非音符事件,接着再使用音符事件时,则必须重新通知打开音符。通过修改音符事件:原来是时间差+音符+力度,现在加入一个打开音符的标志成为:时间差+9x+音符+力度。
注意:时间差为00的控制事件如果出现的时间也是00,在cakewalk中会尽可能的把它们放在轨道信息中,而不在事件列表中重复。可以利用这一点给音轨设置初始乐器和音量
例5:连续使用2个控制器和接着松开音符:00 B6 0A 40 00 B6 07 46 83 30 86 41 40
其中00、00、83 30是时间差,这里使用状态位86去松开音符。
由于发生的事件在任一时刻都带有状态标志位,所以实时分类事件能处理任何时间的状态事件,而运行状态信息事件由于省略了事件的状态标志位,所以不能处理实时分类事件。
运行状态事件仅仅能完成声音分类事件(例如0x80-0xEF)
1.9. 解析MIDI文件
解析MDI文件的难点:
1,时间差是动态字节,无法确定位数;
2按下音符与松开音符一起使用时经常省去状态位;
3控制器一起使用时会省去状态字节。
1.9.1. 解析实时信息(RealTime) MIDI歌曲
本附件的特点是使用任何一种事件,都有明确的状态位,最容易解析MIDI文件的内容
例子来自《克罗地亚狂想曲》多音轨,GS音色库,调号每个音轨的都一样,不能规定多个不同调号,标准规范的格式非常有利于编程提取数据
4D 54 68 64 00 00 00 06 表示”MTHd”,6个字节
00 01多音轨 00 0A指定轨道数是10,其中9个音轨,也即9种乐器,1个总音轨。01 E0 分区是480
4D 54 72 6B 00 00 00 2C 表示“MTRk”,2C(44)个字节,在此总音轨的字节数,不包括“MTRk”的字节数
00 FF 03 13 20 43 72 6F 61 74 69 61 6E 20 52 68 61 70 73 6F 64 79 20歌曲标题和音轨名称13 (16进制)为歌曲标题字节数总共是19个
00 FF 58 04 04 02 18 00节拍(一首歌曲中节拍可以改变的,往往从3/8变换到4/4)
00 FF 51 03 09 A3 1A速度
89 D0 00 FF 2F 00音轨结束标志, 89 D0 00为时间差
4D 54 72 6B 00 00表示“MTRk”,25 B9个字节,第一个轨道信息
00 FF 03 05 50 69 61 6E 6F歌曲标题表示音轨名 05为字节数
00 FF 04 1B 4D 69 63 72 6F 73 6F 66 74 20 47 53 20 B2 A8 B1 ED C8 ED BC FE BA CF B3 C9 C6 F7乐器名称总共有1B个字节,也即是27个字节
00 FF 59 02 FD 00 指定调号,大调
00 C0 00 00 B0 0A 40改变音乐,在0轨道使用乐器00(原声大钢琴),使控制器号码是0A(声像调整pan)值是64
8F 00 90 5B 6E 时间差8F 00,按下音符5B(G),音阶是4,力度6E 表示:在轨道1按下音符G,与控制器的使用相差的时间是8F 00
00 90 56 6E 音符是56(D) 按下音符56,音阶是6,力度6E,时间差00 表示:与音符G同时按下音符D
6C 80 5B 40音符是5B 松开,时间差为6C 表示:隔了时间差6C,松开音符G,
00 80 56 40 音符是56 松开 表示:同音符G一样同时松开音符D,松开力度也一样。
0C 90 57 6E 时间0C,音符是57(D#)按下音符57
6C 80 57 40 时间是6C 松开音符57
0C 90 54 6E 时间是0C音符是54(C)音阶是6, 按下音符54
81 58 80 54 40 松开音符,时间差为81 58
18 90 5B 50 时间是18,音符是5B 按下音符5B
00 90 56 50 按下音符56
6C 80 5B 40 松开5B
……….
88 20 FF 2F 00 结束
4D 54 72 6B 00 00 15 00 第三段音轨迹,字节数 15 00
00 FF 03 06 56 69 6F 6C 69 6E歌曲标题
00 FF 04 1B 4D 69 63 72 6F 73 6F 66 74 20 47 53 20 B2 A8 B1 ED C8 ED BC FE BA CF B3 C9 C6 F7乐器名称总共有1B个字节,也即是27个字节
00 FF 59 02 FD 00 指定调号,大调
00 C6 2C 00 B6 0A 40使用乐器2C(G#),音阶是2,控制器号码是0A控制器参数是40
00 B6 07 46 控制器号码0A,控制器参数是40
00 96 43 50 在通道6,按下音符43,力度50
69 40 86 43 40 松开音符43,时间差69 40
81 36 B6 07 50
…….
4D 54 72 6B 00 00 15 10
00 FF 03 06 56 69 6F 6C 69 6E
00 FF 04 1B 4D 69 63 72 6F 73 6F 66 74 20 47 53 20 B2 A8 B1 ED C8 ED BC FE BA CF B3 C9 C6 F7
00 FF 59 02 FD 00以上功能类似于第三段音轨
00 C6 2C第二次使用乐器2C,此时出现问题与查表不符合,不是violin,
00 B6 0A 40 00 B6 07 46 连续使用控制器(声像调制以及主音量,粗调)
00 96 43 50 以上功能一样
C9 40 86 43 40 按下音符G,音阶是4
81 36 B6 07 50 使用控制器(主音量,粗调)
0A 96 43 50 以下是按下音符及松开音符
86 60 86 43 40 60 96 43 50 83 30 86 43 40 30 96 41 50 83 30 86 41 40 30 96 41 50 83
30 86 41 40 30 96 3E 50 83 30 86 3E 40
1.9.2. 解析运行状态(Running Status)MIDI歌曲(格式1)
下面选自阿刺伯跳舞女郎,多音轨,GM音色表。
特点是省略了音符按下与松开的状态位,一般给定了按下音符的标志位后,会紧接着一串的按下音符事件,但同时由于力度是0,所以可以认为此时是松开音符,相当于按下和松开一串的音符,利用这个特点来分析音符事件。
这里有一条原则就是,肯定是先按下音符,才能松开,还有留心记忆不同的音符,才可以快速分析文件结构。这给编程带来了难度和不准确性。
另外就是关于00的使用,很多是时间差以及松开音符,其中还有大量的控制器,滑音的连续使用。
4D 54 68 64 00 00 00 06 00 01 00 09 00 C0 多音轨,9个轨道,分区是190
4D 54 72 6B 00 00 00 37总音轨是48个字节
00 FF 59 02 00 00,调号是大调,降号
00 FF 21 01 00特殊没有规定
00 FF 58 04 03 03 18 08 节拍
以下描述的是相隔一段时间速度会有变化(一首歌曲中速度往往也是变化的 )
00 FF 51 03 14 58 55 速度 ,时间差为0
81 DE 60 FF 51 03 16 E3 60 速度,时间差为81 DE 60
82 20 FF 51 03 18 BE 75速度,时间差为82 20
82 20 FF 51 03 1C 9C 38速度,时间差为82 20
00 FF 2F 00结束
真实的时间
4D 54 72 6B 00 00 15 7B
00 FF 03 14 42 61 73 73 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20歌曲标题
00 FF 21 01 00 特殊没有规定
00 C1 20 00 B1 07 7F使用乐器Bass,7号控制器(主音量,粗调),使用第二轨道
00 91 2B 78 按下音符G,音阶是2
00 32 78 按下音符D,音阶是3
00 E1 00 40 时间差,使用滑音
01 B1 0A 40 使用控制器,声像调整pan
27 91 2B 00 按下音符G,音阶是2,力度为0,等同松开
08 32 00 松开音符D音阶是3 00 37 78 按下音符1C 37 00 松开14 37 78 按下2C 37 00 松开04 32 78 ,观察知道前面音符没有按下,所以在此是按下,用来编程00 2B 78按下0C 2B 00 松开04 32 00松开20 32 78 按下00 2B 78 按下28 2B 00 松开04 32 00松开04 37 78 按下0C 37 00松开
24 2B 78按下00 32 78 按下2C 2B 00松开 04 32 00 松开
下面引用的例子都是这样判断的,可以借此来加深判断
……
20 1F 78 00 26 78 10 26 00 04 1F 00 1C 2B 78 10 2B 00 20 2B 78 10 2B 00 20 26 78
00 1F 78 0C 1F 00 04 26 00 20 26 78 00 1F 78 0C 1F 00 04 26 00 20 2B 78
10 2B 00 20 26 78 00 1F 78 82 20 26 00 00 1F 00 00 FF 2F 00
……
88 7F 92 3C 64 00 41 64 00 39 64 81 1C 39 00 04 3C 00 04 41 00 1C 3E 64
00 3A 64 3C 3E 00 00 3A 00 24 39 64 00 41 64 00 3C 64 81 20 39 00 00 3C 00
04 41 00 1C 3E 64 00 3A 64 30 3E 00 00 3A 00 30 41 64 00 39 64 00 3C 64 50 39 00
00 3C 00 04 41 00 0C 3F 64 0C 3F 00 04 41 64 10 41 00 08 3F 64 08 3F 00 08 41 64
0C 41 00 04 3F 64 10 3F 00 08 3E 64 00 3A 64 82 40 3E 00 04 3A 00
……
4D 54 72 6B 00 00 05 FC
00 FF 03 14 4D 65 6C 6F 64 79 20 20 20 20 20 20 20 20 20 20 20 20 20 20 歌曲标题
00 FF 21 01 00 00 C3 47 00 B3 07 50 00 E3 00 40 使用滑音 01 B3 0A 40使用控制器
88 7F 93 4D 73 81 2C 4D 00 14 4A 73 44 4A 00 1C 4D 73 81 28 4D 00 18 4A 73 48 4A 00 18 4D 73 44 4D 00 1C 4B 73 10 4B 00 08 4D 73 0C 4D 00 04 4B 73 0C 4B 00
04 4D 73 10 4D 00 00 4B 73 10 4B 00 08 4A 73 82 44 4A 00 3C 4D 73 81 2C 4D 00
14 4A 73 48 4A 00 18 4D 73 81 28 4D 00 18 4A 73 48 4A 00 18 4D 73 4C 4D 00
……
以下选自《MERYXMAS》观察到连续使用控制器,和连续使用音符的区别,当混合使用控制器和音符时,必然会添加状态位,以此区别。
另外注意00作为时间差时,这种描述方法是错误的,00 80,如果描述时间差80,只需写80前面不在多加00,关于这个描述规范可以在前面章节3.2看到
00 FF 21 01 01 表示MIDI port
00 FF 03 14 54 75 62 75 6C 61 72 20 42 65 6C 6C 73 20 20 20 20 20 20 20 mtrk轨道名字通过查询ASCII码可知“TubularspBellsspspspspspspsp”其中0x20H表示”sp”
00 C8 0E 使用Bells 00 B8 00 00音色库选择 使用第8轨道,总轨道00 5B 4F混响效果深度 连续3次使用控制器00 5D 6D 合唱效果深度
83 00 C8 0E 乐器大扬琴,在第9音轨
CC 40 98 46 40按下音符A#,音阶是4
81 40 46 00 00 43 40 81 40 43 00 89 00 46 40 81 40 46 00 00 43 40 81 40 43 00 以音符符号判断按下与松开
00 FF 2F 00结束
4D 54 72 6B 00 00 07 33 使用轨道00 FF 21 01 01
00 FF 03 14 46 58 20 31 20 28 52 61 69 6E 29 20 20 20 20 20 20 20 20 20以下可以根据空格来帮助判断执行何种操作
00 C2 60 00 B2 00 00 00 5B 69 00 5D 7F 83 00 C2 60 97 20 92 41 5D 60 41 00 00 46 5D
60 46 00 00 48 5D 81 40 48 00 00 4A 5D 82 20 4A 00 00 4A 5D 81 40 4A 00 00 48 5D
81 40 48 00 00 4A 5D 60 4A 00 00 46 5D 82 20 46 00 60 46 5D 60 46 00 00 48 5D
60 48 00 00 4A 5D 81 40 4A 00 00 4B 5D 82 20 4B 00 00 4B 5D 81 40 4B 00
00 4A 5D 81 40 4A 00 00 46 5D 60 46 00 00 43 5D 82 20 43 00 60 41 5D
60 41 00 00 46 5D 60 46 00 00 48 5D 81 40 48 00 00 4A 5D 82 20 4A 00 00 4A 5D
81 40 4A 00 00 48 5D 60 48 00 00 4A 5D 81 40 4A00 97 20 90 37 46 其中97 20为时值
24 80 37 3F 0C 90 37 46 24 80 37 40 0C 90 3B 40 24 80 3B 40 0c 90 3E 40 54 80 3E 40
0c 90 3E 40 81 04 80 3E 40 其中81 04为时值
1.9.3. 解析运行状态(Running Status)MIDI歌曲(格式0)
以下选自passport.midi,使用GM音色表。
可以从后面的数据流中了解到aftertouch、滑音的使用规范类似于音符和控制器的使用规范。
特点是:多种轨道块的事件写在同一个音轨中,所以每次某个音轨道出现的不同的事件都要写上相应的音轨的状态位,用来区分不同的音轨的不同的事件,同时又具有运行状态事件的特点。
4D 54 68 64 00 00 00 06
00 00 00 01 01 E0 单音轨
4D 54 72 6B 00 00 5A 67
00 FF 7F 03 00 00 40音符特定信息
00 FF 58 04 04 02 18 08节拍(可以变化)
00 FF 59 02 00 00 调号
00 FF 51 03 05 3B 49 速度
00 FF 06 10 43 31 2D 50 34 20 45 4C 45 43 20 50 49 41 4E 4F 标记……也是很多的
00 FF 06 0D 43 32 2D 50 33 37 2D 42 41 53 53 20 31
00 FF 06 0D 43 33 2D 50 34 30 2D 42 41 53 53 20 32
00 FF 06 10 43 34 2D 50 39 31 2D 50 4F 4C 59 53 59 4E 54 48
00 FF 06 13 43 35 2D 50 38 31 2D 53 59 4E 54 48 20 4D 45 4C 4F 44 59
00 FF 06 10 43 39 2D 50 32 39 20 45 4C 45 43 20 47 55 49 54
00 FF 06 0F 43 36 2D 50 32 37 2D 43 4C 41 56 49 4E 45 54
00 FF 06 0D 43 37 2D 50 37 37 2D 42 4F 54 54 4C 45
00 FF 06 0C 43 38 2D 50 36 32 2D 42 52 41 53 53
00 FF 06 09 43 31 30 2D 44 52 55 4D 53
00 FF 06 10 43 31 31 2D 50 35 36 2D 4F 52 43 48 20 48 49 54
00 FF 06 05 A9 31 39 39 31
00 FF 06 16 50 61 73 73 70 6F 72 74 20 44 65 73 69 67 6E 73 2C 20 49 6E 63 2E
00 FF 06 1A 50 72 6F 64 20 62 79 20 4D 75 73 69 63 20 44 61 74 61 20 43 6F 6D 70 61 6E 79
……
00 B0 00 05 00 20 57 连续使用控制器00 C0 03 使用乐器00 B0 07 53连续使用控制器00 0A ; 3B
00 E0 00 40 使用滑音00 00 40使用滑音00 00 40使用滑音(使用的是第一轨道)
00 B1 00 00 00 20 00连续使用控制器00 C1 24使用乐器00 B1 07 7C 00 0A 40连续使用控制器
00 91 24 5E 按下音符00 B1 5B 3C使用控制器第二轨道00 B5 00 00 00 20 00连续使用控制器
00 C5 1A使用乐器00 B5 07 60 使用控制器 第六轨道00 B3 00 00 00 20 00连续使用控制器
00 C3 5A 00 B3 07 53 00 0A 59 00 5B 4B连续3次使用控制器
00 B6 00 00 00 20 00连续2次使用控制器00 C6 4C 00 B6 07 73 00 B5 0A 63 00 07 3A 00 5B 37
00 B8 07 63 00 B9 07 5D 00 0A 40 00 B4 00 00 00 20 00 00 C4 50使用乐器 00 B4 07 64
00 B7 00 00 00 20 00 00 C7 3D 00 B7 07 6D 00 99 2A 44 00 B2 07 59 00 99 24 79
00 B9 5B 54 00 B8 00 00 00 20 78 00 C8 37 00 B9 00 00 00 20 00 00 C9 00
00 B2 00 00 00 20 00 00 C2 27 12 B2 0A 40 00 5B 1E 00 5D 28 0E B6 0A 40
38 99 2A 00 81 18 2A 30 81 0C 2A 00 1C 24 00 30 91 24 00 18 99 2A 39
78 2A 00 78 2A 2C 00 B7 0A 21 00 91 24 61 00 99 24 6D 7A 2A 00 04 24 00
00 91 24 00 72 99 2A 39 00 26 77 68 2A 00 81 08 91 1F 57 00 99 2A 28 1E 26 00
54 91 1F 00 08 99 2A 00 76 2A 3A 00 91 22 66 00 99 24 7D 42 B4 0A 40 00 5B 37 2C 99 2A 00
81 02 2A 27 6C 2A 00 70 B8 0A 40 00 5B 58连续使用控制器由于前面有控制器标志
0E A0 0C 00 02 03 00 02 02 00连续使用aftertouch
02 99 2A 3B 00 E0 00 40使用滑音00 00 40 00 00 40 连续使用滑音48 99 24 00 轨道10
24 2A 00 81 04 2A 2C 76 2A 00 7A 2A 3C 56 91 22 00轨道2 1C 99 2A 00 轨道10
7E 91 22 5E 轨道2 00 99 2A 2E 轨道10 6C 91 22 00轨道2 1A 99 2A 00轨道10
6A 91 1D 63轨道2 00 99 2A 39以下连续使用轨道10 00 26 77 轨道10 7C 2A 00 74 2A 2F
52 26 00 32 2A 00
08 91 1D 00以下连续使用轨道2 64 22 66 00 99 2A 3C连续使用轨道10 00 24 79按下音符
81 00 2A 00 3E 24 00 32 2A 38 0A 91 22 00 6C 99 2A 00 7A 91 24 5A 00 99 2A 3B
00 24 7B 6C 2A 00 06 E4 08 3A 使用滑音,轨道 00 08 3A 1E 16 33 00 16 33滑音
1E 20 2E 00 20 2E 1E 34 24 00 34 24 1C 3A 21 00 3A 21 08 99 2A 2C
18 E4 3C 20 00 3C 20 1E 3E 1F 00 3E 1F 1E 3C 20 00 3C 20 1E 32 25 00 32 25
04 99 2A 00 1A E4 2A 29 00 2A 29 16 99 24 00 08 E4 22 2D使用滑音 00 22 2D 1E 20 2E
00 20 2E 1E 18 32 00 18 32 06 99 2A 3C 按下音符 18 E4 04 3C 使用滑音00 04 3C
1E 00 40 00 00 40 0E 91 24 00 按下音符,轨道2 2E 99 2A 00按下音符,轨道10
7E 24 79 00 2A 2E 00 91 24 61按下音符,轨道2 76 24 00 10 99 2A 00按下音符,轨道10
26 24 00 44 26 79 00 2A 39 7C 2A 00 74 2A 2F 40 26 00 44 2A 00
6C 2A 3C 81 00 2A 00 70 24 71 00 91 1F 61 00 99 2A 38 76 2A 00 7A 2A 3E
00 2A 44 10 2A 00 00 2A 00 81 38 91 1F 00 12 99 24 00 16 2A 30 00 91 1F 50
78 1F 00 14 99 2A 00 64 24 7D 00 91 21 5C 00 99 2A 39 78 2A 00 64 91 21 00
14 99 2A 2C 2A 24 00 50 2A 00 76 91 22 6A