1. 程式人生 > >speex 回聲消除的用法

speex 回聲消除的用法

speex的回聲訊息

就是speex_echo_cancellation函式的正確用法

回聲訊息的原理:

對參考聲音(解碼的對端原始語音包)做延遲(會有多個延遲,如麥克風直接採集到音箱的聲音,經牆壁反射後再次採集),衰減,

從聲卡里採集到的語音,做一個語音合成。

回聲產生的條件:

通話中,有一方使用音箱(或者雙方都用音箱)。

在實際中如何使用speex_echo_cancellation這個函式呢?錯誤的使用,將導致speex無法快速地收斂回聲濾波器的引數。

使用音箱的那一方,這裡我們稱之為"傳送方",呼叫speex_echo_cancellation,

這樣做就繞開了網路延遲,引起對演算法收斂的干撓。

這是第一點要注意的

(也可以在"接收方"呼叫speex_echo_cancellation,但網路出現抖動時,就會使演算法無法快速收斂,就無法消除回聲了)

這樣,我們的程式碼中,大概會是這樣的邏輯:

解碼網路語音包(記為 play)

寫入音效卡

採集麥克風的聲音(記為rec)

呼叫speex_echo_cancellation 參play與rec傳給這個函式

回想一下,應用層的程式可能會是這樣(當然您的程式也可能不是這樣,但情形類似):

一個接收執行緒,收包,放音

一個傳送執行緒,錄音,發包

我們自然會在錄音執行緒裡呼叫speex_echo_cancellation

但這有一個問題,錄音執行緒與放音執行緒因為系統的排程問題,也會造成抖動,導致speex的回聲消除演算法無法收斂。

以下的一個程式模形,讀者們可以參考

1 接收執行緒A,解碼網路語音包,接語音包推入一個訊息佇列A

2 放音錄音執行緒B,從佇列A中取出語音包,放音,錄音,錄音得到的語音包,通過speex_echo_cancellation處理後,存入佇列B

3 傳送執行緒C,從佇列B中取語音包,編碼,傳送

簡單地說,就是用一個執行緒放音,錄音,然後echo cancel,這樣就不存線上程排程引起的延遲抖動

採用這種方式,就避免了因為執行緒排程引起的抖動,避免了不確定的延遲對speex演算法收斂過程的干撓。

最後一個干撓因素:os提供的錄音放音介面也是非同步的。。。

這個干撓因素基本在應用層是無法排除的了。。。可能就是幾毫秒的誤差,但足以干撓回聲消除演算法了。

多路語音(會議)

選一個超級節點做合成語音,或者終端對語音進行合成,之後,處理就變成與單對單語音通話類似的情形了

直接上speex_echo_cancellation