仅为Note On解析MIDI文件

时间:2012-11-06 00:27:56

标签: c# .net parsing midi

我一直在试图找出MIDI解析的神秘领域,而我却没有运气。我所要做的就是按照它们出现的顺序得到音符值(60 = C4,72 = C5等)。

我的代码如下。它只是简单地将文件作为字节数组打开,并以十六进制读出所有内容:

byte[] MIDI = File.ReadAllBytes("TestMIDI.mid");
foreach (var element in MIDI) {
    string b = Convert.ToString(element,16);
    Debug.WriteLine(b);
}

所有TestMIDI.mid包含的是关于C5的一个注释。 Here's a hex dump它。使用this info,我试图找到Note On(0x9或转储中只有9)的简单十六进制值,但没有。我可以找到一些72,但有3个,这对我没有任何意义(请注意,请注意,然后是什么?)。

这是我第一次尝试将MIDI解析为文件并使用十六进制转储(他们甚至称之为?),所以如果我朝着完全错误的方向前进,我很抱歉。 我需要的只是获取播放的音符,以及以什么顺序播放。我根本不需要时间或任何想法。这背后的原因,如果重要的话 - 就是用不同的语言生成新的代码,用扬声器播放,非常类似于{{1 * nix上的命令。因此,我不想使用任何框架:1)我没有编程,并且实际上没有学到任何东西2)做的远远超过我的需要,使框架比我实际的代码更重

2 个答案:

答案 0 :(得分:3)

要做到这一点,你至少需要一些相似的MIDI解析器。搜索0x9事件是一个很好的开始,但如果速度字段为0,则0x9也是Note-Off事件.0x9也可以存在于其他事件(元事件,MPQN事件,增量时间等)中,所以你会得到误报。因此,您需要一些实际上知道MIDI文件格式才能准确地执行此操作。

寻找一个库,编写自己的库,或者移植一个开源库。如果你想看,Mine是Java版。

答案 1 :(得分:2)

接受的答案不是解决问题的方法。它不适用于常见情况。我将提供一些案例,其中此代码将无效或将失败。这些案例的顺序与它们的概率相对应 - 最可能的案例首先出现。

  • 误报。 MIDI文件包含许多数据结构,您可以在其中找到值为144的字节。这些结构不是Note On事件。对于真正的MIDI文件,你会得到一堆"音符"这不是笔记,而是文件中的随机值。
  • 0以外的频道。大多数现代MIDI文件包含多个轨道块。每个都保存特定MIDI通道的事件(从0到15)。 144(或十六进制90)表示通道0的Note On事件。因此,您将错过很多其他频道的Note On事件。
  • 运行状态。 MIDI文件主动使用运行状态的概念。该技术允许不存储相同类型的连续事件的状态字节。这意味着状态字节144只能为第一个Note On事件写入一次,并且您将无法在文件中找到它。
  • 144是文件中的最后一个字节。 MIDI文件可以以此值结束。例如,如果自定义块是文件中的最后一个块,或者轨道块没有以End of Track事件结束(根据MIDI文件规范是损坏的,但在现实世界中可能出现这种情况)。在这种情况下,你' ll在MIDI [i + 1]上获得IndexOutOfRangeException。

因此,您永远不应该搜索特定值来在MIDI文件中查找某些语义数据结构。您必须使用Internet上提供的一个.NET库。例如,使用DryWetMIDI,您可以使用以下代码:

IEnumerable<Note> notes = MidiFile.Read(filePath)
                                  .GetNotes();