精华内容
下载资源
问答
  • MIDI消息和标准MIDI文件格式剖析及应用
  • MIDI 文件格式和解码

    2012-10-29 14:54:02
    MIDI文件格式说明和解码代码, 原版英文文档。E文不佳慎入。
  • MIDI 文件格式分析

    千次阅读 2017-12-08 18:33:39
    文件头一般包括文件的类型,因为 Midi 文件仅以.mid 为扩展名的就有 0 类和 1 类两种,而大家熟悉的位 图文件格式就更多了,所以才会出现文件头这种东西。 而数据描述部份是主体,我们现在来一起分析它的结构: 在每...

    MIDI 文件属于二进制文件,这种文件一般都有如下基本结构: 文件头+数据描述

    文件头一般包括文件的类型,因为 Midi 文件仅以.mid 为扩展名的就有 0 类和 1 类两种,而大家熟悉的位 图文件的格式就更多了,所以才会出现文件头这种东西。

    而数据描述部份是主体,我们现在来一起分析它的结构:

    在每个 Midi 文件的开头都有如下内容,它们的十六进制代码为:“4d 54 68 64 00 00 00 06 ff ff nn nn dd dd”。

    前四个是 ASCII 字符“MThd”是用来鉴别是否 Midi 文件,而随后的四个字节是指明文件头描述部分的字节 数,它总是 6,所以一定是“00 00 00 06”,以下是剩余部分的含义:

    ff ff

    指定 Midi 的格式

    00 00

    单音轨

    00 01

    多音轨,且同步。这是最常见的

    00 02

    多音轨,但不同步

    nn nn

    指定轨道数

    实际音轨数加上一个全局的音轨

    dd dd

    指定基本时间

    一般为 120(00 78),即一个四分音符的 tick 数,tick 是 MIDI 中的最小时间单位

    以上就是 MIDI 文件头了,后面的所有内容都是真正做事的,我们先来看看它的构成。

    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

    触后音符
    (Key After Touch)

    音符: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

    上次激活格式的参数(8x、9x、Ax、Bx、Cx、Dx、Ex)

    下表详细地列出了 FF 的详细情况,对于字节数由数据决定的情况,表中以“--”表示。

    种类 字 节

    字节 含义
    00 设置轨道音序

    数据 数

    02 音序号 00 00~ FF FF

    01

    歌曲备注 文本信息 --

    音轨文本 文本信息

    02 歌曲版权
    歌曲标题 --

    03

    -- 版权信息

    歌曲标题:用于全局音轨,第一次使用表示主标题,第二次表 示副标题

    音轨名称 -- 音轨名

    04 乐器名称

    -- 音轨文本(同 01/2)

    05歌词 --歌词

    1. 06  标记

    2. 07  开始点

    2F 音轨结束标志

    51 速度

    -- 用文本标记(Marker)

    -- 用文本记录开始点(同 01/2)

    00 无

    03 3字节整数,1个四分音符的微秒数

    58节拍 04分子

    分母:00(1),01(2),02(4),03(8)等

         

    节拍器时钟

    一个四分音符包含的三十二分音符的个数

    59

    调号

    02

    升降号数:-7~-1(降号),0(C),1~7(升号)

    大小调:0(大调),1(小调)

    7F

    音序特定信息

    --

    音序特定信息

    这些就是 MIDI 结构的全部内容

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

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

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

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

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

    我 们先尝试设置歌曲的速度和节拍等基本信息。假设一个四分音符的时间是半 秒,即 0.5*106 微秒。它的十六进制数是 07A120,再看事件表,设置速度是 51, 但是在其前面必须是 FF,然后它须要 3 个字节作为参数,因此字节数为 03,参 数为“07 A1 20”,也就是“FF 51 03 07 A1 20”。这是事件部分,不要忘记 在其之前有个参数——时间差。这是一开始就应该设置的参数,因此时间差为 0 0。所以,完整的事件应该是“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,第二个参数是 0 3(23=8)。 最后,补上前面的时间差和后面的两个被忽略的参数,它应该是“0 0 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 个通道(注意到 M IDI 有 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 6 4”,这里的 00 显然是个时间差,3E 是中音 D,64 是力度,也就是说,在按下 中音 A 的同时按下了中音 D。我们又按下一个键了,要在什么时候,在哪里松 开才能保证输入的是个附点八分音符呢?首先,它的时值是 3 个八分音符,即 1 80,这里还有一点要注意,180 是个大于 128 的数,它的动态字节就应该表示 成“81 34”,在哪里输入才好呢?如果你觉得在按下 D 后输入,或者在任何什 么地方输入这个时间差,然后再写上“3E 00”可以表示松开的话就完全误解了 时间差的概念。其实,我们只要简单地在松开#G 的时候松开 D 就可以了,所以 应该在末尾补上“00 3E 00”。统计好字节数后到 Cakewalk 中去验证验证吧。

    到目前为此,我们应该可以输入任何形式的音符了,不过 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 0 0 F7 00 F0 04 AA BB CC F7”

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

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

    虽 然我们只讨论了同步多音轨的格式,其实对于其他两种,比如较常见的单音 轨格式,所有的事件只写在一个音轨中,即只要存在一个“MTrk”就足够了。而 相对 地,用于记录音轨数的两个字节也永远为“00 01”,连续事件如果出现的 通道不同,也必须重新指定通道(8x~Ex)。在此不详细讨论了。

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

    MIDI 文件格式分析——附件篇 该文档是前两编的补充,主要讲述以下内容: 音符十六进制的计算
    关于乐器选择

    RPN 和 NRPN
    在 MIDI 中,中央 C 是 C5,最低音是 C0,最高音是 G5,要计算任何 一个音符对应的十六进制,可以使用这个公式:
    假设音符是 NO,表示第 O 八度的音名 N,比如 G2 中,N 为 G,O 为 2, 则它的十进制为 O*12+N,N 的值为了简便起见,用下表给出:

    这样 G2 的十进制值为 2*12+7=31,十六进制为 1F。 若知道音符的十六进制,也可以很容易求出音符,比如 64(16)=100(1 0),
    而 100 div 12=8,100 mod 12=4,对应音符为 E8。写成公式就是: N=B mod 12;O=B div 12;(设 B 为表示音符的字节的十进制数)
    乐 器是 MIDI 中比较重要的因素,要选择所有的乐器不仅仅只是使用 Cx 号标志就能完成的,还必须结合 BankSelect(乐队选择),而 Ban kSelect 其实是由 0 号控制器和 32 号控制器完成的,它们的十六进 制代码分别是 00 和 20.比如要选择出 XG 标准中的 Slow Violin,它 在第 08H 个乐队中的第 28H 号乐器中,所以它的完整代码应为“00 B0 00 00 00 20 08 00 C0 28”。我们来分析它的构成:这里我们假 设时间差为 00,所有信息都发给通道 00,所以第一个 00 是时间差, B0 是打开控制器的标志,并指定发送到通道 00,接下来的 00 00, 是由控制器号 00 和控制器参数 00 构成的,它事实上是表示 0 号控制 器的参数为 0,即 BankSelect-MSB 的参数为 0,然后是下一个事件, 它 是“00 20 08”,即时间差是 00,使用 20H 号控制器,参数为 0 8H,即 BankSelect-LSB 的参数是 08H,这样就指定了 Bank(乐队)。 再下来就是 “00 C0 28”,就是所谓的 Patch Change 事件了,它的 时间差为 00,参数是 28H。这样就完成了标准的乐器选择。

    事实上,它是由三个事件共同完成的,如果某次选择乐器和上次的乐 器有共同的参数,可以不必重复使用相关的 X 作。

    在 本例中,您可能发现了一点,当连续使用同类 X 作时可以不必每 次指定 X 作种类,比如这里的连续再次使用控制器,所以第二个控制 器并没有使用 B0 作为标志,而 是直接使用控制器号码和它的参数。 这一点和音符是一样的。其实,如果连续使用 Patch Change 事件(我 是说如果),则也可不必每次都写 Cx,打开了一次就可以了;不过就 Patch Change 事件而言,连续地更换乐器的结果是仅最后一个有效 而已。

    在前面的文档中并没有提及 RPN 和 NRPN,其实它们是由四个连续的 控制器来实现的。我们假设要使用 RPN 事件的 Coarse Turning,它 的参数假设是 4096,则它的字节是“00 B0 65 00 00 64 02 00 06 20 00 26 00”,我们来分析这段字节:首先我们先看看 RPN 是由哪 四个控制器组成的——首先设置 RPN-MSB 和 RPN-LSB,分别对应的控 制器是 65H 和 64H,Coarse Turning 的 RPN 码是 2,所以 MSB 为 0, LSB 为 2;然后是设置 Data Entry MSB 和 Data Entry LSB,对应的 控制器是 06H 和 26H,而 4096 div 128=32,4096 mod 128=0,对应 的十六进制数分别是 20H 和 00H。因此就构成了上面的字节。而 NRP N 和 RPN 原理是一样的,只不过不用 RPN-MSB 和 RPN- LSB,而改用 N

    RPN-MSB 和 NRPN-LSB 而已,它们对应的十六进制数分别为 63H 和 62 H。 


    转载自:http://blog.sina.com.cn/s/blog_6f72ff900101f95b.html

    展开全文
  • 1 前言  随着计算机与电子科学的发展,传统的阅读方式正在发生着天翻地覆的变化。乐谱是一种以印刷或手写制作,用符号来记录音乐的方法。不同的文化和地区发展了不同的记谱方法。记谱法可以分为记录音高和记录指法...
  • MIDI文件格式.pdf

    2021-10-04 21:30:06
    MIDI文件格式.pdf
  • MIDI文件格式(一)

    万次阅读 2018-09-17 21:01:58
    前四个是ASCII字符“MTrk”,用来鉴别是否为Midi文件; 随后的四个字节是指明文件头描述部分的字节数,总是6,所以一定是“00 00 00 06”; 以下是剩余部分的含义: ff ff 指定 Midi 的格式 00 00...

    在每个 Midi 文件的开头都有如下内容它们的十六进制代码为:“4d 54 68 64 00 00 00 06 ff ff nn nn dd dd”。

    前四个是ASCII字符“MTrk”,用来鉴别是否为Midi文件;

    随后的四个字节是指明文件头描述部分的字节数,总是6,所以一定是“00 00 00 06”;

    以下是剩余部分的含义:

    ff ff指定 Midi 的格式00 00单音轨
    00 01多音轨,且同步。这是最常见的
    00 02多音轨,但不同步
    nn nn指定轨道数实际音轨数加上一个全局的音轨
    dd dd指定基本时间一般为 120(00 78),即一个四分音符的 tick 数,tick 是 MIDI 中的最小时间单位

    以上是MIDI文件的文件头。

    MIDI数据是若干个格式相同的子数据构成。这些子数据在多音轨的格式中记录了一个轨道的所有信息。多加一个音轨,就简单地把数据追加在前一音轨的后面就可以了,不过不要忘记更改文件头中的 nn nn(轨道数)。

    接着就是记录数据的地方了:

     

    记录的数据:

    每一个数据都有相同的结构:时间差+事件

    1. 时间差

    指前一个事件到该事件的时间数,单位是tick(MIDI的最小时间单位)

    以这种方式记录整数的字节称为动态字节,它根据记录的整数改变自身的长度。

    表示 65535 tick:

    第一行:当128的次方不为0时,第一行都是1000 0000;只有当次数为0时,才为0000 0000。

    第二行:为128乘数的2进制表示,有8位。

    最后结果为相加之后的十六进制表示。

    其结果为:83 FF 7F

     

    若要通过结果确定时间差,何时截止?发现,当红圈表示的第一位为0时,结束。

    即十六进制表示的第一位小于8,即为0~7时为结束。

    如83 CF C0 33 6D 3E 表示:(83 CF C0 33 )|(6D 3E)

    方法一(简):

    对于“XY”,当X属于8~F:(X - 8)*16 + Y;当X属于0~7:X*16 + Y;

    方法二(繁)(其实就是方法一的原理):

    2. 事件

    大体可分为音符、控制器、系统信息。这些事件都有统一的表达结构:种类+参数

    对于一个音符,由于它的有效范围是 0~127,所以直接用 00~7F 作为“种类”,可以认为是个音符,比如 3C 表示中央 C。而一个音符的最重要的参数是力度(也叫速度:velocity)。比如,3C 64 表示一个力度为十进制100的中央C音符。

    (本句出自https://blog.csdn.net/meicheng777/article/details/52054838

    事件:

    字节含义参数(十六进制)
    8x松开音符音符(00~7F):松开的音符
    力度:00~7F
    9x按下音符音符(00~7F):按下的音符
    力度:00~7F
    Ax

    触后音符

    (Key After Touch)

    音符: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上次激活格式的参数(8x、9x、Ax、Bx、Cx、Dx、Ex)

     

     

    展开全文
  • 1 前言  随着计算机与电子科学的发展,传统的阅读方式正在发生着天翻地覆的变化。乐谱是一种以印刷或手写制作,用符号来记录音乐的方法。不同的文化和地区发展了不同的记谱方法。记谱法可以分为记录音高和记录指法...
  • 一、MIDI 文件简介、 二、MIDI 文件头解析、 1、MIDI 文件头标识、 2、MIDI 文件头长度、 3、MIDI 文件格式、 4、MIDI 轨道个数、 5、基本时间、





    一、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 文件中计算时间的最基本单位 ;

    在这里插入图片描述

    展开全文
  • 3、MIDI 文件格式、 4、MIDI 轨道个数、 5、基本时间、 三、MIDI 轨道分析、 四、MIDI 轨道头、 五、MIDI 轨道长度、 六、delta-time 间隔、 七、FF 03 轨道名称、 八、FF 51 03 四分音符时长、 九、FF 58 04 拍号、...





    一、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 文件解析完毕 ;

    展开全文
  • 本文档概述了MIDI文件的规范。 MIDI文件的目的是提供一种在相同或不同计算机上的不同程序之间交换带时间戳的MIDI数据的方法。主要设计目标之一是紧凑表示,这使其非常适合基于磁盘的文件格式,但可能不适合存储在...
  • 标准MIDI文件格式.wps

    2011-11-25 14:20:43
    标准的MIDI文件格式就像奇异的兽。总体看来,它是那样的让你无法抗拒。当然,你怎样看它无关紧要,可是用足够多的描述符描述一段音乐并使它能够重现,可不是很少的工作就可以完成的。然而,它虽然复杂,但是真正理解...
  • MIDI文件格式分析

    2012-08-20 19:33:31
    MIDI消息和标准MIDI文件格式剖析及应用.
  • MIDI消息和标准MIDI文件格式剖析及应用.
  • MIDI文件格式解析

    千次阅读 2010-07-25 23:41:00
    MIDI文件中包含音符、定时和多达16个通道的演奏定义。文件包括每个通道的演奏音符信息:键通道号、音长、音量和力度等。由于MIDI文件是一系列指 令,而不是波形,它需要的磁盘空间非常少,此外对MIDI数据的编辑和...
  • 嵌入式MIDI 文件格式解析设计与实现 写够20字了吗? 够了木有? 有木有?
  • midi文件解析

    热门讨论 2013-03-26 11:07:42
    midi文件进行解析,获取midi结构,数据,时长等信息。并进行了初步封装,制作成java application程序
  • MIDI文件格式分析(补充和勘误)

    千次阅读 2018-04-12 15:40:10
    MIDI文件格式分析(补充和勘误) 本文是对《MIDI文件格式分析》博客链接的一点补充: 原文复制 vim编辑二进制文件的方法 文中制作的midi文件内容和改动 原文复制 MIDI文件属于二进制文件,这种文件一般都有...
  • 文章目录 前言 一、FF 58 04 拍号 二、音符开指令 三、音符关指令 四、音轨结束标志 前言 在博客 【BLE MIDIMIDI 文件格式分析 ( MIDI 文件头解析 | MIDI 文件头标识 | MIDI 文件头长度 | MIDI 文件格式 | MIDI ...
  • 建立在嵌入式系统平台上的电子乐谱阅读器可以代替传统纸质乐谱和谱架的组合成为乐谱...本文详细说明了从一个MIDI文件解析出五线谱信息的全过程,介绍了MIDI文件格式以及在MIDI格式读取的过程中遇到的种种问题的解决方法
  • 标准MIDI文件格式

    千次阅读 2010-07-26 00:00:00
    标准MIDI文件格式    标准的MIDI文件格式就像奇异的兽。总体看来,它是那样的让你无法抗拒。当然,你怎样看它无关紧要,可是用足够多的描述符描述一段音乐并使它能够重现,可不是很少的工作就可以完成的。...
  • 此应用程序可帮助您在播放MIDI文件或音频源的同时弹奏和即兴演奏和弦。 它通过更新滚动显示以将和弦音符映射到钢琴键盘来实现此目的。 它还可以为MIDI或PC键盘上的键动态分配音符或和弦。 同步是通过MIDI文件自动...
  • 然后可以将该输出重构为标准MIDI文件格式。 主要目标 CNN执行的自动转换是朝自动音乐转录(AMT)更大目标迈出的一步。 AMT和音乐信息检索在行业中有许多应用,包括数字音频工作站软件开发和音乐推荐系统。 设置 ...
  • MIDI 文件格式

    2009-02-08 01:11:00
    MIDI 文件格式 来源:http://blog.chinaunix.net/u/14819/showart.php?id=217924MIDI 文件由 chunks 组成:每个chunk 的组成: 类型 长度数据 4
  • MidiKlavar是从MidiXml到其他文件格式MIDI文件转换器。 MidiXml是由MusicXml.com(MusicXml文件格式背后的组织)管理的文件格式规范。 它与midi.org定义的MIDI二进制文件标准结合使用。 本质上,MidiXml使MIDI二...
  • MIDI文件主旋律音轨的抽取

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,454
精华内容 8,181
关键字:

midi文件格式