music-skill 是做什麼的?
腳本位於此檔案旁邊的 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 秒結束,讓殘響(reverb)能準時消退 |
| 人聲底墊 | --lufs -22 --mute lead(也可以試試靜音 clap) |
| 給 DAW 或混音檢查用的分軌 | --stems 會寫出 stems/<layer>.wav;track.mid 始終會產生 |
小節數決定了曲目的結構:8-10 小節是一個循環(loop);12-22 小節是前奏、高潮、尾奏;24-46 小節會添加一個間奏(breakdown)和一個銜接段(build-up),位於兩個高潮之間;48 小節及以上是完整結構,包含一個律動樂段(groove section)和 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強音。- 貝斯(Bass):
R根音,5五度音,O八度音,3三度音。 - 主旋律(Lead):0-9 的音階音級,跨越兩個小節。
fit表示該聲部在其規則下的符合程度;weakest列出了未達標的規則。
若要挑選種子,可以先透過文字進行試聽:執行 python3 $S/groove.py --seed N 只會執行搜尋(0.5 秒,不產生音訊,無需依賴項)。嘗試幾個種子,閱讀和弦與主旋律,然後渲染你最中意的那一個。你無法判斷「聽起來好不好」:直接說明這一點,並將檔案交給使用者。
一首曲目的產生方式
此方法源自 Banger Lab。這是一個搜尋過程,而非模型,且每一條規則都來自節奏或音高感知的研究。
- 滾動(Roll)。 種子會決定風格、速度、調性、音階以及目標:例如每小節的開合鈸(hats)數量、切分音的程度、不同和弦的數量。
- 猜測(Guess)。 每個樂器先從一個隨機的 16 步節奏模式開始。
- 測試(Test)。 針對每一步的變更(新增、移除、滑動、變大聲、變小聲),根據該樂器的規則進行評分,並同時測試少量隨機的兩步跳躍。保留得分最高的一種變更。
- 鎖定(Lock)。 當沒有任何變更能獲得更高分數時,該聲部即完成,然後在它的基礎上產生下一個樂器。順序為:大鼓(kick)、小鼓(clap)、開合鈸(hats)、開鈸(open hat)、打擊樂(percussion)、貝斯(bass)、和弦(chords)、主旋律(lead)。每個層級會進行四次隨機初始,並保留最佳結果。
- 聆聽(Listen)。
banger.py會獨立渲染每種樂器,測量其能量在六個頻段中的分佈。然後進行第二輪處理,重新調整開合鈸、打擊樂、貝斯、和弦與主旋律,以避免不同聲部在同一時間步(step)佔據相同頻段。 - 編排(Arrange)。 各個聲部被組合成樂段:在每 4 小節和 8 小節的結尾加入過門(fills);在間奏(breakdown)部分有一個低通濾波逐漸打開;在銜接段(build-up)有軍鼓滾奏(snare roll)和 riser 效果;短暫的一拍靜默後,迎來高潮(drop)。
節奏的奧秘:規則
無論你是透過何種方式創作或編輯音樂(手工編寫節奏模式、MIDI、或對音樂模型的提示),都可以利用這些規則。score.json 檔案中包含了針對某首曲目的每條規則的評分與來源。
| 聲部 | 規則 | 來源 |
|---|---|---|
| 大鼓(Kick) | 每個強拍上都要有;最多 0-2 個額外的大鼓,且放置在強拍之前;絕不能連續兩個強拍 | Butler 2006 |
| 小鼓(Clap) | 在強拍 2 和 4 上要大聲,在強拍 1 和 3 上要小聲;額外的小鼓要輕聲且位於弱拍十六分音符上 | Butler 2006; Witek 2014 |
| 開合鈸(Hats) | 位於弱拍(off-beats),即大鼓之間;均勻分佈;在小節的前半與後半保持相同模式;強聲與弱聲交替出現 | Butler 2006; Toussaint 2005 |
| 開鈸(Open hat) | 位於兩個大鼓的中間點,絕不和鼓或小鼓同時出現 | Butler 2006 |
| 打擊樂(Percussion) | 均勻分佈在大鼓和小鼓沒有出聲的地方,包含 25-50% 的輕聲幽靈音符(ghost notes) | Toussaint 2005; Witek 2014 |
| 貝斯(Bass) | 在大鼓沒有出聲的地方演奏;60-90% 的時間演奏根音(或其八度音),其餘時間用五度或三度音增添色彩 | Plomp & Levelt 1965; Krumhansl & Kessler 1982 |
| 和弦(Chords) | 第 1 小節是主和弦;根音以級進、三度或四度進行;每個聲部以最短的路徑移動到下一個和弦 | Krumhansl & Kessler 1982; Tymoczko 2011 |
| 主旋律(Lead) | 在強拍上演奏和弦音;從不演奏比和弦音高一個半音的音符;以小跨度進行為主;第 1 小節營造疑問(結束在非主音上),第 2 小節以相似的節奏回答(結束在主音上);在和弦出現的間隙中演奏 | Plomp & Levelt 1965; Huron 2001; Caplin 1998 |
| 所有聲部 | 中度切分音:一些音符落在弱拍上,並跳過一個強拍。切分太少會很生硬,太多則會失去節奏感 | Witek et al. 2014 |
| 時值(Timing) | 搖擺感(swing)和推拉感(push/pull)每種樂器控制在 12 毫秒以內(開合鈸稍晚,小鼓稍早)。更大的偏移會降低律動評分 | Davies et al. 2013 |
| 混音(Mix) | 兩個聲部在同一時間步佔據同一頻段會相互模糊;同一時間步最多不超過 4 個聲部同時出聲 | Plomp & Levelt 1965 |
| 結構(Form) | 間奏(breakdown)、銜接段(build-up)和高潮(drop):移走大鼓和貝斯,提升緊張感,然後再把它們帶回來 | 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
從時間軸上讀取結構。次低頻(sub)和低頻(bass)下降 20-30 dB 表示間奏(breakdown,大鼓和貝斯消失了)。高頻(high)和空氣感(air)爬升而次低頻保持不變表示銜接段(build-up)。所有頻段同時恢復是高潮(drop)。然後閱讀圖表(波形圖、頻譜圖、六個頻段通道、響度曲線):riser 效果是一條對角線;大鼓是底部一列明亮的點;一片連續無空隙的色塊表示缺乏動態的混音。在描述某個時刻時,請參考圖表軸線上的時間。
以下是根據 24 首已知答案的曲目進行測量的可信度:
- 速度(Tempo):24 首中有 24 首的誤差在 0.2 BPM 以內。它偏好 70-190 BPM,因此在處理其他素材時可能會出現半速或倍速的判斷。當強度(strength)低於 2 時,表示沒有穩定的節拍:請註明 BPM 僅為猜測。
- 調性(Key):24 首中有 19 首的主音判斷正確,在處理短音訊或稀疏音訊時可靠性較差。大調 vs 小調的判斷準確度較低,且無法區分教會調式(modes)。當得分最高的兩個調性分數接近時,工具會進行提示;請同時報告這兩個結果。
- 響度(Loudness)和真實峰值(True Peak):與
ffmpeg -af ebur128=peak=true的結果一致,誤差在 0.1 以內。
分軌之間的比較:mix
RUN $S/listen.py mix <scratch>/b4242/stems
此命令會列出每個分軌的響度及其能量所在位置。然後顯示互相重疊最多的分軌對(同一頻段、同一時間點),以及相對於最大聲分軌顯得非常安靜的分軌。若一對分軌的重疊度超過 60%,表示有兩個聲部在同一個空間中互相干擾:需要透過調整時間、音高或音量來移開其中一個。
需要達標的數值與檢查
| 目標 | 數值 |
|---|---|
| 獨立的曲目(串流平台會將其標準化到附近的值) | -14 LUFS 整合響度 |
| 網路影片或 podcast 的最終混音 | -16 LUFS |
| 人聲底墊 | 大約 -22 LUFS |
| 真實峰值,始終 | -1 dBTP 或以下:有損編碼會導致過衝(overshoot) |
| 峰值與響度比低於 7 dB | 表示過度限制(over-limited):聽起來扁平且令人疲勞 |
| 120 Hz 以下的立體聲相關性低於 0.6 | 低頻在單聲道下可能會消失(手機、夜店) |
RUN $S/listen.py check TRACK --lufs -14 --peak -1 --seconds 30 --bpm 124
在將檔案交付出去之前,check 必須通過;如果任何一項未達標,它會以狀態碼 1 退出。它也會檢測開頭是否有削波和靜音。來自模型的音樂最需要這個檢查:一個生成的底墊曾測量出 +3.2 dBTP,並包含 2,121 個被削波的樣本。使用 ffmpeg 修復(loudnorm=I=-14:TP=-1.5:LRA=11),然後再次進行 check。
交付
- 小型副本:
ffmpeg -i track.wav -c:a aac -b:a 160k track.m4a(或-c:a libmp3lame -q:a 2)。對副本執行check:編碼過程會移動真實峰值。 - 用於影片配樂:使用
--seconds <影片長度>和--lufs -22進行渲染,然後將其交給 video-skill,該技能會檢查最終混音。 - 循環(Loop):使用
--bars 8,然後截掉 2.5 秒的尾部(-t <8 小節的秒數>),使其能夠乾淨地重複播放。 - 將
score.txt與檔案一起保存:其最後一行就是產生該檔案的精確命令。
何時不該使用這個工具
banger.py 使用振盪器和噪音來製作四拍子(four-on-the-floor)電子音樂。它沒有樣本、沒有人聲,也沒有其他類型。其混音聽起來比經過母帶處理的發行版更暗更窄(示範曲的中頻比低頻低了 17 dB)。對於原聲樂器、歌曲或指定的情緒,請使用音樂模型或版權音樂庫,然後對輸出的結果執行 look 和 check。此技能所提供的優勢是:精確的速度、調性和長度;相同種子產生完全相同結果;提供分軌、MIDI;無需授權;並且每個音符都有其理論依據。
常見錯誤
| 錯誤 | 修正方法 |
|---|---|
| 說一首曲目「聽起來很棒」 | 你並沒有真正聽到它。報告數字和圖表顯示的內容;讓使用者來判斷聲音好壞 |
| 為了選一個種子而渲染了 20 個 | groovy.py --seed N 在 0.5 秒內就能列印分數;只需渲染選中的那個 |
比較不同曲目的 fit 值 | 它僅用於對一首曲目內的節奏模式進行排序 |
| 相信一個 10 秒音訊片段的調性判斷 | 同時給出得分最高的兩個候選調性 |
未經 check 就交付 WAV 檔案 | 對其執行 check,並對編碼後的副本也執行 check |
| 直接使用模型產生的音樂而未經處理 | 先執行 look:削波和 +dBTP 的峰值很常見 |
| 底墊音樂與人聲互相干擾 | 使用 --lufs -22 --mute lead,並保持 1-4 kHz 頻段清晰 |