[投稿]譜減法語音降噪原理

本文是音頻處理的朋友icoolmedia(QQ:314138065)的投稿。各位做視音頻技術朋友如果好的原創技術文章並希望通過我的博客分享給大家,也歡迎投稿到我的郵箱:[email protected],我會選擇內容合適的文章註明作者及聯繫方式後進行發佈。希望通過這種方式幫助大家結交更多的同道中人~


譜減法語音降噪基本原理


譜減算法爲最早的語音降噪算法之一,它的提出,基於一個簡單的原理:假設語音中的噪聲只有加性噪聲,只要將帶噪語音譜減去噪聲譜,就可以得到純淨語音幅度。這麼做的前提是噪聲信號是平穩的或者緩慢變化的。

得到純淨信號的幅度譜後,可以結合帶噪語音相位(近似帶替純淨語音相位),從而得到近似的純淨語音,可以這麼做的原因是因爲語音信號相位不會對語音可懂度造成影響。

按上述所示,如果我們設y(n)爲受噪聲污染的信號,則y(n)由純淨語音信號x(n)和加性噪聲d(n)組成,即:y(n)=X(n)+d(n)。其傅里葉變換後表示爲:Y(ω)=X(ω)+D(ω),或寫爲:

X(ω) = Y(ω) – D(ω),如果用功率譜表示可以寫爲:


這裏 被稱爲交叉項,我們假定d(n)具有0均值,並且與x(n)不相關,則交叉項爲0,上述公式簡化爲: 


 或寫爲:

 


音樂噪聲和過減因子、譜下限的關係


如果帶噪語音的幅度譜(功率譜也同此理)與估計出來的噪聲譜相減出現負值時,說明對噪聲出現了過估計問題,對這種現象最簡單的處理就是將負值設爲0,以保證非負的幅度譜。但是對負值的這種處理,會導致信號幀頻譜的隨機位置上出現小的,獨立的峯值。

轉換到頻域後,這些峯值聽起來就像幀與幀之間頻率隨機變化的多頻音,這種情況在清音段尤其明顯,這種由於半波整流引起的“噪聲”被稱爲“音樂噪聲”。從根本上,通常導致音樂噪聲的原因主要有:
(1)對譜減算法中的負數部分進行了非線性處理
(2)對噪聲譜的估計不準
(3)抑制函數(增益函數)具有較大的可變性

減小音樂噪聲的方法是對噪聲譜使用過減技術,同時對譜減後的負值設置一個下限,而不是將它們設爲0,其技術形式如下:
 
其中alpha(大於等於1)爲過減因子,它主要影響語音譜的失真程度。Beta(大於0小於1)是譜下限參數,可以控制殘留噪聲的多少以及音樂噪聲的大小。

使用過減因子與譜下限的動機在於:當從帶噪語音譜中減去噪聲譜估計的時候,頻譜中會殘留一些隆起的部分或譜峯,有些譜峯是寬帶的,有些譜峯很窄,看起來像是頻譜上的一個脈衝。通過對噪聲譜的過減處理,我們可以減小寬帶譜峯的幅度,有時還可以將其完全消除。但是僅僅這樣還不夠,因爲譜峯周圍可能還存在較深的譜谷。因此需要使用譜下限來“填充”這些譜谷。

在高信噪比中,alpha應取小值;對低信噪比中,alpha建議取大值。Berouti等人做了大量實驗來確定alpha與beta的最優值,在這裏我們直接使用就可以了。具體請參考論文:Enhancement of speech corrupted by a acoustic noise。

下面給出譜減算法的Matlab驗證代碼,調用方法爲specsub(‘filename.wav’,’outfile.wav’);

function specsub(filename,outfile)
if nargin < 2
   fprintf('Usage: specsub noisyfile.wav outFile.wav \n\n');
   return;
end

[x,fs,nbits] = wavread(filename);
len = floor(20*fs/1000);            % Frame size in samples
if rem(len,2) == 1, len=len+1; end;
PERC = 50;                          % window overlap in percent of frame size
len1 = floor(len*PERC/100);
len2 = len-len1; 

Thres = 3;      % VAD threshold in dB SNRseg 
Expnt = 2.0;    % power exponent
beta = 0.002;
G = 0.9;

win = hamming(len);
winGain = len2/sum(win); % normalization gain for overlap+add with 50% overlap

% Noise magnitude calculations - assuming that the first 5 frames is noise/silence
nFFT = 2*2^nextpow2(len);
noise_mean = zeros(nFFT,1);
j=1;
for k = 1:5
   noise_mean = noise_mean+abs(fft(win.*x(j:j+len-1),nFFT));
   j = j+len;
end
noise_mu = noise_mean/5;

%--- allocate memory and initialize various variables
k = 1;
img = sqrt(-1);
x_old = zeros(len1,1);
Nframes = floor(length(x)/len2)-1;
xfinal = zeros(Nframes*len2,1);

%=========================    Start Processing   ===============================
for n = 1:Nframes 
    insign = win.*x(k:k+len-1);      % Windowing
    spec = fft(insign,nFFT);         % compute fourier transform of a frame
    sig = abs(spec);                 % compute the magnitude
    %save the noisy phase information 
    theta = angle(spec);  
    SNRseg = 10*log10(norm(sig,2)^2/norm(noise_mu,2)^2);
    if Expnt == 1.0     % 幅度譜
        alpha = berouti1(SNRseg);
    else
        alpha = berouti(SNRseg); % 功率譜
    end
    %&&&&&&&&&
    sub_speech = sig.^Expnt - alpha*noise_mu.^Expnt;
    diffw = sub_speech - beta*noise_mu.^Expnt;     % 當純淨信號小於噪聲信號的功率時
    % beta negative components
    z = find(diffw <0);  
    if~isempty(z)
        sub_speech(z) = beta*noise_mu(z).^Expnt;   % 用估計出來的噪聲信號表示下限值
    end
    % --- implement a simple VAD detector --------------
    if (SNRseg < Thres)   % Update noise spectrum
        noise_temp = G*noise_mu.^Expnt+(1-G)*sig.^Expnt;    % 平滑處理噪聲功率譜
        noise_mu = noise_temp.^(1/Expnt);                   % 新的噪聲幅度譜
    end
% flipud函數實現矩陣的上下翻轉,是以矩陣的“水平中線”爲對稱軸
%交換上下對稱元素
    sub_speech(nFFT/2+2:nFFT) = flipud(sub_speech(2:nFFT/2));
    x_phase = (sub_speech.^(1/Expnt)).*(cos(theta)+img*(sin(theta)));
    % take the IFFT 
    xi = real(ifft(x_phase));
    % --- Overlap and add ---------------
    xfinal(k:k+len2-1)=x_old+xi(1:len1);
    x_old = xi(1+len1:len);
    k = k+len2;
end

wavwrite(winGain*xfinal,fs,16,outfile);

function a = berouti1(SNR)
if SNR >= -5.0 & SNR <= 20
	a = 3-SNR*2/20;
else
    if SNR < -5.0
        a = 4;
    end
    if SNR > 20
        a = 1;
	end
end

function a = berouti(SNR)
if SNR >= -5.0 & SNR <= 20
	a = 4-SNR*3/20; 
else
    if SNR < -5.0
        a = 5;
    end
	if SNR > 20
        a = 1;
    end
end



幾種改進的譜減算法


(1)非線性譜減
Berouti等人提出的譜減算法,假設了噪聲對所有的頻譜分量都有同等的影響,繼而只用了一個過減因子來減去對噪聲的過估計。現實世界中的噪聲並非如此,這意味着可以用一個頻率相關的減法因子來處理不同類型的噪聲。

(2)多帶譜減法
在多帶算法中,將語音頻譜劃分爲N個互不重疊的子帶,譜減法在每個子帶獨立運行。將語音信號分爲多個子帶信號的過程可以通過在時域使用帶通濾波器來進行,或者在頻域使用適當的窗。通常會採用後一種辦法,因爲實現起來有更小的運算量。

多帶譜減與非線性譜減的主要區別在於對過減因子的估計。多帶算法針對頻帶估計減法因子,而非線性譜減算法針對每一個頻點,導致頻點上的信噪比可能有很大變化。這種劇烈變化是譜減法中所遇到的語音失真(音樂噪聲)的原因之一。相反,子帶信噪比變化則不會特別劇烈。

(3)MMSE譜減算法
上面的方法中,譜減參數alpha和beta通過實驗確定,無論如何都不會是最優的選擇。MMSE譜減法能夠在均方意義下最優地選擇譜減參數。具體請參考論文:A parametic formulation of the generalized spectral subtractor method

(4)擴展譜減法
基於自適應維納濾波與譜減原理的結合。維納濾波用於估計噪聲譜,然後從帶噪語音信號中減去該噪聲譜。具體請參考以下兩篇論文:
Extended Spectral Substraction:Description and Preliminary Results.  
Extended Spectral Substraction

(5)自適應增益平均的譜減
譜減法中導致音樂噪聲的兩個因素在於譜估計的大範圍變化以及增益函數的不同。對於第一個問題,Gustafsson等人建議將分析幀劃分爲更換小的子幀以得到更低分辨率的頻譜。子幀頻譜通過連續平均以減小頻譜的波動。對於第二個問題Gustafsson等人提出使用自適應指數平均,在時間上對增益函數做平滑。此外,爲了避免因使用零相位增益函數導致的非因果濾波問題,Gustafsson等人建議在增益函數中引入線性相位。具體請參考論文:Spectral subtraction using reduced delay convolution and adaptive averaging

(6)選擇性譜減法
前面提到的方法對所有語音都做同樣處理。並不區分是濁音段還是清音段。區分濁音與清音的譜減法有:
1> 雙頻帶譜減法。通過將帶噪語音能量與某一閾值進行比較,把語音幀分爲濁音和清音。對於濁音幀,用算法確定一個截止頻率,在該截止頻率之上,語音被認爲是隨機信號。濁音段則通過濾波分爲兩個頻帶,一個頻帶位於截止頻率之下(低通濾波後的語音),另外一個頻帶高於截止頻率(高通濾波後的語音)。然後對低通和高通後的語音信號使用不同的算法進行處理。對低通語音部分在短時傅立葉變換的基礎上使用過減算法,對於高通部分以及清音段,使用Thomson的多窗譜估計器取代FFT估計器。主要目的在於減小高頻部分的頻譜值的波動。具體請參考論文:Adaptive two-band spectral subtraction with multi-window spectral estimation
2> 雙激勵語音模型法,該算法把語音分爲兩個獨立的組成部分--濁音分量和清音分量。也就是說,語音由這兩個分量的和來表示(注意不同於將語音分爲濁音段和清音段)。濁音分量的分析是基於對基音頻率和諧波幅度的提取。然後從帶噪語音譜中減去濁音譜就得到了清音譜。然後使用一個雙通道系統,基中一個包括改進的維納濾波器,被用於增強清音譜。最終增強的語音由增強後的濁音分量和清音分量求和得到。具體請參考論文:Speech enhancement using the dual excitation speech model
3> 還有一種基於濁音、清音的譜減算法,在該算法中語音幀首先根據能量和過零率被劃分爲濁音和清音。然後將帶噪語音譜與銳化函數進行卷積,清音的頻譜就會被銳化(用銳化函數進行鐠銳化的目的在於增加譜對比度,即在抑制譜谷的同時使譜峯更加突出)。具體請參考論文:Spectral subtraction based on phonetic dependency and masking effects

(7)基於感知特性的譜減
前面提到的方法,譜減參數要麼是通過實驗計算短時信噪比得到,要麼是通過最優均方誤差得到,均沒有考慮聽覺系統的特性,該算法的主要目的是使殘餘噪聲在聽覺上難以被察覺。利用了人類聽覺系統改進系統的可懂度(即人耳的掩蔽效應)


本文來自於icoolmedia(QQ:314138065)。
發佈了372 篇原創文章 · 獲贊 2104 · 訪問量 1306萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章