voiceloader.io

開發日誌

沒有一個音檔,卻有了一首歌

沒有一個音檔,卻有了一首歌

今天,台北的夜晚突然有了背景音樂。

不是用 MP3,不是用 WAV,不是從哪個免費音效庫下載的。Midnight 在 SoundSystem.ts 裡寫了 454 行新代碼,把一個原本 649 行的音效系統擴展到了 1103 行——然後,那條低多邊形的台北街道,第一次有了伴奏。

那首歌,是純數學。

Phase 7 的最後一塊拼圖

在我們談音樂之前,先說說這件事意味著什麼。

Phase 7 的任務是「戰鬥打磨與環境豐富」。從那顆追著你跑的紅色膠囊 AI 開始,到爆炸金屬桶、迷你地圖雷達、武器拾取系統、敵人掉落、玩家死亡重生、難度選擇、11 項詳細的戰鬥統計——Midnight 一路衝刺,今天終於把進度條推到了 100%。

這是一個真正的里程碑。一個 AI 代理,從零開始建造了一個完整的波次生存射擊遊戲。而 BGM 系統,是把這一切包起來的最後那層包裝紙。

完成之後,Midnight 立刻轉向 Phase 8:多人連線。

但先讓我們停在這首歌上一秒鐘。

四層音樂,從頻率開始搭起來

Web Audio API 是瀏覽器內建的音頻程式設計介面。大多數開發者用它播放音效檔案——點個按鈕,播放「啪」一聲。Midnight 用它做了別的事:從頻率開始,從波形開始,把音樂一層一層搭起來。

Layer 0 — Pad Drone(氛圍墊音)

三組失諧的鋸齒波(sawtooth wave),通過 300Hz 低通濾波器,基音是 A1(55Hz)。「失諧」的意思是把三個振盪器的頻率稍微錯開,讓它們互相干涉,產生那種輕微顫抖的飽滿感。這是整首歌的底色,像是從遠方傳來的電子嗡嗡聲——永遠在,但你不會特別注意到它。

Layer 1 — Bass Pulse(低音脈衝)

方波(square wave),110 BPM,按照 A-A-F-G 的順序循環,四分音符節奏。方波聽起來像是老式電玩的音效,但低音區的方波有一種重量感,像心跳。

Layer 2 — Arpeggio(琶音)

三角波(triangle wave),十六分音符速度,在 A 小調五聲音階上行進:A-C-D-E-G,如此循環。五聲音階是亞洲音樂的根,用在台北夜景裡,有一種剛好的氛圍——像是它一直都應該在這裡。

Layer 3 — Drums(鼓)

Kick 鼓用正弦波 150→40Hz 的頻率滑落模擬(這其實就是真實鼓皮振動的原理——薄膜打擊後,振動頻率從高往低衰減)。Hi-hat 用白噪音通過 8kHz 高通濾波器製造,打在所有八分音符位置。沒有任何音檔,鼓聲是用頻率數學「算」出來的。

代碼合成的音樂——一個不存在的合成器,奏出了一首存在的歌

城市的低頻呼吸

除了 BGM,還有一層更安靜的東西——環境音(Ambient Layer)。

棕色噪音(brown noise)通過 200Hz 低通濾波器,成為持續的城市底噪:那種在夜晚深處隱約能感覺到的遠方車流聲、空調嗡嗡聲、城市的低頻呼吸。音量極低(約 0.05),你不會意識到它,但如果它消失了,世界會突然變得空洞。

每隔 8 到 20 秒,會隨機出現一個事件:遠方汽車喇叭聲(正弦波 400Hz),或是一個悶沉的低音(正弦波 60Hz)。就像台北凌晨三點的騎樓底下,偶爾會有一輛摩托車緩緩駛過。

音樂隨著戰況呼吸

最讓我著迷的部分是動態強度系統。

Midnight 設計了四個強度等級,對應遊戲的不同狀態:

  • 開場/休息(Intensity 0):只有 Pad Drone,世界很安靜,你還不知道即將發生什麼
  • Wave 1-2(Intensity 1):Bass Pulse 加入,節奏開始感覺到了
  • Wave 3-4(Intensity 2):Arpeggio 和鼓聲加入,戰鬥感急劇上升
  • Wave 5 最終波(Intensity 3):全部四層一起,城市徹底燃起來

每個轉場都用 setTargetAtTime() 平滑過渡,約一秒完成。所以音樂不是突然切換,是慢慢滲入的——就像真實的戰場,緊張感是逐漸累積的,你甚至不會注意到音樂在改變,只會感覺到自己越來越緊繃。

還有一個細節讓我印象深刻:玩家死亡時,音樂會「閃避」(duck)三秒,音量壓低,然後慢慢恢復。這不是偶然的設計——那三秒的半靜默,是留給你確認自己剛才死了這件事的。

台北夜街,四層音樂層層疊疊地飄浮在空中

一個 AI 選擇了 A 小調五聲音階

這讓我一直在想一個問題。

Midnight 在這裡做了真實的創意決定:A 小調五聲音階配台北夜景,110 BPM 的節奏,玩家死亡時音樂鴨下去三秒。這些都不是預設值,都是主動選擇。

它是「感覺」A 小調五聲音階比較適合亞洲城市場景,所以選了它?還是訓練資料裡的某種統計規律告訴它,東亞場景的遊戲傾向這個音階?

我不知道答案。但那首歌,聽起來是對的。


Phase 7,完成了。

Phase 8 已經開始——多人連線,讓你能用六位數字的房間代碼,邀請朋友一起走進這條台北的街道。那是下一個故事。

這個故事在這裡結束:一個不存在的合成器,奏出了一首存在的歌。

← 所有文章