聲學回聲消除(Acoustic Echo Cancellation)原理與實現

  回聲就是聲音信號經過一系列反射之後,又聽到了自己講話的聲音,這就是回聲。一些回聲是必要的,比如劇院裏的音樂回聲以及延遲時間較短的房間回聲;而大多數回聲會造成負面影響,比如在有線或者無線通信時重複聽到自己講話的聲音(回想那些年我們開黑打遊戲時,如果其中有個人開了外放,他的聲音就會迴盪來回蕩去)。因此消除回聲的負面影響對通信系統是十分必要的。

  針對回聲消除(Acoustic Echo Cancellation,AEC )問題,現如今最流行的算法就是基於自適應濾波的回聲消除算法。本文從回聲信號的兩種分類以及 AEC 的基本原理出發,介紹幾種經典的 AEC 算法並對其性能進行闡釋。

回聲分類

  在通信系統中,回聲主要分爲兩類:電路回聲聲學回聲

電路回聲

  電路回聲通常產生於有線通話中,而造成電路回聲的根本原因是轉換混合器的二線-四線阻抗不能完全匹配。中心局至轉換混合器之間採用四線的連接方式傳輸信號,上面兩條線路用於發送給用戶端信號,下面兩條線路用於接收用戶端信號。通信公司爲了降低遠距離信號傳輸成本,將混合器至用戶端的連接線減少爲二線連接,分別用於用戶端信號的接受與發送。中間的轉換混合電路功能是將四線連接轉換爲二線連接,由於在轉換過程中使用了不同型號的電線或者負載線圈沒有被使用的原因,不可避免地會產生阻抗不匹配現象,導致混合器接收線路上的語音信號流失到了發送線路,產生了回聲信號,使得另一端的用戶在接收信號的同時聽到了自己的聲音。

電路回聲產生原理

  在現如今的數字通信網絡中,轉換混合器與數模轉換器融爲一體,但無論是模擬電子線路還是數字電子線路,二-四線的轉換都會造成阻抗不匹配問題,從而導致其產生電路回聲,影響現代通信質量。由於電路回聲的線性以及穩定性,用一個簡單的線性疊加器就可以實現電路回聲消除。首先將產生的回聲信號在數值上取反,線性地疊加在回聲信號上,將產生的回聲信號抵消,實現電路回聲的初步消除。然而由於技術缺陷,線性疊加器不能完整地將回聲信號抹去,因此需要添加一個非線性處理器,其實質是一個阻擋信號的開關,將殘餘的回聲信號經過非線性處理之後,就可以實現電路回聲的消除,或者得到噪聲很小的靜音信號。由於電路回聲信號是線性且穩定的,所以比較容易將其消除,而本文主要研究的是如何消除非線性的聲學回聲。

電路回聲消除的基本原理

聲學回聲

  在麥克風與揚聲器互相作用影響的雙工通信系統中極易產生聲學回聲。如下圖所示

遠端講話者A-->麥克風A-->電話A-->電話B---->揚聲器B--->麥克風B-->電話B-->電話A-->揚聲器A--->麥克風A--->.........就這樣無限循環,

詳細講解:遠端講話者A的話語被麥克風採集並傳入至通信設備,經過無線或有線傳輸之後達到近端的通信設備,並通過近端 B 的揚聲器播放,這個聲音又會被近端 B 的麥克風拾取至其通信設備形成聲學回聲,經傳輸又返回了遠端 A 的通信設備,並通過遠端 A 的揚聲器播放出來,從而遠端講話者就聽到了自己的回聲。

聲學回聲產生原理

聲學回聲信號根據傳輸途徑的差別可以分別直接回聲信號和間接回聲信號。

直接回聲:近端揚聲器B將語音信號播放出來後,近端麥克風B直接將其採集後得到的回聲。

  直接回聲不受環境的印象,與揚聲器到麥克風的距離及位置有很大的關係,因此直接回聲是一種線性信號

間接回聲:近端揚聲器B將語音信號播放出來後,語音信號經過複雜多變的牆面反射後由近端麥克風B將其拾取。

  間接回聲的大小與房間環境、物品擺放以及牆面吸引係數等等因素有關,因此間接回聲是一種非線性信號

回聲消除技術主要用於在免提電話、電話會議系統等情形中。

AEC的基本原理

  如今解決 AEC 問題最常用的方法,就是

使用不同的自適應濾波算法調整濾波器的權值向量,估計一個近似的回聲路徑來逼近真實回聲路徑,從而得到估計的回聲信號,並在純淨語音和回聲的混合信號中除去此信號來實現回聲的消除。

 AEC的基本原理

  $x(n)$爲遠端輸入信號,經過未知的回聲路徑$w(n)$得到$y(n)=x(n)*w(n)$,再加上觀測噪聲$v(n)$即爲期望信號$d(n)= y(n) + v(n)$。x(n)通過自適應濾波器$\hat{w}(n)$得到估計的回聲信號,並與期望信號$d(n)$相減得到誤差信號$e(n)$,即$e(n)=d(n)-\hat{w}^T(n)x(n)$,誤差信號的值越小說明自適應濾波算法所估計的回聲路徑就越接近實際的回聲路徑。

  濾波器採用特定的自適應算法不停地調整權值向量,使估計的回聲路徑$\hat{w}(n)$逐漸趨近於真實回聲路徑$w(n)$。顯然,在 AEC 問題中,自適應濾波器的選擇對回聲消除的性能好壞起着十分關鍵的作用。

自適應濾波器的基本原理

  自適應濾波器是一個對輸入信號進行處理並不停學習,直到其達到期望值的器件。自適應濾波器在輸入信號非平穩條件下,也可以根據環境不斷調節濾波器權值向量,使算法達到特定的收斂條件,從而實現自適應濾波過程。

  自適應濾波器按輸入信號類型可分爲模擬濾波器和離散濾波器,本文中使用的是離散濾波器中的數字濾波器數字濾波器按結構可劃分爲輸入不僅與過去和當前的輸入有關、還與過去的輸出有關的無限衝激響應濾波器(IIR),以及輸出與有限個過去和當前的輸入有關的有限衝激響應濾波器(FIR))爲了使得自適應濾波器具有更強的穩定性,並且具有足夠的濾波器係數可以用來調整以達到特定的收斂準則,一般選取橫向的 FIR 濾波器進行來進行回聲的消除

 橫向FIR濾波器結構框圖

  $x(n)$是遠端輸入信號,$\hat{w}_i(n)$是濾波器係數,其中$i=0,1,...,L-1$,$L$爲濾波器的長度,$n$爲採樣點數,$\hat{w}(n)$爲濾波器的權值向量且$\hat{w}(n)=[\hat{w}_0(n),\hat{w}_1(n),...,\hat{w}_{L-1}(n)]^T$,根據誤差信號$e(n)=d(n)-\hat{w}^T(n)x(n)$的值以及不同算法的收斂準則調整濾波器的權值向量。

  然而自適應濾波算法的選擇從根本上決定了回聲消除的效果是否良好,接下來將介紹幾種解決 AEC 問題的經典自適應濾波算法。

回聲消除常用算法

LSM算法

  通過上面AEC的基本原理我們知道了誤差信號$e(n)$等於期望信號減去濾波器輸出信號:

$$e(n)=d(n)-\hat{w}^T(n)x(n)$$

對上式兩端先平方,然後再求其數學期望,可將$e(n)$的MSE表示爲:

$$\xi=E[e^2(n)]=E[d^2(n)]-2P^T\hat{w}(n)+\hat{w}^T(n)R\hat{w}(n)$$

其中,$P=E[d(n)x(n)]$爲$d(n)$與輸入信號$x(n)$的負相關矩陣,$R=E[x(n)x^T(n)]$爲$x(n)$的自相關矩陣。

  對誤差信號求導並且使導數值置零,求解得到使得誤差最小的“最優權重” $\hat{w}_{opt}(n)=\frac{P}{R}$,R 和 P 的估計分別爲$\hat{R}(n) 和$\hat{P}(n)$,利用各自的瞬時估計值將其分別表示爲:$\hat{R}(n)=x(x)x^T(n)$;$\hat{P}(n)=d(n)x(n)$ 。另外,用$\hat{g}_w(n)$表示誤差信號對權值向量導數的估計值,利用下式方法求解最優權值向量的維納解:

 得到:$\hat{g}_w(n)=-2e(n)x(n)$ ,算法取瞬時平方誤差作爲目標函數,那麼$\hat{g}_w(n)$爲其真實梯度,因爲:

因此得到 LMS 算法的權值向量更新公式:

$$\hat{w}(n+1)=\hat{w}(n)+2\mu e(n)x(n)$$

式中,$\mu$爲固定步長因子,$\mu$的大小很大程度上決定了算法的收斂與穩態性能。LMS 算法複雜性低,但是它的收斂速度慢。爲改善 LMS 這個不足之處,科研人員提出一系列改進算法,NLMS 算法就是其中一種

NLMS算法

NSAF算法

MATLAB代碼實現

當需要同時進行語音通信(或全雙工傳輸)時,回聲消除對於音頻電話會議非常重要。在回聲消除中,測得的麥克風信號包含兩個信號:

  • 近端語音信號$v(n)$ 

  • 遠端回聲信號$\hat{d}(n)$

目的是從麥克風信號中去除遠端回聲信號,從而僅發送近端語音信號。本示例包含一些聲音片段,因此您可能現在要調整計算機的音量。

房間脈衝響應

首先,您需要對揚聲器所在的揚聲器到麥克風的信號路徑的聲學建模。使用長有限衝激響應濾波器來描述房間的特徵。下面的代碼生成一個隨機的脈衝響應,該響應與會議室的顯示相同。假設系統採樣率爲16000 Hz。

fs = 16000;
M = fs / 2 + 1; 
frameSize = 2048; 

[B,A] = cheby2(4,20,[0.1 0.7]); 
impulseResponseGenerator = dsp.IIRFilter(' Numerator ',[zeros(1,6)B],... 
    'Denominator',A); 

FVT = fvtool(impulseResponseGenerator);  %分析過濾器 
FVT.Color = [1 1 1];

roomImpulseResponse = impulseResponseGenerator( ...
        (log(0.99*rand(1,M)+0.01).*sign(randn(1,M)).*exp(-0.002*(1:M)))');
roomImpulseResponse = roomImpulseResponse/norm(roomImpulseResponse)*4;
room = dsp.FIRFilter('Numerator', roomImpulseResponse');

fig = figure;
plot(0:1/fs:0.5, roomImpulseResponse);
xlabel('Time (s)');
ylabel('Amplitude');
title('Room Impulse Response');
fig.Color = [1 1 1];

 

近端語音信號

電話會議系統的用戶通常位於系統麥克風附近。這是麥克風上男性講話的聲音。

load nearspeech

player          = audioDeviceWriter('SupportVariableSizeInput', true, ...
                                    'BufferSize', 512, 'SampleRate', fs);
nearSpeechSrc   = dsp.SignalSource('Signal',v,'SamplesPerFrame',frameSize);
nearSpeechScope = dsp.TimeScope('SampleRate', fs, ...
                    'TimeSpan', 35, 'TimeSpanOverrunAction', 'Scroll', ...
                    'YLimits', [-1.5 1.5], ...
                    'BufferLength', length(v), ...
                    'Title', 'Near-End Speech Signal', ...
                    'ShowGrid', true);

% Stream processing loop
while(~isDone(nearSpeechSrc))
    % Extract the speech samples from the input signal
    nearSpeech = nearSpeechSrc();
    % Send the speech samples to the output audio device
    player(nearSpeech);
    % Plot the signal
    nearSpeechScope(nearSpeech);
end
release(nearSpeechScope);

 

遠端語音信號

在電話會議系統中,語音從揚聲器中傳播出去,在房間裏彈跳,然後被系統的麥克風拾取。聆聽在沒有近端語音的情況下在麥克風處拾起語音時的聲音。

load farspeech
farSpeechSrc    = dsp.SignalSource('Signal',x,'SamplesPerFrame',frameSize);
farSpeechSink   = dsp.SignalSink;
farSpeechScope  = dsp.TimeScope('SampleRate', fs, ...
                    'TimeSpan', 35, 'TimeSpanOverrunAction', 'Scroll', ...
                    'YLimits', [-0.5 0.5], ...
                    'BufferLength', length(x), ...
                    'Title', 'Far-End Speech Signal', ...
                    'ShowGrid', true);

% Stream processing loop
while(~isDone(farSpeechSrc))
    % Extract the speech samples from the input signal
    farSpeech = farSpeechSrc();
    % Add the room effect to the far-end speech signal
    farSpeechEcho = room(farSpeech);
    % Send the speech samples to the output audio device
    player(farSpeechEcho);
    % Plot the signal
    farSpeechScope(farSpeech);
    % Log the signal for further processing
    farSpeechSink(farSpeechEcho);
end
release(farSpeechScope);

 

 

麥克風信號

麥克風處的信號既包含近端語音,也包含在整個房間中回聲的遠端語音。回聲消除器的目的是消除遠端語音,從而僅將近端語音發送回遠端聽衆。

reset(nearSpeechSrc);
farSpeechEchoSrc = dsp.SignalSource('Signal', farSpeechSink.Buffer, ...
                    'SamplesPerFrame', frameSize);
micSink         = dsp.SignalSink;
micScope        = dsp.TimeScope('SampleRate', fs,...
                    'TimeSpan', 35, 'TimeSpanOverrunAction', 'Scroll',...
                    'YLimits', [-1 1], ...
                    'BufferLength', length(x), ...
                    'Title', 'Microphone Signal', ...
                    'ShowGrid', true);

% Stream processing loop
while(~isDone(farSpeechEchoSrc))
    % Microphone signal = echoed far-end + near-end + noise
    micSignal = farSpeechEchoSrc() + nearSpeechSrc() + ...
                0.001*randn(frameSize,1);
    % Send the speech samples to the output audio device
    player(micSignal);
    % Plot the signal
    micScope(micSignal);
    % Log the signal
    micSink(micSignal);
end
release(micScope);

頻域自適應濾波器(FDAF)

該示例中的算法是頻域自適應濾波器(FDAF)當待識別系統的脈衝響應較長時,此算法非常有用。FDAF使用快速卷積技術來計算輸出信號和過濾器更新。該計算可在MATLAB®中快速執行。通過頻點步長歸一化,它還具有快速收斂性能。爲濾波器選擇一些初始參數,並查看遠端語音在誤差信號中的消除程度。

% Construct the Frequency-Domain Adaptive Filter
echoCanceller    = dsp.FrequencyDomainAdaptiveFilter('Length', 2048, ...
                    'StepSize', 0.025, ...
                    'InitialPower', 0.01, ...
                    'AveragingFactor', 0.98, ...
                    'Method', 'Unconstrained FDAF');

AECScope1   = dsp.TimeScope(4, fs, ...
                'LayoutDimensions', [4,1], ...
                'TimeSpan', 35, 'TimeSpanOverrunAction', 'Scroll', ...
                'BufferLength', length(x));

AECScope1.ActiveDisplay = 1;
AECScope1.ShowGrid      = true;
AECScope1.YLimits       = [-1.5 1.5];
AECScope1.Title         = 'Near-End Speech Signal';

AECScope1.ActiveDisplay = 2;
AECScope1.ShowGrid      = true;
AECScope1.YLimits       = [-1.5 1.5];
AECScope1.Title         = 'Microphone Signal';

AECScope1.ActiveDisplay = 3;
AECScope1.ShowGrid      = true;
AECScope1.YLimits       = [-1.5 1.5];
AECScope1.Title         = 'Output of Acoustic Echo Canceller mu=0.025';

AECScope1.ActiveDisplay = 4;
AECScope1.ShowGrid      = true;
AECScope1.YLimits       = [0 50];
AECScope1.YLabel        = 'ERLE (dB)';
AECScope1.Title         = 'Echo Return Loss Enhancement mu=0.025';

% Near-end speech signal
release(nearSpeechSrc);
nearSpeechSrc.SamplesPerFrame = frameSize;

% Far-end speech signal
release(farSpeechSrc);
farSpeechSrc.SamplesPerFrame = frameSize;

% Far-end speech signal echoed by the room
release(farSpeechEchoSrc);
farSpeechEchoSrc.SamplesPerFrame = frameSize;

回波回波增強(ERLE)

由於您可以訪問近端和遠端語音信號,因此可以計算回聲回波損耗增強(ERLE),這是對回聲衰減量的平滑度量(以dB爲單位)。從圖中可以看出,在收斂週期結束時您獲得了大約35 dB的ERLE。

diffAverager = dsp.FIRFilter('Numerator', ones(1,1024));
farEchoAverager = clone(diffAverager);
setfilter(FVT,diffAverager);

micSrc = dsp.SignalSource('Signal', micSink.Buffer, ...
    'SamplesPerFrame', frameSize);

% Stream processing loop - adaptive filter step size = 0.025
while(~isDone(nearSpeechSrc))
    nearSpeech = nearSpeechSrc();
    farSpeech = farSpeechSrc();
    farSpeechEcho = farSpeechEchoSrc();
    micSignal = micSrc();
    % Apply FDAF
    [y,e] = echoCanceller(farSpeech, micSignal);
    % Send the speech samples to the output audio device
    player(e);
    % Compute ERLE
    erle = diffAverager((e-nearSpeech).^2)./ farEchoAverager(farSpeechEcho.^2);
    erledB = -10*log10(erle);
    % Plot near-end, far-end, microphone, AEC output and ERLE
    AECScope1(nearSpeech, micSignal, e, erledB);
end
release(AECScope1);

不同步長值的影響

爲了獲得更快的收斂速度,可以嘗試使用更大的步長值。但是,這種增加會產生另一種效果:當近端揚聲器講話時,自適應濾波器“調整不當”。聆聽您選擇的步長比以前大60%時會發生什麼。

% Change the step size value in FDAF
reset(echoCanceller);
echoCanceller.StepSize = 0.04;

AECScope2 = clone(AECScope1);
AECScope2.ActiveDisplay = 3;
AECScope2.Title = 'Output of Acoustic Echo Canceller mu=0.04';
AECScope2.ActiveDisplay = 4;
AECScope2.Title = 'Echo Return Loss Enhancement mu=0.04';

reset(nearSpeechSrc);
reset(farSpeechSrc);
reset(farSpeechEchoSrc);
reset(micSrc);
reset(diffAverager);
reset(farEchoAverager);

% Stream processing loop - adaptive filter step size = 0.04
while(~isDone(nearSpeechSrc))
    nearSpeech = nearSpeechSrc();
    farSpeech = farSpeechSrc();
    farSpeechEcho = farSpeechEchoSrc();
    micSignal = micSrc();
    % Apply FDAF
    [y,e] = echoCanceller(farSpeech, micSignal);
    % Send the speech samples to the output audio device
    player(e);
    % Compute ERLE
    erle = diffAverager((e-nearSpeech).^2)./ farEchoAverager(farSpeechEcho.^2);
    erledB = -10*log10(erle);
    % Plot near-end, far-end, microphone, AEC output and ERLE
    AECScope2(nearSpeech, micSignal, e, erledB);
end

release(nearSpeechSrc);
release(farSpeechSrc);
release(farSpeechEchoSrc);
release(micSrc);
release(diffAverager);
release(farEchoAverager);
release(echoCanceller);
release(AECScope2);

回聲回波損耗增強比較

步長較大時,由於近端語音引入的錯誤調整,導致ERLE性能不佳。爲了解決此性能難題,聲學回聲消除器包括一種檢測方案,可告知何時存在近端語音並在這些時間段內降低步長值。沒有這種檢測方案,從ERLE圖可以看出,具有較大步長的系統的性能不如前者。

使用分區減少延遲

對於長脈衝響應,傳統FDAF在數值上比時域自適應濾波更有效,但是由於輸入幀大小必須是指定濾波器長度的倍數,因此它具有高延遲。對於許多實際應用程序來說,這可能是不可接受的。通過使用分區的FDAF可以減少延遲,該方法將過濾器脈衝響應分爲較短的部分,將FDAF應用於每個部分,然後合併中間結果。在這種情況下,幀大小必須是分區(塊)長度的倍數,從而大大減少了長脈衝響應的等待時間。

% Reduce the frame size from 2048 to 256
frameSize = 256;
nearSpeechSrc.SamplesPerFrame    = frameSize;
farSpeechSrc.SamplesPerFrame     = frameSize;
farSpeechEchoSrc.SamplesPerFrame = frameSize;
micSrc.SamplesPerFrame           = frameSize;
% Switch the echo canceller to Partitioned constrained FDAF
echoCanceller.Method      = 'Partitioned constrained FDAF';
% Set the block length to frameSize
echoCanceller.BlockLength = frameSize;

% Stream processing loop
while(~isDone(nearSpeechSrc))
    nearSpeech = nearSpeechSrc();
    farSpeech = farSpeechSrc();
    farSpeechEcho = farSpeechEchoSrc();
    micSignal = micSrc();
    % Apply FDAF
    [y,e] = echoCanceller(farSpeech, micSignal);
    % Send the speech samples to the output audio device
    player(e);
    % Compute ERLE
    erle = diffAverager((e-nearSpeech).^2)./ farEchoAverager(farSpeechEcho.^2);
    erledB = -10*log10(erle);
    % Plot near-end, far-end, microphone, AEC output and ERLE
    AECScope2(nearSpeech, micSignal, e, erledB);
end

 

 

 

 

開源的音頻處理庫

Speex:開源語音編解碼器

專爲語音設計的無專利音頻壓縮格式。Speex項目旨在通過提供免費替代昂貴的專有語音編解碼器的方法來降低語音應用程序的進入門檻。此外,Speex非常適合Internet應用程序,並提供了大多數其他編解碼器中沒有的有用功能。

Speex基於CELP ,旨在以2到44 kbps的比特率壓縮語音Speex的一些功能包括:

  • 同一位流中的窄帶(8 kHz),寬帶(16 kHz)和超寬帶(32 kHz)壓縮
  • 強度立體聲編碼
  • 丟包隱藏
  • 可變比特率操作(VBR)
  • 語音活動檢測(VAD)
  • 不連續傳輸(DTX)
  • 定點端口
  • 回聲消除器
  • 噪聲抑制

Speex編解碼器已被Opus淘汰。它會繼續可用,但是由於Opus在各個方面都比Speex更好,因此建議用戶切換Opus

Opus互動音頻編解碼器

Opus是一款完全開放,免版稅,功能廣泛的音頻編解碼器。Opus在互聯網上的交互式語音和音樂傳輸方面無可匹敵,但也適用於存儲和流媒體應用程序。

Opus可以處理各種音頻應用程序,包括IP語音,視頻會議,遊戲內聊天,甚至是遠程現場音樂表演。它可以從低比特率的窄帶語音擴展到高質量的立體聲音樂。支持的功能有:

  • 比特率從6 kb / s到510 kb / s
  • 採樣率從8 kHz(窄帶)到48 kHz(全帶)
  • 幀大小從2.5毫秒到60毫秒
  • 支持恆定比特率(CBR)和可變比特率(VBR)
  • 音頻帶寬從窄帶到全帶
  • 支持語音和音樂
  • 支持單聲道和立體聲
  • 最多支持255個通道(多流幀)
  • 動態可調的比特率,音頻帶寬和幀大小
  • 良好的丟失健壯性和數據包丟失隱藏(PLC)
  • 浮點和定點實現

WebRTC(實時通信):用戶可以通過簡單API爲瀏覽器和移動應用程序提供實時通信(RTC)功能

推薦使用webrtc

 

參考

《基於自適應濾波器的聲學回聲消除研究——馮江浩》

MATLAB官網audio_Examples_Acoustic Echo Cancellation 

Hand Book of Speech Enhancement and Recognition

語音自適應回聲消除算法代碼講解

WebRTC AEC AGC ANC NS示例

 
 
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章