在實時音訊互動場景中,除了我們上一篇講到的編解碼會影響音質與體驗,在端上,降噪、回聲消除、自動增益模組同樣起著重要作用。在本篇內容中我們將主要圍繞回聲消除和降噪模組,講講實時互動場景下的技術挑戰,以及我們的解決思路與實踐。
回聲消除的三大演算法模組優化
在語音通訊系統中,回聲消除(Echo Cancellation)一直扮演著核心演算法的角色。一般來說,回聲消除的效果受諸多因素的影響,包括:
- 聲學環境,包括反射,混響等;
- 通話裝置本身聲學設計,包括音腔設計以及器件的非線性失真等;
- 系統效能,處理器的計算能力以及作業系統執行緒排程的能力。
聲網回聲消除演算法在設計之初,就將演算法效能、魯棒性和普適性作為最終的優化目標,這一點對於一個優秀的音視訊 SDK 來說至關重要。
首先,回聲是怎麼產生的?簡單來講,就是你的聲音從對方的揚聲器發出,這個聲音又被他的麥克風給收錄了進去,這個被麥克風收錄的聲音又傳回到你這一端,你就聽到了回聲。為了消除回聲,我們就要設計一個演算法將這個聲音訊號從麥克風訊號中去除掉。
那麼聲學回聲消除模組(AEC, Acoustic Echo Cancellation)是如何消除回聲的呢?具體的步驟見如下簡圖所示:
- 第一步需要找到參考訊號/揚聲器訊號(藍色折線)跟麥克風訊號(紅色折線)之間的延遲,也就是圖中的 delay=T。
- 第二步根據參考訊號估計出麥克風訊號中的線性回聲成分,並將其從麥克風訊號中減去,得到殘差訊號(黑色折線)。
- 第三步通過非線性的處理將殘差訊號中的殘餘回聲給徹底抑制掉。
與以上的三個步驟相對應,回聲消除也由三個大的演算法模組組成:
- 延遲估計(Delay Estimation)
- 線性自適應濾波器(Linear Adaptive Filter)
- 非線性處理(Nonlinear Processing)
其中「延遲估計」決定了AEC的下限,「線性自適應濾波器」決定了 AEC 的上限,「非線性處理」決定了最終的通話體驗,特別是回聲抑制跟雙講之間的平衡。
注:雙講是指在互動場景中,互動雙方或多方同時講話,其中一方的聲音會受到抑制,從而出現斷斷續續的情況。這是由於回聲消除演算法“矯枉過正”,消除了部分不該去除的音訊訊號。
接下來,我們先圍繞這三個演算法模組,分別講講其中的技術挑戰與優化思路。
一、延遲估計
受具體系統實現的影響,當把參考訊號與麥克風訊號分別送入 AEC 模組進行處理之時,它們所存入的資料 buffer 之間存在一個時間上的延遲,即我們在上圖中看到的“delay=T”。假設這個產生回聲的裝置是一部手機,那麼聲音從它的揚聲器發出後,一部分會經過裝置內部傳導到麥克風,也可能會經過外部環境傳回到麥克風中。所以這個延遲就包含了裝置採集播放 buffer 的長度,聲音在空氣中傳輸的時間,也包含了播放執行緒與採集執行緒開始工作的時間差。正是由於影響延遲的因素很多,因此這個延遲的值在不同系統,不同裝置,不同 SDK 底層實現上都各不相同。它在通話過程中也許是一個定值,也有可能會中途變化(所謂的 overrun 和 underrun)。這也是為什麼一個 AEC 演算法在裝置 A 上可能起作用,但換到另一個裝置上可能效果會變差。延遲估計的精確性是 AEC 能夠工作的先決條件,過大的估計偏差會導致 AEC 的效能急劇下降,甚至無法工作,而無法快速跟蹤時延變化是出現偶現回聲的重要因素。
增強延遲估計演算法魯棒性
傳統演算法通常通過計算參考訊號跟麥克風訊號之間的相關性來決定延遲。相關性的計算可以放在頻域上,典型的就是 Binary Spectrum 的方法,通過計算單頻點上的訊號能量是否超過一定門限值,實際將參考訊號跟麥克風訊號對映成了兩維的0/1陣列,然後通過不斷移動陣列偏移來找到延遲。最新的 WebRTC AEC3 演算法通過並行的多個NLMS線性濾波器來尋找延遲,這個方法在檢測速度及魯棒性方面都取得了不錯的效果,但是計算量非常大。當在時域上計算兩個訊號的互相關時,一個明顯的問題是語音訊號包含大量的諧波成分並且具有時變特性,它的相關訊號常常呈現出多峰值的特徵,有的峰值並不代表真正的延遲,並且演算法容易受到噪聲干擾。
聲網延遲估計演算法通過降低訊號之間的相關性(de-correlate),能夠有效抑制 local maxima 的值以大大增強演算法的魯棒性。如下圖所示,左邊是原始訊號之間的互相關,右邊是聲網SDK處理後的互相關,可見訊號的預處理大大增強了延遲估計的魯棒性:
演算法自適應,降低計算量
通常延遲估計演算法為了降低計算量的需要,會預先假設回聲訊號出現在某個較低的頻段內,這樣就可以將訊號做完下采樣之後再送入延遲估計模組,降低演算法的計算複雜度。然而面對市面上數以萬計的裝置及各種路由,以上的假設往往並不成立。下圖是 VivoX20 在耳機模式下麥克風訊號的頻譜圖,可見回聲都集中在 4kHz 以上的頻段內,傳統的演算法針對這些 case 都會導致回聲消除模組的失效。聲網延遲估計演算法會在全頻段內搜尋回聲出現的區域,並自適應地選擇該區域計算延遲,確保演算法在任何裝置,路由下都有精確的延遲估計輸出。
圖:VivoX20 接入耳機後的麥克風訊號
動態更新音訊演算法庫,提升裝置覆蓋率
為了確保演算法的持續迭代改進,聲網維護了一個音訊演算法的資料庫。我們使用大量不同測試裝置,在不同聲學環境下采集到了各種參考訊號和麥克風訊號的組合,而它們之間的延遲全部通過離線處理的方式進行標定。除了真實採集的資料,資料庫中也包含了大量模擬的資料,包括不同的說話人,不同的混響強度,不同的底噪水平,以及不同的非線性失真型別。為了衡量延遲估計演算法的效能,參考訊號與麥克風訊號之間的延遲可以隨機的變化,用以觀察演算法對突發延遲變化的響應。
所以判斷一個延遲估計演算法的優劣,還需要考察:
1.適應儘量多的裝置、聲學環境,且在儘量短的時間內根據裝置、聲學環境的因素匹配合適的演算法;
2.在突發隨機的延遲變化後,能及時動態調整演算法策略。
以下是聲網 SDK 與友商之間的延遲估計效能對比,總共使用了資料庫中 8640 組測試資料。從圖中資料可以看出,聲網 SDK 可以在更短的時間內找到大多數測試資料的初始時延。在 96% 的測試資料中,聲網 SDK 能在 1s 之內找到它們正確的延遲,而友商這一比例為 89%。
第二個測試的是在通話過程中出現隨機的延遲抖動,測試延遲估計演算法要在儘量短的時間內找到精確的延遲值。如圖中所示,聲網 SDK 在 71% 的測試資料中能在 3s 之內重新找到變化後的精確延遲值,而友商這個比例為 44%。
二、線性自適應濾波器
對於線性濾波器,已有大量的文獻介紹其原理及實踐。當應用於回聲消除的應用場景,主要考慮的指標包含收斂速度(convergence rate),穩態失調(steady-state misalignment)及跟蹤效能(tracking capability)。這些指標之間往往也有衝突,譬如較大的步長可以改善收斂速度,但是會導致較大的失調。這個就是自適應濾波器中的沒有免費的午餐定理(No Free Lunch Theorem)。
對於自適應濾波器的型別,除了最為常用的 NLMS 濾波器(Model Independent),還可以使用 RLS 濾波器(Least Squares Model)或 Kalman 濾波器(State-Space Model)。除了各自理論推導中的各種假設,近似,優化,這些濾波器的效能最終都歸結到如何計算最佳的步長因子(在卡爾曼濾波器裡面步長因子合併到 Kalman Gain 的計算裡面)。在濾波器尚未收斂或是環境傳輸函式突變的情形下,步長因子需要足夠大以跟蹤環境變化,當濾波器收斂及環境傳遞函式變化緩慢的時間段,步長因子應儘量減小以達到儘可能小的穩態失調。對於步長因子的計算,需要考慮自適應濾波器後殘餘回聲跟殘差訊號間的能量比值,建模為系統的 leakage coefficients。這個變數常常等價於求濾波器係數跟真實傳遞函式之間的差(Kalman 濾波器裡面稱為狀態空間狀態向量誤差),這也是整個估計演算法中的難點。除此之外,雙講階段的濾波器發散問題也是一個需要考慮的點,一般來說這個問題可以通過調整濾波器結構,使用 two echo path models 來解決。
聲網自適應濾波器演算法並不使用單一的濾波器型別,而是兼顧了不同濾波器之間的優點,同時搭配自適應演算法計算最優的步長因子。此外,演算法通過線性濾波器係數實時估計環境的傳遞函式,自動修正濾波器長度,以覆蓋通訊裝置連線 HDMI 外設等高混響,強回聲的場景。如下是一個例子,在聲網辦公室的一箇中型會議室中(面積約 20m2,三面玻璃牆),使用 Macbook Pro 通過 HDMI 連線小米電視,圖中是線性濾波器時域訊號的變化趨勢,演算法能自動計算並匹配實際環境傳遞函式的長度(在第 1400 幀左右自動檢測出了強混響環境),以優化線性濾波器的效能。
同樣的,我們也使用資料庫中大量測試資料進行聲網 SDK 與友商之間的效能對比,對比的指標包括穩態失調(濾波器收斂之後對回聲的抑制程度)以及收斂速度(濾波器達到收斂狀態需要的時長)。第一張圖代表自適應濾波器的穩態失調,聲網SDK在 47%的測試資料中能達到超過 20dB 的回聲抑制,而友商的比例為 39%。
下圖顯示的是自適應濾波器的收斂速度,聲網 SDK 在 51% 的測試樣本中能在通話前 3s 之內收斂到穩態,而友商的比例為13%。
三、非線性處理
非線性處理旨在抑制線性濾波器所沒有預測出的回聲成分,通常通過計算參考訊號,麥克風訊號,線性回聲以及殘差訊號間的相關性,或是將相關性直接對映到抑制增益上,或是通過相關性估計出殘留回聲的功率譜,進一步通過維納濾波器等傳統降噪的演算法抑制殘留回聲。
作為回聲消除演算法的最後一個模組,除了抑制殘留回聲之外,非線性處理單元也肩負著監控整個系統是否正常工作的重任,譬如線性濾波器是否因為延遲抖動而無法正常工作?在聲網 SDK 回聲消除之前是否存在硬體回聲消除未能處理的殘餘回聲?
下面是一個簡單的例子,通過自適應濾波器估計出的回聲能量等內部引數,能夠更快的發現延遲變化的現象,並且提示 NLP 採取相應的動作:
隨著聲網 SDK 覆蓋的場景越來越廣,針對音樂訊號的傳輸成為了一個重要的場景。聲網 SDK 針對音樂訊號的回聲消除體驗做了大量的優化,一個典型場景是舒適噪聲的估計演算法改進。傳統演算法使用基於 Minimum Statistics 的演算法原理對訊號中的底噪進行估計,當把這個演算法應用於音樂訊號時,因為音樂訊號比之語音訊號更為平穩,因此會過高的估計噪聲功率,反映到回聲消除中會導致處理後有回聲時段與無回聲時段間的底噪(背景噪聲)不平穩,體驗極差。聲網 SDK通過訊號分類以及模組融合的方式,徹底解決了 CNG 估計導致的底噪起伏現象。
除此之外,聲網 SDK 還針對所有可能碰到的極端情況,包括非因果系統,裝置頻率偏移,採集訊號溢位,音效卡包含系統訊號處理等等,都進行了大量的優化,確保演算法能夠工作在所有的通訊場景中。
音質優先的降噪策略
降噪對訊號音質的影響大於回聲消除模組,這一點源自於在降噪演算法的設計之初,我們先驗的假設底噪都是平穩訊號(至少是短時平穩的),而根據這個假設,音樂跟底噪的區分度明顯弱於語音跟底噪的區分度。
聲網 SDK 在降噪模組的前端預置了訊號分類模組,能夠精確的檢測出訊號的型別,並根據訊號的型別調整降噪演算法的型別及引數,常見的訊號型別包括一般語音、清唱、音樂訊號等。下圖所示是兩個降噪演算法處理的訊號片段,其中第一個是語音與音樂的混合訊號,前15秒為含噪的語音訊號,之後是40s是音樂訊號,再之後是10s的含噪語音,語譜圖從上到下分別是原始訊號、友商處理結果、聲網SDK處理結果。結果顯示在語音段訊號降噪效能差不多的前提下,競品處理過訊號中的音樂部分受到了嚴重的損傷,而聲網SDK的處理並沒有降低音樂的音質。
在第二個例子中,使用的音訊是歌手的清唱,清唱中歌手反覆發出“啊”的聲音。在下圖的語譜圖中,從上到下分別是原始訊號、友商的處理結果、聲網 SDK 處理結果。結果顯示,友商的降噪處理嚴重的損傷了原語音的頻譜成分,而聲網 SDK 完整的保留了原語音的諧波成分,保證了歌手清唱時候的音質體驗。
結語
自1967年貝爾實驗室的M. M. Sondhi開創性的提出以自適應濾波器的方法來消除回聲為開端,無數的研究和實踐都投入到了這個語音通訊的最基本問題上。要完美的解決回聲問題,除了要有強大的演算法作為基礎,也需要在工程優化領域做很多優化。聲網會持續不斷的改進回聲消除在各個不同應用場景下的體驗。
在本系列的下一篇內容中,我們將隨著音訊訊號,從裝置端進入現實的網路環境,一邊實地環行上海,一邊聊聊音訊互動場景下的延時、抖動,以及丟包對抗背後的優化策略。(以一張圖來簡單劇透,敬請期待)