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

如何修改music21代码以仅生成C大调自然音阶范围内的音符(排除升降音)

如何修改music21代码以仅生成C大调自然音阶范围内的音符(排除升降音)

嘿,我来帮你搞定这个问题!你代码里的问题确实出在你标注的那一行——你先给音符指定了C大调自然音的名称,但紧接着又直接随机设置了midi音高,这相当于完全覆盖了之前的名称设置,随机的midi值很容易落到升降音上,自然就出现非自然音阶的音符了。

要解决这个问题,我们应该先明确C大调自然音阶里所有符合你设定的midi范围(60-80)的音高,然后从这个固定的合法音高列表里随机选择,而不是先选名称再乱设midi。

下面是修改后的完整代码,我会给你标注关键的改动:

from music21 import stream, note, pitch, duration, Key  # 新增Key模块导入
import random

def generate_diatonic_notes(num_notes, min_pitch=60, max_pitch=80):
    s = stream.Stream()
    # 1. 创建C大调音阶对象,直接获取该调式下的所有自然音
    c_major = Key('C')
    # 2. 筛选出在指定midi范围内的C大调自然音midi值
    valid_midi_pitches = [p.midi for p in c_major.pitches if min_pitch <= p.midi <= max_pitch]
    
    # 做个兜底判断,避免没有符合条件的音高时出错
    if not valid_midi_pitches:
        print("没有符合范围的C大调自然音,请调整min_pitch和max_pitch参数")
        return s

    for _ in range(num_notes):
        n = note.Note()
        # 3. 直接从合法的midi列表里随机选值,保证都是C大调自然音
        selected_midi = random.choice(valid_midi_pitches)
        n.pitch.midi = selected_midi
        print(n.pitch)  # 现在打印的都是C大调自然音,比如C4、D4等,不会有C#4了
        n.duration = duration.Duration('eighth')
        s.append(n)
    return s

diatonic_notes_stream = generate_diatonic_notes(num_notes=20)

关键改动说明:

  • 新增了Key模块的导入,用它来直接获取C大调的自然音体系,不用自己手动列音名(手动列容易出错,而且music21的调式对象更可靠)
  • 先预先生成所有符合midi范围的C大调自然音midi值列表,后续只从这个列表里随机选择,从根源上避免了升降音
  • 移除了原来先设置n.name再覆盖midi的无效操作,现在直接通过合法midi值生成音符,音名会自动对应正确的自然音

这样修改后,你生成的midi文件里就只会有C大调自然音阶的音符,再也不会出现升降音啦!

备注:内容来源于stack exchange,提问作者tubos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.17 09:54:40