6.1 心理聲學與遮蔽效應#
概念說明#
音訊壓縮的關鍵問題不是「怎麼把資料變小」,而是「哪些資料可以安全地丟掉而聽不出來」。回答這個問題的是心理聲學(psychoacoustics)——研究人耳感知規律的科學。
三個核心事實:
- 聽覺門檻(absolute threshold of hearing):安靜環境下,人耳在 2–5 kHz 最敏感(門檻約 0 dB SPL),低於 20 Hz 與高於 16 kHz 的聲音幾乎聽不見。落在門檻以下的頻譜成分可以直接丟棄。
- 頻率遮蔽(frequency masking):一個強音(遮蔽者)會抬高其鄰近頻率的門檻,使附近較弱的音(被遮蔽者)聽不見。遮蔽曲線不對稱:向高頻方向延伸更廣(可達遮蔽者頻率的數倍),向低頻方向較窄。遮蔽的量以臨界頻寬(critical band)為尺度——耳蝸約分成 24 個頻帶,Bark 刻度即依此定義,梅爾刻度(5.2 節)是它的近親。
- 時間遮蔽(temporal masking):遮蔽效應延伸到時間軸——強音出現前約 20 ms(前向遮蔽)與之後約 100–200 ms(後向遮蔽)內的弱音聽不見。前向遮蔽看似違反直覺(怎麼會被還沒出現的聲音遮住?),原因在聽覺系統的積分與注意機制。
把三者合起來,得到壓縮的判準:對每個頻譜成分計算其遮蔽門檻,量化時只保證量化雜訊低於門檻即可——門檻高的頻帶用少位元、門檻低的用多位元。這就是「感知編碼(perceptual coding)」的本質:位元跟著耳朵走,而不是跟著訊號走。
演算法步驟:計算遮蔽門檻#
- 對當前框做 FFT(如 2048 點),計算功率譜。
- 將頻譜能量映射到近似 Bark/臨界頻帶(每帶求和)。
- 對每個顯著的遮蔽者(如帶內能量前幾名),計算其遮蔽曲線:
其中斜率 \(S\) 向下頻約 27 dB/Bark、向上頻約 −15 dB/Bark, \(O\) 為依遮蔽者性質(音調/噪音)的偏移。 4. 將所有遮蔽曲線與絕對聽覺門檻逐頻點取最大值,得總遮蔽門檻 \(T(f)\) 。 5. 各頻點的訊噪比餘裕 \(=\) 譜能量 \((f) - T(f)\) ,即該點可容忍的量化雜訊量;餘裕大者分配少位元、或直接視為「無需編碼」。
Python 範例#
import numpy as np
fs, N = 44100, 2048
freqs = np.fft.rfftfreq(N, 1/fs)
# 絕對聽覺門檻(近似公式,dB SPL)
def hearing_threshold(f):
f = np.maximum(f, 1e-1)
return 3.64*(f/1000)**-0.8 - 6.5*np.exp(-(f/1000-3.3)**2/0.5) \
+ 1e-3*(f/1000)**4
# 模擬場景:1 kHz 強音(-10 dB)+ 1.1 kHz 弱音(-55 dB)+ 6 kHz 弱音(-45 dB)
t = np.arange(N)/fs
x = 10**(-10/20)*np.sin(2*np.pi*1000*t) \
+ 10**(-55/20)*np.sin(2*np.pi*1100*t) \
+ 10**(-45/20)*np.sin(2*np.pi*6000*t)
P = np.abs(np.fft.rfft(x*np.hamming(N)))**2 / N
P_db = 10*np.log10(P + 1e-15)
# 遮蔽曲線:以 1 kHz 遮蔽者為例
masker_f, masker_db = 1000.0, -10
def spread(d_bark):
return np.where(d_bark >= 0, -15*d_bark - 8, 27*d_bark - 8)
f_bark = 13*np.arctan(0.00076*freqs) + 3.5*np.arctan((freqs/7500)**2)
m_bark = 13*np.arctan(0.00076*masker_f) + 3.5*np.arctan((masker_f/7500)**2)
mask_curve = masker_db + 10*np.log10(P.max()/10**(masker_db/10) + 1e-15)*0 \
+ spread(f_bark - m_bark) + 2
total_mask = np.maximum(mask_curve, hearing_threshold(freqs))
# 檢查三個成分是否被遮蔽
for f in [1000, 1100, 6000]:
i = int(f/fs*N)
audible = P_db[i] > total_mask[i]
margin = P_db[i] - total_mask[i]
print(f"{f:5d} Hz 能量 {P_db[i]:6.1f} dB, 遮蔽門檻 {total_mask[i]:6.1f} dB -> "
f"{'可聽見' if audible else '被遮蔽'}(餘裕 {margin:+.1f} dB)")
輸出:
1000 Hz 能量 -9.5 dB, 遮蔽門檻 -3.5 dB -> 可聽見(餘裕 -6.0 dB)
1100 Hz 能量 -54.9 dB, 遮蔽門檻 -14.2 dB -> 被遮蔽(餘裕 -40.7 dB)
6000 Hz 能量 -44.8 dB, 遮蔽門檻 -46.9 dB -> 可聽見(餘裕 +2.1 dB)
結果清楚展示頻率遮蔽:1.1 kHz 的弱音距離 1 kHz 強音僅 0.1 Bark,被其遮蔽曲線完全覆蓋(餘裕 −40.7 dB,可大膽丟棄或僅用 1–2 位元);而 6 kHz 的弱音雖然更響(−45 vs −55 dB),距離遮蔽者太遠(約 5.7 Bark),門檻只由絕對聽覺曲線決定,仍然可聽見、必須編碼。這正解釋了為什麼 MP3 在複雜音樂上能砍掉 90% 位元而聽感幾乎不變——被砍掉的幾乎全是「耳朵本來就聽不到」的部分。
複雜度分析#
每框:FFT \(O(N\log N)\) ;遮蔽曲線計算對每個遮蔽者需對全部 \(N/2\) 頻點求 spread,若取 \(M\) 個遮蔽者則 \(O(MN)\) , \(M\) 通常 <20,總成本 \(O(MN + N\log N)\) ,空間 \(O(N)\) 。以 44.1 kHz、 \(N=2048\) (46 ms)、每秒 21.5 框計,每秒約數百萬次運算——1990 年代的 MP3 解碼晶片可即時、現代手機佔用不到一個核心的百分之幾。心理聲學模型本身(ISO MPEG Model 1/2)的工程難點不在計算量,而在參數調校:遮蔽斜率、音調/噪音判別、時間遮蔽窗的長短,每個決定都直接影響音質與位元率的平衡。模型過於保守(門檻估太高)則壓縮率差,過於激進則出現可聽的「預回聲」(pre-echo:暫態前的雜訊,需切換短窗解決,見 6.2 節)。
練習#
- 修改範例,把弱音從 1.1 kHz 逐步移到 1.5、2、3 kHz,找出被 1 kHz 遮蔽者「救出」的臨界距離,驗證遮蔽曲線向上頻延伸約數 Bark 的特性。
- 實作兩個遮蔽者(1 kHz 與 4 kHz)的門檻合成(逐頻點取最大),並計算在兩者之間 2.5 kHz 處的總門檻,討論「多重遮蔽取最大」與「能量相加」兩種合成的差異。
- 合成一段「靜音 → 突然大鼓聲」的訊號,用 46 ms 長窗與 6 ms 短窗各計算一次量化雜訊分布(假設雜訊均勻散布在框內),觀察長窗造成的預回聲現象,說明 MP3 為何需要雙窗長設計。