将 midi 时间转换为小节和节拍

Posted

技术标签:

【中文标题】将 midi 时间转换为小节和节拍【英文标题】:Convert midi time to bars and beats 【发布时间】:2020-06-12 01:01:42 【问题描述】:

我想弄清楚如何。 Here is a sample midi file。如果您下载该文件并在 GarageBand 之类的程序中打开文件,您会看到第三首曲目在第一个小节中包含四个音符:

现在,如果您在 Python 中使用 mido 加载文件,您可以在同一轨道中看到前四个音符:

import mido

midi = mido.MidiFile('1079-02.mid')
list(midi.tracks[2])

如果您查看曲目中的事件列表,您会看到曲目中的前四个音符开/关事件:

 <message note_on channel=1 note=60 velocity=100 time=0>,
 <message note_on channel=1 note=60 velocity=0 time=480>,
 <message note_on channel=1 note=63 velocity=100 time=0>,
 <message note_on channel=1 note=63 velocity=0 time=480>,
 <message note_on channel=1 note=67 velocity=100 time=0>,
 <message note_on channel=1 note=67 velocity=0 time=480>,
 <message note_on channel=1 note=68 velocity=100 time=0>,
 <message note_on channel=1 note=68 velocity=0 time=480>,

在这里我们可以看到,在这个特定的文件中,时间值 480 等于一个柱的四分之一。不过,madmom 库 uses 480 as the default ticks per beat value 在它们的一些辅助函数中,所以也许这是一个常见的幻数?但是,在其他文件中,该值是不同的。

我的问题是:如何将 midi 文件中的时间值转换为条形长度的时间值?例如,对于这个文件,我想将第三首曲目的前四个音符中的时间属性表示为 0.25,因为每个音符持续四分之一小节。有谁知道我如何进行这种转换?

作为参考,此文件中的第一首曲目包含以下时间属性:

<meta message smpte_offset frame_rate=24 hours=32 minutes=0 seconds=3 frames=15 sub_frames=0 time=0>,
<meta message time_signature numerator=4 denominator=4 clocks_per_click=24 notated_32nd_notes_per_beat=8 time=0>,
<meta message set_tempo tempo=857143 time=0>,

【问题讨论】:

【参考方案1】:

赞美所有美好和神圣的事物,mido.MidiFile 读取每拍元数据的节拍并将其存储在 mido.MidiFile.ticks_per_beat

import mido

midi = mido.MidiFile('1079-02.mid')
print(midi.ticks_per_beat)

然后,您只需将每个音符的持续时间除以每节拍的节拍值,以表示音符的持续时间(以节拍为单位)!

【讨论】:

要获得准确的小节/节拍位置,您还需要考虑 Midi 文件中的拍号事件。 是的,虽然这在第一首曲目中的一个事件中得到了正确的表示,而我没有看到任何表示 ticks_per_beat 的事件

以上是关于将 midi 时间转换为小节和节拍的主要内容,如果未能解决你的问题,请参考以下文章

MIDI:将 BPM 转换为 FPS 增量时间?

MIDI,如何获取小节和音符

BLE MIDIMIDI 时间标志分析 ( 音符速度设置事件 | 拍号设置事件 | 基本时间 - 每个四分音符有多少 tick 或 pulse | 节拍时值计算 | 小节时值计算 )

Swift 中的 AudioUnitRender 和 ExtAudioFileWrite 错误 -50:尝试将 MIDI 转换为音频文件

将 MIDI 事件转换为 pygame 事件

编写一个程序,帮助 tudio 将 midi 音符编号转换为名称和八度