如何修改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
相关产品推荐
相关产品推荐

