Python: 从类型 0 转换为类型 1 midi
Python: Convert from type 0 to type 1 midi
类型 0 midi 文件 (example) 将所有乐器都塞进了一个轨道。
类型 1 midi 文件将乐器分成不同的音轨。
有没有什么好的方法可以把type 0转换成type 1?如果有任何资源可以 运行 这种转换,我很想听听他们的消息!
我是这样处理的。重要的见解是 midi 文件中的 channel
指定发送某些信息的设备端口(例如一些 midi 键盘输入),而 program
是乐器声音(例如锯齿主音,cajun banjo .. .).
这意味着可以创建一个字典,每个语音一个键,以及包含以该语音播放的音符的值列表。时间最初应该存储在全局坐标中(因为在类型 0 文件中,相对时间坐标在所有声部中表示,但我们现在将声部分离到不同的音符列表中)。
然后可以转换回相对时间单位,存储来自输入类型 0 音轨的 bpm 和时间分辨率值,然后呐喊——这是您的类型 1 midi。
from collections import defaultdict
import mido, os
def subdivide_midi_tracks(path):
'''Convert a type 0 midi file to a type 1 midi file'''
m = mido.MidiFile(path) # load the original type-0 midi file
messages = [] # a list of message dicts, one per track
for track in m.tracks:
time = 0 # store time in aggregate units
track_messages = []
for idx, i in enumerate(track):
i = i.dict()
if i.get('time', None): time += i.get('time')
i['time'] = time
track_messages.append(i)
messages.append(track_messages)
# build a dictionary of the events for each channel
d = defaultdict(list) # d[channel_id] = [notes]
for track_idx, track in enumerate(messages):
for i in track:
channel = i.get('channel', -1)
d[channel].append(i)
# covert time units in each program back to relative units
for channel in d:
total_time = 0
for i in sorted(d[channel], key=lambda i: i['time']):
t = i['time']
i['time'] = t - total_time
total_time = t
# create a midi file and add a track for each channel
m2 = mido.MidiFile()
for channel in sorted(d.keys()):
track = mido.midifiles.tracks.MidiTrack()
# add the notes to this track
for note in d[channel]:
note_type = note['type']
del note['type']
# if this is a meta message, append a meta message else a messaege
try:
track.append(mido.MetaMessage(note_type, **note))
except:
track.append(mido.Message(note_type, **note))
m2.tracks.append(track)
# ensure the time quantization is the same in the new midi file
m2.ticks_per_beat = m.ticks_per_beat
return m2
m = midi.load("data/nes/'Bomb_Man's_Stage'_Mega_Man_I_by_Mark_Richardson.mid")
m2 = subdivide_midi_tracks(m.path)
m2.save('whoop.mid')
os.system('open whoop.mid')
类型 0 midi 文件 (example) 将所有乐器都塞进了一个轨道。
类型 1 midi 文件将乐器分成不同的音轨。
有没有什么好的方法可以把type 0转换成type 1?如果有任何资源可以 运行 这种转换,我很想听听他们的消息!
我是这样处理的。重要的见解是 midi 文件中的 channel
指定发送某些信息的设备端口(例如一些 midi 键盘输入),而 program
是乐器声音(例如锯齿主音,cajun banjo .. .).
这意味着可以创建一个字典,每个语音一个键,以及包含以该语音播放的音符的值列表。时间最初应该存储在全局坐标中(因为在类型 0 文件中,相对时间坐标在所有声部中表示,但我们现在将声部分离到不同的音符列表中)。
然后可以转换回相对时间单位,存储来自输入类型 0 音轨的 bpm 和时间分辨率值,然后呐喊——这是您的类型 1 midi。
from collections import defaultdict
import mido, os
def subdivide_midi_tracks(path):
'''Convert a type 0 midi file to a type 1 midi file'''
m = mido.MidiFile(path) # load the original type-0 midi file
messages = [] # a list of message dicts, one per track
for track in m.tracks:
time = 0 # store time in aggregate units
track_messages = []
for idx, i in enumerate(track):
i = i.dict()
if i.get('time', None): time += i.get('time')
i['time'] = time
track_messages.append(i)
messages.append(track_messages)
# build a dictionary of the events for each channel
d = defaultdict(list) # d[channel_id] = [notes]
for track_idx, track in enumerate(messages):
for i in track:
channel = i.get('channel', -1)
d[channel].append(i)
# covert time units in each program back to relative units
for channel in d:
total_time = 0
for i in sorted(d[channel], key=lambda i: i['time']):
t = i['time']
i['time'] = t - total_time
total_time = t
# create a midi file and add a track for each channel
m2 = mido.MidiFile()
for channel in sorted(d.keys()):
track = mido.midifiles.tracks.MidiTrack()
# add the notes to this track
for note in d[channel]:
note_type = note['type']
del note['type']
# if this is a meta message, append a meta message else a messaege
try:
track.append(mido.MetaMessage(note_type, **note))
except:
track.append(mido.Message(note_type, **note))
m2.tracks.append(track)
# ensure the time quantization is the same in the new midi file
m2.ticks_per_beat = m.ticks_per_beat
return m2
m = midi.load("data/nes/'Bomb_Man's_Stage'_Mega_Man_I_by_Mark_Richardson.mid")
m2 = subdivide_midi_tracks(m.path)
m2.save('whoop.mid')
os.system('open whoop.mid')