pip install mido
使用 mido
库可以方便地处理 MIDI 文件,提取其中音轨的音乐数据。
1.下面的程序会读取指定的 MIDI 文件,并提取指定编号音轨的音乐数据,主要包括音符事件等信息。
编写 mido_extract.py 如下
# -*- coding: utf-8 -*-
""" 用 mido 提取 midi文件中某一音轨的音乐数据 """
import os
import sys
from tkinter import filedialog
import mido
def extract_track_data(midi_file, track_no):
try:
track_data = []
tracks = midi_file.tracks
for i,track in enumerate(tracks):
print(f"Track {i}: {track.name}")
if track_no < len(tracks):
track = tracks[track_no]
for msg in track:
if msg.type in ['note_on', 'note_off', 'control_change', 'program_change']:
track_data.append(msg)
else:
print(f"音轨编号 {track_no} 超出范围,该MIDI文件共有 {len(tracks)}条音轨。")
return track_data
except:
print(" 无法读取MIDI文件.")
return None
def write_track_to_midi(track_data, output_file_path, original_mid):
new_mid = mido.MidiFile(ticks_per_beat=original_mid.ticks_per_beat)
new_track = mido.MidiTrack()
for msg in track_data:
new_track.append(msg)
new_mid.tracks.append(new_track)
new_mid.save(output_file_path)
# main()
if len(sys.argv) ==1:
filetypes = [('mid file','.mid')]
f1 = filedialog.askopenfilename(initialdir='D:/Music', filetypes=filetypes)
elif len(sys.argv) ==2:
f1 = sys.argv[1]
else:
print('usage: python mido_extract.py file1.mid')
sys.exit(1)
if not os.path.exists(f1):
print(f"{f1} is not exists.")
sys.exit(2)
fn,ext = os.path.splitext(f1)
if ext.lower() != '.mid':
print('ext is not .mid ')
sys.exit(2)
midi_file_path = f1 # 替换为实际的MIDI文件路径
x = 1 # 替换为想要提取的音轨编号,从0开始
output_file_path = f"track_{x}.mid" # 替换为输出的MIDI文件路径
try:
original_mid = mido.MidiFile(midi_file_path)
data = extract_track_data(original_mid, x)
if data:
write_track_to_midi(data, output_file_path, original_mid)
print(f"已成功将track {x} 数据写入 {output_file_path}")
except mido.MidiFileError:
print(f"无法读取MIDI文件 {midi_file_path}")
运行 python mido_extract.py moon_river.mid
生成 track_1.mid
上述代码中,extract_track_data
函数负责提取指定音轨的数据,write_track_to_midi
函数则将提取的数据写入新的 MIDI 文件。你需要把midi_file_path
换成原始 MIDI 文件路径,track_number
设为目标音轨编号,output_file_path
指定输出文件路径。
2.下面的代码会复制保留原 MIDI 文件中 Track 0
的全部信息,同时提取 Track 1
的音乐数据,然后将它们合并到一个新的 MIDI 文件中。
编写 mido_extract1.py 如下
# -*- coding: utf-8 -*-
""" 用 mido 复制保留 Track 0 全部信息,提取 Track 1 音乐数据 """
import mido
def copy_track0_and_extract_track1(midi_file_path, output_file_path):
try:
# 读取原 MIDI 文件
original_mid = mido.MidiFile(midi_file_path)
if len(original_mid.tracks) < 2:
print("MIDI 文件中没有足够的音轨(至少需要 2 条音轨)。")
return
# 创建新的 MIDI 文件,复制原文件的 ticks_per_beat
new_mid = mido.MidiFile(ticks_per_beat=original_mid.ticks_per_beat)
# 复制 Track 0 到新的 MIDI 文件
new_mid.tracks.append(original_mid.tracks[0])
# 提取 Track 1 的音乐数据
track1 = original_mid.tracks[1]
track1_data = []
for msg in track1:
if msg.type in ['note_on', 'note_off', 'control_change', 'program_change']:
track1_data.append(msg)
# 创建新的音轨并添加 Track 1 的数据
new_track1 = mido.MidiTrack()
for msg in track1_data:
new_track1.append(msg)
new_mid.tracks.append(new_track1)
# 保存新的 MIDI 文件
new_mid.save(output_file_path)
print(f"已成功将 Track 0 信息和 Track 1 数据写入 {output_file_path}")
except mido.MidiFileError:
print(f"无法读取 MIDI 文件 {midi_file_path}")
if __name__ == "__main__":
midi_file_path = "your_midi_file.mid" # 替换为实际的 MIDI 文件路径
output_file_path = "new_midi_file.mid" # 替换为输出的 MIDI 文件路径
copy_track0_and_extract_track1(midi_file_path, output_file_path)
代码说明:
- 读取原 MIDI 文件:使用
mido.MidiFile
读取指定路径的 MIDI 文件。 - 检查音轨数量:确保 MIDI 文件中至少有 2 条音轨。
- 创建新的 MIDI 文件:使用原文件的
ticks_per_beat
创建新的 MIDI 文件。 - 复制 Track 0:将原文件的
Track 0
直接添加到新的 MIDI 文件中。 - 提取 Track 1 数据:遍历
Track 1
,提取note_on
、note_off
、control_change
和program_change
类型的消息。 - 创建新音轨并添加数据:创建一个新的音轨,并将提取的
Track 1
数据添加到该音轨中,然后将该音轨添加到新的 MIDI 文件中。 - 保存新的 MIDI 文件:将新的 MIDI 文件保存到指定的输出路径。
你需要将 midi_file_path
替换为实际的 MIDI 文件路径,将 output_file_path
替换为你希望保存的新 MIDI 文件的路径。