式中,N为样本容量,下同。 (3) 均方值估计
(4) 方差估计
2.2频谱分析原理
时域分析只能反映信号的幅值随时间的变化情况,除单频率分量的简单波形外,很难明确提示信号的频率组成和各频率分量大小,而频谱分析能很好的解决此问题。由于从频域能获得的主要是频率信息,所以本节主要介绍频率(周期)的估计与频谱图的生成。
2.2.1 DFT与FFT
对于给定的时域信号y,可以通过Fourier变换得到频域信息Y。Y可按下式计算
式中,N为样本容量,Δt = 1/Fs为采样间隔。
采样信号的频谱是一个连续的频谱,不可能计算出所有的点的值,故采用离散Fourier变换(DFT),即
式中,Δf = Fs/N。但上式的计算效率很低,因为有大量的指数(等价于三角函数)运算,故实际中多采用快速Fourier变换(FFT)。其原理即是将重复的三角函数算计的中间结果保存起来,以减少重复三角函数计算带来的时间浪费。由于三角函数计算的重复量相当大,故FFT能极大地提高运算效率。 2.2.2 频率、周期的估计
对于Y(kΔf),如果当kΔf =
时,Y(kΔf)取最大值,则
为频率的估计值,
6
由于采样间隔的误差,也存在误差,其误差最大为Δf / 2。周期T=1/f。
从原理上可以看出,如果在标准信号中混有噪声,用上述方法仍能够精确地估计出原标准信号的频率和周期,这个将在下一章做出验证
2.2.3 频谱图
为了直观地表示信号的频率特性,工程上常常将Fourier变换的结果用图形的方式表示,即频谱图。
以频率f为横坐标,|Y(f)|为纵坐标,可以得到幅值谱; 以频率f为横坐标,arg Y(f)为纵坐标,可以得到相位谱; 以频率f为横坐标,Re Y(f)为纵坐标,可以得到实频谱; 以频率f为横坐标,Im Y(f)为纵坐标,可以得到虚频谱。
根据采样定理,只有频率不超过Fs/2的信号才能被正确采集,即Fourier变换的结果中频率大于Fs/2的部分是不正确的部分,故不在频谱图中显示。即横坐标f ∈[0, Fs/2]
2.3. 模块划分
模块化就是把程序划分成独立命名且可独立访问的模块,每个模块完成一个子功能,把这些模块集成起来构成一个整体,可以完成指定的功能满足用户需求。根据人类解决一般问题的经验,如果一个问题由两个问题组合而成,那么它的复杂程度大于分别考虑每个问题时的复杂程度之和,也就是说把复杂的问题分解成许多容易解决的小问题,原来的问题也就容易解决了。这就是模块化的根据。
在模块划分时应遵循如下规则[4] 张海藩. 软件工程. 北京:人民邮电出版社, 2002:改进软件结构提高模块独立性;模块规模应该适中;深度、宽度、扇出和扇入都应适当;模块的作用域应该在控制域之内;力争降低模块接口的复杂程度;设计单入口单出口的模块;模块功能应该可以预测。
本着上述的启发式规则,对软件进行如图 2所示的模块划分。
7
图 2频谱分析仪的模块划分
3.软件实现
3.1界面设计
MATLAB是Mathworks公司推出的数学软件,它将数值分析、矩阵计算、信号处理和图形显示结合在一起,为众多学科领域提供了一种简洁、高效的编程工具。它提供的GUIDE工具为可视化编程工具,使得软件的界面设计像VB一样方便。故本文采用MATLAB作为编程语言实现声音信号频谱分析仪,以下所讲的都是在MATLAB7.0环境中。
为了实现预期的功能,设计如图 3所示的界面。
8
图 3 频谱分析仪的界面设计
最上面的部分为标题区,用于显示软件标题等信息,不具人机交互功能。 再往下是信号输入区,包含3种输入方式,考虑到WAV文件可能是多声道,故提供了声道选择的界面,因为每次只能对单个声道进行分析。在信号发生器中加入了混迭选项,从而可以将产生的信号与原有的信号进行混迭。界面应该具有:只有当每个单选框被选中时才允许使用对应的输入框、按钮等;采样点数输入框在声卡与WAV文件的输入方式下作为输出,在信号发生器的输入方式下作为输入。
再往下是分析区。对于WAV文件及录音的信号,有时只对其中一部分信号进行分析,故提供了分析对象范围设定的界面。另外就是时域分析与频域分析的按钮,该软件的核心代码都在这两个按钮的回调函数中。
分析区下面是分析结果区,用于显示波形基本参数与统计量的计算结果。
9
分析结果区的下面是波形显示区,用于显示时域波形,在录音结束、打开WAV文件成功或者信号发生器生成波形时会更新显示。
右边为频谱图显示区,用于显示各种频谱的谱线,在点击频域分析后会更新显示。
3.2输入模块的实现
采样频率Fs与采样点数N是声音信号输入时共同需要作用的参数,故将其独立出来。下面为别介绍三种输入方式的实现。
3.2.1 声卡输入
这里声卡输入是指由麦克风录音得到的声音信号的输入,MATLAB提供了wavrecord函数,该函数能够实现读取麦克风录音信号。以下是“开始录音”按钮的回调函数内容。
%首先获得设定的Fs值
Fs=str2double(get(findobj('Tag','samplerate'),'String')); %根据设定的录音时长进行录音,将其存入handles.y中
handles.y=wavrecord(str2double(get(handles.recordtime,'String'))*Fs, Fs,'int16');
%保存handles结构体,使得handles.y在别的函数中也能使用 guidata(hObject,handles); %在波形显示区绘出波形 plot(handles.time,handles.y); title('WAVE');
%将所采到的点的数量输出在“采样点数”中 ysize=size(handles.y)
set(handles.samplenum,'String',num2str(ysize(1)));
3.2.2 WAV文件输入
MATLAB提供了wavread函数,该函数能够方便的打开并读取WAV文件中的声音信息,并且同时读取所有声道。下面是“打开文件”按钮回调函数的部分代码。其它代码与声卡输入的类似。
%从WAV文件中读取的声音信息并临时存放到temp变量中
10