簡體   English   中英

MATLAB:從wav文件中消除高頻噪聲

[英]MATLAB: Remove high frequency noise from wav file

我正在嘗試從以下文件中消除高頻噪聲。

這是一個女人讀新聞的文件,一陣高音在上面大聲播放。 在文件末尾,其他人開始講話,但是使用了另一種語言。

我想過濾掉這種尖銳的聲音,並能夠清晰地聽到女人在看新聞。 看頻域:

未過濾

我嘗試使用低通濾波器和帶阻濾波器。 帶阻濾波器產生的信號不再具有高音調振鈴,但是音頻不是很清晰,很難弄清正在說什么-低通濾波器也是如此。 我猜想這是由於我不僅濾除了噪聲,而且濾除了語音的諧波。 濾波后還需要放大音頻信號,因為它比以前更安靜。

我有什么聰明的方法可以重建語音的和聲,以便更清楚地聽到說話的內容? 還是我有一個聰明的方法來過濾信號而不損失太多音頻清晰度?

如果需要,我可以包括我在matlab中使用的任何代碼。

注意:

  • 我在連結的圖片中將訊號移至0

  • 我確實使用了filtfilt()而不是filter()

  • 我用了butter()作為過濾器

考慮到樣品中干擾的動態性質,固定濾波器不會產生非常令人滿意的結果。 為了提高性能,您需要根據干擾估算值動態調整過濾參數。

幸運的是,在這種情況下,干擾非常強烈,並且呈現出相當規則的模式,這使得估計起來更加容易。 從信號的spectrogram可以看出。 對於以下推導,我們將假設wavfile的樣本已存儲在數組x ,並且采樣率為fs (在提供的樣本中為8000Hz)。

[Sx,f,t] = spectrogram(x, triang(1024), 1023, [], fs, 'onesided');

在此處輸入圖片說明

鑒於干擾很強,可以通過在每個時間片中找到峰值頻率來獲得干擾的頻率:

frequency = zeros(size(Sx,2),1);
for k = 1:size(Sx,2)
    [pks,loc] = findpeaks(Sx(:,k));
    frequency(k) = fs * (loc(1)-1);
end

看到干擾是周期性的,我們可以使用離散傅立葉變換來分解該信號:

M = 32*fs;
Ff = fft(frequency, M);
plot(fs*[0:M-1]/M, 20*log10(abs(Ff));
axis(0, 2);
xlabel('frequency (Hz)');
ylabel('amplitude (dB)');

在此處輸入圖片說明

使用前兩個諧波作為近似值,我們可以將干擾信號的頻率建模為:

T = 1.0/fs
t = [0:length(x)-1]*T
freq = 750.0127340203496
       + 249.99913423501602*cos(2*pi*0.25*t - 1.5702946346796276)
       + 250.23974282864816*cos(2*pi*0.5 *t - 1.5701043282285363);

此時,我們將足以創建一個具有該頻率模型給定的中心頻率(隨着我們不斷更新濾波器系數而動態變化)的窄帶濾波器。 但是請注意,不斷地重新計算和更新濾波器系數是一個相當昂貴的過程,並且鑒於干擾很強,可以通過鎖定干擾相位來做得更好。 這可以通過將原始信號的小塊與所需頻率的正弦和余弦相關聯來完成。 然后,我們可以稍微調整相位以使正弦/余弦與原始信號對齊。

% Compute the phase of the sine/cosine to correlate the signal with
delta_phi = 2*pi*freq/fs;
phi = cumsum(delta_phi);

% We scale the phase adjustments with a triangular window to try to reduce
% phase discontinuities. I've chosen a window of ~200 samples somewhat arbitrarily,
% but it is large enough to cover 8 cycles of the interference around its lowest
% frequency sections (so we can get a better estimate by averaging out other signal
% contributions over multiple interference cycles), and is small enough to capture
% local phase variations.
step = 50;
L    = 200;
win  = triang(L);
win  = win/sum(win);

for i = 0:floor((length(x)-(L-step))/step)
    % The phase tweak to align the sine/cosine isn't linear, so we run a few
    % iterations to let it converge to a phase locked to the original signal
    for iter = 0:1
        xseg   = x[(i*step+1):(i*step+L+1)];
        phiseg = phi[(i*step+1):(i*step+L+1)];
        r1 = sum(xseg .* cos(phiseg));
        r2 = sum(xseg .* sin(phiseg));
        theta = atan2(r2, r1);

        delta_phi[(i*step+1):(i*step+L+1)] = delta_phi[(i*step+1):(i*step+L+1)] - theta*win;
        phi = cumsum(delta_phi);
    end
end

最后,我們需要估計干擾的幅度。 在這里,我們選擇在語音開始前稍有停頓的最初0.15秒內執行估算,以便估算不會因語音幅度而產生偏差:

tmax = 0.15;
nmax = floor(tmax * fs);
amp  = sqrt(2*mean(x[1:nmax].^2));
% this should give us amp ~ 0.250996990794946

然后,這些參數使我們能夠相當精確地重構干擾,並通過直接相減從原始信號中相應地消除干擾:

y = amp * cos(phi)
x = x-y

在此處輸入圖片說明

聆聽結果輸出后,您可能會注意到仍然有微弱的嗡嗡聲,但與原始干擾相比沒有任何變化。 顯然,這是一個相當理想的情況,其中干擾的參數非常容易估算,結果幾乎看起來都太好了,難以置信。 隨機干擾模式更多時,您可能無法獲得相同的性能。

注意 :用於此處理的python腳本(以及相應的.wav文件輸出)可以在此處找到。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM