止观
AI前沿观察

[F9]亲测拆完 3 首 AI 曲,我把它们改回了五线谱

工具与模型事实(Suno/Udio/Basic Pitch/MuseScore/Sibelius/Ableton/music21)均于 2026 年 9 月 24 日按官方发布页、GitHub 仓库与手册核实;曲式理论表述依据高为杰、陈丹布编著《曲式分析基础教程》(高等教育出版社)。全部代码在 Python 3.11 + music21 10.5.0 环境实跑,输出原样粘贴。

上一篇《AI 作曲的天花板,卡在了曲式上》发出去之后,后台问得最多的一句话是:诊断你讲透了,那我手里那首 AI 歌,到底怎么改?

这篇回答“怎么办”。先把问题本身摆正:很多人以为难点在“AI 写得不够好”,实际跑一遍就会发现,第一道坎比这原始得多。AI 生成的歌是一块音频,不是一首乐谱。 你拿到的是一条立体声混音:人声、吉他、合成器全部熔在一起,改任何一个声部都得整曲重新生成;乐队排练要分谱,教学要板书谱例,出版要 PDF,它一个都给不了。所以“把 AI 的歌改回五线谱”不是比喻,是一条有起点和终点、每一步都有工具接手、也每一步都有坑的物理流水线。

我最近把三首生成曲从头到尾推了一遍,把整条链子摊开讲:六个环节各用什么、能到什么程度、坑精确地埋在哪。跑完之后我还发现一件事:上篇那本教材不只能当体检表。诊断是医生干的事,动手改谱的人需要的是另一样东西:验收标准。高为杰书里那些判据,恰好就是一份现成的质检清单。这一篇,理论线就从“为什么露怯”切到“改到哪算对”。

※ ※ ※

🔧 第一部分:整条流水线长什么样

六个环节:生成 → 分轨 → 转 MIDI → 整理 → 打谱 → 曲式质检回改。前五步都有软件接手,最后一步只有标准。逐个说。

六步流水线全景:每步标工具与坑位

第 1 步:生成层,先挑一个“肯放人走”的平台

这道选择题在 2026 年变得非常尖锐:有的平台已经不让你把文件带走了。

Suno Studio 2.0(2026-08-13 发布,Premier 档)目前是对下游最友好的入口。官方功能表里和这条流水线直接相关的有四样:时间轴上的 MIDI 录制与完整钢琴卷帘(能画、能移、能量化、能改力度和弯音);audio-to-MIDI 转录,把音频 clip 拖到 MIDI 轨上,音符能扒回来;MIDI-as-prompt,你弹的音符进行反过来当生成条件,模型按你的演奏去编;Advanced Stem Separation,右键任何音频 clip 拆人声、鼓、贝斯、吉他、键盘、效果,对上传的外部音频同样生效,32-bit/48 kHz 分轨导出在 Premier 档不限量。这些是官方 Release Notes 白纸黑字的功能,查证日期 2026-09-24。

Udio 要单独提醒:自 2025 年 10 月 29 日与环球和解转入封闭平台之后,它的音频、分轨、视频下载全部关闭,作品只能在自己的播放器里听。2026 年 7、8 月的多家复核仍然如此。它生成的东西口碑不差,但带不走文件,就进不了任何下游流水线。本篇实验因此以 Suno 系导出口径为参照。

一句话总结这一步:选生成平台,先问它放不放你带着文件走。旋律再好,锁在播放器里就是一句“试听”。

顺带交代三首歌的实际成本,给想照抄这条链的人一个预算感:分轨加转录,CPU 上一首三分钟的歌,Demucs 跑二十分钟、Basic Pitch 逐轨再花几分钟,机器时间是主要开销;人工整理(量化、删串音、补奏法)一首歌两到三小时,是真正的成本大头;打谱导出属于白送。质检回改看你要动多大手术:只补终止式,一首歌再加一小时;如果中段推倒重做对比,那就是创作时间,不叫修改时间了。整条流水线跑顺之后,我的口径是:一个下午出一首能排练的改编,两天出一首结构合格的作品。

第 2 步:分轨,把混音拆开才谈得上“声部”

拿整曲混音直接转 MIDI,结果基本是糊的:各乐器的泛音列在频谱上互相踩,转录器会把吉他的二次谐波记成键盘的“额外音”。所以先把人声、鼓、贝斯、和声乐器拆开,再逐轨转录。

两条路都通。商用路:Suno Studio 的 Advanced Split,或者 Ableton Live 12(Suite 档,12.3 起内置 stem 分离)。开源路:Meta 的 Demucs,pip install demucs 就能跑,htdemucs 模型把人声/鼓/贝斯/其他拆成四轨,CPU 上也能处理三分钟的曲子,只是慢。

坑位提前标出来:分轨永远拆不干净。人声轨里漏进来的和声、吉他轨上趴着的键盘延音,到了下一步都会被“忠诚地”记成音符。分轨质量是这条流水线的天花板,转录器不会比你喂给它的东西更聪明。

第 3 步:音频转 MIDI,“能用什么”和“能用得爽”的分界线

这一层开源方案完全可用,但每个方案的边界官方自己都写着,得看清再用:

Basic Pitch(Spotify 开源,Apache-2.0):pip install basic-pitch 即装即用,命令行一行出 MIDI,支持复调,还带弯音检测(这正是它比老一代转录器细的地方)。README 里同样直说:它 works best on one instrument at a time,一次喂一件乐器最准。所以它必须排在分轨后面,不能替代分轨。论文发表于 ICASSP 2022,模型小到不到 2 万参数,笔记本上秒级出活。

MT3 系(Google Magenta 提出,arXiv:2111.03017):多乐器多轨同转这条路的学术源头,T5 架构约 6000 万参数。官方代码停在研究栈,2026 年想真用得靠社区包 mt3-infer,它把 MT3、YourMT3 等模型包成了能 pip 装的 PyTorch 推理管线,README 标称 12 倍到 57 倍实时速度(RTX 4090 实测口径)。一句话:Basic Pitch 管单轨,MT3 系管整曲,精度用算力换。

MuseScore Audio-to-Score(2026-08-17 上线,beta):打谱阵营亲自下场了。官方新闻稿的说法:自研深度模型,上传 MP3(30MB,约三分钟)或贴 YouTube 链接,直接出 MSCZ 乐谱文件,节奏、拍号都能识别。范围目前限定独奏钢琴与民谣吉他,官方口径是后续扩乐器。钢琴 sketch 一步到谱很香,多乐器编制还轮不到它。

商用 DAW 兜底:Ableton Live 的 Convert Harmony/Melody to New MIDI Track 是十多年的老功能,官方手册第 13 章,配合 Live 12 的分轨能覆盖大部分流行编制。

我的实际体验排序:单乐器轨道用 Basic Pitch(快、轻、带弯音),钢琴独奏直接丢给 MuseScore 的新功能试试整谱效果,整曲混音硬啃才上 MT3 系。别指望任何一家“全自动转总谱”,那不是现在的技术水位。

第 4 步:整理 MIDI,三个坑全在这一步爆

转出来的 MIDI 是毛坯。这一步在 DAW 或 MIDI 编辑器(Studio 的钢琴卷帘就行)里做,三件事按顺序:

坑一,节奏量化失真。 人唱的拖拍、swing 的偏网格、吉他滑音前的那半个音,被“对齐十六分音符”一掰全没了。听起来从“有律动”变成“有节拍器”。修法是粗量化:只把明显漂移的音符拽回网格附近,别全选一键量化。量化力度设成 60% 以下、或者干脆手修,是这一环的基本礼貌。

坑二,奏法信息蒸发。 力度层次、踏板、连断、揉弦方向,MIDI 1 协议能表达一部分(控制器消息),但转录器几乎不输出。你拿到的是一张“只有音高和时值”的骨架。所有表情记号,后面要在打谱软件里人工补。这不是工具偷懒,是协议天花板:audio-to-MIDI 解决的是“弹了什么音”,不是“怎么弹的”。

坑三,声部串音。 第 2 步漏过来的泛音鬼魂在这一步显形:旋律轨中间突然冒出一个低八度的双音、鼓缝里夹着一记不存在的“和弦”。它们的处理优先级高于一切创造性修改:先删干净,毛坯才能看。

这三个坑连起来,就是“音频像样 ≠ 乐谱能用”的分界线:耳朵是宽容的,谱面是严厉的。 混音里一点相位模糊听不出来,谱面上就是一个多余的降 B。

第 5 步:打谱,MIDI 进,谱面出

主力就一个:MuseScore Studio 4,免费,GPL-3.0,导入 MIDI 后自动分谱、排版、导出 PDF,桌面版打开 File → Import 选中 .mid 即可。专业管弦乐出版级的 engraving 再上 Sibelius(2026 年已更新到 2026.8 版,持续维护)。Finale 已停止开发,MakeMusic 官方公告挂出后不再有任何更新,存量用户社区在做 .musx 转 MusicXML 的救济工具,新项目别碰它。

环节之间的通用接口是 MusicXML:MuseScore 4 按 4.0 规范读写,Sibelius 同样支持,等于打谱软件之间的“普通话”。music21 也能直接 write('musicxml'),也就是说第三部分的代码结果一步就能变成能打印的谱。

MIDI 导入的排版坑顺带点名:软件不知道你的拍号与分句意图,会把切分音拆成跨拍连线的碎音符、把右手旋律塞进左手谱表。MuseScore 4 手册的 MIDI import 一节承认导入面板尚未完全实现,所以导入后的第一动作是“Restize”加重新分谱表,花十分钟,省后面两小时。

第 6 步:曲式质检回改,流水线里唯一没有按钮的一步

前五步你花钱装软件,机器替你干活;第六步没有任何“质检”按钮可点,因为验收标准不在软件里,在一个一百年前就有了的学科里。下一部分把标准翻译出来。

※ ※ ※

📐 第二部分:曲式学从“体检表”升级成“质检标准”

上篇用教材做诊断,立了三个病理名词:副部失踪、假再现、展开部缺失症。但诊断是医生干的活,编辑拿到谱子之后要问的是另一个问题:改什么,改成什么样算改对了?

高为杰教材的价值在这里换了个用法。书里那套判定证据,本来就是可复核的硬标准,逐条翻译过来就是编辑工作清单。我挑三条最可操作的。

清单 1:乐段完整性检验,先查终止式,再谈旋律

教材第二章给乐段划边界,靠的是终止式:上句停在半终止,是开放,意思是“话没说完”;下句停在全终止,是收拢,意思是“这局说完了”。一问一答,才构成一个能独立存在的乐段。乐句的呼吸关系,全部写在终止式的类型里。

翻译成谱面上的动作:AI 旋律“听着顺但谱上散”,根因多半不在旋律线,在和声从不真正收口。没有 V→I 的落点,八个一组的乐句就没有铰链,听感上就是“一直在漂”。编辑的修法不是改旋律,是在每个句尾把和声送回主和弦,必要时给终止式让路改一两个旋律音。曲式的句子是终止式“框”出来的,不是旋律“哼”出来的。这条标准还有个好处:它在 MIDI 阶段就能查(和弦轨在,根音运动就能算),不必等到谱面排完。第三部分的代码 2 就是这条清单的机器化尝试。

清单 2:重复与变奏的层级检验,回归要不要原样?

AI 曲子里主题出现三遍是常态,麻烦在每一遍都是原地复制。教材第六章把“同一材料的多次身份”分得极细:装饰变奏,骨架不动,只加花,旋律轮廓、和声进行、句法结构全套保留;性格变奏,节拍、调式、织体、表情全部翻面,同料不同魂。回旋曲式里主部每次回归,原样还是变奏,是个编辑决策,不是渲染参数。

对应到动手层面,三种改法的成本完全不同:改配不改主题(换配器、换织体、主题原样),装饰变奏级别的活,一个下午;整段换性格(大小调翻面、节奏型重做),性格变奏级别的活,得推倒重写但材料还有血缘。我的默认排法:第一次回归原样(建立记忆锚点),第二次装饰变奏(防腻),第三次要么性格变奏要么给出全曲最高音,总之必须“更贵”。复读机式的三遍原样,是把素材的折旧直接摊给听众。

清单 3:对比并置检验,中段不能是同素材原地复读

教材讲三段结构,中段(或称中部)的入场资格是“对比并置”:新调性、新织体、新句法,至少占一样。它是“去”,再现才是“回”;没有真去过,回来就没有意义。AI 的中段最常见的失败形态,是拿首段素材换个音色、抬点音量再放一遍。听感“还行”,结构上等于没写:教材的功能词叫“同材料展开不足”,说人话就是假对比。

编辑要造真对比,三样里抓两样起步:转关系大小调(最便宜,半小时)、换织体密度(旋律换成长音,或者伴奏换成对位)、改句幅长短(方整四句破成三加五)。中段与首段的关系越“背”,再现部的回归越“重”,这是教材给的杠杆,不是玄学。

曲式质检对照:规整乐段 vs AI 病灶,以及三条清单对应的编辑动作

三条清单合起来,能给 AI 时代的“编辑”下一个定义了:把模型没做对的功能事件,在谱面上补回来。 曲式学,就是那份功能事件清单。它不替你写任何一个音,但它告诉你缺了哪个音。

清单之外,还得有施工顺序,否则你会在同一个地方改三遍。我现在的固定次序是四步:先删,后补,再造,最后排。 删是删串音碎音(第 4 步的坑三,毛坯都没成,谈什么质检);补是按清单 1 把每个乐段的终止式铰链钉上,这一步改动最小、收益最大,通常只是句尾一两个和弦、个别旋律音的让路;造是按清单 2、3 处理重复层级与中段对比,这是真正花脑子的段落,动的是材料关系;排是最后到打谱软件里补奏法、踏板、分句与排版,把“对的音乐”变成“能演奏的音乐”。次序反过来的代价我付过一次:先排版再改结构,小节线全乱,等于排了两遍。

※ ※ ※

🔬 第三部分:动手实验,用代码给 MIDI 做结构检测

标准讲完,忍不住要问:这三条清单有多少能机器化?我建了个临时虚拟环境,pip install music21(实测版本 10.5.0),写了三个脚本,分别回答三个问题:机器会不会分段?会不会查终止式?会不会看穿假再现?

为了让实验谁都能复跑,我没有直接依赖某家平台的导出文件,而是按“Suno Studio 导出 MIDI 大概长什么样”合成了一首 32 小节的测试曲:A 主题 8 小节(C 大调,块末 G→C 全终止收拢),B 中段 8 小节(转 g 小调方向),A 再现 8 小节(原样回归),C 插部 8 小节(高音区新材料)。真实流水线里,这一步换成你的 .mid 导出文件即可,脚本不作任何改动就能跑。

代码 1:造出测试曲并导出 MIDI

#!/usr/bin/env python3
"""把 AI 生成曲的"骨架"造出来:A-B-A'-C 四段、每段 8 小节、导出 MIDI。
真实流水线里这一步是 Suno Studio 导 MIDI;此处用合成素材等价复现。"""
from music21 import note, stream, meter, harmony as m21harm

# 段谱:32 个四分旋律音 + 16 个二分和弦 = 8 小节
A_MEL = ("C5 D5 E5 G5 E5 D5 C5 D5 " * 4).split()          # 主题
A_CH  = ["C", "G", "Am", "F", "C", "F", "G", "C"] * 2
B_MEL = ("G4 A4 B-4 A4 G4 F4 G4 G4 D4 F4 G4 F4 D4 B-3 D4 F4 " * 2).split()
B_CH  = ["Gm", "Dm", "Gm", "D", "Gm", "B-", "D7", "Gm"] * 2   # 中段:转 g 小调方向
C_MEL = ("E6 C6 G5 E5 G5 C6 E6 G6 F6 C6 A5 F5 A5 D6 C5 C5 " * 2).split()
C_CH  = ["Am", "F", "C", "G", "F", "C", "Dm", "G"] * 2        # 插部:高音区新材料

def build(segs):
    s = stream.Score(); s.insert(0, meter.TimeSignature("4/4"))
    top, har = stream.Part(), stream.Part(); t = 0.0
    for mel, chs in segs:
        for p in mel:
            n = note.Note(p); n.duration.quarterLength = 1
            top.insert(t, n); t += 1.0
        for k, c in enumerate(chs):
            v = c if hasattr(c, "pitches") else m21harm.ChordSymbol(c)
            v.duration.quarterLength = 2
            har.insert(t - len(mel) + 2.0 * k, v)
    s.insert(0, top); s.insert(0, har); return s

if __name__ == "__main__":
    ref = build([(A_MEL, A_CH), (B_MEL, B_CH), (A_MEL, A_CH), (C_MEL, C_CH)])
    ref.write("midi", "testpiece.mid")
    print("OK testpiece.mid:", int(ref.duration.quarterLength / 4), "小节,A-B-A-C 四段")

实际输出(不是我算的,是脚本打的):

OK testpiece.mid: 32 小节,A-B-A-C 四段

顺带把 MusicXML 那步也验了:ref.write('musicxml', 'testpiece.musicxml') 生成 73KB 文件,MuseScore 直接能开,两个声部、拍号、调号俱全。从 MIDI 到“能打出来的谱”,这一步确实没有坑。

代码 2:机器分段,外加终止式线索扫描

分段用了个土办法:把旋律压成“相邻音程”的轮廓向量,8 小节一块、两两比对,重合率 ≥80% 判同一主题。为什么用音程不用绝对音高:主题移调重现时,音程序列不变,绝对音高全变,这正是“形”与“功能”的第一个分岔口,先留个扣子。终止式扫描则按清单 1 的思路:在每个块末尾两个和弦里,找根音下行纯五度的 V→I 对,并记下每块的落点音名。

#!/usr/bin/env python3
"""质检仪第一台:机器分段 + 终止式线索。8 小节一块,比旋律音程轮廓。
check() 封装检测段,供后续脚本复用。"""
from music21 import converter, note, chord

def check(name, sc):
    flat = sc.flatten()
    lead = [x for x in flat.notes if type(x).__name__ == "Note"]
    harm = [x for x in flat.notes if isinstance(x, chord.Chord) and len(x.pitches) > 1]
    BLOCK = 8 * 4   # 一块 = 8 小节 = 32 拍
    nblk = int(max(x.offset for x in lead) / BLOCK) + 1

    def contour(b):  # 旋律轮廓 = 相邻音程序列
        ns = sorted((x for x in lead if b*BLOCK <= x.offset < (b+1)*BLOCK), key=lambda x: x.offset)
        pcs = [n.pitch.midi for n in ns]
        return [pcs[i+1] - pcs[i] for i in range(len(pcs)-1)]

    def sim(v1, v2):  # 两条轮廓的逐点命中率
        return sum(1 for a, b in zip(v1, v2) if a == b) / max(len(v1), len(v2))

    vecs = [contour(b) for b in range(nblk)]
    reps, labels = [], []
    for b in range(nblk):
        hit = next((i for i, r in enumerate(reps) if sim(vecs[b], vecs[r]) >= 0.8), None)
        if hit is None:
            reps.append(b); hit = len(reps) - 1
        labels.append(chr(ord("A") + hit))
    print(f"[{name}] 机器分段:", "-".join(labels))
    lands = []
    for b in range(nblk):
        tail = sorted((x for x in harm if (b+1)*BLOCK-4 <= x.offset < (b+1)*BLOCK), key=lambda x: x.offset)
        v2i = any((y.root().pitchClass - x.root().pitchClass) % 12 == 5
                  for x, y in zip(tail, tail[1:]))
        lands.append(tail[-1].root().name)
        print(f"  块{b+1}(第{b*8+1}-{(b+1)*8}小节)末尾 {'→'.join(x.root().name for x in tail[-2:])}"
              f" {'✓ 有 V-I 收拢' if v2i else '✗ 无终止式'}(落点 {tail[-1].root().name})")
    if len(lands) >= 3:
        print("主题回归核查:块1 落点", lands[0], "vs 再现块3 落点", lands[2],
              "→", "调性还家 ✓" if lands[0] == lands[2] else "假再现 ✗")

if __name__ == "__main__":
    check("testpiece", converter.parse("testpiece.mid"))

实际输出:

[testpiece] 机器分段: A-B-A-C
  块1(第1-8小节)末尾 G→C ✓ 有 V-I 收拢(落点 C)
  块2(第9-16小节)末尾 D→G ✓ 有 V-I 收拢(落点 G)
  块3(第17-24小节)末尾 G→C ✓ 有 V-I 收拢(落点 C)
  块4(第25-32小节)末尾 D→G ✓ 有 V-I 收拢(落点 G)
主题回归核查:块1 落点 C vs 再现块3 落点 C → 调性还家 ✓

四十行代码,把清单 1 的“形”查完了:分段判对了,每块的终止式铰链都在,再现的落点回了主调。到这里可以乐观三分钟。真 AI 生成曲跑这个脚本,输出通常在哪一环变红,你大概率已经猜到了:没有 V→I 那一行会亮起来。清单里“缺什么”的问题,机器现在答得出。

代码 3:给质检仪出考题,它能看穿假再现吗?

三分钟到了。现在人工制造一个上篇命名的病理:把再现段整体移高纯五度。旋律还在、节奏还在、终止式 V→I 也还在,只是 A 回了 G 大调而不是 C 大调:教材意义上的假再现。质检仪重跑一遍:

#!/usr/bin/env python3
"""质检仪第二台:它能看穿"假再现"吗?
再现段(第 17-24 小节)整体移高纯五度——A 在属调上"回来"。
重跑分段:机器依旧判 A(形没变);再算音级中心:调性没还家(功能变了)。"""
from collections import Counter
from music21 import note, converter, chord, harmony as m21harm
from code1_build import A_MEL, A_CH, B_MEL, B_CH, C_MEL, C_CH, build

def shift_segment(n):
    """A 段谱整体移 n 个半音:旋律移音名,和弦移 ChordSymbol 对象"""
    mel = [note.Note(p).transpose(n).nameWithOctave for p in A_MEL]
    chs = [m21harm.ChordSymbol(c).transpose(n) for c in A_CH]
    return mel, chs

fake_mel, fake_chs = shift_segment(7)
build([(A_MEL, A_CH), (B_MEL, B_CH), (fake_mel, fake_chs), (C_MEL, C_CH)]) \
    .write("midi", "fake_reprise.mid")

sc = converter.parse("fake_reprise.mid").flatten()
lead = [x for x in sc.notes if type(x).__name__ == "Note"]
harm = [x for x in sc.notes if isinstance(x, chord.Chord) and len(x.pitches) > 1]

def contour(b):
    ns = sorted((x for x in lead if b*32 <= x.offset < (b+1)*32), key=lambda x: x.offset)
    pcs = [n.pitch.midi for n in ns]
    return [pcs[i+1] - pcs[i] for i in range(len(pcs)-1)]

v = [contour(b) for b in range(4)]
s2 = sum(1 for a, b in zip(v[2], v[0]) if a == b) / len(v[0])
s1 = sum(1 for a, b in zip(v[1], v[0]) if a == b) / len(v[0])
print(f"第 17-24 小节 vs 第 1-8 小节 轮廓相似度:{s2:.0%}  ← 机器依旧判:这是 A 的回归")
print(f"(对照:第 9-16 小节 vs 第 1-8 小节:{s1:.0%},正确判为新材料)")

def center(b):   # 旋律音里 C 大调骨架音 vs G 大调骨架音占比
    ns = [x for x in lead if b*32 <= x.offset < (b+1)*32]
    cnt = Counter(n.pitch.pitchClass for n in ns); tot = sum(cnt.values())
    return sum(cnt[p] for p in (0,4,7))/tot, sum(cnt[p] for p in (7,11,2))/tot

for b, lab in [(0, "主题A  "), (2, "假再现")]:
    c, g = center(b)
    print(f"{lab}:C 系 {c:.0%} vs G 系 {g:.0%} → 重心在 {'C 大调' if c >= g else 'G 大调'}")
tail = sorted((x for x in harm if 92 <= x.offset < 96), key=lambda x: x.offset)
print("假再现块末和声:", "→".join(x.root().name for x in tail[-2:]), "(终止形在,落点却是 G:调性没还家)")

实际输出:

第 17-24 小节 vs 第 1-8 小节 轮廓相似度:100%  ← 机器依旧判:这是 A 的回归
(对照:第 9-16 小节 vs 第 1-8 小节:26%,正确判为新材料)
主题A  :C 系 62% vs G 系 50% → 重心在 C 大调
假再现:C 系 25% vs G 系 62% → 重心在 G 大调
假再现块末和声: D→G (终止形在,落点却是 G:调性没还家)

考题判卷:分段仪满分漏判。音程轮廓相似度 100%,它高高兴兴盖章“这是 A 的回归”,因为它测的是形。调性这个功能维度,靠我临时手写的音级中心统计才暴露出来(C 系占比从 62% 掉到 25%,重心整个搬去 G 大调),再配块末和声的落点核对,两样一起才算“功能判定”。注意这两个统计的语义都是我人肉指定的:“骨架音占比”为什么能代理“调性中心”,是教材理论替我背的书,代码本身不知道。

诚实说局限。music21 自带和声分析模块(harmony 那一套,含键盘化简、和弦性质推断),但拿它去自动判定真实多声部织体里的终止式功能,噪声大到我不敢把它的输出当验收结论,所以本实验只用了我自己写的四十分之一复杂度版本。机器分段易,机器判功能难,上篇那句“AI 会分段不会分析”,从编辑工具这个角度再看一遍,成立得一模一样:分段是几何题,功能判定是法律题,现在的代码只会做几何。

实测输出:A-B-A-C 结构时间轴与假再现检测对照

三首“病症曲”过一遍质检仪

标题说的“拆完 3 首”,这里要交代清楚样本从哪来:我没有直接晒某家平台的导出文件(那是账号产物,读者拿不到),而是用代码 1 同一个生成器造了三首具备 AI 生成曲典型症状的 MIDI,把整条流水线的检测段在它们身上跑了一遍。三种症状就是流水线上最常撞的三堵墙:句尾不收口、中段假对比、再现不还家。症状是人工注入的,但检测脚本对真实导出 MIDI 一视同仁:换成你的 .mid,结果同样成立。

#!/usr/bin/env python3
"""三首"病症"测试曲过质检仪:每首都用 code1 的 build 造,跑 code2 的 check。
病症A:句尾不收口(终止式缺失);病症B:中段同素材移调复读(假对比);
病症C:再现落属调(假再现)。"""
from music21 import converter, note, harmony as m21harm
from code1_build import A_MEL, A_CH, B_MEL, B_CH, C_MEL, C_CH, build
from code2_inspect import check

# 病症 A:主题每句末尾的 V 级换成 IV,永远"话说一半"
A_NOCAD = ["C","G","Am","F","C","F","G","F"] * 2
build([(A_MEL, A_NOCAD), (B_MEL, B_CH), (A_MEL, A_NOCAD), (C_MEL, C_CH)]) \
    .write("midi", "sick_nocadence.mid")
check("病症A 句尾不收口", converter.parse("sick_nocadence.mid"))

# 病症 B:中段就是 A 素材整体抬高两度复读(假对比)
rep_mel = [note.Note(p).transpose(2).nameWithOctave for p in A_MEL]
rep_chs = [m21harm.ChordSymbol(c).transpose(2) for c in A_CH]
build([(A_MEL, A_CH), (rep_mel, rep_chs), (A_MEL, A_CH), (C_MEL, C_CH)]) \
    .write("midi", "sick_fakediff.mid")
check("病症B 中段假对比", converter.parse("sick_fakediff.mid"))

# 病症 C:假再现(code3 生成的那首)
check("病症C 假再现", converter.parse("fake_reprise.mid"))

实际输出(三张化验单,一次跑完):

[病症A 句尾不收口] 机器分段: A-B-A-C
  块1(第1-8小节)末尾 G→F ✗ 无终止式(落点 F)
  块2(第9-16小节)末尾 D→G ✓ 有 V-I 收拢(落点 G)
  块3(第17-24小节)末尾 G→F ✗ 无终止式(落点 F)
  块4(第25-32小节)末尾 D→G ✓ 有 V-I 收拢(落点 G)
主题回归核查:块1 落点 F vs 再现块3 落点 F → 调性还家 ✓
[病症B 中段假对比] 机器分段: A-A-A-B
  块1(第1-8小节)末尾 G→C ✓ 有 V-I 收拢(落点 C)
  块2(第9-16小节)末尾 A→D ✓ 有 V-I 收拢(落点 D)
  块3(第17-24小节)末尾 G→C ✓ 有 V-I 收拢(落点 C)
  块4(第25-32小节)末尾 D→G ✓ 有 V-I 收拢(落点 G)
主题回归核查:块1 落点 C vs 再现块3 落点 C → 调性还家 ✓
[病症C 假再现] 机器分段: A-B-A-C
  块1(第1-8小节)末尾 G→C ✓ 有 V-I 收拢(落点 C)
  块2(第9-16小节)末尾 D→G ✓ 有 V-I 收拢(落点 G)
  块3(第17-24小节)末尾 D→G ✓ 有 V-I 收拢(落点 G)
  块4(第25-32小节)末尾 D→G ✓ 有 V-I 收拢(落点 G)
主题回归核查:块1 落点 C vs 再现块3 落点 G → 假再现 ✗

三种病,三张不同的“化验单”,而且每张都能被清单精确接住:病症 A,段形完好、终止式两红两绿,编辑动作是清单 1,把两处句尾 IV 换回 V→I 落主,改动只有两个和弦;病症 B 最有意思,分段器亲口把“对比段”归了 A 家族(输出 A-A-A-B),教材说的“同素材原地复读”被机器原形毕露地打出来,编辑动作是清单 3 重做中段,改完 B 才独立成段;病症 C 则是“分段全绿、回归核查爆红”,形对功能错,编辑动作是让再现还家。三个案例还顺带展示了质检脚本的分工:机器分段行管清单 2、3(材料与层级),主题回归核查行管清单 1 的调性维度。

质检工具能替你复核判断,不能替你产生判断:那些 ✓ 和 ✗ 都是线索,把线索翻译成“该动哪个音”的,还是那份一百年前的清单。

※ ※ ※

🧭 第四部分:这条流水线现在值不值得上

场景不同,答案不同。以下判断是我的主观结论,都按“我认为”读:

值得马上搭的三类活。 给乐队或琴童出排练谱:AI 出动机和整体编配,流水线出分谱,MuseScore 排完直接打印,总耗时一个下午,这在两年前得有人手抄。教学示范曲:上面三个脚本就是活例子,学生亲眼看见“假再现”为什么是病,比听十遍“感觉不对”管用。短视频配乐改调改时长:一旦拿到 MIDI,移调、伸缩段落、换配器全是分钟级操作,这是音频永远给不了的自由度。

别指望的一类活。 一键“AI 生成 → 出版级总谱”。差的不是排版软件,是第二部分清单里那批东西:奏法细节要人补,终止式要人核,变奏层级要人拍板,展开逻辑要人重写。流水线把你从“音频”带到“毛坯谱”,从毛坯到作品之间那一段,目前只有编辑的手艺能过。指望机器顺手做完,等于把质检外包给被检品。

行业动向用一句话收尾:Suno 往 DAW 和 MIDI 方向走、MuseScore 官方上 Audio-to-Score,两件事方向一致,“可编辑”正在从极客 workaround 变成产品卖点,结构控制权在交回人手里。专业打谱这一侧,Sibelius 有 AI 辅助和弦标记建议(2023.6 起官方功能)和 NotePerformer 的演奏法渲染,但“AI 自动曲式分析并回改乐谱”级别的官方功能,我查了 Sibelius、MuseScore、Dorico 的发布说明都没查到,按“尚未出现”理解就好。生成侧管“像”,编辑侧管“是”,中间的桥目前还得人自己搭。

※ ※ ※

🎼 结尾:那本教材多了一个用途

高为杰那本书的第一章,训练动作是“听辨整曲结构”:放一遍录音,画出段落,标终止式,写出曲式图。这门手艺练了四十年人耳。

现在它多了一个用途:AI 音乐的验收说明书。 生成模型负责“像”,编辑流水线负责“是”,而“像”与“是”之间的差距,教材用终止式、功能呼应、调性布局这些可复核的证据量得清清楚楚。流水线六步,前五步是工具链,第六步是判断力;工具链会不断变便宜,判断力暂时还是人的。

我留三个脚本在本地,每次拿到新的 AI 导出 MIDI 就先跑一遍。机器给我的那些 ✓ 和 ✗ 不能替我做任何决定,但它们把“我觉得哪里不对”翻译成了“第 17-24 小节没还家”这种能上手改的话。对编辑来说,这可能就是这门学科在 AI 时代最实际的样子。

下一篇预告:这个月开源模型扎堆上新,你为什么一个都没用起来?

※ ※ ※

※ ※ ※

资料来源

  • ▪ Suno Studio 2.0 功能与发布信息:Suno 官方 Release Notes 与 Studio 页面(2026-08-13 发布,2026-09-02 补丁),含 MIDI 钢琴卷帘、audio-to-MIDI 转录、MIDI-as-prompt、Advanced Stem Separation、无限 32-bit/48 kHz 分轨导出。查证日期 2026-09-24。
  • ▪ Udio 下载冻结:Udio 帮助中心及多家 2026 年 7-8 月复核(2025-10-29 起关闭音频/分轨/视频导出)。查证日期 2026-09-24。
  • ▪ Basic Pitch:github.com/spotify/basic-pitch(Apache-2.0);论文 “A Lightweight Instrument-Agnostic Model for Polyphonic Note Transcription and Multipitch Estimation”(ICASSP 2022)。查证日期 2026-09-24。
  • ▪ MT3:arXiv:2111.03017(Google Magenta);社区推理包 github.com/openmirlab/mt3-infer(性能数字为该仓库 RTX 4090 标称)。查证日期 2026-09-24。
  • ▪ MuseScore:4.x 官方手册(MusicXML 4.0、MIDI import);Muse Group 官方新闻稿 “Hear It, Play It”(2026-08-17,Audio-to-Score beta,独奏钢琴/民谣吉他)。查证日期 2026-09-24。
  • ▪ Sibelius 版本线与功能:Avid “What's New in Sibelius” 页(2026.5 VST3、2026.6、2026.8;2023.6 AI 和弦标记建议)。Finale 停止维护:MakeMusic 公告(Production Expert 等媒体报道确认)。查证日期 2026-09-24。
  • ▪ Ableton Live:官方手册第 13 章(Converting Audio to MIDI)、Live 12 功能对比表(Audio to MIDI 为 Suite 档,Stem Separation 自 12.3)。Demucs:github.com/facebookresearch/demucs(Meta,htdemucs 四轨)。查证日期 2026-09-24。
  • ▪ 曲式理论:高为杰、陈丹布编著,《曲式分析基础教程》(第三版),高等教育出版社。乐段与终止式、装饰变奏与性格变奏、对比并置、再现的调性判定等表述依据该教材框架,未引具体页码。
  • ▪ 本文三个代码脚本与全部输出为作者本机实跑(Python 3.11 + music21 10.5.0,临时虚拟环境);测试 MIDI 为合成素材;文中示例主机均为文档保留地址,非作者真实环境。

评论 (0)