gpt4 book ai didi

c# - 仅针对 Note On 解析 MIDI 文件

转载 作者:行者123 更新时间:2023-11-30 15:01:58 32 4
gpt4 key购买 nike

我一直试图弄清楚 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 解析为文件并使用十六进制转储(他们甚至这么叫吗?),所以如果我走错了方向,我很抱歉。 我只需要得到播放的音符,以及播放的顺序。我根本不需要计时或任何花哨的东西。 这背后的原因(如果重要的话)是用不同的语言生成新代码以通过扬声器播放,与 非常相似*nix 上的 beep 命令。正因为如此,我不想使用任何框架 1) 我没有编程,也没有学到任何东西 2) 做的远远超过我需要的,使框架比我的实际代码更重.

最佳答案

接受的答案不是问题的解决方案。它在一般情况下不起作用。我将提供几种情况,在这些情况下,此代码将无法正常工作或失败。这些案例的顺序对应于它们的概率 - 最可能的案例排在第一位。

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

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

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

关于c# - 仅针对 Note On 解析 MIDI 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13242646/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com