创建MIDI文件并编码事件时间:为什么按时间间隔均匀分布的音符实际上会减慢?

时间:2016-12-22 10:51:50

标签: hex midi

我正在尝试编写一个用于创建MIDI文件的简单界面。作为测试,我尝试创建一个大规模的文件,所有相同长度的笔记。我得到的文件如下(为了便于阅读而缩进)

4d 54 68 64 00 00 00 06 00 01 00 02 00 08
   4d 54 72 6b 00 00 00 0b
      00 ff 51 03 00 27 0f
      00 ff 2f 00
   4d 54 72 6b 00 00 00 54
      00 c0 00
      00 90 40 7f
      7d 80 40 7f
      7d 90 42 7f
      81 7a 80 42 7f
      81 7a 90 44 7f
      82 77 80 44 7f
      82 77 90 45 7f
      83 74 80 45 7f
      83 74 90 47 7f
      84 71 80 47 7f
      84 71 90 49 7f
      85 6e 80 49 7f
      85 6e 90 4b 7f
      86 6b 80 4b 7f
      86 6b 90 4c 7f
      87 68 80 4c 7f
      00 ff 2f 00

说明:第1行是文件头。第2行是轨道标题。 (在我的界面中,我保留了一个用于打击乐的音轨,并且还设置了节奏。因为在这个例子中我没有打击乐器它没有音符。)第3行设置速度,第4行结束音轨。第5行是另一个轨道标题。此曲目包含旋律。第6行为通道0设置仪器。接下来是通道0的8个交替音符开启和8个音符关闭事件,然后跟踪结束。开始和结束笔记的时间是:

00, 7d, 81 7a, 82 77, 83 74, 84 71, 85 6e, 86 6b, 87 68

据我所知,它们应该是均匀间隔的,因为对于事件时间,MIDI使用7位字节格式,其中数字的长度是灵活的,除了最后一个字节之外的所有字节都设置了msnzb。所以00应该转换为0,7d应该转换为125,81 7a应该转换为250等等。但是由于某种原因,当你播放文件时,它听起来并不是时间均匀,而是放慢速度。为什么会这样?我是否误解了编码事件计时的正确方法,如果是,那么正确的方法是什么?或者我的文件还有其他问题导致问题吗?

1 个答案:

答案 0 :(得分:1)

MIDI文件中的时间戳是delta-times - 您不编码事件发生的时间,您编码该轨道上的连续事件之间的时差。如果事件在时间上均匀分布,则它们的增量时间应该相同。

来自标准:

  

MTrk事件的语法非常简单:

     

<MTrk event> = <delta-time><event>

     

<delta-time>存储为可变长度数量。它表示以下事件之前的时间量。如果轨道中的第一个事件发生在轨道的最开始,或者如果两个事件同时发生,则使用零增量时间。 Delta-times始终存在。 (不存储delta-times为0需要至少两个字节用于任何其他值,并且大多数delta时间不为零。)Delta-time在一个节拍的一小部分(或一秒,用于使用SMPTE记录轨道)时间),如标题块中所指定的。

参见例如http://www.music.mcgill.ca/~ich/classes/mumt306/StandardMIDIfileformat.html