You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Mido实现与MIDIUtil等效的MIDI文件创建?

用Mido实现等效MIDIUtil的MIDI生成功能

下面是和你提供的MIDIUtil代码完全等效的Mido实现,同时包含调号设置的示例:

from mido import MidiFile, MidiTrack, Message, MetaMessage

# 配置参数
degrees = [60, 62, 64, 65, 67, 69, 71, 72]  # MIDI音符编号
channel = 0
time = 0  # 初始时间(拍数)
duration = 1  # 音符时长(拍数)
tempo = 60  # BPM
volume = 100  # 音量(0-127)
ticks_per_beat = 480  # Mido默认PPQ,可自定义

# 1. 创建MIDI文件对象(格式1,对应MIDIUtil的默认格式)
mid = MidiFile(type=1, ticks_per_beat=ticks_per_beat)

# 2. 创建音轨并添加到文件
track = MidiTrack()
mid.tracks.append(track)

# 3. 设置速度(将BPM转换为微秒/拍,MIDI标准单位)
microseconds_per_beat = 60000000 // tempo
track.append(MetaMessage('set_tempo', tempo=microseconds_per_beat, time=0))

# 4. 设置拍号(对应原代码的4/2拍,clocks_per_click=24)
track.append(MetaMessage('time_signature', numerator=4, denominator=2,
                         clocks_per_click=24, notated_32nd_notes_per_beat=8, time=0))

# 5. 设置调号(示例:C大调,对应key=0;小调可加'm',如'Am'或key=-3)
track.append(MetaMessage('key_signature', key='C', time=0))

# 6. 添加音符(note_on和note_off消息组合)
for i, pitch in enumerate(degrees):
    # 计算音符起始和结束的tick时间
    start_tick = (time + i) * ticks_per_beat
    end_tick = start_tick + duration * ticks_per_beat

    # 发送note_on消息(时间差相对于上一条消息)
    track.append(Message('note_on', channel=channel, note=pitch, velocity=volume,
                         time=start_tick - track[-1].time if track else start_tick))
    # 发送note_off消息(时间差为时长对应的tick)
    track.append(Message('note_off', channel=channel, note=pitch, velocity=volume,
                         time=end_tick - start_tick))

# 7. 保存MIDI文件
mid.save('midifile.mid')

关键步骤说明:

  • 创建MIDI对象:MidiFile(type=1)对应MIDI格式1(包含速度轨和音轨,和MIDIUtil默认一致),ticks_per_beat是每拍的脉冲数,默认480,可按需调整。
  • 设置速度:MIDI用微秒/拍作为速度单位,通过60000000 // tempo转换BPM到该单位,用set_tempo元消息添加。
  • 设置拍号:time_signature元消息的参数对应MIDI标准:
    • numerator:拍号分子
    • denominator:分母的2次幂(比如4/4拍填4,3/8拍填3)
    • clocks_per_click:每点击的时钟数,原代码用24直接对应
  • 添加音符:MIDI需要note_on和note_off消息成对出现,time参数是相对于上一条消息的时间差(tick数),所以要计算好时间间隔。
  • 设置调号:key_signature元消息可直接传入调名(如'C'、'G#'、'Am')或数字(0=C大调,-1=F大调,-3=A小调等)。
  • 保存文件:调用mid.save()方法直接保存到指定路径。

内容的提问来源于stack exchange,提问作者Philip Bergwerf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 18:23:32