速查 › 播報與音訊系統
播報與音訊系統
主播的每一句話、場館廣播、觀眾應援、全壘打音效 ——
全都在 data/audio/ 底下。這一區比整個遊戲其他部分加起來還大,
而且它的索引檔是純文字,你可以直接打開驗算。
先看規模
| 項目 | 數字 | 備註 |
|---|---|---|
| 音訊分區 | 13 個 | 每個分區一個資料夾 |
| 檔案數 | 111 個 | 相對於它的體積,檔案數少得驚人 |
| 合計大小 | 736.9 MB | 其中 729 MB 集中在 cd/ 一個資料夾 |
| 最大的單一檔案 | 212 MB | cd/spch_pbp/pbpdat.big,主播的全部語音 |
| 主播語音的名稱條目 | 23,013 條 | 其中 18,492 個不重複名稱 |
上面每個數字都是把 data/audio/ 現場走過一遍數出來的,不是引用他人資料。
每個分區都是同一套模板
13 個分區裡有 6 個結構完全一致,各自 6 個檔,
而且這 6 個分區的副檔名組成一模一樣(.txt、.nam、.evt、
.big、以及兩個 .off)。以觀眾應援 chants/ 為例:
chants/
spch_cht.txt 名稱表(純文字,可以直接讀)
spch_cht.nam 名稱表(二進位版)
events.evt 事件表(二進位)
chanthdr.big 標頭資料
chanthdr.off 標頭索引(純文字)
chantdat.off 資料索引(純文字)
cd/chants/
chantdat.big ← 真正的聲音在這裡,56 MB
索引跟聲音是分開放的
注意最後一行:索引在 audio/chants/,聲音本體在 audio/cd/chants/。
13 個分區都是這樣。
cd 這個名字透露了設計意圖 —— 2005 年的遊戲,
體積龐大的語音是預期從光碟串流播放的,所以索引留在硬碟、資料放在「光碟」那一側。
推測 這個解讀本站未經證實。
那個叫 .off 的檔可以直接驗算
索引檔 .off 是純文字,打開就看得懂,每行兩個數字:
chantdat.off 的前四行(原檔內容)
0,865536,
865536,805632,
1671168,1658624,
3329792,917760,
│ └── 這一段有多長
└───────── 這一段從第幾個位元組開始
把每一行的兩個數字加起來,就是下一行的開頭:
0 + 865536 = 865536,865536 + 805632 = 1671168。
一路對到最後一行都不會斷。
一條可以自己驗證的規則
把 .off 裡所有的「長度」加起來,
結果會剛好等於它對應那個資料檔的大小。
本站把全部 16 個 .off 檔都算了一遍:
16 個全部完全相符,一個 byte 都不差。而且每一段都緊接著上一段,
中間沒有任何空隙、也沒有重疊。
| 索引檔 | 段數 | 長度加總 | 對應檔案大小 | 結果 |
|---|---|---|---|---|
| pbpdat.off | 2,056 | 212,219,648 | 212,219,648 | 相符 |
| pbphdr.off | 2,056 | 107,484 | 107,484 | 相符 |
| chantdat.off | 90 | 56,474,880 | 56,474,880 | 相符 |
| padat.off | 66 | 13,428,480 | 13,428,480 | 相符 |
| rallydat.off | 3 | 13,075,456 | 13,075,456 | 相符 |
| plchtdat.off | 17 | 11,826,432 | 11,826,432 | 相符 |
| hsfxdat.off | 3 | 6,396,928 | 6,396,928 | 相符 |
| stdmdat.off | 2 | 5,339,392 | 5,339,392 | 相符 |
| bdcstdat.off | 3 | 4,872,192 | 4,872,192 | 相符 |
全部 16 個索引檔分成兩半:8 個資料索引(*dat.off)與
8 個標頭索引(*hdr.off)。上表列出 8 個資料索引,
外加 pbphdr.off 當作標頭索引的例子;沒列出的 7 個標頭索引同樣全部相符。
為什麼這件事重要
逆向一個沒有文件的格式,最難的是「怎麼知道自己猜對了」。
這裡剛好給了一個免費的檢查點:如果你對 .off 的理解是對的,
數字加起來就會剛好等於檔案大小;差一個 byte 就代表你哪裡想錯了。
這種「格式自己帶著驗算方法」的情況不常見,遇到了要用。
.big 在這裡有三種完全不同的格式
data/audio/ 底下有 28 個副檔名是 .big 的檔案。
實測前四個位元組,只有 12 個是真的 BIGF 封裝檔:
| 檔數 | 開頭四碼 | 實際是什麼 | 哪些檔 |
|---|---|---|---|
| 12 | BIGF | 真的封裝檔 | 10 個是球員名/隊名/球場名(pname、tname、stdnm),
另外 2 個是裝純文字 CSV 的資料庫(crowddb/audiocsv.big、speechdb/speechdb.big) |
| 8 | SCHl | EA 的音訊串流容器 | 全部是 cd/ 底下的 *dat.big,也就是聲音本體 |
| 8 | 各不相同 | 各分區自己的標頭格式 | 全部是 *hdr.big,八個檔的開頭四碼沒有兩個一樣 |
副檔名會騙人,這裡是最好的例子
同一個副檔名、同一個資料夾底下,代表三種毫無關係的格式。
如果你寫的工具看到 .big 就直接套 BIGF 解析器,
28 個檔裡會有 16 個當場失敗。
正確做法是看開頭四個位元組,不是看副檔名。 五秒看穿一個檔案教的就是這件事。
主播語音:三層名稱,而且對不上
主播 spch_pbp/ 是全遊戲最大的一區。它的名稱表 spch_pbp.txt
是 1.1 MB 的純文字,長這樣:
1b_pbp_ex ← 群組標頭(沒有數字)
yil.6+.1 230656 ← 名稱 + 在資料檔裡的位置
yil.6+.3 241152
yil.6+.4 251648
| 層 | 檔案 | 數量 |
|---|---|---|
| 名稱層 | spch_pbp.txt | 23,013 條名稱 分屬 8,889 個群組 |
| 索引層 | pbpdat.off | 2,056 段 |
| 事件層 | events.evt | 205,530 bytes(二進位) |
23,013 個名稱,但只有 2,056 個資料段。 這兩個數字差了十倍以上,所以名稱跟資料段不是一對一。 名稱表裡的 23,013 條只用到 5,704 個不重複的位置值, 代表同一段聲音會被很多個名稱共用。
這裡要誠實
本站已經解開 events.evt 的外層結構
(見下方「事件表自己會驗算」),
但沒有解出每筆事件裡各欄位的意思,也沒有解出三層之間確切的對應規則。
上面列的是量得到的數量關係,不是機制說明。
能確定的是:這三個檔的數字彼此對不上,所以不能假設「第 N 個名稱對應第 N 段聲音」。 任何想換掉主播語音的工具,都得先解決這個對應問題。
13 個分區各是什麼
| 資料夾 | 大小 | 裝什麼 | 證據 |
|---|---|---|---|
| cd | 729.0 MB | 所有分區的聲音本體,外加 9 首選單音樂 | 實測 底下依分區分資料夾,檔名與各分區的 .off 一一對應 |
| spch_pbp | 2.8 MB | 主播(逐球播報)的索引 | 實測 對應 cd/ 底下 212 MB 的資料 |
| spch_pa | 0.4 MB | 場館廣播的索引 | 實測 群組名有 7th_inning_stretch;first_aid、guest_services 這一類
是 annnc_end 群組底下的條目 |
| aems | 4.3 MB | 環境音效庫 | 實測 18 個 .abk;cd/aems/ 有 vendor、crowd4a、heckle 系列 |
| chants | <0.1 MB | 觀眾應援的索引 | 實測 名稱表叫 spch_cht,資料 56 MB |
| plyr_cht | 0.1 MB | 場上球員互相喊話(不是應援) | 實測 17 個群組、623 個音檔:
playpredict 197、defalign 177、preplay 93、
onthefly 87、inplay_call 19、inplay_confirm 22、steal 11。
本站原本照名字猜成「球員專屬應援」,打開看才知道猜錯 |
| rally | <0.1 MB | 管風琴助威曲 | 實測 3 個群組:org_lng(長)、
org_shrt(短)、takemeOUTwCrowd。
38 個音檔裡 org 開頭 30 個,另有 beat 3、
rock 2、trmpt(小號)2 |
| hmrn_sfx | <0.1 MB | 全壘打音效:煙火與警報,兩支球隊另有火車與霧笛 | 實測 3 個群組:generic、
teamspecific:03、teamspecific:19。
21 個音檔裡 16 個帶 fireworks 或 siren,
另外 5 個是 trainhorn1.03、cablecar.19、foghorn1.19、
foghorn2.19、watersplash.19 |
| stadium | <0.1 MB | 只有兩座球場有專屬音效,而且是火車跟飛機 | 實測 群組只有 stadiums:03、
stadiums:29;9 個音檔是 train、
airpln727/737/777、
airplnpassenger。詳見下面 |
| bdcst_mx | <0.1 MB | 轉播的轉場音樂 | 實測 3 個群組:intro(開場)、
firstinningtrans(第一局轉場)、inningtrans(每局轉場),
共 5 個音檔 |
| orca | 0.2 MB | 前端/暫停選單音效 | 實測 兩個檔開頭都是 BNKl,雖然副檔名一個 .bnk 一個 .gen |
| crowddb | 0.1 MB | 群眾反應的機率表 | 實測 裡面是 21 個純文字 CSV、1,478 條規則。詳見下面 |
| speechdb | <0.1 MB | 播報事件分類資料庫 | 實測 12 個純文字 CSV、1,568 筆。詳見下面 |
⚠️ 本站 2026-08-28 把 batdit 從上面那一列搬出來了
上一版把 batdit 跟 batmini、ptcmini、minicom
放在同一列,寫成「小遊戲的音效」。下面那三份證據講的其實只有
batmini 與 ptcmini(它們對上 BMG/PMG),
batdit 是被順手一起放進去的。
打開它自己的控制檔就知道了。audio\aems\batdit.abk 只有 3,612 個位元組,
裡面全是控制字串,其中三條寫著:
| CgBatterDitty_Vol | 打者上場音樂的音量 |
| gBatdit_on_or_off | 開關 |
| gBatterditty_kill | 中斷播放 |
「Batter Ditty」就是打者上場音樂,跟
出場音樂曲風那一欄是同一個東西。
這也解釋了大小差異:batdit.abk 只有 3.5 KB 的控制字串,
而 batmini.abk 與 ptcmini.abk 各有 642 KB 與 594 KB
的實際音效資料 —— 它們根本不是同一種檔。
對應的音訊庫 audio\cd\aems\batdit.ast 是 17.6 MB、
裡面有 86 段 SCHl 音訊(batmini.ast 24 段、ptcmini.ast 2 段)。
⭐ 這個錯的形狀:三份證據只證了兩個檔名,而結論被套到四個上。
檔名長得像(都以 bat 開頭、都在同一個資料夾)就一起歸類,
是最容易發生的分類錯誤。證據涵蓋到哪裡,結論就只能寫到哪裡。
噓聲、小販、裁判在哪裡
環境音效放在 audio\aems\,只有 20 個檔。
而且檔名直接說了它是什麼:
| 檔名 | 幾個 | 是什麼 | 最大的那個 |
|---|---|---|---|
| heckle a–e | 5 | 噓聲 | 62 KB |
| ump a–c | 3 | 裁判 | 228 KB |
| crowd4a/4b | 2 | 觀眾 | 1.4 MB 全區最大 |
| vendor/vndrcbp | 2 | 小販 | 17 KB |
| sfx a/b | 2 | 一般音效 | 92 KB |
| batmini/ptcmini/ minicom | 3 | 小遊戲的音效。已確認 原本標「推測」,2026-08-26 用三份互相獨立的證據關掉了 —— 見下方 | 642 KB |
| batdit | 1 | 打者上場音樂。已確認 2026-08-28 從上一列搬出來 —— 見下方 | 3.5 KB |
| tpevents | 2 | 唯二不是 .abk 的.a1c 與 .csi |
16 KB |
「名字帶 mini」原本是推測,現在關掉了
本站原本只敢寫「檔名帶 mini,可能跟小遊戲有關」。
後來在另外三個完全不同的地方各找到一份證據:
| 證據 | 在哪 |
|---|---|
混音表裡有 BMGVolume、PMGVolume、FMGVolume
三組獨立的音量群組,各自還有自己的音樂音量 |
總設定檔 |
| 遊戲的文字檔裡有 Batting Mini Game、Pitching Mini Game 這兩句選單文字 | IGENG.LOC |
frontend\minigame.big 裡 35 個版面檔,
名字是 fes_bmggamesummary.fel、fes_hudleftbmg.fel 這一類;
另有 minibat.big 與 minipit.big 各裝一張圖 |
封裝檔目錄 |
音效檔名 batmini/ptcmini 對上
BMG/PMG,
三份證據來自三種不同的檔,互相對得起來。
查下去發現一個更有意思的東西:有一個小遊戲只存在於程式內部
混音表裡除了 BMG、PMG 之外還有第三組 FMG
(FMGVolume、FMGMusicVol%),
而攝影機那邊也有一筆記錄叫
FieldingMiniGame。
但是把玩家看得到的東西找一遍:
| 找什麼 | 結果 |
|---|---|
| 語系檔裡有沒有「Fielding Mini Game」這句 | 兩個語系檔都沒有 |
audio\aems\ 底下有沒有守備小遊戲的音效庫 |
20 個檔全部列出來看過,沒有(只有 batmini、ptcmini) |
| 玩家看得到的第三個小遊戲是什麼 | Untimed Pitching Mini Game(無時限投球),不是守備 |
所以情況是:守備小遊戲在程式內部有音量群組、有專屬攝影機, 卻沒有任何一句玩家看得到的文字,也沒有自己的音效。
這通常代表「做到一半沒出」,但本站沒有證據說它是被砍掉的
—— 也可能是共用了別的資源。未解
另外,混音表裡還有第四組 HRS,那個玩家看得到:
語系檔裡是 Home Run Showdown。
18 個 .abk 檔的開頭四個位元組全部是 ABKC。
audio\cd\aems\ 底下另有 11 個 .ast,檔名一一對應。
⚠️ 本站原本在這裡寫反了
原文是「觀眾的音檔比噓聲大二十倍 ——
crowd4a.abk 有 1.4 MB,而五個噓聲檔加起來還不到 200 KB」,
然後說「合理,觀眾聲要一直播」。
那是拿索引在比,不是拿聲音在比。
.abk 是索引與音色控制,真正的聲音在
audio\cd\aems\ 的 .ast 裡。
兩邊一起列出來就看得很清楚:
索引 .abk |
聲音 .ast | |
|---|---|---|
crowd4a(觀眾) |
1,402,292 | 24,356,352 |
| 五個噓聲檔加起來 | 181,144 | 64,998,016 |
| 誰比較大 | 觀眾大 7.7 倍 | 噓聲大 2.7 倍 |
方向是反的。索引大不代表聲音多 —— 那一句連推理都是錯的:本站當時還替它編了一個「觀眾聲要一直播」的解釋, 而那個解釋讓錯誤看起來更可信。
順帶訂正上一行:「audio\cd\aems\ 底下另有 11 個
.ast,檔名一一對應」——
11 個是對的,但 18 個 .abk 裡只有 11 個有同名的 .ast,
不是全部對應。剩下 7 個(crowd4b、umpa/b/c、
sfxa/b、minicom)沒有自己的 .ast。
那 7 個的聲音放在哪,本站還沒查
應援曲:索引是純文字,而且看得出來 EA 幫誰錄了
上面說過聲音本體在 cd\chants\chantdat.big(56 MB)。
可是索引 chants\spch_cht.txt 是純文字,記事本直接打得開:
spch_cht.txt 的開頭(原檔內容)
beat_backs
beat_backs.lg.01.wav 0
beat_backs.md.01.wav 432640
mvp
mvp.lg.01.wav 0
mvp.md.01.wav 458752
pchants:0004
pchant.0004.typ1.1.lg.01.wav 0
格式很單純:一行群組名,底下每個音檔一行,後面那個數字是它在資料檔裡的位置。 原版共 90 個群組、103 個音檔。
| 群組長什麼樣 | 幾個 | 是什麼 |
|---|---|---|
| 有名字的 | 7 | beat_backs、beat_la、larry、mvp、
overrated、rally_monkey、tomahawk |
| tchants:NN | 26 | 球隊的隊呼 |
| pchants:NNNN | 57 | 某一位球員專屬的應援曲 |
| 合計 | 90 | 群組 |
驗算:這個檔非空行共 193 行 = 群組 90 + 音檔 103, 一行不多一行不少。
那個 .lg/.md 不是隨便標的
103 個音檔裡,lg 有 96 個、md 有 7 個。
把這 7 個 md 是誰的列出來:
| 群組類型 | 幾組 | 每組有幾個音檔 |
|---|---|---|
有名字的(tomahawk 那七個) | 7 | 剛好一個 lg + 一個 md |
| 球隊隊呼 | 26 | 22 組一個、3 組兩個、1 組三個 —— 全部是 lg |
| 球員專屬 | 57 | 56 組一個、1 組兩個 —— 全部是 lg |
7 個 md 剛好對應 7 個有名字的應援,一個不多一個不少。
其他 83 組一個 md 都沒有。
所以這兩個字尾不是「檔案格式」或「音質」之類每個檔都會有的東西 —— 它是只有那七個全場性的應援才錄了兩種版本。 至於那兩種版本差在哪(人數?長度?強度?), 檔案裡沒有寫,本站沒有答案
另外,檔名結尾的 .01/.02/.03
是同一段的第幾個版本:
第 2 號球隊錄了三段,第 18、19、20 號各兩段,
球員裡只有一個號碼錄了兩段。
球員的檔名帶 typ1、球隊的帶 gen1,
這兩個字串各代表什麼未解
那四位數編號指向誰,可以自己對出來
pchants:0004 的 0004,是球員資料檔裡
playerattrib_audioid 那一欄的值
(剛安裝好的原版排在第 17 欄,本站測試機那份社群名冊排在第 16 欄,
欄號會因名冊而異)。
把 57 個編號拿去 原版的 attrib.dat 對:
56 個對得上,剩下 1 個對不上(下面說)。
EA 幫這 56 個人錄了專屬應援曲
編號小於 2000 的 43 位,是 2004 年當時的現役球員:
| 4 | Bobby Abreu | 24 | Garret Anderson | 46 | Jeff Bagwell |
| 67 | Carlos Beltran | 79 | Lance Berkman | 95 | Aaron Boone |
| 96 | Bret Boone | 195 | Jose Cruz Jr. | 215 | Carlos Delgado |
| 230 | J.D. Drew | 240 | Jim Edmonds | 289 | Rafael Furcal |
| 304 | Brian Giles | 333 | Ken Griffey Jr. | 339 | Vladimir Guerrero |
| 367 | Todd Helton | 404 | Torii Hunter | 421 | Derek Jeter |
| 435 | Andruw Jones | 438 | Chipper Jones | 482 | Carlos Lee |
| 483 | Derrek Lee | 503 | Paul Lo Duca | 510 | Javy Lopez |
| 517 | Mike Lowell | 636 | Trot Nixon | 656 | Magglio Ordonez |
| 724 | Manny Ramirez | 757 | Alex Rodriguez | 761 | Ivan Rodriguez |
| 765 | Scott Rolen | 805 | Richie Sexson | 808 | Gary Sheffield |
| 867 | Mike Sweeney | 875 | Miguel Tejada | 879 | Frank Thomas |
| 880 | Jim Thome | 940 | Vernon Wells | 962 | Preston Wilson |
| 1069 | Aubrey Huff | 1239 | Albert Pujols | 1263 | Ichiro |
| 1363 | Marcus Giles | — | — |
編號 2126 之後的 13 位,全部是傳奇球員:
| 2126 | Luis Aparicio | 2127 | Richie Ashburn | 2128 | Yogi Berra |
| 2129 | Lou Brock | 2130 | Rod Carew | 2138 | Reggie Jackson |
| 2141 | Al Kaline | 2142 | Harmon Killebrew | 2147 | Willie McCovey |
| 2148 | Joe Morgan | 2153 | Pee Wee Reese | 2161 | Willie Stargell |
| 2164 | Billy Williams | — | — |
現役球員的編號散在 4 到 1363 之間,傳奇球員擠在 2126–2164。
編號本身就把兩群人分開了。
上表有一位只有一個字:Ichiro。
他在資料裡姓有、名是空的 —— 57 個人裡只有他這樣。
有一首應援曲,找不到它是為誰錄的
57 個編號裡有一個對不到人:pchants:0538 有音檔,
但 538 這個 audioid 在原版的球員資料檔裡不存在。
本站另外去看裝了模組那台,也沒有。
不過先別急著說「這是被砍掉的球員」——
原版用到的 audioid 只有 1,300 個,
範圍卻是 3 到 2665,中間有 1,363 個空號。
538 只是其中一個。
能確定的是:這首應援曲存在,而它指向的編號沒有人使用。 至於為什麼,本站沒有答案。未解
這就是 2008 年台灣玩家換應援曲的地方
當年社群把台灣模組的加油歌換進遊戲,動的就是這一套:
把聲音接進資料檔、在索引裡加一行、讓球員的 audioid 對上。
本站沒有提供做這件事的腳本,也沒有散布任何聲音檔。 這一節只講「檔案是怎麼組織的」。 ✓ 可用 想把某一首應援曲指給別的球員,有一課教這個(只改一行純文字)。
⚠️ 2026-08-29 訂正:這裡原本寫「放進自己錄的音檔目前還做不到 —— 那需要把聲音編成 EA 自家格式,本站還沒有做出那個編碼器」。
那個編碼器後來做出來了 —— 見換掉遊戲的聲音。
本站拿那支腳本對這個 56 MB 的 chantdat.big 實際跑過:它是編碼器 2、
2 聲道 24000 Hz、裡面 103 段,其中 40 段解得完整,可以匯出成 WAV、也可以編回去;
另外 63 段有區塊切不出相位,腳本會拒絕寫入(對不齊就不寫,那是保護不是故障)。
⚠️ 提醒一件跟技術無關的事:把別人的音樂放進遊戲檔案, 跟你自己在家聽是兩回事。自己錄的、有授權的、或已進入公有領域的才拿來用。
檔名裡那個數字,是球隊資料表裡的一欄
索引檔裡到處是 tchants:19、teamspecific:03、
stadiums:29 這種寫法。那個數字對得到人:
球隊資料檔 team.dat
第 6 欄 team_artid,值是 1 到 126 的連號。
26 支球隊有自己的隊呼
把 26 個 tchants:NN 對回球隊:
| 1 | Anaheim Angels | 2 | Oakland Athletics | 3 | Seattle Mariners |
| 4 | Texas Rangers | 5 | Chicago White Sox | 6 | Cleveland Indians |
| 7 | Detroit Tigers | 8 | Kansas City Royals | 9 | Minnesota Twins |
| 10 | Baltimore Orioles | 13 | Tampa Bay Devil Rays | 14 | Toronto Blue Jays |
| 15 | Arizona Diamondbacks | 16 | Colorado Rockies | 17 | Los Angeles Dodgers |
| 18 | San Diego Padres | 19 | San Francisco Giants | 20 | Chicago Cubs |
| 21 | Cincinnati Reds | 22 | Houston Astros | 23 | Milwaukee Brewers |
| 24 | Pittsburgh Pirates | 25 | St. Louis Cardinals | 27 | Florida Marlins |
| 29 | New York Mets | 30 | Philadelphia Phillies | — |
1 到 30 裡面,剛好缺四支
| 11 | Boston Red Sox |
| 12 | New York Yankees |
| 26 | Atlanta Braves |
| 28 | Washington Nationals |
而同一個索引檔裡,另外有七個不用編號、直接取名字的應援:
beat_backs beat_la larry mvp overrated rally_monkey tomahawk
本站量到的就到這裡:26 個有編號、7 個有名字、 1 到 30 裡缺這四支。 檔案裡沒有任何一行把「名字」跟「球隊」連起來, 所以本站不寫「哪個名字是哪一隊的」。 名字與球隊的對應未解
值得一提的是第 28 號:那支球隊在這款遊戲出的那一年 才剛換城市、換名字。新球隊還沒有應援可以錄,是說得通的 —— 但這是推想,不是量到的。推測
只有兩座球場有專屬音效,而且是火車跟飛機
stadium\std_spec.txt 整份只有兩個群組、九個音檔:
| 群組 | 對到哪一隊 | 音檔 |
|---|---|---|
| stadiums:03 | Seattle Mariners | train(2 個檔) |
| stadiums:29 | New York Mets | airpln727、airpln737、
airpln777、airplnpassenger(7 個檔) |
全遊戲 87 個球場封裝檔(58 座場地),只有這兩座有自己的環境音效, 而且內容是一列火車跟四種飛機(連機型都分開錄:727、737、777、還有一種客機)。
為什麼是這兩座,檔案裡沒有寫
本站量到的是:只有這兩個編號有專屬音效,內容是火車與飛機。 原因未解
一個站外的背景知識(不是本站量到的): 這兩座球場都以「比賽中聽得到交通工具」出名,一座旁邊有鐵路, 一座在機場航道底下。本站把它寫在這裡當脈絡, 但不主張 EA 是為了這個才錄的。
兩個資料庫打開就是 Excel 表
站上原本把 crowddb 與 speechdb 標成「未確認」,
理由是「只有一個 .big」。
把它們打開之後,裡面完全沒有加密也沒有壓縮,就是純文字 CSV。
群眾在什麼情況下發出什麼聲音,是一張表
crowddb\audiocsv.big 裡有 21 個 CSV、合計 1,478 條規則,
一個檔對應一種場上事件:
| 檔 | 什麼事件 | 規則數 | 檔 | 什麼事件 | 規則數 |
|---|---|---|---|---|---|
| foulcont.csv | 界外球 | 224 | forceout.csv | 封殺 | 168 |
| hitreslt.csv | 安打結果 | 144 | catchout.csv | 接殺 | 104 |
| heckevnt.csv | 噓聲事件 | 104 | hitcont.csv | 擊球接觸 | 104 |
| runscord.csv | 得分 | 77 | ball.csv | 壞球 | 72 |
| swngstrk.csv | 揮棒好球 | 64 | lkstrike.csv | 看球好球 | 64 |
| homerun.csv | 全壘打 | 32 | walk.csv | 四壞 | 32 |
另外 9 個:chants(40)、landfoul(48)、
swngstko(52)、lkstriko(52)、newbater(32)、
landfair(24)、htbypich(16)、steal(16)、
heckgen(9)。
拿全壘打那個檔來看,一行是這樣:
homerun.csv 的表頭與兩行
team_at_bat,runs_scored_play,game_state,crowd1_reaction,crowd1_percent,and_or,crowd2_reaction,crowd2_percent
away,1,earlyclose,oh_medium,100,and,none,0
away,1,lateclose,oh_high,100,and,angry,100
兩行的差別只有一欄:比賽進行到哪個階段。 客隊在比賽前段打出帶一分打點的全壘打,主場觀眾發出中等的「喔——」; 同一件事發生在後段的接近比賽,觀眾就變成 高強度的「喔——」加上憤怒,兩種都 100%。
這代表什麼
觀眾不是隨機播音效的。它有一張表, 欄位是「誰在打擊、跑回幾分、比賽階段」, 輸出是「播哪一種反應、機率多少、要不要疊第二種」。
而這張表是純文字,記事本打得開。 本站沒有實機驗證改了會怎樣
播報員那邊還多一層:EA 自己給台詞打分數
speechdb\speechdb.big 裡有 12 個 CSV、合計 1,568 筆:
204 個事件類別、166 條限制條件、8 種計數器、64 個觸發時機、76 個虛擬事件,
以及六張把它們串起來的對照表。
其中最短的那個檔只有 7 行,卻是整批資料裡最有人味的一份 —— 它是「這句話放在這個情境有多合適」的評分標準:
ContextualEventRatings.csv(EA 自己寫的分類名稱)
100.00 Perfection
10.00 Correct but jarring/random
2.00 Partial coverage
1.00 Bad samples
0.00 Just plain wrong
-1.00 Might get us sued
-1000.00 If we play this everyone will die
那兩行是開發者寫的,不是本站翻的
倒數兩個分類的原文就是
Might get us sued(可能害我們被告)與
If we play this everyone will die(放這句的話大家都會死)。
分別是 −1 分與 −1000 分。
這是一份內部評分表,跟著遊戲一起出貨了。 它讓人看到 2004 年那個音訊團隊實際在煩惱什麼: 不是「這句話好不好聽」,是「這句話會不會出事」。
本站只列出這 7 個分類名稱與分數 —— 那是資料格式的一部分,不是台詞內容。 本站不轉載任何一句播報台詞。
事件表自己會驗算
八個分區各有一個 events.evt。它是二進位檔,但結構單純,
而且自己帶著一道驗算 —— 算得對就代表你讀對了。
| 位元組 | 是什麼 |
|---|---|
| 1–4 | 固定是 03 12 3C 07(八個檔完全一樣) |
| 5–8 | 事件表從第幾個位元組開始 |
| 9–12 | 分區編號(0 到 7) |
| 17–20 | 事件有幾筆 |
| 接下來 | 每筆 32 個位元組的事件表 |
| 再接下來 | 一串以 0 結尾的事件名稱 |
驗算式
事件表起點 + 筆數 × 32 = 名稱表的起點
名稱表切出來的字串數 = 筆數
八個檔全部通過,零例外。
| 分區 | 編號 | 事件筆數 | 切出來的名稱數 | 檔案大小 |
|---|---|---|---|---|
| spch_pbp | 0 | 472 | 472 | 205,530 |
| spch_pa | 1 | 23 | 23 | 2,800 |
| plyr_cht | 2 | 7 | 7 | 6,328 |
| chants | 3 | 10 | 10 | 1,108 |
| rally | 4 | 3 | 3 | 286 |
| stadium | 5 | 1 | 1 | 104 |
| hmrn_sfx | 6 | 1 | 1 | 220 |
| bdcst_mx | 7 | 3 | 3 | 271 |
分區編號 0 到 7,一個不缺,順序跟上面那張分區表對得起來。
想自己驗,從最小的那個開始
stadium\events.evt 只有 104 個位元組、只有一筆事件。
用十六進位工具打開,
整個檔可以用眼睛數完。算對了再去看 472 筆的那個大檔。
解開的是外殼,不是內容
知道「有幾筆、每筆佔幾個位元組、事件叫什麼名字」, 但每筆那 32 個位元組裡各欄位是什麼意思,本站沒有解出; 第 13–16 個位元組也還沒解讀。未解
那 9 個 .asf 不是 ASF
選單音樂的副檔名是 .asf,看起來就是微軟的
Advanced Systems Format。不是。
微軟 ASF 的檔案開頭四個位元組是 30 26 B2 75。
實際打開這 9 個檔:
menu1.asf 53 43 48 6c SCHl
menu2.asf 53 43 48 6c SCHl
...(9 個全部一樣)
SCHl 就是這一頁前面講過的 EA 自家音訊容器。
換句話說,選單音樂跟主播語音用的是同一種容器,只是副檔名不同。
整個 data\ 底下沒有一個真正的 ASF
本站把 data\ 底下所有 .asf、.wma、.mp3
全部掃過一遍,比對檔頭:一個真的都沒有。
9 個 .asf 全是 SCHl,其餘兩種副檔名一個檔都沒有。
自己驗(把路徑換成你的遊戲資料夾):
xxd -l 4 "…\data\audio\cd\music\menu1.asf"
⚠️ 本站改過這一段
這頁與另外兩頁原本寫「選單音樂檔案層級直接換,不必解析格式」。
那句話沒有任何量測支持 —— 照字面把一個 MP3 改名成
menu1.asf 丟進去,是在賭遊戲讀不讀得動,而本站沒有實測過。
現在改成上面的寫法:副檔名是騙人的,容器是 SCHl,
裡面是 EA 自己的編碼。
(2026-09-05 訂正:這一段原本接著寫「最內層的聲音編碼本站沒有解開, 所以本站不寫換選單音樂的教學」,還掛著一個未解徽章。那句話已經失效 —— 最內層的編碼 2026-08-29 解開了(見下面換播報語音那一節的狀態表), 課也開了:七分鐘置換遊戲音樂、 換掉遊戲的聲音。 但格子是定長的,比原本長的歌會被切掉,所以仍然不是「丟進去就好」。)
✅ 這個問號 2026-08-28 關掉了
這一段原本寫著:「本站測試機這 9 個檔的日期是 2023 年,代表已經被模組換過,
所以 EA 原廠出貨時是不是也用 SCHl,本站無法確認。」
後來拿到兩份剛安裝好、沒動過的遊戲(官方英文版與官方繁體中文版), 同樣的量法再跑一次:
.asf 個數 | 開頭是 SCHl | 真正的微軟 ASF | |
|---|---|---|---|
| 剛安裝好的英文版 | 9 | 9 | 0 |
| 剛安裝好的中文版 | 9 | 9 | 0 |
是 EA 自己這樣出貨的,不是模組留下的。
兩份原版的 data\ 底下也一個 .wma、.mp3、.wav、.ogg 都沒有。
順便把語音也整份數了。剛安裝好的中文版 data/audio/ 裡,
封裝檔內共 14,023 筆:6,995 筆聲音全部是 SCHl(100%)、
6,995 筆是配對的檔頭記錄、33 筆是純文字的事件與對照表。
聲音與檔頭剛好 1:1,跟這一頁前面講的配對關係對得起來。
⚠️ 這裡有一個容易上當的數字:如果把 14,023 筆一起算, 「SCHl 佔 49.88%」看起來像有一半格式不明。 分母裡混了本來就不是聲音的檔頭記錄。 算比例之前先問分母裡有什麼 —— 這是本站反覆踩到的坑。
二十年前的社群教學早就在轉「asf」了 —— 但那是 EA 的 asf
2008 年 7 月,一位叫 brime 的玩家在遊戲基地寫過一篇做應援曲的教學,
裡面的關鍵一行是用 EA 自己的 sx 工具批次轉檔,
轉完再把副檔名改成 .dat 丟進遊戲。
那篇教學把中間產物叫作「asf」。照字面看會以為是 Windows Media,
但實際做出來的東西開頭是 SCHl ——
因為轉檔的是 EA 自己的工具,它口中的 asf 是 EA 的 asf。
同一個副檔名,兩種完全不同的格式。 當年沒有人被這件事絆倒,是因為大家用的都是 EA 的工具, 一路上根本沒機會遇到微軟那個 ASF。 會踩到坑的是二十年後照著文字重做的人 —— 例如本站。
本站不重貼那篇教學的內容,也不提供任何工具下載。 這裡記的是它讓本站確認了什麼:容器從 2005 年到現在沒有變過。
想換聲音的話
| 你可能想做的事 | 現況 |
|---|---|
| 換掉選單音樂 | 做得到但有但書 cd/music/ 底下 9 個 .asf(menu1–menu9),
但那個副檔名是騙人的 —— 見上面〈那 9 個 .asf 不是 ASF〉。
做法見七分鐘置換遊戲音樂;
格子是定長的,比原本長的歌會被切掉 |
| 換掉主播唸的名字 | 做得到 —— 而且二十年前就有人做了,見下方訂正 |
| 加入中文播報 | 做得到但工作量極大 技術路徑同上一列(格式已經解開),
卡的是 spch_pbp.txt 那 23,013 條名稱要一條一條錄,不是格式沒解開 |
| 換掉全壘打音效/應援 | 兩半不一樣 索引結構已清楚;SCHl 內部編碼 2026-08-29 解開了
(見換掉遊戲的聲音)。
本站實測:應援曲 chantdat.big 是編碼器 2,103 段裡 40 段寫得回去;
全壘打音效 hsfxdat.big 是編碼器 3,那一種 2026-08-30 已經處理了
(卡的是位元組序不是編碼器),但這個檔的 19 段編碼器 3 目前一段都解不出來 |
完整的可改/不可改分級見 什麼改得動、什麼還不行。
⚠️ 本站 2026-08-28 訂正:換播報語音做得到
錯在哪
本頁原本把「換掉主播的某一句話」標成 未解, 理由是「SCHl 內部編碼未解」。
那個理由把「未解」貼在錯的層次。 要換語音,需要的不是「把 EA 的音訊解碼出來」, 而是「產生一個遊戲吃得下去的檔」—— 那是兩件事。
證據:社群做的語音檔跟 EA 的不是同一種子格式,而遊戲照吃
本站把剛安裝好的原版與兩個社群語音包的每一個聲音檔,
讀它們 SCHl 後面那四個位元組:
| 聲音檔數 | 子格式 | |
|---|---|---|
| 剛安裝好的原版 | 6,995 | PT —— 6,995 個全部是,零例外 |
| 一個社群語音包 | 481 | GSTR 474 個、PT 7 個 |
| 另一個台灣語音包 | 69 | GSTR 63 個、PT 6 個 |
那些包是當年真的裝來玩的。所以遊戲兩種子格式都吃 ——
而 GSTR(generic stream)正是 EA 自家轉檔工具的輸出。
換句話說:不必解開 EA 的編碼,用 EA 自己的工具產生一個就好。 2008 年那批社群教學記錄的正是這個流程。
整條路每一段的狀態
| 步驟 | 狀態 |
|---|---|
檔頭 .hdr(16 個位元組) |
完全解開 前四個位元組 = 編號 × 65536 + 類別碼。 原版 4,580/4,580、社群 447/450、另一包 69/69 全部成立, 而類別碼在原版與社群完全一致 (見語音檔頭) |
聲音 .dat 的容器 |
完全解開 SCHl,遊戲吃 PT 也吃 GSTR
(原版 6,995/6,995 標籤長度吻合) |
| 聲音資料怎麼擺 | 完全解開 每段開頭是取樣數 + 聲道起點表, 兩個聲道各自連續,不是交錯;社群包 1,945 段零例外 (見拆開一個語音檔) |
| 一個聲道裡怎麼切 | 完全解開 每 15 個位元組一組。 掃相位 97.7%,切錯時約 50%(=亂猜的水準);左右聲道各自獨立印證 |
怎麼產生一個 GSTR |
有現成路徑 EA 自己的轉檔工具,社群用了二十年 |
| 配對規則 | 完全解開 a/c/d 三個要做齊,
.hdr 與 .dat 一比一
(見當機診斷) |
| 15 個位元組還原成 28 個取樣的公式 | 2026-08-29 解開了 —— 係數表與位移公式都出來了,
解碼對照 ffmpeg 的 21,678,328 個取樣 0 個不同,
編碼寫回去再讀出來 98.1 dB。做法見
換掉遊戲的聲音。
(原本這一格寫「未解 —— 試過一千種以上的參數組合,最好只有 0.16」。 那不是不夠努力,是當時沒有東西能告訴我「你錯了」; 後來拿 ffmpeg 當標準答案,一次就對上。) |
所以本站原本說「做不到」是錯的。正確的說法是: 做得到,而本站還沒有從頭到尾做過一次。
(2026-09-06 訂正:「還沒有從頭到尾做過一次」這句已經過期。
換掉遊戲的聲音那一課 2026-08-29 開了,
檔案層級的一整趟本站走過:拿剛安裝好的原版切出的 8 個區塊做「匯出 → 匯入 →
再用 ffmpeg 當獨立解碼器讀回來」,0 個取樣不同。
還沒驗的只剩最後一步 —— 換完之後遊戲裡真的會不會唸出來,本站沒有實機聽過。)
這一課後來做出來了(2026-08-29)
這裡原本寫「因為它需要一支本站沒有、也不散布的轉檔工具, 那一步目前只有 EA 自己的工具做得到」。
那句話已經不成立。本站現在有一支純 Python、零相依的編碼器
(mvp_audio.py),寫得回去,課也開了:
換掉遊戲的聲音。
⭐ 這條訂正的教訓:「未解」要貼在真正卡住的那一格,不要貼在整條路上。 本站原本因為「編碼沒解開」就把整件事標成做不到, 但真正需要的能力是「產生」不是「解讀」 —— 而那一格早就有人走通了。
⭐ 後續:那一格後來整個關掉了。本站先把容器裡面量開 (聲道怎麼擺、一個聲道裡怎麼切),最後連「15 個位元組怎麼變回 28 個取樣」也解開了。 完整過程(含一個差點推翻正確結論的假紅燈)在 拆開一個語音檔。
📌 重點整理
- 一句話 音訊這一區比整個遊戲其他部分加起來還大,它的索引是純文字、可以自己加總驗算,而這裡的副檔名一再騙人。
- 規模與那道免費驗算 13 個分區、111 個檔、736.9 MB,其中 729 MB 集中在
cd/,最大的單一檔是 212 MB 的主播語音。.off索引是純文字,把裡面所有「長度」加起來會剛好等於對應資料檔的大小,本站算過的 16 個全部相符,一個 byte 都不差。events.evt也自帶一道驗算,八個檔零例外。 - 最容易誤讀的:看副檔名
data/audio/底下 28 個.big,真正是 BIGF 封裝檔的只有 12 個(8 個是SCHl音訊容器、8 個*hdr.big開頭四碼沒有兩個一樣)。看到.big就套 BIGF 解析器,28 個裡會有 16 個當場失敗。9 個選單音樂的.asf也不是微軟 ASF,兩份剛安裝好的原版量下來都是 9 個全部SCHl。判準是開頭四個位元組。 - 名稱跟聲音不是一對一 主播那一區有 23,013 條名稱(18,492 個不重複),卻只有 2,056 個資料段,只用到 5,704 個不重複的位置值。不能假設「第 N 個名稱對應第 N 段聲音」。
- 本站訂正一:方向整個寫反了 原本寫「觀眾的音檔比噓聲大二十倍」,那是拿索引在比。真正的聲音在
.ast裡,論聲音是噓聲大 2.7 倍、論索引才是觀眾大 7.7 倍。更糟的是本站當時還替它編了一個「觀眾聲要一直播」的解釋,讓錯誤看起來更可信。 - 本站訂正二:「未解」貼錯了層次 換播報語音原本標成做不到,理由是「SCHl 內部編碼未解」。實際上要換語音需要的是產生一個遊戲吃得下去的檔,不是把 EA 錄的解碼出來;社群語音包用的是
GSTR子格式而遊戲照吃。同一輪也把batdit從「小遊戲音效」那一列搬出來,它是打者上場音樂,原本的三份證據只證了batmini與ptcmini兩個檔名。 - 順手撿到的
speechdb裡跟著遊戲出貨的是一張 EA 內部評分表,最低兩級寫著Might get us sued(−1 分)與If we play this everyone will die(−1000 分)。另外全遊戲 87 個球場封裝檔(58 座場地)只有兩座有專屬環境音效,內容是一列火車跟四種飛機;EA 錄了 57 組球員專屬應援曲(剛安裝好的英文版原版、剛安裝好的中文版原版、本站測試機三份spch_cht.txt都是 57 組,號碼集合完全相同),其中 56 組在兩份原版的名冊裡對得到球員、13 位是傳奇球員,剩下的pchants:0538指向沒有人使用的編號;編號本身就把兩群人分開了。 - 本站沒驗的 應援曲
lg/md兩種版本差在哪、檔名裡的typ1/gen1各代表什麼、七個有名字的應援分別屬於哪一隊、pchants:0538為什麼指向一個沒人使用的編號、那兩座球場為什麼是它們、events.evt每筆 32 個位元組裡的欄位意義、18 個.abk裡沒有同名.ast的那 7 個聲音放在哪,全部未解。群眾反應那張機率表改了會怎樣,本站沒有實機驗證。(「15 個位元組還原成 28 個取樣」的公式原本也列在這一條裡,2026-08-29 已經解開 —— 對照 ffmpeg 驗過 21,678,328 個取樣 0 個不同,見上面〈整條路每一段的狀態〉那張表。)