zl程序教程

您现在的位置是:首页 >  其它

当前栏目

【BLE MIDI】MIDI 文件格式分析总结 ★★★

分析 总结 文件格式 BLE Midi
2023-09-27 14:28:11 时间





一、MIDI 文件简介



下面的 mid 文件是一个简单 midi , 其中只有一条轨道 , 一个音符 ;

这个 mid 文件很简单 , 但是麻雀虽小 , 五脏俱全 , 其中有所有的必须的 midi 文件头 , midi 轨道头 , 时间标志 , 等信息 ;

下面开始逐个字节 , 解析上述 midi 文件 ;

4D 54 68 64 00 00 00 06 00 00 00 01 01 E0 4D 54 
72 6B 00 00 00 25 00 FF 03 05 B2 E2 CA D4 30 00 
FF 51 03 07 A1 20 00 FF 58 04 04 02 18 08 00 90 
3C 64 8E 7E 80 3C 40 00 FF 2F 00

在这里插入图片描述

在这里插入图片描述





二、MIDI 文件头解析



文件头数据 :

4D 54 68 64 00 00 00 06 00 00 00 01 01 E0

在这里插入图片描述


1、MIDI 文件头标识


4D 54 68 64 : 0 ~ 3 字节 , " MThd " 字符串 ASCII 码 , 这是 mid 文件的标识 ;


2、MIDI 文件头长度


00 00 00 06 : 4 ~ 7 字节 , 这是个 4 字节整型数据 , 大端格式显示 , 整型低位在高字节 , 整型高位在低字节 , 该数据表示 mid 文件文件头长度 , 这里的文件头长度为 6 , 表示后面 6 字节是 mid 文件文件头的范围 ;

在这里插入图片描述
大端格式 : 高位存储在低字节中 , 符合人的书写习惯 ;

在这里插入图片描述

小端格式 : 低位存储在低字节中 , 符合计算机处理逻辑 ;

在这里插入图片描述


3、MIDI 文件格式


00 00 : 8 ~ 9 字节 , 表示 mid 文件的格式 ; 这两个字节是 short 类型整型 , 大端格式 ;

  • 0 : mid 文件只有一条轨道 , 所有的通道都在一条轨道中 ;
  • 1 : mid 文件有多个音轨 , 并且是同步的 , 即所有的轨道同时播放 ;
  • 2 : mid 文件有多个音轨 , 不同步 ;

这里是 0 格式 , 也就是说只有一条轨道 ;

在这里插入图片描述


4、MIDI 轨道个数


00 01 : 10 ~ 11 字节 , 表示 MIDI 轨道个数 , short 类型 , 大端格式 ;

此处表示有一条轨道 , 所有通道的音符和节拍信息都在该轨道中 ;

在这里插入图片描述


5、基本时间


01 E0 : 12 ~ 13 字节 , 用于指定基本时间 ;

2 个字节 , 要拆分成 3 部分 , 最高位 ( 第 15 位 ) 作为标识位 , 第 8 ~ 14 位 作为一部分 , 第 0 ~ 7 位 作为一部分 ;

由于是大端格式排列 , mid 文件第 12 字节 ( 低地址 ) 是 高位 , mid 文件第 13 字节 ( 高地址 ) 是低位 ;

01 E0 的二进制形式如下 : 0000 0001 11110 0000 ;

最高位 0000 0001 11110 0000 是 0 , 红色的是最高位 , 表示当前 代表的事件格式是 类型1 , 第 0 ~ 14 位 代表的是 四分音符的 tick 数 ;

十六进制 01 E0 对应的十进制数字是 480 , 也就是说一个四分音符有 480 tick ;

tick 是时间单位 , 这是 mid 文件中计算时间的最基本单位 ;

在这里插入图片描述







三、MIDI 轨道分析



MIDI 轨道 , 以 MTrk 4D 54 72 6B 开始 , 以 FF 2F 00 结束 ;

下面的内容是一个完整的 MIDI 轨道二进制信息 ;

4D 54 72 6B 00 00 00 25 00 FF 03 05 B2 E2 CA D4 30 00 FF 51 03 07 A1 20 00 FF 58 04 04 02 18 08 00 90 3C 64 8E 7E 80 3C 40 00 FF 2F 00

在这里插入图片描述





四、MIDI 轨道头



4D 54 72 6B : MTrk 的 ASCII 码 ;

在这里插入图片描述





五、MIDI 轨道长度



00 00 00 25 : 这是一个 int 类型的整型数据 , 大端格式显示 , midi 轨道长度是十六进制的 0x25 , 也就是十进制的 37 , 代表从下一个字节开始计数 到 轨道结束位置 FF 2F 00 的最后一个字节 , 一共有 37 个字节 ;

每个轨道开始的标志是 MTrk , 后面的 4 字节就是轨道的长度 ;

在这里插入图片描述

在下图中 , 选中的字节有 37 37 37 个字节 ;

在这里插入图片描述





六、delta-time 间隔



delta-time 间隔 是 mid 中的重要机制 ;

midi 中的音符 , 事件 的时间间隔 , 都是通过 delta-time 体现的 ;

delta-time 是一个整数 , 位数不固定 , 其单位是 tick , 也就是 【BLE MIDI】MIDI 文件格式分析 ( MIDI 文件头解析 | MIDI 文件头标识 | MIDI 文件头长度 | MIDI 文件格式 | MIDI 轨道个数 | 基本时间 ) 二、MIDI 文件头解析 5、基本时间 博客章节中计算的 tick 时间 ;

delta-time 的每个字节中 , 最高位 第 7 位 用于表示连续标志 , 后面的 0 ~ 6 位 表示真实的数据 ;

如果一个 delta-time 由 2 字节组成 , 每个字节中最高位是连续标志 , 后面 0 ~ 6 位是数据 , 也就是说该 delta-time 实际的数值位数只有 14 位 ;

以后面的 8E 7E delta-time 为例 :

在这里插入图片描述

8E 7E 对应的二进制位数为 : 1000 1110 0111 1110

第一个字节 8E 对应的二进制数据位 1000 1110 , 其中第七位的 1 表示这是 delta-time 的高位字节 , 后面的 000 1110 是实际的数值数据 ;

第一个字节 7E 对应的二进制数据位 0111 1110 , 其中第七位的 0 表示这是 delta-time 的低位字节 , 后面的 111 1110 是实际的数值数据 ;

则该 delta-time 的实际数据是 000 1110 111 1110 , 重新组合后为 111 0111 1110 , 该 delta-time 的值是 1918 , 也就是 1918 个 tick 数 ;

在这里插入图片描述


82 C0 03 为例 , 对应的二进制数据为 1000 0010 1100 0000 0000 0011

第一个字节 82 对应的二进制数据位 1000 0010 , 其中第七位的 1 表示这是 delta-time 的高位字节 , 后面的 000 0010 是实际的数值数据 ;

第二个字节 C0 对应的二进制数据位 1100 0000 , 其中第七位的 1 表示这是 delta-time 的高位字节 , 后面的 100 0000 是实际的数值数据 ;

第三个字节 03 对应的二进制数据位 0000 0011 , 其中第七位的 0 表示这是 delta-time 的低位字节 , 后面的 000 0011 是实际的数值数据 ;

则该 delta-time 的实际数据是 000 0010 100 0000 000 0011 , 重新组合后为 1010 0000 0000 0011 , 该 delta-time 的值是 40963 , 也就是 40963 个 tick 数 ;

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述





七、FF 03 轨道名称



FF 03 05 B2 E2 CA D4 30 : 23 ~ 30 字节 , FF 03 是 Meta 事件 , 轨道名称设置 ;

FF 03 后面是长度信息 , 05 表示该轨道名称有 5 字节 , 后面的 5 字节就是轨道名称 ;

在这里插入图片描述
轨道信息后面的 31 字节 00 是 delta-time ;





八、FF 51 03 四分音符时长



FF 51 03 07 A1 20 : 32 ~ 37 字节 , 音符速度标志 ;

FF 51 03 是音符速度标志位 , 后面的 07 A1 20 3 字节是一个数字 , 代表 四分音符 的时长 , 单位是微秒 ;

在这里插入图片描述

07 A1 20 对应十进制数是 500000 , 五十万 , 也就是一个四分音符是 50 万微秒 ;

在这里插入图片描述

在之前的 【BLE MIDI】MIDI 文件格式分析 ( MIDI 文件头解析 | MIDI 文件头标识 | MIDI 文件头长度 | MIDI 文件格式 | MIDI 轨道个数 | 基本时间 ) 二、MIDI 文件头解析 5、基本时间 博客章节 解析到一个四分音符有 480 个 tick ;

此时可以计算出每个 tick 的时长为 500000 480 \cfrac{500000}{480} 480500000 微秒 ;

在这里插入图片描述

再回顾下 delta-time 的计算 :

8E 7E 对应的二进制位数为 : 1000 1110 0111 1110

第一个字节 8E 对应的二进制数据位 1000 1110 , 其中第七位的 1 表示这是 delta-time 的高位字节 , 后面的 000 1110 是实际的数值数据 ;

第一个字节 7E 对应的二进制数据位 0111 1110 , 其中第七位的 0 表示这是 delta-time 的低位字节 , 后面的 111 1110 是实际的数值数据 ;

则该 delta-time 的实际数据是 000 1110 111 1110 , 重新组合后为 111 0111 1110 , 该 delta-time 的值是 1918 , 也就是 1918 个 tick 数 ;

上述的 delta-time 是 1918 个 tick , 对应的时间是 500000 × 1918 480 \cfrac{500000 \times 1918}{480} 480500000×1918 微秒





九、FF 58 04 拍号



FF 58 04 04 02 18 08 : 39 ~ 45 字节 , 拍子记号 ;

FF 58 04 是拍子记号的标志 ;

04 02 18 08 分别表示 :

  • 04 : 拍子记号的分子 ;
  • 02 : 拍子记号分母标志 , 这里的值是 2 的次幂值 , 如当前设置的值是 2 , 则拍子记号的分母是 2 2 = 4 2^2 = 4 22=4 , 分母是 4 ;
  • 18 : 每个 MIDI 时钟包含的 tick 数 ; 标准值是 24 , 一般不会改变 ;
  • 08 : 每 24 个 MIDI 时钟 , 对应的 32 分音符的数目 ; 标准值是 8 , 一般不会改变 ;

在这里插入图片描述

后面的 00 是 delta-time , 与下一个 midi 事件间隔的 tick 数 ;

delta-time 参考 【BLE MIDI】MIDI 文件格式分析 ( MIDI 轨道分析 | MIDI 轨道头 | MIDI 轨道长度 | delta-time 间隔 ) 四、delta-time 间隔 博客章节 ;





十、音符开指令



90 3C 64 : 47 ~ 49 字节 , 音符开指令 ;

90 是音符开标志 ;

3C 是音符音高 60 , 取值范围 0 ~ 127 ;

64 是音符的力度值 , 取值范围 0 ~ 127 ;

在这里插入图片描述

后面的 8E 7E 是 delta-time , 与后面的指令间隔的 tick 数 ;

delta-time 参考 【BLE MIDI】MIDI 文件格式分析 ( MIDI 轨道分析 | MIDI 轨道头 | MIDI 轨道长度 | delta-time 间隔 ) 四、delta-time 间隔 博客章节 ;





十一、音符关指令



80 3C 40 : 52 ~ 54 字节 , 音符关指令 ;

80 是音符开标志 ;

3C 是音符音高 60 , 取值范围 0 ~ 127 ;

40 是音符的力度值 , 取值范围 0 ~ 127 ;

在这里插入图片描述

后面的 00 是 delta-time , 与后面的指令间隔的 tick 数 ;

delta-time 参考 【BLE MIDI】MIDI 文件格式分析 ( MIDI 轨道分析 | MIDI 轨道头 | MIDI 轨道长度 | delta-time 间隔 ) 四、delta-time 间隔 博客章节 ;





十二、音轨结束标志



FF 2F 00 : 56 ~ 58 字节 , 音轨结束标识 ;

在这里插入图片描述

至此 , 整个 midi 文件解析完毕 ;