信號(hào)處理實(shí)驗(yàn)實(shí)驗(yàn)報(bào)告 - 實(shí)驗(yàn)名稱:音頻頻譜分析儀的設(shè)計(jì)與實(shí)現(xiàn)
- 實(shí)驗(yàn)?zāi)康模?/font>構(gòu)建交互界面,具有播放聲音功能,顯示波形與頻譜,并可測(cè)量聲音時(shí)與參數(shù)
- 實(shí)驗(yàn)原理:
MATLAB是一個(gè)數(shù)據(jù)分析與數(shù)據(jù)處理功能十分強(qiáng)大的工程應(yīng)用軟件,其數(shù)據(jù)采集工具箱為數(shù)據(jù)的輸入和輸出提供了十分方便的函數(shù)與命令。本實(shí)驗(yàn)要求基于聲卡和MATLAB實(shí)現(xiàn)音頻信號(hào)頻譜分析儀的設(shè)計(jì)與實(shí)現(xiàn),功能包括音頻信號(hào)的輸入、 信號(hào)波形分析、信號(hào)頻譜分析 。 1.頻率周期檢測(cè): 采用過零點(diǎn)的時(shí)間間隔即是周期,頻率為周期的倒數(shù),求出多個(gè)時(shí)間差求平均值,采用平均值作為周期的估計(jì)值。 在一個(gè)周期內(nèi),求出信號(hào)的最小值和最大值差的一半,即y= ,第一個(gè)A值對(duì)應(yīng)的最大值和最小值不是一個(gè)周期內(nèi)得到的,因此除第一個(gè)A值以外的平均值作為估計(jì)值。 通過判斷與同頻信號(hào)過零點(diǎn)時(shí)刻,計(jì)算其時(shí)間差,然后換算成相應(yīng)的相位差。 同樣以 的平均值作為估計(jì)值。 - 數(shù)字信號(hào)統(tǒng)計(jì)量的估計(jì):
(1)峰值估計(jì):利用下面的公式  (2)均值估計(jì):  (3)均方值估計(jì):  (4)方差估計(jì):  
圖3.13 頻率、幅值和相位估計(jì)的流程圖 其中tin表示第n個(gè)過零點(diǎn),yi為第i個(gè)采樣點(diǎn)的值,F(xiàn)s為采樣頻率。 
式中, =Fs/N。但是上式計(jì)算效率低,故利用FFT快速計(jì)算,其原理是把重復(fù)的三角函數(shù)計(jì)算結(jié)果保存起來,以減少重復(fù)三角數(shù)的計(jì)算。 對(duì)于Y(k )如果 = 時(shí),其取最大值, 為頻率估計(jì)值,其存在誤差,最大誤差 /2, 從原理上分析,混有噪聲時(shí),用上述方法也可以得到周期和頻率。 為了直觀地表示信號(hào)的頻率特性,工程上常常將Fourier變換的結(jié)果用圖形的方式表示,即頻譜圖。 以頻率f為橫坐標(biāo),|Y(f)|為縱坐標(biāo),可以得到幅值譜; 以頻率f為橫坐標(biāo),arg Y(f)為縱坐標(biāo),可以得到相位譜; 以頻率f為橫坐標(biāo),Re Y(f)為縱坐標(biāo),可以得到實(shí)頻譜; 以頻率f為橫坐標(biāo),Im Y(f)為縱坐標(biāo),可以得到虛頻譜。 根據(jù)采樣定理,只有頻率不超過Fs/2的信號(hào)才能被正確采集,即Fourier變換的結(jié)果中頻率大于Fs/2的部分是不正確的部分,故不在頻譜圖中顯示。即橫坐標(biāo)f ∈[0, Fs/2]。


設(shè)計(jì)音頻信號(hào)頻譜分析儀,功能包括: - 信號(hào)輸入:實(shí)現(xiàn)從聲卡、WAV文件、標(biāo)準(zhǔn)信號(hào)發(fā)生器輸入信號(hào)。
- 信號(hào)波形分析:包括幅值、頻率、周期的估計(jì),以及統(tǒng)計(jì)量峰值、均值、均方值和方差的計(jì)算;
- 信號(hào)頻譜的分析、頻率、周期的估計(jì),圖形顯示幅度譜、相位譜、實(shí)頻譜、虛頻譜和功率譜。
五、實(shí)驗(yàn)步驟與結(jié)果(附程序和結(jié)果圖片): (1)程序: - function soundcard_Callback(hObject, eventdata, handles); %guide自動(dòng)生成聲卡函數(shù)
- set(findobj('Tag','recordtime'),'enable','on'); %set函數(shù)用于設(shè)定屬性,使能TAG名為recordtime的選項(xiàng)卡。
- h=findobj('Tag','wenben_filename');
- set(h,'enable','off');% %關(guān)閉Tag名為wenben_filename的選項(xiàng)卡
- h=findobj('Tag','freq');
- set(h,'enable','off'); %關(guān)閉Tag名為wenben_filename的選項(xiàng)卡
- h=findobj('Tag','fu_du'); %關(guān)閉Tag名為fu_du的選項(xiàng)卡,off為關(guān)閉,即該選項(xiàng)卡不起 作用,只有聲卡起作用
- set(h,'enable','off');
- h=findobj('Tag','phrase');
- set(h,'enable','off');
- %上述程序?qū)崿F(xiàn)聲卡輸入功能,只將Tag名為recordtime、startrecord的選項(xiàng)卡使能打開,而其他選項(xiàng)卡都是off狀態(tài),例如set(findobj('Tag','recordtime'),'enable','on')語句是將Tag名為recordtime的選項(xiàng)卡打開,on代表打開,off為關(guān)閉。
- set(handles.edit10,'enable','off');
- set(handles.openfile,'enable','off');
- set(handles.wavemaker,'enable','off');
- set(handles.wavetype,'enable','off');
- set(handles.add,'enable','off');
- set(handles.startrecord,'enable','on');
- function startrecord_Callback(hObject, eventdata, handles)
- %以下為開始錄音程序,audiorecorder函數(shù)可以實(shí)現(xiàn)得到麥克風(fēng)聲音,函數(shù)功能與wavrecord函數(shù)功能相同,但是MATLAB2017中沒有wavrecord,只有audiorecorder
- Fs=30000;
- Y=audiorecorder(Fs,24,1);
- recordblocking(Y,2);
- handles.y = getaudiodata(Y);
- ysize=size(handles.y);
- set(handles.samplenum,'String',num2str(ysize(1)));
- plot(handles.axes4,handles.y);
- guidata(hObject,handles);
復(fù)制代碼(2)實(shí)驗(yàn)結(jié)果 
通過編寫函數(shù)實(shí)現(xiàn)了聲卡錄音并且對(duì)聲音進(jìn)行時(shí)域和頻域分析。 2. WAV文件輸入: - %同理以下實(shí)現(xiàn)的是WAV文件輸入,只將'Tag'為'filename'的選項(xiàng)卡打開,而其他選項(xiàng)卡的狀態(tài)均關(guān)閉,實(shí)現(xiàn)WAV文件輸入handles.'recordtime'等同于findobj('Tag','recordtime')的功能,都是找到'Tag'為'recordtime'的選項(xiàng)卡。h=findobj('Tag','recordtime');set(h,'enable','off')兩個(gè)語句的功能和語句set(findobj('Tag','recordtime'),'enable','off')的功能相同
- h=findobj('Tag','filename');
- set(h,'enable','on');
- h=findobj('Tag','freq');
- set(h,'enable','off');
- h=findobj('Tag','amp');
- set(h,'enable','off');
- h=findobj('Tag','phase');
- set(h,'enable','off');
- set(findobj('Tag','recordtime'),'enable','off');
- set(handles.edit10,'enable','on');
- set(handles.openfile,'enable','on');
- set(handles.wavemaker,'enable','off');
- set(handles.wavetype,'enable','off');
- set(handles.add,'enable','off');
- set(handles.startrecord,'enable','off');
- %以下程序?qū)崿F(xiàn)打開文件功能
- function openfile_Callback(hObject, eventdata, handles)
- [temp,Fs]=audioread(get(findobj('Tag','filename'),'String'));%WAV文件中讀取的信息臨時(shí)保存到temp中
- handles.y=temp(:,2);
- guidata(hObject,handles)%在波形顯示區(qū)顯示波形
- plot(handles.axes4,handles.y);
- title('WAVE');
- ysize=size(handles.y)%將所采集到的數(shù)據(jù)點(diǎn)數(shù)輸出在采樣點(diǎn)數(shù)中
- set(handles.samplenum,'String',num2str(ysize(1)));
- %同理此程序?qū)崿F(xiàn)的是WAV文件輸入,只將'Tag'為'filename'的選項(xiàng)卡打開,而其他選項(xiàng)卡的狀態(tài)均關(guān)閉,實(shí)現(xiàn)WAV文件輸入handles.'recordtime'等同于findobj('Tag','recordtime')的功能,都是找到'Tag'為'recordtime'的選項(xiàng)卡。h=findobj('Tag','recordtime');set(h,'enable','off')兩個(gè)語句的功能和語句set(findobj('Tag','recordtime'),'enable','off')的功能相同
復(fù)制代碼
可以對(duì)WAV類型的文件自動(dòng)打開、播放以及時(shí)頻域分析等功能。 - %以下程序是實(shí)現(xiàn)輸入頻率、幅度等信息的程序,打開'Tag'為'freq'、'amp'、'phase'、wavemaker、add的選項(xiàng)卡,即生成波形按鈕可使用,而且可以輸入頻率、相位和幅度。同時(shí)關(guān)閉錄音時(shí)間(recordtime)、文件輸入(openfile)輸入功能
- h=findobj('Tag','filename');
- set(h,'enable','off');
- h=findobj('Tag','freq');
- set(h,'enable','on');
- h=findobj('Tag','amp');
- set(h,'enable','on');
- h=findobj('Tag','phase');
- set(h,'enable','on');
- set(findobj('Tag','recordtime'),'enable','off');
- set(handles.edit10,'enable','off');
- set(handles.openfile,'enable','off');
- set(handles.wavemaker,'enable','on');
- set(handles.wavetype,'enable','on');
- set(handles.add,'enable','on');
- set(handles.startrecord,'enable','off');
- %下面的程序?qū)崿F(xiàn)的是波形生成的功能
- function wavemaker_Callback(hObject, eventdata, handles)
- Fs=str2double(get(findobj('Tag','samplerate'),'String'));得到采樣頻率
- N=str2double(get(findobj('Tag','samplenum'),'String'));得到采樣點(diǎn)數(shù)
- x=linspace(0,N/Fs,N);
- soundtype=get(handles.wavetype,'Value');得到wavetype選項(xiàng)卡的值給soundtype
- frequency=str2double(get(handles.freq,'String'));
- amp=str2double(get(handles.amp,'String'));
- phase=str2double(get(handles.phase,'String'));
- %根據(jù)soundtype值不同選擇不同的波形類型,soundtype范圍為1到5,分別對(duì)應(yīng)五種波形,
- 超出范圍報(bào)錯(cuò)
- switch soundtype
- case 1
- y=amp*sin(2*pi*x*frequency+phase);
- case 2
- y=amp*sign(sin(2*pi*x*frequency+phase));
- case 3
- y=amp*sawtooth(2*pi*x*frequency+phase,0.5);
- case 4
- y=amp*sawtooth(2*pi*x*frequency+phase);
- case 5
- y=amp*(2*rand(size(x))-1);
- otherwise
- errordlg('Illegal wave type','Choose errer');
- End
- if get(handles.add,'Value')==0.0%得到add(混疊)的值,如果為0(沒有選混疊),則不混疊
- handles.y=y;
- Else %否則混疊
- handles.y=handles.y+y;
- end
- plot(handles.axes4,handles.y) %畫出波形
- guidata(hObject,handles);
- title('WAVE');
- axis([0 N -str2double(get(handles.amp,'String')) str2double(get(handles.amp,'String'))]);
- %標(biāo)記坐標(biāo)軸范圍和標(biāo)題
復(fù)制代碼

三角波 
方波 
白噪聲 
正弦波


正弦波混疊
信號(hào)發(fā)生器信號(hào)輸入實(shí)現(xiàn)了正弦波、方波、三角波、白噪聲以及鋸齒波的產(chǎn)生,并可以實(shí)現(xiàn)混疊、時(shí)頻域分析等功能,但是在時(shí)域分析分析時(shí),由于其是利用多個(gè)采樣點(diǎn),利用計(jì)算公式來進(jìn)行時(shí)頻域分析,采樣點(diǎn)不能完全逼近實(shí)際波形,因此會(huì)造成一定誤差。 Fs=str2double(get(findobj('Tag','samplerate'),'String')); %得到'Tag'為'samplerate'的名稱并轉(zhuǎn)換為數(shù)字即得到輸入頻率的數(shù)值。 N=str2double(get(findobj('Tag','samplenum'),'String')); %得到'Tag'為'samplenum'的名稱并轉(zhuǎn)換為數(shù)字即得到采樣點(diǎn)數(shù)。 T=[];amp=[];ti=[]; n=1; ymax=max([handles.y(1) handles.y(2)]); %將y(2),y(1)的最大值給ymax ymin=min([handles.y(1) handles.y(2)]); %將y(2),y(1)的最小值給ymin from=str2double(get(handles.point1,'String')); %得到point1方框的數(shù)值, 即分析起始點(diǎn) to=str2double(get(handles.pointlast,'String')); %得到pointlast方框的數(shù)值,即分析終止點(diǎn) if from<1|to-from<5; msgbox('error'); return; End %如果起始點(diǎn)小于1或者分析間隔小于5報(bào)錯(cuò),提示'error' for i=from+2:to-1; if handles.y(i-1)<0 & handles.y(i-2)<0 & handles.y(i)>=0 & 0 if handles.y(i)==0handles.y(i+1)> ti(n)=i; else ti(n)=i-handles.y(i)/(handles.y(i)-handles.y(i-1)); end amp(n)=(ymax-ymin)/2;得到幅度 ymax=0; ymin=0; n=n+1; else if ymax<handles.y(i) ymax=handles.y(i); end if ymin>handles.y(i) ymin=handles.y(i); end end end n=n-1; for i=1:n-1 T(i)=ti(i+1)-ti(i); End %利用過零點(diǎn)時(shí)間間隔求周期, freq = Fs/mean(T); %周期均值的的倒數(shù)得到頻率 set(handles.wenben_zhouqi,'String',1/freq); %分別在相應(yīng)位置顯示周期、頻率、均值 set(handles.wenben_pinlv,'String',num2str(freq)); set(handles.wenben_fudu,'String',num2str(mean(amp(2:n-1))));%以幅度均值作為幅度的估計(jì)值 phase=2*pi*(1-(ti(1:n-1)-1)./T+floor((ti(1:n-1)-1)./T));%將待分析信號(hào)的過零點(diǎn)與標(biāo)準(zhǔn)信號(hào)的過零點(diǎn)比較,得到相位 set(handles.wenben_xiangwei,'String',num2str(mean(phase))); %利用同頻信號(hào)零點(diǎn)取均值得到相位 set(handles.wenben_fengzhi,'String',(max(handles.y(from:to))-min(handles.y(from:to)))/2); %利用 得到峰值
set(handles.wenben_junzhi,'String',mean(handles.y(from:to))); %得到均值 set(handles.wenben_junfangzhi,'String',mean(handles.y(from:to).^2));%得到均方值 %得到均方值并在Tag名為wenben_junfangzhi顯示,mean(handles.y(from:to)取所有點(diǎn)的均值 set(handles.wenben_fangcha,'String',std(handles.y(from:to))^2); %得到方差,并在Tag名為wenben_fangcha顯示 
三角波時(shí)域分析 
矩形波時(shí)域分析
- function freqanalysis_Callback(hObject, eventdata, handles)
- Fs=str2double(get(findobj('Tag','samplerate'),'String'));
- N=str2double(get(findobj('Tag','samplenum'),'String'));
- if handles.wavetype==0
- msgbox('No wave!');如果wavetype=0,顯示no wave
- return;
- end
- from=str2double(get(handles.point1,'String'));%得到point1方框的數(shù)值, 即分析起始點(diǎn)
- to=str2double(get(handles.pointlast,'String'));%得到pointlast方框的數(shù)值,即分析終止點(diǎn)
- sample=handles.y(from:to); %得到波形采樣點(diǎn)矩陣
- f=linspace(0,Fs/2,(to-from+1)/2); %在[0,(to-from+1)/2]之間取Fs/2個(gè)點(diǎn)
- Y=fft(sample,to-from+1); %to-from+1點(diǎn)FFT算法
- [C,I]=max(abs(Y)); %得到頻譜最大值
- set(handles.freqzhouqi,'String',1/f(I)) ;%得到周期并顯示
- set(handles.freqpinlv,'String',f(I)); %得到頻率并顯示
- Y=Y(1:(to-from+1)/2);
- plot(handles.axes5,f,2*sqrt(Y.*conj(Y)));%分別繪制實(shí)頻譜、虛頻譜、相位譜、幅度譜、功率譜
- plot(handles.axes6,f,angle(Y));
- plot(handles.axes7,f,real(Y));
- plot(handles.axes8,f,imag(Y));
- plot(handles.axes9,f,abs(Y).^2);
- xlabel(handles.axes5,'freq(Hz)'); %標(biāo)記坐標(biāo)軸
- xlabel(handles.axes6,'freq(Hz)');
- xlabel(handles.axes7,'freq(Hz)');
- xlabel(handles.axes8,'freq(Hz)');
- xlabel(handles.axes9,'freq(Hz)');
- ylabel(handles.axes5,'amp');
- ylabel(handles.axes6,'phase');
- ylabel(handles.axes7,'real');
- ylabel(handles.axes8,'imag');
- ylabel(handles.axes9,'power');
復(fù)制代碼

輸入分析點(diǎn)數(shù)起始點(diǎn)小于1報(bào)錯(cuò) 
正弦波時(shí)頻域分析結(jié)果 
通過實(shí)驗(yàn)結(jié)果分析,我們可以看出,交互界面基本上實(shí)現(xiàn)了頻域和時(shí)域分析的功能,而且實(shí)現(xiàn)了自動(dòng)報(bào)錯(cuò)功能,時(shí)域分析結(jié)果周期、頻率、幅度誤差較小,可能是由于采樣點(diǎn)數(shù)或者在取值時(shí)量化誤差造成的,在誤差允許范圍內(nèi)實(shí)現(xiàn)了時(shí)域分析。但是相位有較大的誤差,通過過零點(diǎn)檢測(cè)相位可能由于采集過零點(diǎn)時(shí)刻誤差較大,造成相位估計(jì)值誤差較大。頻域分析周期以及頻率雖然有一定誤差,但是誤差很小。誤差可能由于MATLAB利用離散點(diǎn)來逼近波形,不可能完全和實(shí)際一樣。 本次實(shí)驗(yàn)完成了音頻頻譜分析儀的設(shè)計(jì)與實(shí)現(xiàn),基本上滿足了題目要求,并且為分析儀增加了錯(cuò)誤輸入提醒、自動(dòng)查找文件等新功能。 通過本次實(shí)驗(yàn),學(xué)習(xí)使用了MATLABguide交互界面的設(shè)計(jì)方法,掌握了guide交互界面設(shè)計(jì)的基本流程、guide交互界面函數(shù)的編寫,重新認(rèn)識(shí)了MATLAB的強(qiáng)大功能,MATLAB不僅提供了基本的函數(shù),幫助我們實(shí)現(xiàn)設(shè)計(jì)功能,而且根據(jù)我們?cè)O(shè)計(jì)的界面,自動(dòng)生成了模板,極大的方便了我們的設(shè)計(jì)工作。 本次實(shí)驗(yàn)相對(duì)前六次實(shí)驗(yàn)難度加大,在前幾次實(shí)驗(yàn)的基礎(chǔ)上,依然感覺無從下手,通過借閱圖書、上網(wǎng)查閱資料終于完成了本次實(shí)驗(yàn),通過本次實(shí)驗(yàn)接觸了交互界面的設(shè)計(jì)方法,同時(shí)也認(rèn)識(shí)到MATLAB強(qiáng)大的功能,提供了友好的交互界面設(shè)計(jì)。在本次試驗(yàn)中遇到了很多的問題,比如基本函數(shù)的調(diào)用格式,在使用findobj函數(shù)時(shí)報(bào)錯(cuò),提示輸入?yún)?shù)不足,通過上網(wǎng)查找資料、請(qǐng)教同學(xué),才發(fā)現(xiàn)調(diào)用格式出錯(cuò)。還有根據(jù)教材使用wavrecord函數(shù)時(shí),提示未定義該函數(shù),在命令窗口help wavrecord,發(fā)現(xiàn)MATLAB不提供該函數(shù),上網(wǎng)查找發(fā)現(xiàn)MATLAB2013以后刪除了該函數(shù)。 總之,通過本次實(shí)驗(yàn),初步認(rèn)識(shí)了交互界面的設(shè)計(jì)方法,同時(shí)認(rèn)識(shí)到MATLAB強(qiáng)大的功能,在設(shè)計(jì)過程中遇到了很多問題,通過查找資料解決問題,提高了查找資料、解決問題的能力。通過信號(hào)處理七次實(shí)驗(yàn)掌握了MATLAB的使用方法以及強(qiáng)大功能,激發(fā)了自己學(xué)習(xí)MATLAB的熱情,必將為今后的學(xué)習(xí)打下良好的基礎(chǔ)。
完整的Word格式文檔51黑下載地址:
實(shí)驗(yàn)七音頻頻譜分析儀的設(shè)計(jì)與實(shí)現(xiàn)2.docx
(658.31 KB, 下載次數(shù): 44)
2018-1-18 13:50 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|