MIDI的数据是由若干个格式相同的子数据构成的这些子数据在多音轨的格式中记录了一个轨道的所有信息多加一个音轨就简单地把数据追加在前一音轨的后面就可以了不过
不要忘记更改文件头中的nn nn(轨道数)
先看全局音轨全局音轨包括歌曲的附加信息(比如标题和版权)歌曲速度和系统码(Sysx)等内容
不管是全局音轨还是含有音符的音轨都以4D 54 72 6B开头它其实是ASCII字符MTrk其后跟着一个4个字节的整数它标志了该轨道的字节数这不包括前面的4个字节和本身的4个字节这一点我们可以在后面的例子中去理解
接着就是记录数据的地方了每一个数据有着相同的结构:时间差+事件
所谓时间差指的是前一个事件到该事件的时间数它的单位是tick(MIDI的最小时间单位)它的构成比较特殊这里要用二进制来说明
一个字节有8位如果仅使用7位它可以表示0~127这128个数而剩下的一位则用来作为标志如果要表示的数在以上范围则这个标志为0这时一个7位的
字节可以表示0~127tick如果要表示的数超出了这个范围(比如240)则把标志设置成1然后记录下高7位剩下的留给下一个字节在该例中240可以分解成128*1+112这里的1就是第一个字节要记录的加上标志位应该为10000001即十六进制的81而112是下一个字节记录的它的十六进制为70:所以要表示240这个时间要写成81 70同理如果要表示65535tick则可以先计算出65535=1282*3+1281*127+1280*127然后得出结果:83 FF 7F由此我们反过来也可以知道如何确定时间差:只要标志位为0则表示结束读取时间差比如82 C0 03表示1282*2+1281*64+1280*3=40963如果基本时间为120则有341:043个四分音符
以这种方式记录整数的字节称为
动态字节它根据记录的整数改变自身的长度这在后面还要用到所以必须熟练计算
看完了这么麻烦的东西我们再来看个更麻烦的东西:
事件在这些标准的解释后面我们会通过一些例子来进一步掌握这些内容
事件大体上可以分为音符控制器和系统信息这几个种类对于这些事件都有统一的表达结构:种类+参数
对于一个音符由于它的有效范围是0~127所以直接用00~7F作为种类可以认为是个音符比如3C表示中央C而一个音符的最重要的参数是力度(也叫速度:velocity)比如3C 64 表示一个力度为十进制100的中央C音符
因为一个字节有8位所以剩余的一位如果置1再联合其他的7位则可以表示各种信息我们暂且无视一个音轨到底是全局的还是用于记录音符的它们归根结底都是用来记录各种事件的只不过有些应出现在全局音轨比较合乎逻辑而已既然这样我们就可以从下面的表来看事件:
下表中x表示音轨0~F比如81表示松开第二轨的音符
种类
字节含义
|
参数(十六进制)
|
8x 松开音符
|
音符(00~7F):松开的音符 力度:00~7F
|
9x按下音符
|
音符(00~7F):按下的音符
力度:00~7F
|
Ax触后音符
|
音符:00~7F
力度:00~7F
|
Bx 控制器
|
控制器号码:00~7F
控制器参数:00~7F
|
Cx改变乐器
|
乐器号码:00~7F
|
Dx触后通道
|
值:00~7F
|
Ex滑音
|
音高(Pitch)低位:Pitch mod 128
音高高位:Pitch div 128
|
F0系统码
|
系统码字节数:动态字节
系统码:不含开头的F0,但包括结尾的F7
|
FF其他格式
|
程式种类:00~FF
数据占用的字节数:动态字节
数据:个数由上一参数确定
|
00~7F
|
上次激活格式的参数(8x9xAxBxCxDxEx)
|
下表详细地列出了FF的详细情况对于字节数由数据决定的情况表中以--表示
种类
字节 含义
|
字节数
|
数据
|
00 设置轨道音序
|
02
|
音序号 00 00~ FF FF
|
01 歌词备注
音轨文本
|
--
|
文本信息
文本信息
|
02 歌曲版权
|
--
|
版权信息
|
03 歌曲标题
音轨名称
|
--
|
用于全局音轨
音轨名
|
04 乐器名称
|
--
|
音轨文本(同01/2)
|
05 歌词
|
--
|
歌词
|
06 标记
|
--
|
用文本标记(Marker)
|
07 开始点
|
--
|
用文本记录开始点(同01/2)
|
2F音轨结束标志
|
00
|
无
|
51速度
|
03
|
3字节整数1个四分音符的微秒数
|
58节拍
|
04
|
略
|
59调号
|
02
|
大小调:0(大调)1(小调)
升降号数:-7~-1(降号),0(C),1~7(升号)
|
7F音序特定信息
|
--
|
音序特定信息
|