游戏百科

101超酷!用Python写回文音乐,3步搞定你的MIDI创作处女作

回环诗_旋律模进_开嗓音频生成_sequence回忆上次 研究了 回文诗对称 的 文字可以用 列表反转 的 方式进行判断
回环诗_旋律模进_开嗓音频生成_sequence回忆

上次 研究了 回文诗

对称 的 文字

可以用 列表反转 的 方式

进行判断

音符也可以 实现 类似于 回文的效果

卡农螃蟹曲式

能做段 简单的 回文音乐 吗?🤔

怎么 才能 唱出 歌词 呢?

回文开嗓歌

可以下载x-studio

https://xstudio.music.163.com/

具体过程

让 虚拟歌姬 唱歌 应该分两步

在软件中 导入 开嗓旋律 的 mid

然后 右键音符 编辑全部歌词

去 生成mid

哼鸣练习

曲式的对称 很像 回文的对称

配合回文

能用代码 生成这个mid吗?

提示词

ide启动

首先新建文件

m.py

humming

from mido import Message, MidiFile, MidiTrack# 创建一个新的MIDI文件和音轨mid = MidiFile()track = MidiTrack()mid.tracks.append(track)# 定义C4对应的MIDI音符编号c4_note = 60# 定义每个音符的持续时间(这里设为0.5秒,可按需调整)note_duration = 0.5# 定义BPM(每分钟节拍数),控制节奏速度bpm = 120# 计算每拍对应的时间(秒)tick_per_beat = mid.ticks_per_beattime_per_beat = 60 / bpmtime_per_tick = time_per_beat / tick_per_beat# 定义“哆来咪发嗦发咪来哆”对应的音符偏移量# 基于C4(60号音符),在C大调中,各音符偏移量对应关系note_offsets = [0, 2, 4, 5, 7, 5, 4, 2, 0]# 遍历音符偏移量来添加音符事件到音轨for offset in note_offsets:    note_number = c4_note + offset    # 按下音符事件    track.append(Message('note_on', note=note_number, velocity=64, time=0))    # 计算音符持续时间对应的tick数    tick_duration = int(note_duration / time_per_tick)    # 松开音符事件    track.append(Message('note_off', note=note_number, velocity=64, time=tick_duration))# 保存MIDI文件mid.save('warmup.mid')

注意哼鸣练习中的 列表

依然是 回文结构的

下载mid

在线编辑midi

https://midi-to-gcode.bambulab.com/edit

选择 文件-打开

打开 刚下好的mid文件

修改效果

目前是 4/4 拍

以 4分音符 为 1拍

每小节 有 4拍

最后一个小节

只有一个 四分音符

应该是 全音符

时长4拍

独占一个小节

修改

from mido import Message, MidiFile, MidiTrack# 创建一个新的MIDI文件和音轨mid = MidiFile()track = MidiTrack()mid.tracks.append(track)# 定义C4对应的MIDI音符编号c4_note = 60# 定义除最后一个音符外其他音符的持续时间(这里设为0.5秒,可按需调整)note_duration = 0.5# 定义BPM(每分钟节拍数),控制节奏速度bpm = 120# 计算每拍对应的时间(秒)tick_per_beat = mid.ticks_per_beattime_per_beat = 60 / bpmtime_per_tick = time_per_beat / tick_per_beat# 定义“哆来咪发嗦发咪来哆”对应的音符偏移量# 基于C4(60号音符),在C大调中,各音符偏移量对应关系note_offsets = [0, 2, 4, 5, 7, 5, 4, 2, 0]# 遍历音符偏移量来添加音符事件到音轨for i, offset in enumerate(note_offsets[:-1]):    note_number = c4_note + offset    # 按下音符事件    track.append(Message('note_on', note=note_number, velocity=64, time=0))    # 计算音符持续时间对应的tick数    tick_duration = int(note_duration / time_per_tick)    # 松开音符事件    track.append(Message('note_off', note=note_number, velocity=64, time=tick_duration))# 处理最后一个音符(全音符,四拍)last_offset = note_offsets[-1]last_note_number = c4_note + last_offset# 按下最后一个音符事件track.append(Message('note_on', note=last_note_number, velocity=64, time=0))# 全音符时长对应的tick数(四拍)tick_duration_for_last = int(4 * time_per_beat / time_per_tick)# 松开最后一个音符事件track.append(Message('note_off', note=last_note_number, velocity=64, time=tick_duration_for_last))# 保存MIDI文件mid.save('warmup2.mid')

配合

演唱一下

可以让 开嗓midi越开越高吗?

手动过程

先复制一个开嗓 片段

然后将 片段 上移 一个半音

得到 C#大调 的 哼鸣练习

这样 第二段哼鸣 就升高了半音

更多

1段 变 2段

2段 变 4段

4段 变 8段

继续

8段 变 16段

删除 其中3段

还剩 13段

从c开始

到c结束

开嗓

想用代码 实现这个mid

提问

from mido import Message, MidiFile, MidiTrack# 基础参数base_note = 60       # C4的MIDI音符编号(60对应C4)note_offsets = [0, 2, 4, 5, 7, 5, 4, 2, 0]  # 123454321的音程偏移(C大调)bpm = 120ticks_per_beat = 480  # 可自定义MIDI精度time_per_beat = 60 / bpmtime_per_tick = time_per_beat / ticks_per_beatnote_duration = 0.5   # 前8个音符时长(秒),最后一个音为4拍# 生成12个半音调的MIDI文件for transpose in range(13):  # 0(原调)到12(升12半音)    mid = MidiFile(ticks_per_beat=ticks_per_beat)    track = MidiTrack()    mid.tracks.append(track)        # 添加调号(仅为示意,实际MIDI调号需用SysEx信息,此处通过音符移位实现)    current_note = base_note + transpose  # 基础音升高transpose个半音        for i, offset in enumerate(note_offsets):        note_number = current_note + offset        # 音符按下        track.append(Message('note_on', note=note_number, velocity=64, time=0))        # 计算时长(最后一个音为4拍)        if i == len(note_offsets) - 1:            tick_duration = int(4 * time_per_beat / time_per_tick)        else:            tick_duration = int(note_duration / time_per_tick)        # 音符松开        track.append(Message('note_off', note=note_number, velocity=64, time=tick_duration))        # 保存文件(调名对应:C, C#, D, ..., B)    sharps = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B', 'C'][transpose]    mid.save(f'scale_{sharps}_major.mid')    print(f"已生成 {sharps} 大调音阶 MIDI 文件")

文件

生成了好多midi文件

大调 是啥意思?

总结🤔

这次我们 制作了回文音符序列

123454321

要整合成一个

从c开始

到c结束

序列不断升级

可以整合吗?🤔

下次再说 👋