在 java 的 MIDI 文件中找到正确的 noteOff 事件
Finding the correct noteOff event in a midi file in java
我正在 Java 编写一个工具,它在 midis 上执行一些批处理,包括创建音轨和将音符从一个音轨移动到另一个音轨。
但是,我找不到可靠的方法来查找特定 NoteOn 的关联 Noteoff 事件。我看到一些 post 说要在同一音高上搜索下一个 NoteOff(或 Velocity = 0 的 NoteOn),但这是假设没有重叠的音符。如果有重叠音符,则在正确音符之前的同一音高上可能有多个音符关闭。
有没有办法可靠地找到 NoteOn 的 NoteOff 事件?
https://www.mediafire.com/view/6c4wg0i7extifyw/WhosebugMidi.png/file
感谢您的宝贵时间。
注意原始 Midi 文件中的 Midi 事件仅携带 pitch、velocity 和 channel 信息.因此,如果音符重叠,则无法确定此音符关闭对应于此音符打开。
此外,Midi 规范没有指定如何对同一个 pitch/channel 的多个音符 ON 做出反应。这就是为什么根据使用的 Midi 设备(硬件合成器、VST 插件、Midi 播放器等)您可能会听到不同的结果。
然而,算法可能会选择如何以一致的方式处理意外的音符事件。有3种可能。
假设您的 Midi 文件包含 2 个重叠的 C 音符(相同的音高,相同的通道)。那么您将始终拥有以下 Midi 事件序列:C_ON(tick1), C_ON(tick2), C_OFF(tick3), C_OFF(tick4)
,其中 tick1 <= tick2 <= tick3 <= tick4
.
有些程序认为音符重叠是一个错误,因此它们会忽略 redundant/unexpected 音符事件。这里表示 C_ON(tick2) 和 C_OFF(tick4) 被忽略。你最终得到一个音符 C(tick1-tick3).
其他程序使用列表 (FIFO) 来存储相同 pitch/channel 的音符打开。音符实际上是在按照音符开启的顺序解析音符关闭时创建的。所以你最终得到 2 个音符 C(tick1-tick3) 和 C(tick2-tick4)
最后一种可能性,使用堆栈(后进先出)将每个音符推入相同 pitch/channel,并在解析音符时将其弹出。在这种情况下,您将以 2 个音符 C(tick1-tick4) 和 C(tick2-tick3) 结束。
请注意,当您使用 DAW 文件格式保存带有 Midi 轨道的 DAW 项目时,DAW 可以存储附加信息以正确管理重叠。
我正在 Java 编写一个工具,它在 midis 上执行一些批处理,包括创建音轨和将音符从一个音轨移动到另一个音轨。 但是,我找不到可靠的方法来查找特定 NoteOn 的关联 Noteoff 事件。我看到一些 post 说要在同一音高上搜索下一个 NoteOff(或 Velocity = 0 的 NoteOn),但这是假设没有重叠的音符。如果有重叠音符,则在正确音符之前的同一音高上可能有多个音符关闭。 有没有办法可靠地找到 NoteOn 的 NoteOff 事件? https://www.mediafire.com/view/6c4wg0i7extifyw/WhosebugMidi.png/file
感谢您的宝贵时间。
注意原始 Midi 文件中的 Midi 事件仅携带 pitch、velocity 和 channel 信息.因此,如果音符重叠,则无法确定此音符关闭对应于此音符打开。
此外,Midi 规范没有指定如何对同一个 pitch/channel 的多个音符 ON 做出反应。这就是为什么根据使用的 Midi 设备(硬件合成器、VST 插件、Midi 播放器等)您可能会听到不同的结果。
然而,算法可能会选择如何以一致的方式处理意外的音符事件。有3种可能。
假设您的 Midi 文件包含 2 个重叠的 C 音符(相同的音高,相同的通道)。那么您将始终拥有以下 Midi 事件序列:C_ON(tick1), C_ON(tick2), C_OFF(tick3), C_OFF(tick4)
,其中 tick1 <= tick2 <= tick3 <= tick4
.
有些程序认为音符重叠是一个错误,因此它们会忽略 redundant/unexpected 音符事件。这里表示 C_ON(tick2) 和 C_OFF(tick4) 被忽略。你最终得到一个音符 C(tick1-tick3).
其他程序使用列表 (FIFO) 来存储相同 pitch/channel 的音符打开。音符实际上是在按照音符开启的顺序解析音符关闭时创建的。所以你最终得到 2 个音符 C(tick1-tick3) 和 C(tick2-tick4)
最后一种可能性,使用堆栈(后进先出)将每个音符推入相同 pitch/channel,并在解析音符时将其弹出。在这种情况下,您将以 2 个音符 C(tick1-tick4) 和 C(tick2-tick3) 结束。
请注意,当您使用 DAW 文件格式保存带有 Midi 轨道的 DAW 项目时,DAW 可以存储附加信息以正确管理重叠。