Web Audio API 第3章 音量和響度

池中物王二狗發表於2024-03-29

此章介紹的科普物理聲音知識相當有用,程式設計的反而涉及的少

音量和響度

Loudness 響度 注:根據《韋氏詞典》,響度是“一種聲音的屬性,它決定了所產生的聽覺感覺的大小,主要取決於所涉及聲波的振幅。”這意味著響度取決於你大腦中感知到的聲音。而是聲音對你來說有多大。這是主觀的——例如,對你來說很響的聲音對有聽力問題的人來說可能聽不到

Volume 音量 注:我們通常用在收音機、電視、立體聲或其他樂器上。你可以用控制按鈕或滑塊來控制響度。即使響度仍然是基於你的感知,樂器也可以以不同的水平播放音訊

一旦我們準備與聲音打交道,無論是 AudioBuffer 還是其它來源的聲音,最基本的可控引數就是聲音的響度

最主要可以影響音量響度的方式就是使用 GainNode。正如之前提到過的,音訊節點都有一個 gain 引數,作為聲音輸入緩衝的乘數。預設值是 1,意為著沒有任何影響。值從 0 至 1,如果值超過了 1 則放大了輸入聲音的響度。將 gain 值設為負值(值小於0) 則波形反轉(幅度翻轉了)。

重要理論: 音量(Volume),增益(Gain) 和響度(Loudness)

讓我們從它們的定義開始。響度是我們耳朵理解聲音的主觀衡量。音量是從物理聲波振幅來衡量。增益則是處理聲波過程中對其波形振幅乘數縮放。

換句話來說,增益時一個聲音波形的振幅乘以增益乘數後被縮放了。舉個例子,當值為 1 時不影響聲音波形,圖 3-1 圖示了當聲音波形透過增益值為2的節點後的結果

image

圖 3-1 左側是原波形,右側是增益2後的波形

一般來說,波的功率以分貝(decibels, 縮寫為dB)或貝爾的十分之一來測量,貝爾以亞歷山大·格雷厄姆·貝爾命名。分貝是相對的,將被測量的等級與某個參考點進行比較的對數單位。有多種不同的參考點用於測試分貝,每一種參考點都有著指示字首單位。沒有參考點說訊號的分貝是無意義的!舉個例子,dBV, dBu, 和 dBm 都是非常有用的衡量電訊號方式。由於我們僅關心數字音訊,我們主要關心兩種測量方式: dBFS 和 dBSPL

第一種 dBFS (decibels full scale) .音訊裝置產生的最高聲級是0 dBFS。** 所有其他級別都以負數表示 **.

dBFS 的數學描述如下:

dBFS = 20 * log( [sample level] / [max level] )

dBFS 最大值 在 16位音訊系統中:

max = 20 * log(1111 1111 1111 1111/1111 1111 1111 1111) = log(1) = 0

注意,dBFS 由定義可得最大值總是為 0

最小 dBFS 值在類似的系統中是:

min = 20 * log(0000 0000 0000 0001/1111 1111 1111 1111) = -96 dBFS

** dBFS 衡量的是增益而非音量。** 你可以試試 0-dBFS 將立體聲節點增益設為最小值,這樣應該幾乎就聽不到了。相反如果是 −30-dBFS這樣的低音量,如果設一個最大的增益值,那麼依然可能將你的耳膜吹破。

儘管如此,你還是很可能聽到有人跟你用分貝來描述用音量。從技術上講,他們指的是dBSPL,(decibels relative to sound pressure level)即分貝相對聲壓等級的。這裡,參考點是每平方米0.000002牛頓(大約是蚊子在3米外飛行的聲音)。dBSPL 沒有上限,但在實踐中,我們希望保持在耳朵損傷水平(~120 dBSPL)以下,遠低於疼痛閾值(~150 dBSPL)。Web Audio API 不使用 dBSPL,只使用 dBFS 這是因為最終音量取決於作業系統的增益和楊聲器的增益。

分貝的對數定義在某種程度上與我們的耳朵感知聲響的方式有關, 但響度依然是時分主觀的概念。將一個聲音的dB值與具有2倍增益的相同聲音進行比較,我們可以看到差值大約是 6dB

diff = 20 * log(2/2^16) - 20 * log(1/2^16) = 6.02 dB

每次增加 6dB 左右,我們實際是對訊號放大了雙倍。對比搖滾音樂會(~110 dBSPL) 與你的鬧鐘(~80 dBSPL), 兩者之差是 (110 − 80)/6 dB,或大概是5倍大小,即增益乘數2^5 = 32倍。立體音響的旋鈕音量調節也是標準的指數增幅。也就是說音量旋鈕轉3個刻度單位意即音訊號增大2的3次方也就是8倍。在此用指數模型描述僅僅是近似我們人耳認知的聲響,而音響生產商一般都有自己的定製化增益曲線它即不是線性也不是指數形。

注:人耳對舒適聲音的範圍一般在20-40分貝之間,猶如輕聲絮語。一般情況下,人體所能承受的音量是在80分貝以下,如果長期在80分貝以上的環境生活,就會出現頭痛,記憶力衰減以致失眠等症狀。當人耳聽到的音量達100分貝時,時間較長可造成不可恢復性的聽力損傷;長時間受120分貝以上音量的刺激,聽覺細胞就會受到永久性的破壞,嚴重者還會造成聽力喪失。

等功率交叉漸變(crossfade)

在遊戲開發中,你會遇到一種情況,就是在兩個擁有不同聲音的環境中交叉漸變(crossfade), 然而什麼時候漸變,漸變多少不是提前已知的; 很有可能是根據玩家的位置而變化的,這取決於玩家對角色的控制位置。所以在這種情況下,我們無法做到自動計算。

通常,直接進行線性漸變會得到以下圖。它可能聽起來不平衡,因為兩個樣本之間的音量下降,如圖 3-2

image

圖 3-2 兩條音軌的線性交叉漸變

為了解決這種情況,我們使用等功率曲線,其中相應的增益曲線既不是線性的也不是指數的,它會在更高的振幅處相交圖 3-3 。這有助於當兩個聲音均勻地混合在一起時避免在交叉漸變的中間部分音量下降。

image

圖 3-3 等功率曲線線性交叉漸變要好的多

圖 3-3 用一點點數學就能搞定:

function equalPowerCrossfade(percent) {
  // Use an equal-power crossfading curve:
  var gain1 = Math.cos(percent * 0.5*Math.PI);
  var gain2 = Math.cos((1.0 - percent) * 0.5*Math.PI); 
  this.ctl1.gainNode.gain.value = gain1; 
  this.ctl2.gainNode.gain.value = gain2;
}

重要理論: 裁剪和計量

就像圖片邊界超過 canvas ,聲音波形如果超出最大值限制也可以被裁剪。這種顯著的失真肯定是不能接受的。為了不讓工程師和使用者感知處理音訊時不被裁剪,音響裝置通常會提供指示器顯示音訊數值等級。這些指示器被稱為 meters (圖 3-4),它通常有一個綠色區域(不裁剪),黃色區域(接近裁剪區),紅色區(裁剪)。

image

圖 3-4

被裁剪的聲音看起來和聽起來都不太好。重要的是要聽刺耳的失真,或者相反,過度柔和的混音,迫使你的聽眾調大音量。如果你處於以上任何一種情況,請繼續往下讀

使用儀表檢測與阻止裁剪

由於同時播放的多個聲音是疊加的,這些聲音音量沒有降低階別,你可能會發現自己處於超出揚聲器能力閾值的情況。16位的音訊音量最高階 是 0 dBFS, 或 216。在訊號的浮點數版本中,這些位元值都對映到了 [-1, 1]. 聲音的波形被裁剪看起來像是圖 3-5, 在 Web Audio API 上下文中,傳遞給目的節點(destination node)值如果超過了目的節點裝置的範圍則會發生裁剪。給最後混音留出一些空間(稱為 headroom) 的做法就很好,這樣你就不會太接近裁剪閾值了。

image

圖 3-5 波形被裁剪的示意圖

除了仔細聆聽之外,您還可以透過將指令碼處理器節點放入音訊圖中來檢查是否以程式設計方式擷取聲音。如果任何 PCM 值超出可接受範圍,可能會發生剪下。在這個示例中,我們檢查左通道和右通道的裁剪,如果檢測到裁剪,則儲存最後的裁剪時間:

function onProcess(e) {
  var leftBuffer = e.inputBuffer.getChannelData(0); 
  var rightBuffer = e.inputBuffer.getChannelData(1); 
  checkClipping(leftBuffer); 
  checkClipping(rightBuffer);
}

function checkClipping(buffer) {
  var isClipping = false;
  // 檢測迴圈迭代 buffer 是否超出值 1
  for (var i = 0; i < buffer.length; i++) {
    var absValue = Math.abs(buffer[i]); 
    if (absValue >= 1.0) {
      isClipping = true;
      break; 
    }
  }
  this.isClipping = isClipping; 
  if (isClipping) {
    lastClipTime = new Date(); 
  }
}

測量的另一種實現方式是在音訊圖內輪詢一個實時解析器,在渲染時為 getFloatFrequencyData,它取決於 requestAnimationFrame 方法(見第5章)。這種方式更高效,但訊號丟失的比較多(包含用於可能裁剪的空間位置),由於渲染大多是每秒 60次,而音訊訊號相對變化的更快

阻止裁剪的方式是降低訊號總電平。如果您正在進行音訊剪輯,請在主音訊增益節點上應用一些分數增益,以使您的混音降低到阻止裁剪。一般來說,你應該調整增益來預測最壞的情況, 但把它調的更好則是一種藝術而非科學的事兒了。由於遊戲或互動式應用程式中播放的聲音可能取決於執行時決定的各種因素,因此很難在所有情況下選擇阻止裁剪的主增益節點值。對於這種不可預測的情況,請考慮動態壓縮( Dynamics Compression )

重要理論: 理解動態範圍

動態範圍:音訊或廣播系統能夠傳輸或重現的最強和最弱聲音強度之比, 具體來說,最強聲音強度指的是系統能夠產生或傳輸的最大響度或音量,而最弱聲音強度則指系統能夠檢測或重現的最小響度或音量。這個比例反映了系統在聲音強度方面的表現力和解析度。

較高的聲音強度之比意味著系統能夠呈現出更明顯的音量差異,從而提供更豐富的音訊細節和動態範圍。例如,一個具有較大聲音強度之比的系統可以更好地表現出輕柔的聲音和強烈的聲音,使聽眾能夠感受到更廣闊的音訊頻譜和更強的音訊衝擊力。

相反,較小的聲音強度之比可能意味著系統在處理音量差異方面的能力較弱,可能會導致一些細節丟失或音訊表現力的受限。

在音訊領域,動態範圍是聲音的最高音與最低音的之間的部分。音樂作品的動態範圍因流派而異。經典音樂擁有大的動態範圍並且有非常安靜的部分常伴有跟著的相關的響亮部分。而流行音樂如搖滾和電子樂則傾向於小的動態範圍,並且由於明顯的競爭(被蔑稱為“響度戰爭”)來提高音高以滿足消費者的需求,所以聲音都很響。這種均勻的響度通常是透過使用動態範圍壓縮來實現的。

有多種合理的動態壓縮手段可用。有時候錄製的音樂有一個大的動態範圍,其中有非常高和非常低的片段以至於聽者需要不斷用手指調節音量旋鈕。壓縮可以使大聲的部分安靜下來,同時使安靜下來的部分可以被聽到 圖 3-6 展示了波形上圖是正常波形圖下圖是壓縮後的。你可以看到聲音都變大了,且振幅差異也小了。

image

在遊戲和互動式應用中,你可能事先不知道你的聲音輸出會是什麼樣子。由於遊戲天然的動態性,你可能需要在一個非常安靜的音訊週期(比如,鬼鬼祟祟的溜)後跟一個高音(比如,遊戲《使命召喚:戰爭地帶》)。一個壓縮節點對需要處理聲音突然變高音的情況下下非常有用,可以降低被裁剪的可能性。

壓縮器可以用包含多個引數的壓縮曲線來建模,所有這些引數都可以透過 Web Audio API 進行調整。兩個主要的的可調引數是 threshold 和 ratio。Threshold 閾值是指壓縮器 開始減小動態範圍的最低音量。ratio 比率決定了壓縮器應用多少增益降低。圖 3-7 闡述了閾值與變化的壓縮比率在壓縮曲線上的影響效果。

image

動態壓縮

壓縮器在 Web Audio API 中也能使用被叫做 DynamicsCompressorNodes。使用溫和的動態壓縮量在混音中是比較好的做法,特別是在我們之討論過的在不知道何時何地播放聲音遊戲設定中。有一種情況下應該避免使用壓縮,那就是在曲目被故意設計成這樣,因為已經被精確調好,它不應該再和其它通道混合了。

在 Web Audio API 內實現動態壓縮比較簡單,只要在音訊圖內引入一個動態壓縮器節點,一般就是在目標節點之前:

var compressor = context.createDynamicsCompressor(); 
mix.connect(compressor); 
compressor.connect(context.destination);

此節點還可以被配置一些額外的引數,正如描述過的理論章節中所述,但對於大多數情況預設值已經相當棒。更多關於壓縮曲線的配置資訊,可以檢視 Web Audio API 說明書


注:轉載請註明出處部落格園:王二狗Sheldon池中物 (willian12345@126.com)

相關文章