使用music21读写Groove MIDI鼓组文件时出现内容变更问题
问题分析与解决
你的操作本身语法没问题,但鼓组MIDI属于MIDI通道10(打击乐专用通道),music21默认处理逻辑会忽略打击乐轨道的特殊属性,导致重写后的文件与原文件出现差异,核心原因包括:
- 原Groove MIDI的鼓轨道带有打击乐专属标记,music21解析时可能将其转为普通旋律轨道,丢失轨道类型标识
- 哪怕设置了
quantizePost=False,music21内部对打击乐事件的时间戳、力度参数仍可能做隐性调整 - 原文件的微量化时间偏移(Groove MIDI的核心特性)在写入时被默认对齐到标准节拍
针对鼓组轨道的特殊处理方案
1. 修改代码保留打击乐属性与原始事件
调整解析和写入逻辑,明确保留鼓轨道的专属设置:
from pathlib import Path import music21 file_path = Path("groove/drummer1/eval_session/1_funk-groove1_138_beat_4-4.mid") # 读取时禁用自动量化,强制保留原始事件源数据 stream = music21.converter.parse(file_path, quantizePost=False, forceSource=True) # 遍历轨道,标记鼓组轨道(Groove MIDI鼓轨道默认用MIDI通道9,对应显示的通道10) for part in stream.parts: instr = part.getContextByClass('Instrument') if instr.midiChannel == 9: part.isPercussion = True # 强制锁定打击乐通道,避免music21自动调整 instr.midiChannel = 9 # 写入时保留原始事件顺序,禁用自动对齐 stream.write( "midi", fp="/tmp/test_write.mid", midiTranslateArgs={'preserveEventsOrder': True} )
2. 验证修改效果
重写后在MIDI编辑器中检查:
- 轨道是否被标记为「打击乐轨道」
- 事件的时间偏移、力度参数是否与原文件完全匹配
- MIDI通道是否为10(部分编辑器显示为索引9,属于正常现象)
补充说明
Groove MIDI的鼓文件核心价值是包含人类演奏的微量化偏移,music21默认MIDI写入器会尝试将事件对齐到标准节拍,因此必须通过preserveEventsOrder=True和明确的打击乐标记来保留这些细节。
内容的提问来源于stack exchange,提问作者leleogere
相关产品推荐
相关产品推荐

