在 python 中构建 MIDI 合并程序,带有恢复选项

Posted

技术标签:

【中文标题】在 python 中构建 MIDI 合并程序,带有恢复选项【英文标题】:Build MIDI merger program in python, with option for recovery 【发布时间】:2020-06-04 17:34:44 【问题描述】:

我尝试将 2 个 MIDI 文件合并为一个,这样在播放输出 MIDI 文件时就不会听到第二个 MIDI 文件。 我已经设法得到一个只播放第一首歌的结果,但我想知道是否有办法隐藏(加密)第二个文件,并可以选择从输出文件中恢复它。

以我的方式,没有恢复的选项,因为第二首歌的所有音符都处于速度 0,所以除非我将原始速度写入外部文件或类似的东西,否则无法恢复它们。

def merge(first, second):
  mid1 = MidiFile(first)
  mid2 = MidiFile(second)
  output = MidiFile(ticks_per_beat=mid1.ticks_per_beat, clip=mid1.clip, charset=mid1.charset, type=mid1.type)

  for i, track in enumerate(mid2.tracks):
      for j, msg in enumerate(mid2.tracks[i]):
          try:
              msg.velocity = 0
          except Exception as e:
              pass
      output.tracks.append(track)

  for i, track in enumerate(mid1.tracks):
      output.tracks.append(track)

  print(output.length)
  output.save(filename="merged.mid")

谢谢!

【问题讨论】:

【参考方案1】:

我已经设法用元消息隐藏了速度。

对于每个音符的消息,我使用它的速度并使用 json 对象“index_of_note_in_track: old_velocity”创建一个新的元消息,并将这些元消息放在轨道的末尾。

def merge(first, second):
mid1 = MidiFile(first)
mid2 = MidiFile(second)
output = MidiFile(ticks_per_beat=mid1.ticks_per_beat, clip=mid1.clip, charset=mid1.charset, type=mid1.type)

for i, track in enumerate(mid2.tracks):
    new_msgs = []
    for j, msg in enumerate(mid2.tracks[i]):
        if "velocity" in msg.dict().keys():
            new_msgs.append(MetaMessage('text', **'text': f'"j":str(msg.velocity)'))
            msg.velocity = 0
    for msg in new_msgs:
        track.insert(len(track), msg)
    output.tracks.append(track)

for i, track in enumerate(mid1.tracks):
    output.tracks.append(track)

print(output.length)
output.save(filename="merged.mid")

你能想出其他方法将一个 MIDI 文件隐藏在另一个文件中吗?

【讨论】:

以上是关于在 python 中构建 MIDI 合并程序,带有恢复选项的主要内容,如果未能解决你的问题,请参考以下文章

在使用 HTML5 构建的钢琴应用程序中嵌入 MIDI(mp3,如果不能使用 mp3)文件

如何合并轨道中的所有 Midi 事件?

带有 Javascript 的 MIDI 键盘 [关闭]

合并 Arduino 草图 (MIDI)

如何强制 MIDI 设备报告控制状态?

在 python 中从 MIDI 文件预览乐谱