第一键盘 - 电子琴在线论坛

 找回密码
 现在注册

QQ登录

只需一步,快速开始

查看: 11585|回复: 14
打印 上一主题 下一主题

读书笔记:MIDI Tick、Meta-event、变长数表示法、区分MIDI文件中单个字节的含义

  [复制链接]

跳转到指定楼层
1#
发表于 2012-3-24 23:22:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MIDI Tick与TPQN:
MIDI中常用的时间度量法是采用Midi Tick。Midi Tick是MIDI系统中最小的时间单位,MIDI系统的所有时间功能,如节拍的产生,都是基于Midi Tick的。MIDI系统中的设备,只需要对Tick计数,就可以获得曲子的时间信息。
TPQN是一个缩写,全称是“Ticks Per Quarter-Note”,即“每四分音符所具有的Tick数”。从字面就可以理解其含义。在一个MIDI文件的MThd chunk中,我们能找到这个参数。通常这个值可以取48-480(这个是准确值,原来那个帖子的60-480写错了,抱歉……)之间。
每Tick的绝对时间长度是关联于曲子拍速(tempo)的。比如在一首4/4拍,tempo为60bpm的曲子中,一个四分音符为一拍,发音长度为1秒。我们将一个四分音符的音长规定为480 Ticks,则480 Ticks为1秒,单个Tick的时间长度就是(1/480)秒。如果MIDI文件中要播放一个四分音符,即一拍,只要在播放时对MIDI Tick计数,计满480个MIDITick后停下,就达到了目的。同理,八分音符就是240 Ticks,一个三连音中的每个连音就是160 Ticks。
具体的解释,请参考笔者曾经编辑的这个帖子:
https://www.cndzq.com/bbs/thread-110934-1-1.html



Meta-event事件:
meta-event事件也 MIDI事件的一部分,但它并不会被发送出去。它只是代表了MIDI文件的一些特征,如速度、调号、拍号、版权信息、音轨名称等等。它的数据格式是:

FF xx nn dd dd dd dd ……

FF代表了此数据类型为meta-event;
xx代表了具体的meta-event事件类型,取值范围为00-7F;
nn代表了其后的meta-event数据长度,用可变长度数来表示;
dd dd dd则是具体的数据。

话说0xFF这个数据,既表示meta-event的标志,同时也是MIDI事件“系统复位”的指令码。如何区分这两个数据呢?我的理解是:系统复位事件属于系统实时信息,是不会出现在MIDI文件中的。所以在MIDI文件中的0xFF,都是meta-event的标志,不会是属于系统实时信息的“系统复位”事件;而meta-event事件是不会被音序器发送出去的,所以MIDI系统中接收到的0xFF,只可能是系统复位事件,不会是meta-event。



变长数表示法:

举一个可变长度数的例子:81 70,那么这个delta-time实际表示的数为0xF0。怎么来的?0x81的二进制为10000001,后边还有数据;0x70的二进制为01110000,后面没有数据了,这个变长数表示完毕。把下划线部分的数组合起来,就变成了:000 0001111 0000,就是1111 0000,0xF0。

再举个例子:E3 9A B4 70,这个可变长度数实际上表示的是0xC669A70。这串数是这么变化的:0xE3 = 1110 0011,后面还有数据;0x9A = 10011010,后面还有数据;0xB4 = 1011 0100,后面还有数据;0x70 = 0111 0000,后面没有数据了,这个变长数表示完毕。把下划线部分的数组合起来,就变成了:1100 0110 0110 1001 1010 0111 0000 = 0xC669A70.

找到规律了吗?这种表示法,将每个字节的最高位,作为一个标志位,标志该字节是否是整个可变长度数的最后一字节。如果最高位为1,则表明此字节不是最末尾的字节;如果最高位为0,表明此字节为最后一字节,即可变长度数表示完成。剩下的七位则是实际要表示的数的数位。所以在把可变长度数改为普通整数时,就顺序阅读可变长度数,并且判断当前字节的最高位,如果是1,说明下一个字节依然是这个可变长度数的下一部分;如果是0,就说明本字节已经是这个可变长度数的最后一字节了。然后只需要把每个字节的后七位取出来,按其所处各自字节的先后顺序,也顺序地拼在一起,就是它所代表的整数了。



如何区分MIDI文件中的某一个字节是做什么用的?

如果单独看MIDI文件中的某个字节,我们是看不出这个字节代表的含义的。所以在阅读MIDI文件时,最好是从Track Chunk头开始慢慢阅读,顺藤摸瓜,才能找到这个字节的具体含义。

MIDI文件读取的难度也正在此。因为一个MIDI文件中混杂着各种文件标志符(如有多少Track Chunk、MIDI Tick定义等等)、delta-time(而且还是以变长数表示法表示)、MIDI事件码(还包括可发送的事件和meta-event事件)、事件数据(而且不同事件的数据还不定长),等等等等。各种标志和事件数据码大小不一,长短不齐,十分混乱。

所以说单纯地考察MIDI文件中某个字节的数据,其作用是什么,这很难考察出来。比如一个小于0x80的数,它可能是一个delta-time数据结构的最后一字节,也可能是某个Note-On事件的数据部分,还可能是设置MIDI Tick的TPQN。如果仅仅凭借上下文,也很难猜出这个字节数据的作用,因为它的上下文也可能具有不同的含义,依然会造成歧义。

但实际上MIDI文件依然是有规律可循的。解析MIDI文件的线索就在于:MIDI文件中所记录的每种MIDI事件,或是每种MIDI文件标志符,其数据段长度都是规定好的,要么是协议中已经规定死的,要么是文件中具有指定其大小长度的标志。这是MIDI文件最重要的特点。知道了每个事件或者标志的长短,我们才能准确无误地从MIDI文件中提炼出内容。

一个MIDI文件中记录的内容,无非就是一些MIDI文件本身的标志符,和一些MIDI事件数据,还包括一些meta-event事件,还有delta-time结构,有时(或者说常常)具有省略MIDI事件指令码的缩略结构。

文件本身的标志符长度,通常是固定长度的(比如Header Chunk中的内容);MIDI事件和一部分meta-event都具有协议中规定的长度,如多数MIDI事件具有1-3个字节的长度,系统事件和一部分meta-event虽然长度不定,但这些事件中也都标明了各自的数据段长度;delta-time数据结构采用可变长度数,但因其只能存在于MIDI事件之前,或者说存在于两个事件之中,所以也能很容易地被读取,并且根据可变长度数的特征(最高位作为可变长度数结构是否结束的标志),我们也能知道可变长度数的结构何时结束;对于缩略结构,因其只能适用于MIDI事件之中,所以在读取完delta-time结构后,就可以判断下一字节是否大于0x80,如果大于,则是另一个MIDI事件,如果小于,表明这是一个数据段,其事件类型和指令码依然是上一个指令的类型,数据段大小也和上一指令类型相同。

根据不同事件或标志的不同长度,以及各个MIDI事件和标志符之间位置的关系,还有事件指令码与数据段的大小差异,等等诸多MIDI文件的特点,我们还是能够比较容易地将各个MIDI事件与标志符一一分开的。

所以,在解析一个MIDI文件时,我们要从文件头开始,找到各个Chunk后,以Chunk为单位,慢慢地往下解析。Header Chunk的解析相对容易,Track Chunk在解析时注意区分delta-time数据结构,MIDI事件结构,还有缩略结构。

在以后的介绍中,笔者会用流程图的方式来解释MIDI文件的解析方法。

分享到: QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
回复

使用道具 举报

2#
发表于 2012-3-24 23:44:56 | 只看该作者
我想知道,琴上的效果器的选择在MIDI文件里面是怎么选择的?我看了一下,通过系统专用信息可以弄,但是,里面的字符字母好长的一串,我只能是复制琴上写好的粘上去……
回复 支持 反对

使用道具 举报

3#
发表于 2012-3-25 00:50:41 | 只看该作者
这个贴子中有许多MIDI的实用程序,可以拿来就用。http://oldwww.cndzq.com/bbs/Show ... BoardID=28&TB=1
有一个MIDI to TEXT 以及 TEXT to MIDI 的程序,可以方便地分析MIDI的阅读结构。
回复 支持 反对

使用道具 举报

4#
 楼主| 发表于 2012-3-25 12:00:45 | 只看该作者
为你弹琴 发表于 2012-3-24 23:44
我想知道,琴上的效果器的选择在MIDI文件里面是怎么选择的?我看了一下,通过系统专用信息可以弄,但是,里 ...

呃,有S550说明书的电子版吗?说明书中有关MIDI的章节应该会介绍具体的数据格式,有空我来看看~
回复 支持 反对

使用道具 举报

5#
 楼主| 发表于 2012-3-25 12:03:30 | 只看该作者
zhw63 发表于 2012-3-25 00:50
这个贴子中有许多MIDI的实用程序,可以拿来就用。http://oldwww.cndzq.com/bbs/Show.asp?id=56590&BoardID=28&T ...

原来想DIY一个基于MCU的MIDI播放器,所以研究了一段时间。MIDI解析这一块的程序,我一个哥们用C写出来了。只是他的代码,我不方便自作主张把程序传上来……以后有机会自己写一个吧。只要找到规律,coding还是挺快的~
回复 支持 反对

使用道具 举报

6#
发表于 2012-3-25 12:56:25 | 只看该作者
我也写过MIDI播放器,用了MIDI 转txt ,直接修改TXT,再播放此TXT,或转回MIDI。用TXT文本,更便于读MIDI
挺好玩的。
回复 支持 反对

使用道具 举报

7#
发表于 2012-3-25 19:07:35 | 只看该作者
华北kingsky 发表于 2012-3-25 12:00
呃,有S550说明书的电子版吗?说明书中有关MIDI的章节应该会介绍具体的数据格式,有空我来看看~

他的每个效果器后面都有MSB和LSB的数值,可是就是不懂怎么用?不是在MIDI轨道里面输入的吧?
回复 支持 反对

使用道具 举报

8#
 楼主| 发表于 2012-3-25 19:21:43 | 只看该作者
为你弹琴 发表于 2012-3-25 19:07
他的每个效果器后面都有MSB和LSB的数值,可是就是不懂怎么用?不是在MIDI轨道里面输入的吧?

我下了一份S550的说明书。看起来好像在说明书第134页中,描述了这些数据串。比如设置一个混响类型,就要发送“F0 43 1n 4C 02 01 00 mm ll F7”这个MIDI串,其中mm和ll就是具体的混响类型代号,n被忽略,是这样的含义吗?我记得cakewalk中有一个发送sysex信息的窗口,可以自己编辑一个sysex串然后发送出去。至于如何往MIDI文件当中的某个位置,插入这么一个串,我暂时没研究过……不过应该有办法。实在不行就杀手锏,手动编辑MIDI文件,嘿嘿~
我去cakewalk里找找先……不过一会儿要出去请人吃饭,今晚可能没时间研究这个了……
回复 支持 反对

使用道具 举报

9#
发表于 2012-3-25 19:26:05 | 只看该作者
我现在用的土方法是:在琴上选好这个DSP和混响种类后录一个小MIDI段落,然后导出来,将系统信息里面的那一长串数字字母复制下载,粘贴到制作的MIDI的系统信息……
不过这样只能用同一种DSP,中途要换的话就不知道应该怎么弄了
回复 支持 反对

使用道具 举报

10#
 楼主| 发表于 2012-3-25 19:27:54 | 只看该作者
为你弹琴 发表于 2012-3-25 19:26
我现在用的土方法是:在琴上选好这个DSP和混响种类后录一个小MIDI段落,然后导出来,将系统信息里面的那一长 ...

或者去问问K大呢,他也许知道如何在cakewalk中操作吧。最终目的一定是要在MIDI文件的某一段中,插入这个字符串,所以估计只是咱俩没在cakewalk中找对地方~
回复 支持 反对

使用道具 举报

11#
发表于 2012-3-25 19:34:37 | 只看该作者
华北kingsky 发表于 2012-3-25 19:27
或者去问问K大呢,他也许知道如何在cakewalk中操作吧。最终目的一定是要在MIDI文件的某一段中,插入这个字 ...

以前问过他呢,他说用一个啥软件的,我嫌麻烦,哈哈~
回复 支持 反对

使用道具 举报

12#
 楼主| 发表于 2012-3-25 22:56:00 | 只看该作者
吃完饭,回来摸索了一下,看看是否可行吧。PS:魏公村这边的金汉斯自助烤肉居然都涨到68元一位了,苍天啊……那里曾经只才38元啊……
插入系统信息的方法.rar (167.37 KB, 下载次数: 26)


回复 支持 反对

使用道具 举报

13#
发表于 2012-12-19 17:59:22 | 只看该作者
呵呵,你说的是什么意思呀~~~~~~~
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 现在注册

本版积分规则

关闭

新闻头条上一条 /1 下一条

【重要通知】|申请友链|Archiver|手机版|第一键盘 - 电子琴信息网 - 电子琴在线论坛 ( 粤ICP备14036084号 )

GMT+8, 2024-4-19 22:14 , Processed in 0.153750 second(s), 34 queries .

Powered by Discuz! X3

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表