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

如何用Music21检测MIDI文件中的转调?现有代码仅识别初始调

检测MIDI文件中的转调方法

你当前用midi_data.analyze('key')得到的是整个MIDI文件的全局调式分析,自然无法识别中途的转调。要检测转调,核心思路是把MIDI文件拆分成更小的片段(比如按小节、按固定时长),对每个片段单独做调式分析,再通过对比片段间的调式变化来定位转调位置。

具体实现步骤(以按小节分割为例)

  1. 解析MIDI文件后,遍历其中的每个小节;
  2. 对每个小节的音乐内容单独进行调式分析;
  3. 记录每个小节的调式,对比相邻小节的调式差异,判断转调发生的位置。

示例代码

import music21 as m21

# 解析MIDI文件
midi_data = m21.converter.parse("your_midi_file.mid")

# 遍历所有小节,记录每个小节的调式
previous_key = None
for idx, measure in enumerate(midi_data.parts[0].measures(1, None)):  # 取第一声部的所有小节
    # 分析当前小节的调式
    current_key = measure.analyze('key')
    # 跳过空小节或调式不明确的情况
    if not current_key:
        continue
    # 对比前一个小节的调式,判断转调
    if previous_key and current_key.name != previous_key.name:
        print(f"在第{idx+1}小节发生转调:从{previous_key.name}转到{current_key.name}")
    previous_key = current_key

# 如果需要全局初始调式,仍可以保留全局分析
global_key = midi_data.analyze('key')
print(f"全局初始调式:{global_key.name}")

优化建议

  • 过滤短暂离调:如果只是单个小节的调式变化,可能是临时离调而非真正转调,可以设置连续2-3个小节调式一致才判定为转调;
  • 按时长分割:如果MIDI没有明确的小节划分,可以用midi_data.splitAtQuarterLength()按固定节拍长度分割片段(比如每4拍一个片段);
  • 多声部合并分析:如果MIDI有多个声部,可以把所有声部的音符合并后再分析片段调式,避免单声部的局部偏差。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 09:51:30