這篇文章來源于DevicePlus.com英語網站的翻譯稿。
本文是DSP Arduino系列的續篇。上文中,我們介紹了傅里葉變換的基礎知識,并使用MATLAB學習了如何將正弦信號從時域變換到頻域。這次,在添加了失真濾波器后,我們將在MATLAB中創建一個簡單的GUI來記錄我們的語音信號!
硬件
? Arduino Uno
? 用于Arduino的CJMCU-9812 MAX9812L駐極體麥克風放大器開發板
軟件
? Arduino IDE
? MATLAB
步驟3:應用失真濾波器
在前文中,我們已經得到了一個通過了40階低通濾波器的信號。在此步中,我們需要添加另一個會使信號失真的濾波器。這可以通過MATLAB中的filter函數來完成。您可能已經想到了,我們還需要添加下文所示的系數。
[s,fe2,bits] = wavread(‘s’);
sound(s,fe2);
pause(9)
b = [0.1662, -0.0943, 0.2892, -0.1227, 0.2348, 0.0180, 0.0415, 0.1388, -0.0616, 0.1290, -0.0434, 0.0420, -0.0010, -0.0009, 0.0032, -0.0015, 0.0056] ;
a = [1.0000, -0.7548, 3.4400, -1.6385, 4.8436, -0.8156, 3.2813, 1.2582, 0.6571, 2.1922, -0.4792, 1.4546, -0.2905, 0.4693, -0.0208, 0.0614, 0.0120] ;
x = filter(b,a,s);
figure
plot(t1,s2,t1,x),grid
title(‘The initial signal vs the distorted signal’);
sound(x,fe2);
pause(9)
audiowrite(‘x.wav’,x,fe2);
請注意,s是指在上一步中應用了低通濾波器之后獲得的信號。在圖1中,藍色信號代表原始信號,綠色信號代表失真信號。與藍色信號相比,綠色信號具有較低的幅度。
圖1:重疊信號
為了進一步進行檢驗,我們將使用FFT算法。
為了更好地進行比較,我們對兩個信號分別進行了繪制。下面的兩個圖將會說明在時域和頻域中兩者之間的差異。
% s si x signals (time-frequency domain)
t1=(0:length(s)-1)/(fe2);
figure
subplot(2,1,1), plot(t1,s),grid
title(‘s signal in time domain(low-pass filter)’);
xlabel(‘Time’)
ylabel(‘Amplitude’)
t2=(0:length(x)-1)/(fe2);
subplot(2,1,2), plot(t2,x),grid
title(‘x signal in time domain(distorted)’);
xlabel(‘Time’)
ylabel(‘Amplitude’)
圖2:時域中信號失真前后圖形
在時域中,圖形發生了很大的變化:s信號幅度較小(雖然這兩張圖在視覺可能會給您一種x信號具有較高幅值的感覺)。如果您仔細看一下y軸的比例,就可以看出兩者幅度的差異。對于這一現象,您可能會想知道是應用了哪種濾波,以及是什么修改方式導致的這些系數值。
答案可以在頻域中找到:
figure
s1 = abs(fft(s,NS));
subplot(2,1,1), plot((0:(NS-1))/NS*fe2, s1), grid
title(‘Single-Sided Amplitude Spectrum of s(t)’)
xlabel(‘Frequency (Hz)’)
ylabel(‘|s(k)|’)
x1 = abs(fft(x,NS));
subplot(2,1,2), plot((0:(NS-1))/NS*fe2, x1), grid
title(‘Single-Sided Amplitude Spectrum of x(t)’)
xlabel(‘Frequency (Hz)’)
ylabel(‘|X(k)|’)
我們應用傅里葉變換來得到等效頻率。正如您在圖3中看到的那樣,y軸對稱的中心點大約是采樣率的1/2。
圖3:頻域中信號失真前后圖形
這兩個信號具有不同的頻譜
? 頂部圖像
? Y軸值約為800。
? 值達到2000 Hz后,幾乎沒有信號。
? 底部圖像:
? Y軸值約為40。
? 值達到2000 Hz后,可以觀察到仍有信號。
研究此頻率范圍內的樣本點是很困難的。因此,讓我們將目標鎖定在2000 Hz左右處,對該范圍內的幅值進行研究。
圖4:2500Hz附近小范圍頻率內圖像
如果我們仔細觀察幅值變化,可以看出兩個信號具有相同的形狀,而它們在圖3中看起來并不相似。上一張圖像中的兩個信號之所以看起來不同是因為它們的坐標軸比例設置不同。
從兩個圖中,我們可以觀察到振幅降低了。可是我們還是不知道濾波器的頻率響應是什么,以及它對我們的信號帶來了其他什么變化。在這種情況下,我們使用Matlab對其進行繪制。
[h1,w1] = freqz(b,a,NS,fe2);
figure
plot(w1,abs(h1)), grid
xlabel(‘Frequency (Hz)’)
ylabel(‘Frequency response’)
圖5:一個新型濾波器
這個新的濾波器稱為帶通濾波器。因為這是第一次使用該濾波器,所以在應用之前,我們先了解一下它的一些屬性:
? 可以通過將低通濾波器電路和高通濾波器電路相連接來實現。
? 應用該濾波器時,濾波器通帶中的信號保持不變,而在頻帶外部的頻率分量將被衰減。
? 高通帶和低通帶上的分量將被衰減。
? 在我們的項目中,驗證了2000 Hz的頻率分量發生了衰減。
? 理想的帶通濾波器具有平坦的通帶,但在我們的應用中,如圖4所示,出現了一個增益(也可能發生衰減)。我們只能在理論中獲得理想的濾波器。
圖6:帶通濾波器
您可以看到,圖6中的濾波器和圖5中的濾波器具有相似的形狀。因此,我們已經獲得了一個新的濾波器。
步驟4:創建GUI
作為一個實用項目,我們接下來將會對自己的語音信號進行處理。對!這就是我們將要與Arduino相結合的地方。
圖7:Arduino套件
在本項目中,我選擇了帶有MAX9812L放大器和駐極體麥克風的模塊。該模塊具有以下三個端子:
? VCC(2.7V至3.6V之間—由Arduino的3.3V引腳供電)
? GND(接地端—連接到Arduino接地端)
? OUT(本項目中連接到A0)
圖7:Arduino套件
我們不打算使用Arduino IDE串行監視器,而是直接在Matlab中讀取傳感器值。
Arduino 代碼:
void setup() {
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(A0);
float voltage = sensorValue * (3.3 / 1023.0);
Serial.println(voltage);
}
我們還將使用Matlab來進行處理。為了處理語音信號,我們將創建一個圖形用戶界面。該圖形用戶界面中有兩個按鈕:
? 藍色(start) – 用戶開始語音記錄
? 橙色(push button)– 用戶停止通過連接到Arduino的麥克風進行錄音(關閉串行傳輸)。
在該程序中創建GUI非常容易,因為您可以使用拖動功能來繪制連接點。首先,在命令窗口中輸入guide。
圖9:在Matlab中創建GUI
當您點擊“Create New GUI(創建新GUI)”時,將會顯示出來一個用戶友好界面。Matlab GUI不像C#或其他語言那樣需要較高的編程技能。在這里,您需要選擇要添加的塊,并對生成的代碼進行修改。
圖10:如何在Matlab中創建塊
在左側菜單中包含了用于您的GUI的不同指令。對于本項目來說,需要的元素不會超過三個,因為我們只是要對語音信號進行顯示而已。因為我們希望在記錄后可以使用數據,所以將創建一個包含錄音內容的.csv文件,該文件可用于信號處理。
在我的GUI中,我使用了:
? 坐標軸;
? 2個按鈕;
圖11:GUI設計
該按鈕的代碼是根據按鈕的規格來構建的。整個代碼將被上傳到GitHub上供您下載。
fid = fopen(‘signal.csv’,’w’)
S=1;
s = serial(‘COM9’);
set(s,’BaudRate’,9600);
fopen(s);
fprintf(s,’%s’,’S’);
圖12:Matlab應用程序中的語音信號
如果您已經完成了這一步,那么恭喜您!到此為止,我們的數字信號處理系列教程已經結束了。我們介紹了有關信號處理的各種概念。這是一個非常具有挑戰性的課題,所以如果現在沒有對所有內容都了解得很清楚,也不要氣餒!當您覺得在某些概念的理解上出現困難時,您可以從網上大量的資源中獲取更多有關信息。隨時歡迎您對我們的工作進行訪問和評論,并與我們分享您的成果!
審核編輯黃宇
-
matlab
+關注
關注
185文章
2979瀏覽量
230648 -
數字信號
+關注
關注
2文章
972瀏覽量
47589 -
GUI
+關注
關注
3文章
662瀏覽量
39761
發布評論請先 登錄
相關推薦
評論