MIDI文件格式分析──实践篇

要书写二进制(十六进制)文件,应该准备好一些工具,比如我自己用的是VC++,因为学习MIDI格式无非是想写它的软件,既然VC++可以编辑二进制文件,就将就着用吧。其次,应该找个可以编辑和播放MIDI文件的软件,比如Cakewalk,这样就可以开始了。

首先书写文件头“4d 54 68 64 00 00 00 06”,我们直接写同步多音轨的格式,先写1个音轨,并以120为一个音符的基本时间。这样,随后的字节是:“00 01 00 01 00 78”。

现在,如果用Cakewalk打开会失败,因为我们指定的音轨数为1,但是并没有书写任何音轨,如果改成“00 0100 0000 78”再打开,就不会出问题了。所以,今后如果更改了音轨数,千万不要忘记向“上头”汇报。

把轨道数改回01,继续我们的实验。先写音轨的头信息:“4D 54 72 6B”(MTrk),因为我们还不能确定后面有多少字节,所以先把它假设成“00 00 00 00”,以后再回来改。

我们先尝试设置歌曲的速度和节拍等基本信息。假设一个四分音符的时间是半秒,即0.5*106微秒。它的十六进制数是07A120,再看事件表,设置速度是51,但是在其前面必须是FF,然后它须要3个字节作为参数,因此字节数为03,参数为“07

A1 20”,也就是“FF 51 03 07 A1

20”。这是事件部分,不要忘记在其之前有个参数??时间差。这是一开始就应该设置的参数,因此时间差为00。所以,完整的事件应该是“00 FF 51

03 07 A1 20”,我们把这一段追加在Midi文件末尾。

这时先不要急着用Cakewalk验证,因为我们还没有向“上级”报告,没错,把前面表示字节数的“00

00 00 00”改成“00 00 00

07”,如果用VC++作为二进制文件的编辑器,选择了事件后,可以在状态栏看到选择的字节长。保存后,再用Cakewalk打开,就可以看见速度是120。

我们再来设置节拍和调号,因为一般用Cakewalk新建一个Midi会默认地设置成4/4,C大调,我们就改设成6/8,A大调。查阅事件表知道,58和59是分别用来设置节拍和调号的。虽然设置节拍的参数很多,但在现在的系统中,后两个参数是被忽略的,而且Cakewalk还会对其进行修正。因此,我们只要设置好实际有用的就可以了。分子是6,分母是8,所以第一个参数是06,第二个参数是03(23=8)。最后,补上前面的时间差和后面的两个被忽略的参数,它应该是“00 FF 58 04 06 03 00 00”;再看调号,A调有3个升号,因此可以这样的事件可以表示为“00 FF 59 02 03 00”。事实上,大小调是个被忽略的参数。我们统计一下至今为止事件的字节数,然后更改前面的参数,即把“00 00 00 07”改成“00 00 00 15”。保存后用Cakewalk打开,再进入五线谱窗口,就可以马上验证了。细心的你可能已经发现,进入五线谱窗口前和平常有些延迟,这是因为我们并没有设置好那些可以忽略的字节,而Cakewalk就是在对其进行重新验证,这一点,我们以后再讨论。

用同样的方法,您可以很容易地设置歌曲的标题和版权,这作为一个练习,在这里就不多写了。我们现在学习写一个含有音符的轨道。首先您应该知道要做哪些事:1、写新音轨的信息头;2、向上级汇报多了一个音轨。接下来,我们开始写入一个简单的音符。

假设向第一拍写一个中音A,这里可能要先说明一下,音符是从C0开始一起向上数的,数到中央C(C5)是十六进制的3C,则中音A应该为45,在附件中有详细的计算方法。我们知道在音乐中一个音符通常有三个属性:音高、力度和时值。可是我们在事件表中并没有看见有什么可以直接设置音符时值的标志。不错,事实上,音符的时值是由按下的时间和松开的时间决定的。我们假设要写入一个八分音符。它的Tick数是四分音符的一半,即60,十六进制表示成3C。我们先来看看与音符有关的标志。

在事件表中,9x是用来打开一个音符,我们这里假设使用第7个通道(注意到MIDI有16个通道(Channel),而第10个被默认地用作打击乐,所以,我们在这个阶段(没有学习Sysx之前),先不要使用第10个通道),则9x中的x是6;再看它的参数,一个是音符,这里我们写入45,第二个是力度,我们用70,因为是一开始就触发的,所以前面的时间差还是00。这样我们就在第5个通道以力度112按下了一个中音A。对应的字节描述是“00 96 45 70”。它的时值不用想都知道一定是0,这取决于什么时候把它松开。

特别地,如果一个音符的力度为0,则MIDI认为用户想松开这个键,因为9x已经打开了通道,所以我们直接写入一个带00力度的同一音符就可以决定这个音符的时值了。根据前面的分析,这个时间差应该是3C,所以我们在写入3C后写上音符45和它的力度00,即“3C

45 00”。统计好字节数并向这一轨的头信息中更新,然后保存到磁盘,用Cakewalk打开并进入事件列表窗口便可以验证了。

在这个基础上,我们再尝试在A的后面增加一个四分音符中音#G。因为96已经打开了通道,我们没有必要每次都使用9x,只要输入事件信息即可。对于中音#G,它的十六进制是44,相对刚才输入00力度的A来说时间差为00,因此可以表示成“00

44 64”,这里我们已经假设力度为100;然后是松开它,因为是四分音符,所以时间差是78H,别忘记力度是00,它的字节应表示成“78 44

00”,做好后面的工作,然后验证看对不对。

我们再做个稍微复杂一点的实验:在原来的基础上,在同一轨的第一拍加上一个附点四分中音D。这里就不能再使用追加的方法了,因为前面的事件已经过了3个八分音符的时间,无论再加上什么,都只会发生在后面,所以我们要在前面插入一些字节。

9x已经打开了通道,我们直接在9x按下的音符后加上一个音符事件“00 3E 64”,这里的00显然是个时间差,3E是中音D,64是力度,也就是说,在按下中音A的同时按下了中音D。我们又按下一个键了,要在什么时候,在哪里松开才能保证输入的是个附点八分音符呢?首先,它的时值是3个八分音符,即180,这里还有一点要注意,180是个大于128的数,它的动态字节就应该表示成“81 34”,在哪里输入才好呢?如果你觉得在按下D后输入,或者在任何什么地方输入这个时间差,然后再写上“3E 00”可以表示松开的话就完全误解了时间差的概念。其实,我们只要简单地在松开#G的时候松开D就可以了,所以应该在末尾补上“00 3E 00”。统计好字节数后到Cakewalk中去验证验证吧。这里附有我们目前写下的Midi文件样本

到目前为此,我们应该可以输入任何形式的音符了,不过MIDI除了音符以外,还可以包括各种控制器和系统码,它们的地位不亚于音符,我们现在马上学习如何使用控制器。

控制器比音符要简单多了,我们尝试在#G前加入相位控制(Pan),它的十进制代码是10,十六进制是0A,我们将参数设置成111,即十六进制的6F。首先查得控制器是Bx,这里的x和上面一样,也是6。接下来写入控制器号0A,然后是参数6F,别忘了前面的时间差是00。所以这段字节是“00

B6 0A

6F”,它应放在松开#G的事件之前,与按下#G同时。不过,一旦使用了非音符,而后面还有音符事件时,则必须重新通知打开音符,这说起来复杂,做起来还是比较容易的,我们只要稍微改写下一个音符事件即可:原本是“时间差+音符+力度”,我们加入一个打开音符的标志,成为“时间差+9x+音符+力度”即可。校验过头信息后,去Cakewalk中进行更进一步的检验便知它的可行。

其实,时间差为00的控制事件如果出现的时间也是00,则在Cakewalk中会尽可能地把它们放在轨道信息中,而不在事件列表中重复。我们可以利用这一点给音轨设置初始乐器和音量,这就作为一个练习,在此就不再说明了。

至于其他的诸如触后键等与控制器类似的格式在此就不多说了。在这里有必要提醒的是滑音。滑音的乐理范围是-8192~8191,但是在使用时参数是个正数,比如要设置成0,则应该是0-(-8192)=8192,它才是参数。8192的7位双字节表示成“8192 mod 128=00H;8192 div 128=40H”。如果时间差是00,则应表示成“00 E6 00 40”

最后我们看看系统码。系统码的构成本来是“F0 厂家ID 设备号码 格式代码 传送命令 具体参数 F7”,而在文件中,则不以开头的“F0”为系统码,而字节数也仅记录剩余的系统码,比如XG的复位码是“F0 43 10 4C 00 00 7E 00 F7”,则在文件中应写成“00 F0 08 43 10 4C 00 00 7E 00 F7”,其中第一个00是时间差,F0是系统码标志,08是后面的字节数。有一点要注意的是,几个系统码不可以写在一起,比如“00 F0 0D 43 10 4C 00 00 7E 00 F7 F0 AA BB CC F7”或“00 F0 0C 43 10 4C 00 00 7E 00 F7 AA BB CC F7”都是不好的写法。如果存在以上系统码集,可以分成两个事件:“00 F0 08 43 10 4C 00 00 7E 00 F7 00 F0 04 AA BB CC F7”

当然系统码可以写在任何音轨,不过一般我们会考虑把歌曲播放前发送的系统码写在全局音轨中,并把时间差设成00。

作为一个参考,这里再附上一个MIDI样本

虽然我们只讨论了同步多音轨的格式,其实对于其他两种,比如较常见的单音轨格式,所有的事件只写在一个音轨中,即只要存在一个“MTrk”就足够了。而相对地,用于记录音轨数的两个字节也永远为“00

01”,连续事件如果出现的通道不同,也必须重新指定通道(8x~Ex)。在此不详细讨论了。

到目前为此,我们应该可以构造出任何MIDI音乐了,作为一些辅助性的参考,可以查阅下一篇连载《MIDI文件格式分析??附件篇》。另外,对于扩展名为.rmi的格式,可以参阅下下篇连载《MIDI文件格式分析??RMI篇》。

文章出处:http://www.midifan.com/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • MIDI文件属于二进制文件,这种文件一般都有如下基本结构: 文件头+数据描述 文件头一般包括文件的类型,因为Mid...
    钱鑫_9771阅读 1,455评论 0 2
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,800评论 6 13
  • 要在计算机内播放或是处理音频文件,也就是要对声音文件进行数、模转换,这个过程同样由采样和量化构成,人耳所能听到的声...
    Viking_Den阅读 10,098评论 1 10
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • 上帝使人发愁, 还要照他诸般的 慈爱发怜悯。 因他并不甘心使 人受苦, 使人忧愁。 耶利米哀歌3章32-33
    碧罗思爱阅读 490评论 0 1