戰(zhàn):基于FIR低通濾波器的完整實(shí)現(xiàn)指南)
1. 項(xiàng)目拆解與整體設(shè)計(jì)思路1.1 這個(gè)“探索性項(xiàng)目”到底要做什么先說(shuō)結(jié)論這是一個(gè)用Matlab把“帶噪音頻”變成“干凈音頻”的完整閉環(huán)項(xiàng)目。核心路徑是給一段干凈音頻疊加噪聲——模擬現(xiàn)實(shí)中麥克風(fēng)收到的環(huán)境干擾然后設(shè)計(jì)FIR低通濾波器把噪聲濾掉最后用頻譜對(duì)比、波形對(duì)比、主觀(guān)聽(tīng)感三個(gè)維度驗(yàn)證濾波效果。這類(lèi)項(xiàng)目在數(shù)字信號(hào)處理課程里非常經(jīng)典但很多人做的時(shí)候容易用力過(guò)猛。有的把代碼堆得很長(zhǎng)幾百行下來(lái)核心邏輯反而被淹沒(méi)有的只關(guān)注濾波器能不能濾掉噪聲完全不考慮音頻本身的細(xì)膩度損失。我做的這個(gè)版本刻意做了減法代碼量控制在120行以?xún)?nèi)但把“加噪—觀(guān)察—設(shè)計(jì)—濾波—評(píng)估”這條鏈路完整走通每一步都有對(duì)應(yīng)的可視化結(jié)果適合拿來(lái)當(dāng)課堂展示、課程設(shè)計(jì)也適合新手自己練手理解FIR濾波器的行為特征。適合誰(shuí)看呢第一類(lèi)是剛學(xué)完DSP理論、想用Matlab把課本上的原理落地的人第二類(lèi)是正在做課程設(shè)計(jì)、需要一套能跑通且能講清楚原理的完整方案的人第三類(lèi)是工作中偶爾需要處理音頻噪聲、想快速驗(yàn)證FIR濾波器效果的工程師。如果你對(duì)理論完全陌生我的建議是先看第2章的原理講解再回到本章看整體流程就不容易卡住。1.2 為什么要選FIR而不是IIR濾波器這是整個(gè)項(xiàng)目里第一個(gè)需要想清楚的決策點(diǎn)。既然目標(biāo)是去噪IIR濾波器比如巴特沃斯、切比雪夫計(jì)算量更小、過(guò)渡帶更陡為什么我堅(jiān)持用FIR關(guān)鍵在于線(xiàn)性相位。音頻信號(hào)經(jīng)過(guò)濾波器后不同頻率成分在時(shí)間軸上會(huì)產(chǎn)生不同的延遲如果相位響應(yīng)是非線(xiàn)性的波形就會(huì)畸變。IIR濾波器處理后的音頻聽(tīng)起來(lái)往往“發(fā)飄”就是這個(gè)原因。FIR濾波器只要系數(shù)對(duì)稱(chēng)就能保證嚴(yán)格的線(xiàn)性相位也就是所有頻率成分延遲量一致波形形狀在時(shí)間軸上被整體平移而不是被扭曲。對(duì)語(yǔ)音、音樂(lè)這類(lèi)對(duì)相位敏感的信號(hào)這個(gè)特性非常關(guān)鍵。另一個(gè)原因和項(xiàng)目本身的可視化教學(xué)目的有關(guān)。FIR濾波器的單位脈沖響應(yīng)是有限長(zhǎng)度的你能直觀(guān)地看到抽頭系數(shù)長(zhǎng)什么樣IIR濾波器有反饋結(jié)構(gòu)分析起來(lái)更復(fù)雜。在一個(gè)以“理解原理”為導(dǎo)向的項(xiàng)目里FIR從原理到代碼再到圖形都自洽能讓學(xué)習(xí)者沿著一條清晰的主線(xiàn)走完。當(dāng)然IIR也有一席之地比如對(duì)實(shí)時(shí)性要求高、對(duì)相位失真容忍度高的場(chǎng)景。但在音頻去噪這個(gè)場(chǎng)景里FIR是更穩(wěn)妥的回答——它犧牲了一些計(jì)算效率換來(lái)了信號(hào)保真度和設(shè)計(jì)上的確定性。1.3 從原始音頻到去噪結(jié)果的整體流程整個(gè)項(xiàng)目的執(zhí)行路徑大概是這樣用Matlab生成一段帶噪聲的測(cè)試信號(hào)或者讀取某個(gè)音頻文件。觀(guān)察信號(hào)的時(shí)域波形和頻域頻譜明確噪聲頻率范圍。根據(jù)噪聲頻帶設(shè)定FIR濾波器的通帶邊界。使用Matlab濾波器設(shè)計(jì)函數(shù)設(shè)計(jì)濾波器系數(shù)并查看頻率響應(yīng)。用該濾波器對(duì)帶噪信號(hào)進(jìn)行濾波。對(duì)比濾波前后的時(shí)域波形、頻譜圖計(jì)算信噪比提升量。用sound函數(shù)試聽(tīng)主觀(guān)驗(yàn)證去噪效果。我實(shí)際跑下來(lái)最耗時(shí)的是第3步到第4步之間的“參數(shù)取舍”而不是寫(xiě)代碼本身。比如采樣率是8000還是44100直接影響歸一化頻率的計(jì)算通的邊界設(shè)到多少才能既濾掉噪聲又不過(guò)多損傷有用信號(hào)需要反復(fù)試。第2章和第3章會(huì)詳細(xì)展開(kāi)這些細(xì)節(jié)這里先不展開(kāi)。關(guān)鍵是要意識(shí)到這個(gè)項(xiàng)目探索的本質(zhì)不是“調(diào)用一個(gè)濾波函數(shù)”而是理解濾波器參數(shù)與信號(hào)特性的匹配關(guān)系。濾波器是通用的麻煩的是信號(hào)本身。2. FIR濾波器核心原理與參數(shù)選擇2.1 從差分方程理解FIR的本質(zhì)FIR的數(shù)學(xué)定義不復(fù)雜輸出信號(hào)是當(dāng)前輸入和前N-1個(gè)歷史輸入的加權(quán)平均不依賴(lài)任何過(guò)去的輸出值。寫(xiě)成差分方程就是y(n) b(0)·x(n) b(1)·x(n-1) ... b(N-1)·x(n-N1)這里的系數(shù)向量b就是濾波器系數(shù)也叫抽頭系數(shù)或單位脈沖響應(yīng)。因?yàn)椴簧婕胺答丗IR天生穩(wěn)定——無(wú)論系數(shù)怎么設(shè)置輸出都不會(huì)發(fā)散。這一點(diǎn)和IIR有本質(zhì)區(qū)別IIR如果極點(diǎn)設(shè)計(jì)在單位圓外用著用著就爆了。用生活類(lèi)比理解FIR相當(dāng)于一個(gè)“移動(dòng)加權(quán)平均窗口”每個(gè)新輸入點(diǎn)進(jìn)來(lái)都用附近幾個(gè)點(diǎn)給它一個(gè)“混合值”窗口越長(zhǎng)參與計(jì)算的歷史點(diǎn)越多對(duì)高頻細(xì)節(jié)的平滑作用越強(qiáng)——也就是低通效果越明顯。這就是為什么階數(shù)越高過(guò)渡帶越窄但信號(hào)也會(huì)越“鈍”。2.2 窗函數(shù)選擇對(duì)頻譜泄漏的影響直接截?cái)嗬硐霝V波器的無(wú)限脈沖響應(yīng)會(huì)產(chǎn)生頻域上的吉布斯現(xiàn)象——通帶邊緣出現(xiàn)明顯振蕩阻帶衰減也不夠。解決方法是給截?cái)噙^(guò)程加窗讓截?cái)嗖皇怯采亩瞧交^(guò)渡。Matlab的fir1函數(shù)默認(rèn)使用Hann窗但實(shí)際項(xiàng)目里我會(huì)根據(jù)需求選擇Hamming、Blackman甚至Kaiser窗。窗函數(shù)的選擇直接決定阻帶衰減和過(guò)渡帶寬度窗函數(shù)主瓣寬度過(guò)渡帶寬度最小阻帶衰減適用場(chǎng)景Rectangular最窄-21dB僅用于理論展示Hann較窄-44dB通用語(yǔ)音去噪Hamming較窄-53dB大多數(shù)音頻場(chǎng)景Blackman較寬-74dB要求高阻帶衰減的音頻Kaiser可調(diào)可調(diào)(β控制)需要精確控制過(guò)渡帶寬度時(shí)這個(gè)項(xiàng)目里如果噪聲幅度不大Hamming窗就夠用了。如果噪聲很強(qiáng)、需要更大的抑制度就用Blackman。記住一個(gè)原則阻帶衰減要求越高窗函數(shù)的主瓣越寬過(guò)渡帶越寬階數(shù)需求也越高。2.3 階數(shù)N怎么定才合理FIR濾波器的階數(shù)沒(méi)有唯一正確解但有經(jīng)驗(yàn)公式。最常用的是基于過(guò)渡帶寬度的估算N ≈ 過(guò)渡帶寬度因子 / (過(guò)渡帶寬度/采樣率)不同窗函數(shù)的過(guò)度帶寬度因子不一樣比如Hann窗大約是3.1Hamming窗大約是3.3Blackman窗大約是5.5。這里的“過(guò)渡帶寬度”是實(shí)際頻率值不是歸一化頻率。舉個(gè)例子。假設(shè)采樣率Fs 8000Hz需要濾除2500Hz以上的噪聲通帶截止頻率設(shè)為2000Hz過(guò)渡帶寬度就是500Hz。用Hamming窗N ≈ 3.3 / (500/8000) 52.8向上取整到奇數(shù)位就是53為什么要取奇數(shù)因?yàn)镸atlab里很多濾波器設(shè)計(jì)函數(shù)要求階數(shù)為偶數(shù)或奇數(shù)取決于濾波器類(lèi)型低通用fir1時(shí)建議階數(shù)取偶數(shù)這樣系數(shù)長(zhǎng)度N1為奇數(shù)便于實(shí)現(xiàn)嚴(yán)格的線(xiàn)性相位。實(shí)際調(diào)試時(shí)我會(huì)先按經(jīng)驗(yàn)公式算一個(gè)初值然后觀(guān)察頻率響應(yīng)圖里的過(guò)渡帶是否滿(mǎn)足需求再微調(diào)階數(shù)。階數(shù)也不是越高越好。階數(shù)越高計(jì)算量越大群延遲越大實(shí)時(shí)處理延遲越高。音頻離線(xiàn)處理還好但如果要實(shí)時(shí)處理或者嵌入式部署階數(shù)就要盡量低。2.4 截止頻率的選擇與歸一化陷阱Matlab的fir1函數(shù)要求截止頻率以Nyquist頻率為基準(zhǔn)做歸一化也就是實(shí)際頻率除以采樣率的一半Wn 截止頻率 / (Fs/2)很多人在這里踩坑。比如Fs 8000Hz想把2000Hz以上的頻率濾掉Wn應(yīng)該是2000 / (8000/2) 0.5而不是2000/8000 0.25。這個(gè)錯(cuò)誤導(dǎo)致濾波器實(shí)際截止頻率差了一倍濾波效果完全不對(duì)。另外fir1支持多頻段設(shè)計(jì)比如帶通濾波器可以傳Wn [低截止 高截止]。對(duì)于低通去噪只傳一個(gè)截止頻率就好。帶通如果做得好可以同時(shí)濾掉低頻環(huán)境噪聲和高頻噪聲但對(duì)參數(shù)要求更高容易出現(xiàn)過(guò)擬合。3. Matlab實(shí)現(xiàn)細(xì)節(jié)與復(fù)現(xiàn)步驟3.1 讀入音頻與觀(guān)察噪聲頻段第一步是準(zhǔn)備音頻。Matlab里用audioread讀取音頻文件返回采樣數(shù)據(jù)y和采樣率Fs。我自己測(cè)試用的是一段8kHz采樣的語(yǔ)音樣本時(shí)長(zhǎng)5秒內(nèi)容是某人朗讀的一段文字。實(shí)際操作上任何語(yǔ)音或音樂(lè)都可以但采樣率要和后續(xù)參數(shù)匹配。讀取之后關(guān)鍵動(dòng)作是觀(guān)察頻譜。對(duì)音頻數(shù)據(jù)做FFT變換然后繪制幅度譜y audioread(speech_clean.wav); Fs 8000; % 如果音頻自帶采樣率用audioread返回值 L length(y); NFFT 2^nextpow2(L); % 取2的冪提高FFT效率 Y fft(y, NFFT); freq Fs * (0:(NFFT/2))/NFFT; subplot(2,1,1); plot(y); title(干凈信號(hào)時(shí)域波形); subplot(2,1,2); plot(freq, 20*log10(abs(Y(1:NFFT/21)))); title(干凈信號(hào)頻譜);從頻譜圖上能清楚看到語(yǔ)音能量集中在300Hz-2000Hz之間2000Hz以上基本沒(méi)有有效內(nèi)容。這意味著如果疊加2500Hz以上的高頻噪聲就能在不損失有用信號(hào)的前提下把它濾掉。3.2 給音頻疊加模擬噪聲模擬噪聲我用的是randn函數(shù)生成的白噪聲然后通過(guò)高通濾波器處理一下讓噪聲集中在高頻段模擬現(xiàn)實(shí)中那種“滋滋”的環(huán)境底噪。白噪聲直接加到干凈信號(hào)上會(huì)得到均勻分布在所有頻段的窄帶噪聲濾除時(shí)要把0-2000Hz都保護(hù)起來(lái)比較難分離。更貼近實(shí)際的做法是讓噪聲偏置在高頻noise randn(size(y)); % 用一個(gè)簡(jiǎn)單的高通濾波器把噪聲推到高頻 [b_hp, a_hp] butter(4, 0.4, high); noise_high filter(b_hp, a_hp, noise); noise_high noise_high / max(abs(noise_high)) * 0.3; % 控制噪聲幅度 noisy y noise_high;這里的0.4是歸一化截止頻率。如果原始音頻采樣率是8000Hz0.4對(duì)應(yīng)1600Hz也就是說(shuō)噪聲主要分布在1600Hz以上。之所以這樣做是因?yàn)檎Z(yǔ)音在1600Hz以上還有諧波成分完全濾掉會(huì)損失清晰度這為后面“濾波器參數(shù)權(quán)衡”留出了討論空間。噪聲設(shè)置在2500Hz以上更干凈但那樣過(guò)濾太容易缺少真實(shí)感。疊加完噪聲后重新畫(huà)一次頻譜能直觀(guān)看到高頻區(qū)域出現(xiàn)了明顯的噪聲底。此時(shí)信噪比我估算在10dB左右屬于“能聽(tīng)到但忍受不了”的程度。3.3 基于fir1的經(jīng)典濾波器設(shè)計(jì)現(xiàn)在是整個(gè)項(xiàng)目的核心環(huán)節(jié)。設(shè)計(jì)低通FIR濾波器目標(biāo)是把高頻噪聲壓下去同時(shí)盡量保留語(yǔ)音諧波。用fir1實(shí)現(xiàn)fc 2400; % 截止頻率 Wn fc / (Fs/2); % 歸一化 N 41; % 濾波器階數(shù)先用經(jīng)驗(yàn)公式粗算 b fir1(N, Wn, low, hamming(N1)); % 查看頻率響應(yīng) freqz(b, 1, 1024, Fs);這里N41是根據(jù)經(jīng)驗(yàn)公式粗選的結(jié)果。Fs8000時(shí)Wn0.6Hann窗對(duì)應(yīng)的過(guò)度帶大約0.1歸一化頻率換算成實(shí)際頻率就是400Hz左右——從2400Hz到2800Hz噪聲逐漸被衰減。如果感覺(jué)過(guò)渡帶太寬就加大N如果阻帶衰減不夠換Blackman窗。我的實(shí)測(cè)記錄N41時(shí)2000Hz以下的語(yǔ)音內(nèi)容幾乎沒(méi)有損失在2400Hz處衰減約3dB到了3000Hz已經(jīng)衰減了30dB以上。這個(gè)時(shí)候試聽(tīng)高頻底噪明顯降低但語(yǔ)音中原本蘊(yùn)含的一些高頻明亮感也丟失了一部分。這屬于預(yù)期行為——低通濾波本身就是“小魚(yú)小蝦一鍋端”。3.4 使用fdatool圖形界面設(shè)計(jì)濾波器如果覺(jué)得寫(xiě)代碼不好估參數(shù)Matlab還提供了交互式濾波器設(shè)計(jì)工具fdatool。這是一個(gè)圖形化界面左側(cè)選濾波器類(lèi)型低通、設(shè)計(jì)方法FIR-窗函數(shù)、階數(shù)設(shè)定右側(cè)實(shí)時(shí)顯示頻率響應(yīng)曲線(xiàn)。我一般在兩種場(chǎng)景下使用fdatool一是快速試驗(yàn)多種參數(shù)組合拖一拖滑條就能看到頻率響應(yīng)變化比反復(fù)改代碼畫(huà)圖直觀(guān)得多二是拿它生成系數(shù)后直接導(dǎo)出到工作區(qū)再用代碼處理音頻。不過(guò)實(shí)際項(xiàng)目里我仍然建議寫(xiě)代碼為主——因?yàn)閒datool生成的濾波器設(shè)計(jì)代碼是自動(dòng)生成的可讀性差不利于學(xué)習(xí)和調(diào)試。使用fdatool時(shí)記得把采樣頻率設(shè)置為8000或你的實(shí)際Fs否則界面上的頻率讀數(shù)會(huì)和實(shí)際對(duì)不上。這是很多人用fdatool設(shè)計(jì)完濾波器后放進(jìn)代碼里發(fā)現(xiàn)截止頻率不對(duì)的常見(jiàn)原因。3.5 濾波執(zhí)行與頻譜對(duì)比設(shè)計(jì)好濾波器系數(shù)后執(zhí)行濾波本身只是一行代碼y_filtered filter(b, 1, noisy);注意filter函數(shù)的用法第一個(gè)參數(shù)是分子系數(shù)b第二個(gè)是分母系數(shù)a對(duì)FIR濾波器來(lái)說(shuō)a1。有些地方會(huì)用conv函數(shù)做卷積效果一樣但filter更方便處理長(zhǎng)信號(hào)。濾波后在時(shí)間軸上對(duì)比三組信號(hào)——干凈信號(hào)、帶噪信號(hào)、濾波后信號(hào)再用頻譜對(duì)比觀(guān)察濾除效果Y_noisy fft(noisy, NFFT); Y_filt fft(y_filtered, NFFT); figure; subplot(3,1,1); plot(y); title(干凈信號(hào)); subplot(3,1,2); plot(noisy); title(帶噪信號(hào)); subplot(3,1,3); plot(y_filtered); title(濾波后信號(hào));濾波后的時(shí)域波形明顯比帶噪信號(hào)平滑但在細(xì)節(jié)上和干凈信號(hào)仍有差異——這就是“過(guò)平滑”現(xiàn)象高頻諧波部分被削弱了。頻譜上2500Hz以上的能量被大幅壓低通帶內(nèi)0-2000Hz的形狀和干凈信號(hào)對(duì)比基本一致。3.6 信噪比計(jì)算與主觀(guān)聽(tīng)感驗(yàn)證量化評(píng)估濾波效果最簡(jiǎn)單的指標(biāo)是SNR信噪比SNR_noisy 10*log10(sum(y.^2) / sum((noisy-y).^2)); SNR_filt 10*log10(sum(y.^2) / sum((y_filtered-y).^2));這里的y是原始干凈信號(hào)。噪聲部分用“濾波后信號(hào) - 干凈信號(hào)”來(lái)估算得出來(lái)的值可以粗略反映殘留噪聲能量。實(shí)際項(xiàng)目里我是這么算的帶噪信號(hào)SNR大約是11dB濾波后SNR提升到19dB提升了8dB。當(dāng)然這個(gè)值和噪聲特性、濾波器參數(shù)密切相關(guān)不代表普遍水平。主觀(guān)聽(tīng)感我建議用sound函數(shù)比較比如sound(noisy, Fs); pause(2); sound(y_filtered, Fs);聽(tīng)感效果取決于噪聲類(lèi)型。如果是白噪聲濾波后會(huì)有一種“毛刺感消失”的清爽感如果是高頻窄帶噪聲濾波后底噪幾乎聽(tīng)不到了。但我必須說(shuō)單純靠SNR數(shù)字衡量有局限性——SNR提升并不等于主觀(guān)感知變好因?yàn)槿说穆?tīng)覺(jué)對(duì)不同頻率的敏感度不同。這也是為什么最終評(píng)估要結(jié)合頻譜圖、波形圖和聽(tīng)感一起來(lái)判斷。3.7 嘗試不同濾波器性能對(duì)比做這個(gè)項(xiàng)目時(shí)我額外做了一個(gè)對(duì)比實(shí)驗(yàn)用不同階數(shù)的濾波器處理同一段帶噪音頻對(duì)比頻譜圖和SNR。這個(gè)實(shí)驗(yàn)對(duì)理解濾波器階數(shù)的意義幫助很大。階數(shù)N過(guò)渡帶寬度(Hz)濾波后SNR(dB)主觀(guān)聽(tīng)感21約80015.2底噪殘留較多41約40018.7底噪明顯降低81約20019.8底噪很低但語(yǔ)音稍悶可以看到階數(shù)從21提高到41SNR提升最明顯從41到81提升變緩但主觀(guān)上語(yǔ)音“悶”感更重。這是因?yàn)檫^(guò)渡帶越窄截止頻率附近的語(yǔ)音諧波被削得越多。工程上要在這兩者之間找一個(gè)平衡點(diǎn)而不是一味追求高阻帶衰減。這個(gè)權(quán)衡思路在任何“濾波”類(lèi)問(wèn)題里都通用。4. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄4.1 濾波器設(shè)計(jì)出來(lái)了但濾波后信號(hào)完全沒(méi)變化這種情況十有八九是濾波器系數(shù)沒(méi)生效。檢查方向有幾個(gè)首先看濾波器的頻率響應(yīng)是否正常freqz(b, 1)畫(huà)出來(lái)如果通帶是0到0.5那濾波器沒(méi)問(wèn)題如果通帶范圍異常多半是歸一化頻率算錯(cuò)了。其次檢查代碼里是否把filter(noisy, b, 1)和filter(b, 1, noisy)搞混了——filter函數(shù)第一個(gè)參數(shù)是分子系數(shù)把帶噪信號(hào)放到第一個(gè)參數(shù)位會(huì)導(dǎo)致輸入輸出完全錯(cuò)亂而且程序不報(bào)錯(cuò)非常隱蔽。最后檢查是否忘記把濾波器系數(shù)賦值過(guò)去代碼里定義了b但后續(xù)又用了之前的變量名。這種細(xì)節(jié)在調(diào)試時(shí)最消耗時(shí)間我的建議是每次設(shè)計(jì)完濾波器后立即freqz看一眼響應(yīng)曲線(xiàn)確認(rèn)參數(shù)真的符合預(yù)期。4.2 濾波后的聲音出現(xiàn)“咕嚕咕?!钡念澮暨@個(gè)現(xiàn)象如果出現(xiàn)大概率是濾波器設(shè)計(jì)時(shí)截止頻率定得太低把語(yǔ)音本身的主要能量成分也濾掉了導(dǎo)致語(yǔ)音信號(hào)出現(xiàn)明顯的包絡(luò)調(diào)制效應(yīng)。語(yǔ)音在300Hz以下的基礎(chǔ)頻率成分和共振峰都集中在中低頻如果把通帶截止設(shè)在1000Hz以下語(yǔ)音就會(huì)像在水下說(shuō)話(huà)一樣含混不清。排查時(shí)先把信號(hào)頻譜圖調(diào)出來(lái)找到語(yǔ)音能量最集中的頻段把截止頻率設(shè)置在這個(gè)頻段之上、噪聲頻段之下。如果兩者離得太近就需要提高濾波器階數(shù)來(lái)收窄過(guò)渡帶而不是把截止頻率一味壓低。4.3 聲卡播放出來(lái)的聲音有延遲感這是FIR階數(shù)過(guò)高的典型癥狀。階數(shù)N越大群延遲越長(zhǎng)實(shí)時(shí)播放時(shí)就能感覺(jué)到聲音變“鈍”。離線(xiàn)處理無(wú)所謂但如果你的項(xiàng)目需要實(shí)時(shí)監(jiān)控或者流式處理階數(shù)就要控制在合理范圍內(nèi)。經(jīng)驗(yàn)值8kHz采樣率下語(yǔ)音應(yīng)用FIR階數(shù)在20~80之間比較合理超過(guò)100就會(huì)明顯感受到延遲。如果設(shè)計(jì)要求很高的阻帶衰減優(yōu)先考慮換用多級(jí)濾波方案——比如每級(jí)濾波用一個(gè)較低階數(shù)的低通濾波器逐級(jí)壓低噪聲而不是一上來(lái)就用一個(gè)200階的超長(zhǎng)濾波器。級(jí)聯(lián)的好處是每一級(jí)都更穩(wěn)定、延遲可控壞處是總體計(jì)算量略高。4.4 頻譜圖上出現(xiàn)奇怪的峰值濾波后的頻譜如果出現(xiàn)周期性峰值或明顯毛刺有可能是FFT參數(shù)設(shè)置問(wèn)題比如NFFT不是信號(hào)長(zhǎng)度的合適值導(dǎo)致頻譜分辨率不夠。這種情況不影響濾波效果本身只是顯示層面的“不適”增加NFFT或調(diào)整窗參數(shù)就能解決。也有一種可能是原始音頻本身帶有直流偏置。matlab里讀取的音頻數(shù)據(jù)如果錄音設(shè)備存在直流偏移頻譜圖上會(huì)在0Hz附近出現(xiàn)一個(gè)很大的尖峰。濾波后這個(gè)直流分量不會(huì)消失因?yàn)榈屯V波器不會(huì)濾除直流。解決辦法是先用detrend函數(shù)去掉直流成分再做后續(xù)處理。4.5 濾波器頻率響應(yīng)看似正確但實(shí)際效果不好這種情況其實(shí)不罕見(jiàn)。原因是頻率響應(yīng)圖展示的是理想情況——濾波器系數(shù)是浮點(diǎn)精度設(shè)計(jì)的但在音頻信號(hào)處理中音頻文件本身的動(dòng)態(tài)范圍、噪聲的統(tǒng)計(jì)特性、濾波器的暫態(tài)響應(yīng)都會(huì)影響實(shí)際效果。濾波的暫態(tài)現(xiàn)象值得單獨(dú)說(shuō)一下。濾波器剛啟動(dòng)時(shí)某段時(shí)間內(nèi)的輸出信號(hào)會(huì)有一段瞬態(tài)響應(yīng)表現(xiàn)為信號(hào)起始處的輕微波動(dòng)。對(duì)于長(zhǎng)時(shí)間音頻信號(hào)來(lái)說(shuō)這段影響不大但如果你只截取了一段很短的信號(hào)瞬態(tài)現(xiàn)象就可能占總時(shí)長(zhǎng)的很大比例聽(tīng)起來(lái)像加了一個(gè)“回聲”。遇到這種情況處理方式是濾波后丟棄開(kāi)頭的N個(gè)樣本N等于濾波器階數(shù)或者用filter的初始條件參數(shù)zi來(lái)抵消瞬態(tài)效應(yīng)。4.6 拿不到干凈參考信號(hào)SNR怎么算很多時(shí)候你手上只有一段帶噪音頻沒(méi)有對(duì)應(yīng)的干凈信號(hào)上面公式里的SNR計(jì)算就用不了了。這時(shí)有幾種替代方案第一個(gè)方案是噪聲估算法。在沒(méi)有語(yǔ)音的靜音段估計(jì)噪聲功率然后對(duì)整段信號(hào)用維納濾波或者其他譜減法做降噪再對(duì)比降噪前后的噪聲功率變化間接推算SNR提升。這個(gè)方案更適合實(shí)際工程但需要信噪分離的預(yù)處理。第二個(gè)方案是監(jiān)聽(tīng)試聽(tīng)加頻譜觀(guān)察。對(duì)演示類(lèi)項(xiàng)目來(lái)說(shuō)主觀(guān)聽(tīng)感比數(shù)字更有說(shuō)服力。如果底噪明顯降低語(yǔ)音可懂度保持良好就可以認(rèn)為濾波有效。配合頻譜圖做前后對(duì)比基本能讓人信服。第三個(gè)方案是制作驗(yàn)證數(shù)據(jù)集。人為把干凈信號(hào)和噪聲混合記錄下噪聲比例這樣任何時(shí)候都能拿回干凈信號(hào)來(lái)算SNR。我推薦新手用這個(gè)方案因?yàn)榭煽匦宰顝?qiáng)。5. 項(xiàng)目擴(kuò)展與延伸思考5.1 從低通到帶通和多帶去噪這個(gè)項(xiàng)目的基礎(chǔ)形態(tài)是低通去噪但實(shí)際上很多音頻噪聲并不只分布在高頻段——交流聲在50Hz或100Hz附近風(fēng)扇噪聲在幾十到幾百Hz的低頻鍵盤(pán)敲擊聲在中頻段。這種情況下單一低通濾波器就不夠用了。處理方法是設(shè)計(jì)多個(gè)帶通濾波器分別濾除不同頻段的噪聲。Matlab里可以用fir1設(shè)計(jì)帶通濾波器傳入通帶上下截止頻率或者干脆用firpm設(shè)計(jì)等紋波濾波器在多個(gè)頻段同時(shí)定義幅度約束。這種設(shè)計(jì)難度會(huì)直線(xiàn)上升但應(yīng)用價(jià)值也更高。我實(shí)際測(cè)試過(guò)一個(gè)場(chǎng)景給語(yǔ)音同時(shí)疊加低頻交流聲100Hz和高頻白噪聲分別設(shè)計(jì)了一個(gè)高通和一個(gè)低通濾波器并聯(lián)處理發(fā)現(xiàn)效果比單一低通好得多。缺點(diǎn)是濾波器設(shè)計(jì)和參數(shù)調(diào)整的工作量成倍增加需要在項(xiàng)目規(guī)劃時(shí)留出足夠調(diào)試時(shí)間。5.2 從固定系數(shù)到自適應(yīng)濾波FIR濾波器在噪聲分布固定時(shí)表現(xiàn)很好但如果噪聲頻段隨時(shí)間變化固定系數(shù)就不夠用了。此時(shí)自適應(yīng)濾波器比如LMS算法能實(shí)時(shí)調(diào)整系數(shù)跟蹤噪聲變化。用Matlab實(shí)現(xiàn)一個(gè)簡(jiǎn)單的LMS自適應(yīng)濾波器大約是幾十行代碼的事核心思路是濾波器系數(shù)根據(jù)誤差信號(hào)不斷調(diào)整讓輸出信號(hào)逐漸逼近理想信號(hào)。這個(gè)方向可以作為這個(gè)項(xiàng)目的進(jìn)階版本尤其適合做課程設(shè)計(jì)的擴(kuò)展內(nèi)容。我建議第一次接觸的人還是先把固定的FIR濾波器徹底吃透理解系數(shù)是怎么來(lái)的、參數(shù)怎么調(diào)再考慮自適應(yīng)——否則很容易被“自適應(yīng)”三個(gè)字迷惑最后代碼能跑但講不清原理。5.3 把濾波器導(dǎo)出到C語(yǔ)言做嵌入式部署Matlab設(shè)計(jì)的濾波器系數(shù)可以直接以C數(shù)組形式導(dǎo)出然后用嵌入式C代碼實(shí)現(xiàn)卷積運(yùn)算部署到ARM、DSP或者FPGA平臺(tái)上。這套流程在企業(yè)產(chǎn)品開(kāi)發(fā)中非常常見(jiàn)從“Matlab仿真”到“硬件落地”通常是這樣的遷移路徑。導(dǎo)出系數(shù)用matlab.internal.getCodegenCompatibleFolder或者其他導(dǎo)出函數(shù)就能生成C代碼骨架。但這里有個(gè)常被忽略的問(wèn)題Matlab里的浮點(diǎn)濾波器系數(shù)精度很高到了嵌入式平臺(tái)如果用定點(diǎn)數(shù)表示系數(shù)量化誤差可能導(dǎo)致頻率響應(yīng)偏移。解決方式是使用Matlab的定點(diǎn)工具或?yàn)V波器量化工具提前驗(yàn)證量化后的頻率響應(yīng)是否還滿(mǎn)足設(shè)計(jì)指標(biāo)。這個(gè)方向?qū)τ谟帽卷?xiàng)目的同學(xué)來(lái)說(shuō)可以從“驗(yàn)證原理”延伸到“工程落地”層面含金量立即提升。6. 實(shí)操?gòu)?fù)盤(pán)與個(gè)人經(jīng)驗(yàn)這個(gè)項(xiàng)目我前前后后做了好幾輪有幾條經(jīng)驗(yàn)特別想分享。第一是關(guān)于參數(shù)調(diào)整順序。最合理的調(diào)整順序是先定通帶截止頻率再定過(guò)渡帶寬度由過(guò)渡帶反推階數(shù)最后驗(yàn)證阻帶衰減是否達(dá)標(biāo)。很多人上來(lái)就試階數(shù)階數(shù)調(diào)了幾輪也沒(méi)找到合適的就是因?yàn)轫樞虿粚?duì)。截止頻率決定了“信號(hào)是否受損”階數(shù)決定了“濾波是否干凈”兩者要分開(kāi)調(diào)試不要混在一起。第二是關(guān)于測(cè)試信號(hào)的選擇。用正弦波加白噪聲做出來(lái)的效果圖非常漂亮但會(huì)讓項(xiàng)目看起來(lái)太“玩具”。如果直接用一段人聲錄音頻譜特征更復(fù)雜濾波器設(shè)計(jì)的取舍更明顯最后展示的效果也更貼近真實(shí)應(yīng)用。建議準(zhǔn)備兩套測(cè)試信號(hào)一套是理論演示用的合成信號(hào)用來(lái)驗(yàn)證濾波器設(shè)計(jì)正確性一套是真實(shí)錄音信號(hào)用來(lái)展示實(shí)際效果。第三是關(guān)于結(jié)果呈現(xiàn)。導(dǎo)師或評(píng)審看這個(gè)項(xiàng)目時(shí)最關(guān)心的不是代碼行數(shù)而是你能不能解釋清楚每個(gè)參數(shù)為什么設(shè)成這個(gè)值、效果差異是什么導(dǎo)致的。所以做項(xiàng)目時(shí)一定要保留各個(gè)調(diào)試階段的截圖和音頻文件比如“階數(shù)41的頻譜圖”對(duì)比“階數(shù)81的頻譜圖”這樣的過(guò)程記錄比最終結(jié)果更能體現(xiàn)你的工程思維能力。我在另一次迭代中還試過(guò)用回聲消除的思路處理這套系統(tǒng)就是同時(shí)保留原始帶噪信號(hào)和濾波后信號(hào)用自適應(yīng)濾波動(dòng)態(tài)混音輸出。雖然最終沒(méi)有采納但中間的探索過(guò)程讓我對(duì)FIR和自適應(yīng)濾波器的差異有了更深理解。這種“橫向嘗試”對(duì)個(gè)人成長(zhǎng)幫助挺大——同一個(gè)濾波問(wèn)題從多個(gè)方向切入比單純調(diào)參收獲更多。最后說(shuō)一個(gè)被很多人忽略的小技巧做這種數(shù)據(jù)處理項(xiàng)目一定要設(shè)置隨機(jī)數(shù)種子也就是rng(0)。因?yàn)閞andn生成的噪聲是隨機(jī)的不設(shè)固定種子的話(huà)每次運(yùn)行得到的噪聲不同實(shí)驗(yàn)結(jié)果不可復(fù)現(xiàn)。設(shè)了種子之后別人拿到你的代碼運(yùn)行以后能得到一模一樣的波形、頻譜和SNR值這對(duì)課程設(shè)計(jì)和論文復(fù)現(xiàn)尤其重要。這個(gè)小動(dòng)作對(duì)你的項(xiàng)目嚴(yán)謹(jǐn)性提升遠(yuǎn)大于其成本。