这篇文章来源于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文章
2974浏览量
230405 -
数字信号
+关注
关注
2文章
969浏览量
47539 -
GUI
+关注
关注
3文章
659浏览量
39658
发布评论请先 登录
相关推荐
评论