兩條來源路徑,一個 runtime soundbank
音樂仍由 ROMFS 的 music.mus 與原始 song ID 決定流程;
build 端使用 41 首 TYM 表示保存 LDS/OPL2 pattern、patch、note、
channel volume 與 carrier total-level,再轉成 Maxmod 的 IT modules;
41 首中實際使用第九聲道的 26 首不再刪除最低能量聲部。
音效則直接由 tyrian.snd 與 voices.snd
拆出原始 8-bit PCM。最後由 mmutil 組成同一份
soundbank.bin。
為什麼不能逐曲正規化
早期轉換沿用為 SNES S-DSP/BRR 建立的 channel gain,還會把每首歌 最大的 voice gain 再正規化。結果是同一音色跨歌曲沒有共同響度基準, 而一首歌最強的聲道會連帶改變其他聲道比例。稀疏鼓聲尤其容易為了追上 整曲 RMS 而被放大成尖銳瞬態。
新流程以 channel-calibration.json 的完整 OPL2 stem RMS
作固定 reference,對 Maxmod 真正使用的 signed 8-bit sample、
IT volume-column 量化與 runtime module volume 896/1024
重新量測。原始參考與 GBA 內建喇叭都是 mono,因此以
L+R fold-down 比對,但 IT 內的 stereo pan 仍完整保留。
- 保留 TYM event velocity 已包含的 carrier loudness;
- 全 catalog 只使用一次固定 +3 dB presentation gain;
- 不做 per-track 或 per-sample master normalization;
- 8-bit 量化後重新量測,clipping 或缺少 target 會讓 build 失敗。
鼓聲要看 peak,不只看 RMS
短 one-shot 的平均能量很低,若只追 RMS,kick、snare、hi-hat 或
crash 的單一下 peak 可能被推得過高。校準器因此另以原版 peak 的
1.60× 作軟上限;22 個稀疏 percussion sources 寧可略低於
RMS target,也不製造刺耳爆點。
程序鼓聲以 GBA mixer 原生 15,768 Hz 產生,並依類型使用不同 sample length,不再共用同一段 46 ms noise。 每個 one-shot 使用 1.5 ms smoothstep attack 與 5 ms release,並只移除 極低頻 DC;沒有對全部曲目強套 120 Hz high-pass 或 8 kHz shelf, 避免把不同 Tyrian 音色 EQ 成同一種聲音。
原版 SFX 與語音不經手工替代
tyrian.snd 內 29 個一般音效與 voices.snd
內 9 段語音以原始 archive offset 拆出,轉為 11,025 Hz mono 8-bit WAV。
與 OpenTyrian 的 JE_loadSndFile() 相同,每段 voice 都移除
尾端 100-byte 損壞資料,不只處理 Level End。遊戲中的爆炸、打擊、
Cube、Boss 與提示語音仍依 source sound number 呼叫。
極限全武器壓力測試可以選擇把密集 SFX 導向 GBA 原生 DMG square channel,以隔離 sample-mixer voice pressure;這是診斷 profile, 一般遊戲仍使用完整 Maxmod SFX。
循環曲與只播一次的提示曲
Maxmod 的 MM_PLAY_ONCE 只控制 order list 結束後的行為;
原始 IT 內若仍有 Bxx 跳轉,歌曲仍會無限循環。因此 End of
Level(09)、Game Over(10)與 Secret Level(30)各保留兩種 module:
一般版供 JukeBox 循環,_once 版只移除 Bxx,讓遊戲流程自然
播到結尾停止。
兩種檔案的 PCM payload 完全相同,Maxmod 也會全域去重相同 sample。 三份有限 order/pattern 只讓 soundbank 增加 4,028 bytes,換來正確的 勝利、死亡與秘密關卡播放語意。
切歌先跨過零點
直接在 Direct Sound FIFO 還含非零波形時 mmStop(),
容易在選單進關卡的一瞬間產生爆音。現行 VBlank 狀態機只淡出背景
module,保留 UI 確認音效:
- 18 VBlanks 淡出。選單歌曲平順降到零。
- 1 個完整靜音 VBlank。讓 Maxmod 送出靜音 buffer。
- 停止並載入場景。切換 module 與關卡資料。
- 30 VBlanks 淡入。新關卡歌曲從零開始。
暫停則比照來源邏輯,只把 module volume 降為一半;死亡淡出、勝利與 Game Over 的 natural stop 都由 telemetry 計數,避免日後又退回無限循環。
把聽感變成可重建的證據
Build 會輸出逐曲、逐 source 的 gain、RMS error、peak ceiling、 clipping 與 track mapping 報告;回歸另驗證 41 首/334 個 OPL sources、 三首 finite cues、18 個 mixer slots、場景淡出/靜音/淡入步數、自然 停止次數與所有 source SFX ID。人耳 A/B 仍不可取代,但每次修改不必 再從零猜測「哪個聲道變大」。