WebRTC系列之音訊的那些事

網易雲信 發表於 2020-06-30

年初因為工作需要,開始學習WebRTC,就被其複雜的編譯環境和巨大的程式碼量所折服,註定是一塊難啃的骨頭。俗話說萬事開頭難,堅持一個恆心,終究能學習到WebRTC的設計精髓。今天和大家聊聊WebRTC中音訊的那些事。WebRTC由語音引擎,視訊引擎和網路傳輸三大模組組成,其中語音引擎是WebRTC中最具價值的技術之一,實現了音訊資料的採集、前處理、編碼、傳送、接受、解碼、混音、後處理、播放等一系列處理流程。

enter image description here 音訊引擎主要包含:音訊裝置模組ADM、音訊編碼器工廠、音訊解碼器工廠、混音器Mixer、音訊前處理APM。

音訊工作機制

想要系統的瞭解音訊引擎,首先需要了解核心的實現類和音訊資料流向,接下來我們將簡單的分析一下。

音訊引擎核心類圖:

enter image description here enter image description here

音訊引擎WebrtcVoiceEngine主要包含音訊裝置模組AudioDeviceModule、音訊混音器AudioMixer、音訊3A處理器AudioProcessing、音訊管理類AudioState、音訊編碼器工廠AudioEncodeFactory、音訊解碼器工廠AudioDecodeFactory、語音媒體通道包含傳送和接受等。

1.音訊裝置模組AudioDeviceModule主要負責硬體裝置層,包括音訊資料的採集和播放,以及硬體裝置的相關操作。

2.音訊混音器AudioMixer主要負責音訊傳送資料的混音(裝置採集和伴音的混音)、音訊播放資料的混音(多路接受音訊和伴音的混音)。

3.音訊3A處理器AudioProcessing主要負責音訊採集資料的前處理,包含回聲消除AEC、自動增益控制AGC、噪聲抑制NS。APM分為兩個流,一個近端流,一個遠端流。近端(Near-end)流是指從麥克風進入的資料;遠端(Far-end)流是指接收到的資料。

4.音訊管理類AudioState包含音訊裝置模組ADM、音訊前處理模組APM、音訊混音器Mixer以及資料流轉中心AudioTransportImpl。

5.音訊編碼器工廠AudioEncodeFactory包含了Opus、iSAC、G711、G722、iLBC、L16等codec。

6.音訊解碼器工廠AudioDecodeFactory包含了Opus、iSAC、G711、G722、iLBC、L16等codec。

音訊的工作流程圖: enter image description here

1.發起端通過麥克風進行聲音採集

2.發起端將採集到的聲音訊號輸送給APM模組,進行回聲消除AEC,噪音抑制NS,自動增益控制處理AGC

3.發起端將處理之後的資料輸送給編碼器進行語音壓縮編碼

4.發起端將編碼後的資料通過RtpRtcp傳輸模組傳送,通過Internet網路傳輸到接收端

5.接收端接受網路傳輸過來的音訊資料,先輸送給NetEQ模組進行抖動消除,丟包隱藏解碼等操作

6.接收端將處理過後的音訊資料送入音效卡裝置進行播放

NetEQ模組是Webrtc語音引擎中的核心模組

enter image description here

在 NetEQ 模組中,又被大致分為 MCU模組和 DSP 模組。MCU 主要負責做延時及抖動的計算統計,並生成對應的控制命令。而 DSP 模組負責接收並根據 MCU 的控制命令進行對應的資料包處理,並傳輸給下一個環節。

音訊資料流向

根據上面介紹的音訊工作流程圖,我們將繼續細化一下音訊的資料流向。將會重點介紹一下資料流轉中心AudioTransportImpl在整個環節中扮演的重要角色。

enter image description here

資料流轉中心AudioTransportImpl實現了採集資料處理介面RecordDataIsAvailbale和播放資料處理介面NeedMorePlayData。RecordDataIsAvailbale負責採集音訊資料的處理和將其分發到所有的傳送Streams。NeedMorePlayData負責混音所有接收到的Streams,然後輸送給APM作為一路參考訊號處理,最後將其重取樣到請求輸出的取樣率。

RecordDataIsAvailbale內部主要流程:

1.由硬體採集過來的音訊資料,直接重取樣到傳送取樣率

2.由音訊前處理針對重取樣之後的音訊資料進行3A處理

3.VAD處理

4.數字增益調整採集音量

5.音訊資料回撥外部進行外部前處理

6.混音傳送端所有需要傳送的音訊資料,包括採集的資料和伴音的資料

7.計算音訊資料的能量值

8.將其分發到所有的傳送Streams

NeedMorePlayData內部主要流程:

1.混音所有接收到的Streams的音訊資料 1.1 計算輸出取樣率CalculateOutputFrequency() 1.2 從Source收集音訊資料GetAudioFromSources(),選取沒有mute,且能量最大的三路進行混音 1.3 執行混音操作FrameCombiner::Combine()

2.特定條件下,進行噪聲注入,用於採集側作為參考訊號

3.對本地伴音進行混音操作

4.數字增益調整播放音量

5.音訊資料回撥外部進行外部前處理

6.計算音訊資料的能量值

7.將音訊重取樣到請求輸出的取樣率

8.將音訊資料輸送給APM作為一路參考訊號處理

由上圖的資料流向發現,為什麼需要FineAudioBuffer和AudioDeviceBuffer?因為WebRTC 的音訊流水線只支援處理 10 ms 的資料,不同的作業系統平臺提供了不同的採集和播放時長的音訊資料,不同的取樣率也會提供不同時長的資料。例如iOS上,16K取樣率會提供8ms的音訊資料128幀;8K取樣率會提供16ms的音訊資料128幀;48K取樣率會提供10.67ms的音訊資料512幀。

AudioDeviceModule 播放和採集的資料,總會通過 AudioDeviceBuffer 拿進來或者送出去 10 ms 的音訊資料。對於不支援採集和播放 10 ms 音訊資料的平臺,在平臺的 AudioDeviceModule 和 AudioDeviceBuffer 還會插入一個 FineAudioBuffer,用於將平臺的音訊資料格式轉換為 10 ms 的 WebRTC 能處理的音訊幀。在AudioDeviceBuffer 中,還會10s定時統計一下當前硬體裝置過來的音訊資料對應的取樣點個數和取樣率,可以用於檢測當前硬體的一個工作狀態。

音訊相關改動

1.音訊Profile的實現,支援Voip和Music 2種場景,實現了取樣率、編碼位元速率、編碼模式、聲道數的綜合性技術策略。 iOS實現了採集和播放執行緒的分離,支援雙聲道的播放。

2.音訊3A引數的相容性下發適配方案。

3.耳機場景的適配,藍芽耳機和普通耳機的適配,動態3A切換適配。

4.Noise_Injection噪聲注入演算法,作為一路參考訊號,在耳機場景的回聲消除中的作用特別明顯。

5.支援本地伴音檔案file和網路伴音檔案http&https。

6.Audio Nack的實現,提高音訊的抗丟包能力,目前正在進行In-band FEC。

7.音訊處理在單講和雙講方面的優化。

8.iOS在Built-In AGC方面的研究: 1. Built-In AGC對於Speech和Music有效,對於noise和環境底噪不會產生作用。 2. 不同機型的麥克風硬體的增益不同,iPhone 7 Plus > iPhone 8 > iPhone X;因此會在軟體AGC和硬體AGC都關閉的情況下,遠端聽到的聲音大小表現不一樣。 3. iOS除了提供的可開關的AGC以外,還有一個AGC會一直工作,對訊號的level進行微調;猜想這個一直工作的AGC是iOS自帶的analog AGC,可能和硬體有關,且沒有API可以開關,而可開關的AGC是一個digital AGC。 4. 在大部分iOS機型上,外放模式“耳機再次插入後”,input的音量會變小。當前的解決方案是在耳機再次插入後,增加一個preGain來把輸入的音量拉回正常值。

音訊問題排查

和大家分享一下音訊最常見的一些現象以及原因: enter image description here