boxmoe_header_banner_img

Hello! 欢迎来到悠悠畅享网!

文章导读

使用 Mido 在 MIDI 文件中实现速度变化


avatar
站长 2025年8月8日 10

使用 Mido 在 MIDI 文件中实现速度变化

本文档旨在指导开发者如何使用 Mido 库在 Python 中创建包含速度变化的 MIDI 文件。我们将深入探讨如何正确计算和应用 delta time,以确保速度变化在 MIDI 文件中准确同步。通过一个实际的代码示例,我们将演示如何根据给定的位置和速度值生成正确的 MIDI 输出。

理解 Delta Time

在 MIDI 文件中,delta time 是指事件发生的时间间隔,而不是绝对时间。它表示从上一个 MIDI 事件到当前事件所经过的 “ticks” 数。正确计算和应用 delta time 对于实现准确的速度变化至关重要。Mido 库使用 ticks_per_beat 属性来定义每个四分音符的 ticks 数。

代码示例:创建包含速度变化的 MIDI 文件

以下代码展示了如何使用 Mido 创建包含速度变化的 MIDI 文件,并正确计算 delta time:

import mido from mido import MidiFile, MidiTrack, MetaMessage  def create_tempo_map_midi(positions, tempos, sample_rate=44100, output_midi_file='tempo_map.mid'):     midi = MidiFile()     track = MidiTrack()     midi.tracks.append(track)     ticks_per_beat = 480      current_ticks = 0  # Track the cumulative ticks      for position, tempo in zip(positions, tempos):         bpm_to_microseconds = 60_000_000 / tempo  # Convert BPM to microseconds per beat         time_seconds = position / sample_rate          # Calculate the ticks directly without using mido.second2tick         time_ticks = int(time_seconds * ticks_per_beat * tempo / 60)          # Ensure that the calculated time_ticks is non-negative         delta_ticks = max(0, time_ticks - current_ticks)          # Add the tempo change event to the track         track.append(MetaMessage('set_tempo', tempo=int(bpm_to_microseconds), time=delta_ticks))          # Update current_ticks         current_ticks = time_ticks      # Save the MIDI file     midi.save(output_midi_file)  if __name__ == "__main__":     tempo_values = [98.0, 98.0, 101.5467, 103.3155, 105.0865, 106.8571, 108.6168, 110.3756, 112.1227, 113.8698, 115.6076, 117.3423, 119.0782, 120.8079, 122.5382, 124.2676, 126.0, 156.0, 156.0, 152.5883, 149.1766, 145.7649, 142.3532, 138.9415, 135.5298, 132.1181, 128.7064, 125.2947, 121.883, 118.4713, 115.0596, 111.6479, 108.2362, 104.8245, 98.0]     pos_values = [0, 1404000, 1417500, 1430528, 1443333, 1455922, 1468303, 1480483, 1492469, 1504268, 1515886, 1527329, 1538603, 1549713, 1560664, 1571460, 1592242, 1592745, 8309514, 8317994, 8326664, 8335532, 8344608, 8353901, 8363422, 8373183, 8383196, 8393475, 8404034, 8414888, 8426055, 8437553, 8449402, 8461625, 8474246]     create_tempo_map_midi(pos_values, tempo_values)

代码解释:

  1. create_tempo_map_midi(positions, tempos, sample_rate=44100, output_midi_file=’tempo_map.mid’) 函数:

    • 接收位置列表 positions 和速度列表 tempos 作为输入。
    • 创建一个新的 MIDI 文件和音轨。
    • 设置 ticks_per_beat 为 480,这是一个常用的值。
    • 使用 current_ticks 变量跟踪累积的 ticks 数。
  2. 循环遍历位置和速度:

    • 使用 zip 函数同时迭代 positions 和 tempos 列表。
    • 将 BPM 转换为每拍的微秒数 bpm_to_microseconds。
    • 将位置(以采样数为单位)转换为秒数 time_seconds。
    • 关键步骤: 使用公式 time_ticks = int(time_seconds * ticks_per_beat * tempo / 60) 将秒数转换为 ticks 数。
    • 计算 delta_ticks,即当前事件与上一个事件之间的时间差。使用 max(0, time_ticks – current_ticks) 确保 delta_ticks 非负。
    • 将速度变化事件(MetaMessage(‘set_tempo’, …))添加到音轨,并设置正确的 delta_ticks。
    • 更新 current_ticks 以便计算下一个 delta_ticks。
  3. 保存 MIDI 文件:

    • 使用 midi.save(output_midi_file) 将生成的 MIDI 文件保存到磁盘。

注意事项:

  • 确保 positions 和 tempos 列表的长度相同。
  • sample_rate 应该与您的音频数据的采样率相匹配。
  • ticks_per_beat 的选择会影响 MIDI 文件的精度。较高的值可以提供更精细的控制。
  • time_ticks 的计算必须精确,否则速度变化可能会出现偏差。
  • 务必使用 max(0, time_ticks – current_ticks) 确保 delta_ticks 为非负值,否则会导致 MIDI 文件解析错误。

总结

通过理解 delta time 的概念并正确计算其值,您可以利用 Mido 库在 Python 中创建包含复杂速度变化的 MIDI 文件。上述代码示例提供了一个清晰的起点,您可以根据自己的需求进行修改和扩展。 记住,精确的时间计算和对 MIDI 规范的理解是至关重要的。



评论(已关闭)

评论已关闭