11-2 Filter Design (瞈暹郭?刻身閮?

在上一節中,我們介紹了幾種基本的濾波器,並說明其應用。本節將介紹如何以簡單的 MATLAB 指令來設計濾波器,並顯示其效果。

我們可以使用 butter 指令來設計一個 Butterworth 濾波器,範例如下:

Example 1: butter01.mfs=8000; % Sampling rate filterOrder=5; % Order of filter cutOffFreq=1000; % Cutoff frequency [b, a]=butter(filterOrder, cutOffFreq/(fs/2), 'low'); % === Plot frequency response [h, w]=freqz(b, a); plot(w/pi*fs/2, abs(h), '.-'); title('Magnitude frequency response'); grid on

在上述範例中,我們使用 butter 指令來設計一個 Butterworth 低通濾波器,其格式如下:
[b, a] = butter(order, Wn, function)
對於輸入參數,我們可以說明如下: 上述範例所產生的四個圖形,事實上是同一個圖,只是分別在x軸或y軸使用對數刻度,所以造成不同的效果。這些圖都稱為濾波器的「頻率響應」(Frequency Response),顯示不同頻率的訊號經過此濾波器時,所乘上的衰減率。上述範例中,我們是要設計一個截止頻率為 1000 Hz 的濾波器,由頻率響應可以看出,這果然是一個低通濾波器。

當濾波器的階數越高時,,因為濾波器參數 a 和 b 的長度變長,濾波的效果越明顯,但是計算量也會跟著提高;反之,若階數越低,濾波器參數 a 和 b 的長度變短,計算量降低,但是濾波的效果也會變差,請見下列範例:

Example 2: butter02.mfs=8000; % Sampling rate cutOffFreq=1000; % Cutoff frequency allH=[]; for filterOrder=1:8; [b, a]=butter(filterOrder, cutOffFreq/(fs/2), 'low'); % === Plot frequency response [h, w]=freqz(b, a); allH=[allH, h]; end plot(w/pi*fs/2, abs(allH)); title('Frequency response of a low-pass utterworth filter'); legend('order=1', 'order=2', 'order=3', 'order=4', 'order=5', 'order=6', 'order=7', 'order=8');

在上述範例中,可以很明顯地看出,當階數由 1 慢慢增大成 8 時,濾波器的效果也會越來越明顯。

我們可以將音訊通過截止頻率為 1000 Hz 的低通濾波器,看是否能夠把過濾高音,範例如下:

Example 3: butter03.mcutOffFreq=1000; % Cutoff frequency filterOrder=5; % Order of filter au=myAudioRead('wubai_solicitude.wav'); [b, a]=butter(filterOrder, cutOffFreq/(au.fs/2), 'low'); au.signal=au.signal(60*au.fs:90*au.fs); % 30-second signal y=filter(b, a, au.signal); % ====== Plot the result time=(1:length(au.signal))/au.fs; subplot(2,1,1); plot(time, au.signal); subplot(2,1,2); plot(time, y); % ====== Save output files myAudioWrite(au, 'wubai_solicitude_orig.wav'); au.signal=y; myAudioWrite(au, sprintf('wubai_solicitude_%d.wav', cutOffFreq)); [Warning: Data clipped when writing file.] [> In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('audiowrite>clipInputData', 'E:\MATLAB\R2015a\toolbox\matlab\audiovideo\audiowrite.m', 396)" style="font-weight:bold">audiowrite>clipInputData</a> (<a href="matlab: opentoline('E:\MATLAB\R2015a\toolbox\matlab\audiovideo\audiowrite.m',396,0)">line 396</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('audiowrite', 'E:\MATLAB\R2015a\toolbox\matlab\audiovideo\audiowrite.m', 176)" style="font-weight:bold">audiowrite</a> (<a href="matlab: opentoline('E:\MATLAB\R2015a\toolbox\matlab\audiovideo\audiowrite.m',176,0)">line 176</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('myAudioWrite', 'd:\users\jang\matlab\toolbox\sap\myAudioWrite.m', 29)" style="font-weight:bold">myAudioWrite</a> (<a href="matlab: opentoline('d:\users\jang\matlab\toolbox\sap\myAudioWrite.m',29,0)">line 29</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('butter03', 'D:\users\jang\books\audioSignalProcessing\example\butter03.m', 16)" style="font-weight:bold">butter03</a> (<a href="matlab: opentoline('D:\users\jang\books\audioSignalProcessing\example\butter03.m',16,0)">line 16</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile>dummyFunction', 'D:\users\jang\books\goWriteOutputFile.m', 85)" style="font-weight:bold">goWriteOutputFile>dummyFunction</a> (<a href="matlab: opentoline('D:\users\jang\books\goWriteOutputFile.m',85,0)">line 85</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile', 'D:\users\jang\books\goWriteOutputFile.m', 55)" style="font-weight:bold">goWriteOutputFile</a> (<a href="matlab: opentoline('D:\users\jang\books\goWriteOutputFile.m',55,0)">line 55</a>)]

我們可以聽看看原訊號和濾波器輸出訊號的差異: 可以很明顯地聽到,高音部分都幾乎被刪除了。

如果我們將截止頻率設定成 100 Hz,此時濾波器的訊號,就幾乎只能聽到低音鼓的聲音,範例如下:

Example 4: butter04.mcutOffFreq=100; % Cutoff freq (截止頻率) filterOrder=5; % Order of filter (濾波器的階數) au=myAudioRead('wubai_solicitude.wav'); [b, a]=butter(filterOrder, cutOffFreq/(au.fs/2), 'low'); au.signal=au.signal(60*au.fs:90*au.fs); % 30 seconds of singing (30 秒歌聲) y=filter(b, a, au.signal); % ====== Plotting (畫圖) time=(1:length(au.signal))/au.fs; subplot(2,1,1); plot(time, au.signal); subplot(2,1,2); plot(time, y); % ====== Save wav files (存檔) myAudioWrite(au, 'wubai_solicitude_orig.wav'); au.signal=y; myAudioWrite(au, sprintf('wubai_solicitude_%d.wav', cutOffFreq)); [Warning: Data clipped when writing file.] [> In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('audiowrite>clipInputData', 'E:\MATLAB\R2015a\toolbox\matlab\audiovideo\audiowrite.m', 396)" style="font-weight:bold">audiowrite>clipInputData</a> (<a href="matlab: opentoline('E:\MATLAB\R2015a\toolbox\matlab\audiovideo\audiowrite.m',396,0)">line 396</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('audiowrite', 'E:\MATLAB\R2015a\toolbox\matlab\audiovideo\audiowrite.m', 176)" style="font-weight:bold">audiowrite</a> (<a href="matlab: opentoline('E:\MATLAB\R2015a\toolbox\matlab\audiovideo\audiowrite.m',176,0)">line 176</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('myAudioWrite', 'd:\users\jang\matlab\toolbox\sap\myAudioWrite.m', 29)" style="font-weight:bold">myAudioWrite</a> (<a href="matlab: opentoline('d:\users\jang\matlab\toolbox\sap\myAudioWrite.m',29,0)">line 29</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('butter04', 'D:\users\jang\books\audioSignalProcessing\example\butter04.m', 16)" style="font-weight:bold">butter04</a> (<a href="matlab: opentoline('D:\users\jang\books\audioSignalProcessing\example\butter04.m',16,0)">line 16</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile>dummyFunction', 'D:\users\jang\books\goWriteOutputFile.m', 85)" style="font-weight:bold">goWriteOutputFile>dummyFunction</a> (<a href="matlab: opentoline('D:\users\jang\books\goWriteOutputFile.m',85,0)">line 85</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile', 'D:\users\jang\books\goWriteOutputFile.m', 55)" style="font-weight:bold">goWriteOutputFile</a> (<a href="matlab: opentoline('D:\users\jang\books\goWriteOutputFile.m',55,0)">line 55</a>)]

很明顯地,經過了濾波器的作用,只留下低音鼓的聲音,而且由這些規律出現的低音鼓聲音,我們就可以進行節拍追蹤,找出這一段音樂的節拍。(當然,這只是一個開始,若要進行節拍追蹤,還有很多細節要處理。)

如果你還是聽不出來低音鼓在原來音樂的位置,可以嘗試逐次聽聽下列檔案(最好使用 CoolEdit 來聽,可以同步顯示播放進度),就應該可以慢慢抓到低音鼓的位置:


Audio Signal Processing and Recognition (音訊處理與辨識)