通过脚本编辑 midi 文件

通过脚本编辑 midi 文件

我需要以编程方式从 midi 文件中删除一个通道(通道 10,因此是打击乐通道)。有很多音乐程序允许您编辑 midi 文件,但我希望我可以通过脚本来执行此操作以节省一些时间。

我对此很陌生,我在网上找到的唯一可能对我有帮助的东西似乎是 ffmpeg。但我真的不明白该怎么做。

总结一下:

  1. ffmpeg 可以编辑 midi 文件吗?
  2. 如果是,ffmpeg 是编写 midi 操作脚本的最佳工具吗?
  3. 您有一些可以展示的工作代码吗?

谢谢!

答案1

FFmpeg 是为音频和视频文件(如.mp3和 )制作的.mp4。这些文件的结构与 MIDI 文件非常不同。虽然可能有人添加了 MIDI 支持,但我对此表示怀疑。

幸运的是,MIDI 文件并不难理解:

MIDI 文件由块组成,每个块以四个 ASCII 字母开头(总共占用四个字节),后跟一个四字节值。该值是块的大小。

第一个块总是以 ASCII 字母开头MThd,告诉您这是标题,接下来的四个字节编码大小。如果您跳过大小值告诉您的字节数,您应该到达下一个块,即一个轨道。如果一切正确,您应该读到 ASCII 字母MTrk,后面跟着四个字节的大小。跳过此站点应该会带您到下一个轨道。计算您跳过的轨道数,直到到达第十个轨道。您可以通过删除此轨道中原本会跳过的字节(包括MTrk删除的字节)来删除它。

这可能会删除您的打击乐音轨,如果不行,您可以尝试删除其他音轨。如果这不起作用,那么事情就会变得有点复杂。

例外情况:

  • 这个 MIDI 文件可能在单个音轨中嵌入了整首歌曲,这里事情会变得稍微复杂一些。

更复杂的情况:在音轨中,还存储了每个音符的音轨编号,要读取这些音符,您需要制作(或找到)一个完整的 MIDI 解释器。要删除这些音符,您需要过滤掉具有该特定音轨编号的音符。

来源

答案2

如果你不介意用 Python,那么这个图书馆用于处理 MIDI 的 Mido。它允许您像 SP4CEBAR 的答案一样在更高级别上迭代音轨。

以下函数检查每条“消息”并检查是否存在频道属性以及该频道值是否与您要删除的频道匹配。

你可以使用它来开始:

import mido

def remove_channel_from_midi(input_path, output_path, channel_to_remove):
    try:
        # Load the MIDI file
        midi_file = mido.MidiFile(input_path)
        
        # Create a new MIDI file to store the modified data
        new_midi_file = mido.MidiFile()
        
        for msg in midi_file:
            # Check if the message is on the channel to be removed
            if hasattr(msg, 'channel') and msg.channel == channel_to_remove:
                continue  # Skip this message
            new_midi_file.tracks.append([msg])  # Add the message to the new file
        
        # Save the modified MIDI file
        new_midi_file.save(output_path)
        print(f"Channel {channel_to_remove} removed and saved to {output_path}")
    except Exception as e:
        print(f"An error occurred: {e}")

# Example usage:
input_midi_path = "input.mid"
output_midi_path = "output.mid"
remove_channel_from_midi(input_midi_path, output_midi_path, channel_to_remove=10)

相关内容