解码未知的MIDI事件

时间:2011-07-30 21:33:24

标签: java events parsing midi

我正在用Java编写MIDI文件阅读器(主要是作为练习,可能用于Android项目,因为它不包括javax.sound.midi库)。我正在遵循this规范。

我在我的项目中很好地实现了规范细节,实际读数逐个事件地进行。在文件上打开InputStream,并且传递相同的对象以解析各种事件对象,使得当事件解析自身时,流被定位在下一个事件处。这一切都很精彩。

我的第一个测试文件只是一个带有在Sonar 8中创建的空数据轨道的速度图。速度轨迹被完美地解析。空轨道在其块标识符和轨道名称之后具有以下数据:

00 B0 07 47 00 0A 40 00 FF 2F 00

成功解析了第一个字节。 00 = delta时间为0,B0 =通道0上的控制器事件,07 =主音量控制,47 =音量值为71。

下一个字节令我困惑。 00 0A 40最可能的情况是它是一个值为64的Pan事件。0A是一种Controller事件,我期望在事件前面跟B0一样。但由于它之前没有已知的事件标识符字节,我的读者无法解析此事件。

所以我想我的问题是如何解释这类事件?在文件格式中是否可以将Controller事件与单个B0标识符串在一起?另外,如果我在文件中遇到无法识别的事件类型,如果我不知道该事件应该是什么,是否真的有办法知道我可以跳过多少数据?我希望能够跳过未知事件,以便我的读者不会失败,但如果我无法识别事件,我不知道如何跳过它。希望能对这些具体案例有所了解。

2 个答案:

答案 0 :(得分:4)

这称为运行状态。它是MIDI规范的一部分。你正在做的事情是正确的。对不起,您必须通过逆向工程MIDI数据流来解决这个问题。 Here is a longer explanation of running status.

并且,是的,具有速度0的Note On事件是Note Off。实际的Note Off事件具有相关的速度,但几乎没有设备实现Note Off velocity,因此在零速度下看Note On更为常见。

答案 1 :(得分:0)

我会回答我自己的问题,以防有人遇到类似的问题。 (但不太可能)

我的上述评论似乎成立了。在读取第一个识别的事件之后,如果后续事件没有事件标识符,则可以将其视为与前一事件相同的事件类型。

所以在我的例子中:

00 B0 07 47 00 0A 40 00 FF 2F 00

即使只存在一个事件标识符,

也可以解释为两个连续的Controller事件。所以这确实是一个音量事件07,后面跟着一个事件0A,当然还有一个事件结束事件FF 2F 00

我的代码中的解决方案是记住看到的最后一个标识符,如果流中的下一个字节不是有效标识符,则下一个字节块被解释为与前一个事件相同的事件类型。似乎有意义,更重要的是,我的读者成功完成了。