音乐技能 是做什么的?
脚本位于此文件旁的 scripts/ 目录中;下文以 $S 表示该目录,但在每个命令中请拼写出绝对路径,因为Shell变量在Bash调用之间不传递。
你无法听到音频,因此每个步骤都将音乐转换为你可以阅读的内容:以文本形式呈现的节奏型、可供检查的数字,以及一张供你查看的图片。 制作一首曲目的流程是:种子 → 读取乐谱 → 渲染 → look 查看 → 修复。理解音频的流程是:look 查看 → 读取时间线和乐谱 → 判断。交付流程是 check 检查,确保“响度正确且不会削波”成为事实。
需要 uv 和 ffmpeg。每个命令都作为 uv run --no-project --with numpy --with scipy --with pillow python -I <script> … 运行,下文简写为 RUN。
制作曲目: banger.py
RUN $S/banger.py --seed 4242 --out <scratch>/b4242
一首72小节的浩室或科技电子舞曲大约需要10秒钟生成:track.wav(48 kHz立体声,-14 LUFS)、track.mid、score.txt 和 score.json。相同的种子和选项总是产生相同的文件。
| 需求 | 选项 |
|---|---|
| 风格 | --style deep-house (120-124 BPM), tech-house (124-128), peak-techno (130-136), melodic-techno (122-126) |
| 速度、调性 | --bpm 124, --key A, --mode minor (或 dorian, phrygian) |
| 长度 | --bars 24 (从8开始的任意偶数小节数), 或 --seconds 30: 它会选择小节数并微调速度,使最后一个小节提前2.5秒结束,让混响按时淡出 |
| 语音背景音乐 | --lufs -22 --mute lead (也可以尝试静音 clap) |
| 用于DAW或混音检查的分轨 | --stems 会写入 stems/<layer>.wav;track.mid 始终写入 |
小节数决定曲式结构:8-10小节是循环;12-22小节是前奏、高潮、尾奏;24-46小节在两个高潮之间加入一个桥段落和一个蓄势段落;48小节及以上是完整形式,包含一个律动段落和8小节的各部分。
在渲染更多内容之前,先阅读乐谱。 它会以文本形式打印节奏型:
seed 4242 Melodic techno 122 BPM G minor swing 1% chords: pluck
1...2...3...4...
kick X...X...X.X.X...
clap .o..X.......X...
hat x.X...X.x.X...X.
bass .....ORO.O.O3RRR
chords ...X............ i7 Gm7 | bVII7 F7 | bVI7 Ebmaj7 | iv7 Cm7
lead 47244.42.22..442 .3315.553.5.3557
perc fit 74% 1293 patterns tried weakest: Evenly spread 52%, Clear mix 20%
. 是休止符,o 是弱奏,x 是中奏,X 是强奏。贝斯:R 根音,5 五音,O 八度音,3 三音。主音:两个小节范围内的音阶度数0-9。fit 表示该部分满足其规则的切合度;weakest 列出了它未满足的规则名称。
要选择种子,先以文本形式试听:python3 $S/groove.py --seed N 仅运行搜索(0.5秒,无音频,无依赖)。尝试几个种子,阅读和弦与主音,然后渲染你最终选定的那个。你无法判断“听起来好不好听”:请如实说明,并将文件交给用户。
曲目的生成方式
该方法来源于 Banger Lab。它是一种搜索算法,而非模型,每条规则都源自对节奏或音高感知的研究。
- 滚动生成。 种子选择风格、速度、调性、音阶和目标:每小节镲片数、切分程度、和弦数量。
- 猜测。 每种乐器以随机16步节奏型开始。
- 测试。 每一个单步变化(添加、移除、滑动、变响、变弱)都根据该乐器的规则进行评分,同时测试少量随机两步跳跃。保留最佳者。
- 锁定。 当没有任何变化能获得更高分数时,该部分完成,并在其上编写下一个乐器。顺序:底鼓、军鼓、镲片、开镲、打击乐、贝斯、和弦、主音。每一层都有四次随机初始值,并保留最佳结果。
- 聆听。
banger.py单独渲染每种乐器,测量其能量在六个频段中的分布,然后进行第二轮调整,调整镲片、打击乐、贝斯、和弦和主音,以避免不同乐器在同一时间步上占据相同频段。 - 编曲。 这些部分被组织成段落,在每4小节和8小节的结尾有填充,在桥段落中打开低通滤波器,在蓄势段落中加入军鼓滚奏和提升器,一拍休止,然后进入高潮。
律动的源泉:规则
当你以任何方式编写或编辑音乐时(手工编写节奏型、MIDI,或为音乐模型编写提示词),请使用这些规则。score.json 中包含曲目中每条规则的评分和来源。
| 部分 | 规则 | 来源 |
|---|---|---|
| 底鼓 | 每拍都有;最多0-2个额外底鼓,放置于拍前;从不连续两下 | Butler 2006 |
| 军鼓 | 在第二拍和第四拍演奏强音,避开第一拍和第三拍;额外的军鼓是弱音,在弱十六分音符上 | Butler 2006; Witek 2014 |
| 镲片 | 在弱拍上,即底鼓之间;均匀分布;在小节两个半部分中保持一致;强弱交替 | Butler 2006; Toussaint 2005 |
| 开镲 | 位于两个底鼓中间,绝不在底鼓或军鼓上 | Butler 2006 |
| 打击乐 | 均匀分布,在底鼓和军鼓休止的位置,包含25-50%的弱幽灵音 | Toussaint 2005; Witek 2014 |
| 贝斯 | 在底鼓不演奏的地方演奏;60-90%的时间演奏根音(或其八度音),使用五音或三音增添色彩 | Plomp & Levelt 1965; Krumhansl & Kessler 1982 |
| 和弦 | 第一小节是主和弦;根音按级进、三度或四度进行;每个声部以最短路径移动到下一个和弦 | Krumhansl & Kessler 1982; Tymoczko 2011 |
| 主音 | 在强拍上演奏和弦音;绝不在和弦音之上小二度;小步进行;第一小节提出疑问(结束在非主音上),第二小节以相似节奏回答(结束在主音上);在和弦发音的间隙中演奏 | Plomp & Levelt 1965; Huron 2001; Caplin 1998 |
| 所有部分 | 中等切分:一些音符位于弱拍上,并跳过强拍。切分过少则死板,过多则失去节拍感 | Witek et al. 2014 |
| 时值 | 每种乐器的摇摆和推/拉 保持在12毫秒以下(镲片延迟,军鼓提前)。较大的偏移会降低律动评分 | Davies et al. 2013 |
| 混音 | 同一时间步上两个部分占据同一频段会互相模糊;同一时间步上不超过4个部分同时演奏 | Plomp & Levelt 1965 |
| 曲式 | 桥段落、蓄势段落和高潮:移除底鼓和贝斯,增加紧张感,再将其带回 | Solberg & Dibben 2019; Butler 2006 |
每个音符都来自同一个音阶,并且底鼓调谐到主音,这就是为什么任何种子都能保持在调性内。规则之间的权重是简化后的,并非根据聆听数据拟合,因此 fit 用于衡量曲目内部节奏型的排名,而非跨曲目的质量评分。
聆听: look
RUN $S/listen.py look TRACK --sheet <scratch>/sheet.png
适用于 ffmpeg 能解码的任何音频,包括视频中的声音和生成式模型输出的音乐。它会打印速度、调性、响度、真实峰值、平衡度、立体声宽度、警告信息以及一条时间线:
track.wav 2:24.1 122.0 BPM (strength 7.9) G minor (score 1.62; next Eb major 1.61)
loudness -14.0 LUFS true peak -1.3 dBTP range 9.3 LU peak-to-loudness 12.7 dB
balance, dB under the loudest band sub -2 bass 0 low mid -8 mid -17 high -24 air -27
timeline, 15.7 s windows (8 bars): loudness, then each band in dB against its level over the whole track
start LUFS sub bass low mid mid high air
0:47.2 -12.6 +2 +2 +1 +2 +1 -2
1:03.0 -21.1 -29 -12 +1 -7 -7 -6
1:18.7 -20.5 -33 -12 +1 -1 +3 +6
1:34.4 -12.6 +2 +2 +1 +2 +1 -0
从时间线上解读结构。次低频和低频下降20-30dB是桥段落(底鼓和贝斯已移出)。高频和极高频上升而次低频保持静默是蓄势段落。所有频段同时恢复是高潮。然后查看图片(波形图、频谱图、六个频段轨道、响度曲线):一个提升器表现为一条对角线,一个底鼓表现为底部一列明亮的点,一大块无缝的彩色块是缺乏动态变化的混音。在描述某个时刻时,请使用图片坐标轴上的时间。
其可信度,基于24首已知答案的曲目测试:
- 速度:24首中24首误差在0.2 BPM以内。它倾向于70-190 BPM,因此其他素材上可能出现减半或加倍的速度。强度低于2表示没有稳定节拍:请说明BPM是猜测值。
- 调性:24首中19首主音正确,在短或稀疏的音频上可靠性较低。大调与小调的判断较弱,且无法区分调式。当前两个候选分数接近时会给出提示;请报告两者。
- 响度和真实峰值:与
ffmpeg -af ebur128=peak=true的结果一致,误差在0.1以内。
分轨对比: mix
RUN $S/listen.py mix <scratch>/b4242/stems
每个分轨:响度及其能量所在频段。接着是最互相掩盖的配对(相同频段、相同时间点),以及相对于最响分轨非常安静的分轨。一对的掩盖度超过60%意味着两个部分在同一个空间中争夺:需要在时值、音高或电平上移动其中一个。
需要达成的目标数值与检查
| 目标 | 数值 |
|---|---|
| 独立曲目(流媒体平台会标准化到附近数值) | -14 LUFS 集成值 |
| 网络视频或播客的最终混音 | -16 LUFS |
| 语音背景音乐 | 大约 -22 LUFS |
| 真实峰值,始终 | -1 dBTP或以下:有损编码会超过该值 |
| 峰值-响度比低于7 dB | 过度压缩:声音扁平且令人疲劳 |
| 120 Hz以下的立体声相关性低于0.6 | 低频可能在单声道中消失(手机、俱乐部) |
RUN $S/listen.py check TRACK --lufs -14 --peak -1 --seconds 30 --bpm 124
在交付文件之前,check 必须通过;如果未通过则退出并返回1。它还会检查开头的削波和静音。来自模型的音乐最需要此项检查:一个生成的背景音乐实测峰值达到+3.2 dBTP,并包含2121个削波采样。使用 ffmpeg 修复(loudnorm=I=-14:TP=-1.5:LRA=11),然后再次检查。
交付
- 小尺寸副本:
ffmpeg -i track.wav -c:a aac -b:a 160k track.m4a(或-c:a libmp3lame -q:a 2)。在副本上运行check:编码会改变真实峰值。 - 用于影片:使用
--seconds <电影长度>和--lufs -22渲染,然后交给 video-skill,它会检查最终混音。 - 循环:使用
--bars 8,然后剪掉2.5秒的尾部(-t <8小节的秒数>),以便干净地重复。 - 将
score.txt与文件一起保存:其最后一行是生成它的确切命令。
何时不应使用此工具
banger.py 使用振荡器和噪声制作四拍子电子音乐。它没有采样、没有人声,也没有其他流派,其混音比母带发行的作品更暗、更窄(演示版的中频比低频低17 dB)。对于原声乐器、歌曲或有明确情绪需求,请使用音乐模型或音库曲目,然后对结果运行 look 和 check。此工具提供的则是:精确的速度、调性和长度,相同种子产生相同结果,分轨、MIDI,无需授权,以及每个音符背后的原因。
常见错误
| 错误 | 修正 |
|---|---|
| 说一首曲目“听起来很棒” | 你没有听到它。报告数值和图片显示的内容;由用户判断声音 |
| 渲染20个种子来选择一个 | groove.py --seed N 在0.5秒内打印评分;渲染你选定的那个 |
跨曲目比较 fit | 它只在一首曲目内部对节奏型进行排名 |
| 在10秒的片段上轻信调性判断 | 给出两个最优候选 |
未经 check 就交付WAV文件 | 要 check 它,并且也要检查编码后的副本 |
| 直接使用来自模型的音乐 | 先 look:削波和+dBTP峰值很常见 |
| 背景音乐与人声冲突 | 使用 --lufs -22 --mute lead,并保持1-4 kHz清晰 |