Python双音轨简谱生成mid音频文件程序代码QZQ

from mido import Message, MidiFile, MidiTrack, MetaMessage

# 简谱音符到 MIDI 音符的映射,包含低音、中音和高音
note_mapping = {
    # 低2音区
    "1..": 34,  # 低2八度的do
    "2..": 36,  # 低2八度的re
    "3..": 38,  # 低2八度的mi
    "4..": 40,  # 低2八度的fa
    "5..": 42,  # 低2八度的sol
    "6..": 44,  # 低2八度的la
    "7..": 46,  # 低2八度的si
        # 低音区
    "1.": 48,  # 低八度的do
    "2.": 50,  # 低八度的re
    "3.": 52,  # 低八度的mi
    "4.": 53,  # 低八度的fa
    "5.": 55,  # 低八度的sol
    "6.": 57,  # 低八度的la
    "7.": 59,  # 低八度的si
    # 中音区
    "1": 60,  # do
    "2": 62,  # re
    "3": 64,  # mi
    "4": 65,  # fa
    "5": 67,  # sol
    "6": 69,  # la
    "7": 71,   # si
    # 高音区
    "1'": 72, # 高八度的do
    "2'": 74, # 高八度的re
    "3'": 76, # 高八度的mi
    "4'": 77, # 高八度的fa
    "5'": 79, # 高八度的sol
    "6'": 81, # 高八度的la
    "7'": 83, # 高八度的si
        # 高2音区
    "1''": 72, # 高2八度的do
    "2''": 74, # 高2八度的re
    "3''": 76, # 高2八度的mi
    "4''": 77, # 高2八度的fa
    "5''": 79, # 高2八度的sol
    "6''": 81, # 高2八度的la
    "7''": 83, # 高2八度的si
    "0": 0    # 表示休止符之类的,这里简单处理
}

# 以字符串形式输入的第一个简谱,音符数字之间没有空格
simple_score_str1 = "00006'6'7'7'1''1''7'7'6'6'3'3'1'1'665'5'4'4'3'4'5'4'4'000004'4'5'5'6'6'7'7'5'5'2'2'4'4'3'3'2'3'4'3'000003'61'3'2'3'61'3'2'3'61'4'3'4'61'4'3'4'4'3'4'4'5'5'6'5'6'3'000003''6'1''3''2''3''6'1''3''2''3''6'1''4''3''4''6'1''4''3''4''4''3''4''4''5''5''6''5''6''3''00001''3'3'4'4'2'2'7'7'2'2'3'3'1'1'6'5'6'1'1'2'2'73'2'3'000001''01''1''2''2''1''7'6'5'5'6'5'3'0000001''1''1''1''2''2''1''7'6'5'5'6'5'6'0000000"
# 以字符串形式输入的第二个简谱,音符数字之间没有空格
simple_score_str2 = "6..3.013.013.0103.00006..0300103.0103.0103.002.06.00406.0406.005..02.007.02.007.02.007.001.005.003003.006..003.0013.0103006..003.0012.06040006.0406.005..02.007.001.17.006..003.0013.0103006..003.0012.06040006.0406.005..02.007.001.17.006..003.0012.0604005..02.007.01.001.005.007..006..03.17..0006..03.17..4.02000"

# 处理第一个简谱字符串,将其转换为音符和时长的列表
simple_score1 = []
i = 0
while i < len(simple_score_str1):
    if simple_score_str1[i].isdigit():
        if i + 1 < len(simple_score_str1) and simple_score_str1[i + 1] in [".", "'"]:
            note = simple_score_str1[i:i + 2]
            i += 2
        else:
            note = simple_score_str1[i]
            i += 1
        simple_score1.append((note, 1))  # 每个音符默认占一拍
    else:
        i += 1

# 处理第二个简谱字符串,将其转换为音符和时长的列表
simple_score2 = []
i = 0
while i < len(simple_score_str2):
    if simple_score_str2[i].isdigit():
        if i + 1 < len(simple_score_str2) and simple_score_str2[i + 1] in [".", "'"]:
            note = simple_score_str2[i:i + 2]
            i += 2
        else:
            note = simple_score_str2[i]
            i += 1
        simple_score2.append((note, 1))  # 每个音符默认占一拍
    else:
        i += 1

mid = MidiFile()

# 第一个音轨
track1 = MidiTrack()
mid.tracks.append(track1)

# 设置第一个音轨的速度为 120 BPM (500000 us per beat)
tempo = 200000
track1.append(MetaMessage('set_tempo', tempo=tempo, time=0))

# 设置第一个音轨的乐器(例如,钢琴,program=0)
track1.append(Message('program_change', program=0, time=0))

# 时间变量,用于计算第一个音轨 MIDI 消息之间的时间间隔
current_time1 = 50

# 遍历第一个简谱,将其转换为 MIDI 消息
for note, duration in simple_score1:
    if note in note_mapping:
        midi_note = note_mapping[note]
        # 音符开启消息
        track1.append(Message('note_on', note=midi_note, velocity=64, time=current_time1))
        current_time1 = 0
        # 音符关闭消息
        track1.append(Message('note_off', note=midi_note, velocity=127, time=duration * 480))  
    else:
        print(f"不支持的音符: {note}")

# 第二个音轨
track2 = MidiTrack()
mid.tracks.append(track2)

# 设置第二个音轨的速度为 120 BPM (500000 us per beat)
track2.append(MetaMessage('set_tempo', tempo=tempo, time=0))

# 设置第二个音轨的乐器(例如,吉他,program=24)
track2.append(Message('program_change', program=24, time=0))

# 时间变量,用于计算第二个音轨 MIDI 消息之间的时间间隔
current_time2 = 50

# 遍历第二个简谱,将其转换为 MIDI 消息
for note, duration in simple_score2:
    if note in note_mapping:
        midi_note = note_mapping[note]
        # 音符开启消息
        track2.append(Message('note_on', note=midi_note, velocity=64, time=current_time2))
        current_time2 = 0
        # 音符关闭消息
        track2.append(Message('note_off', note=midi_note, velocity=127, time=duration * 480))  
    else:
        print(f"不支持的音符: {note}")

mid.save('梦中的婚礼.mid')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EYYLTV

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值