gusucode.com > 声音的处理有:LPC,FFT,共振峰,频谱源码程序 > siganlandsystemusingMatlab/SSUM/filters/pzfilter/pzfilterexpofn.m
% This code borrows heavily from MAD polezero demonstration function pzfilterexpo(action,datastruct) if nargin < 1 action='init'; end % Colormap isn't working as predicted name = mfilename; figname = [name(1:end-2) '_fig']; f=findobj('Tag',figname); handles = get(f,'UserData'); switch action case 'help' display_help(figname); case 'init' setdefaults; reset(handles.specplot); reset(handles.timeplot); reset(handles.pz_plot); reset(handles.Hz_plot); handles.Fs = 44100; handles.npoints = 256; makePZPlot(handles); handles = makeHzPlot(handles); set(gcf,'KeyPressFcn','pzfilterexpofn keypressed'); case 'loadsound' handles.audiodata = load_audiodata; handles.original = handles.audiodata; if ~isfield(handles.audiodata, 'filenamepath') return; end if (size(handles.audiodata.data,2) > 1) handles.audiodata.data = to_mono(handles.audiodata.data); end handles.Fs = handles.audiodata.Fs; contents = get(handles.fftsize,'String'); fftsize = str2double(contents{get(handles.fftsize,'Value')}); contents = get(handles.Window,'String'); shape = contents{get(handles.Window,'Value')}; [handles.spectrum, handles.bin, handles.st] = ... spectrogram(handles.audiodata, fftsize, shape); handles = makeTimePlot(handles); handles = makeSpecPlot(handles); handles = makeHzPlot(handles); handles = updateHzPlot(handles); linkedzoom([handles.timeplot, handles.specplot],'onx'); place_header(f,handles); set(handles.freqzoom,'Value',1); case 'readinput' if isfield(datastruct,'polepos') handles.Fs = 44100; handles = makeHzPlot(handles); if isfield(datastruct, 'gain') set(handles.gain,'String',num2str(datastruct.gain)); end z = datastruct.zeropos; % Remove zeros from 0 z = z(find(z)); zc = conj(z); elem = find(z == zc); if (elem > 0) % Add just a bit so that the plot doesn't make them invisible mult = 0.00000; z = [z(1:elem-1); z(elem)+j*mult; z(elem)-j*mult; z(elem+1:end)]; datastruct.zeropos = z; end p = datastruct.polepos; % Remove poles from 0 p = p(find(p)); pc = conj(p); elem = find(p == pc); if (elem > 0) mult = 0.00000; p = [p(1:elem-1); p(elem)+j*mult; p(elem)-j*mult; p(elem+1:end)]; datastruct.polepos = p; end for i=1:length(datastruct.zeropos)/2, x = real(datastruct.zeropos(i*2-1)); y = imag(datastruct.zeropos(i*2-1)); p1=text('Parent',handles.pz_plot,'Position',[x y],... 'String','o','ButtonDownFcn','pzfilterexpofn selectzero',... 'EraseMode','xor','Tag','Zero',... 'HorizontalAlignment','center'); if y ~= 0, p2=text('Parent',handles.pz_plot,'Position',[x -y],... 'String','o','ButtonDownFcn','pzfilterexpofn selectzero',... 'EraseMode','xor','Tag','Zero',... 'HorizontalAlignment','center'); set(p1,'UserData',p2); set(p2,'UserData',p1); end end for i=1:length(datastruct.polepos)/2, x = real(datastruct.polepos(i*2-1)); y = imag(datastruct.polepos(i*2-1)); p1=text('Parent',handles.pz_plot,'Position',[x y],... 'String','x','ButtonDownFcn','pzfilterexpofn selectpole',... 'EraseMode','xor','Tag','Pole',... 'HorizontalAlignment','center'); if y ~= 0, p2=text('Parent',handles.pz_plot,'Position',[x -y],... 'String','x','ButtonDownFcn','pzfilterexpofn selectpole',... 'EraseMode','xor','Tag','Pole',... 'HorizontalAlignment','center'); set(p1,'UserData',p2); set(p2,'UserData',p1); end end handles = updateHzPlot(handles); else handles.audiodata = datastruct; clear datastruct; if (size(handles.audiodata.data,2) > 1) handles.audiodata.data = to_mono(handles.audiodata.data); end handles.original = handles.audiodata; contents = get(handles.fftsize,'String'); fftsize = str2double(contents{get(handles.fftsize,'Value')}); contents = get(handles.Window,'String'); shape = contents{get(handles.Window,'Value')}; [handles.spectrum, handles.bin, handles.st] = ... spectrogram(handles.audiodata, fftsize, shape); handles = makeTimePlot(handles); handles = makeSpecPlot(handles); handles = makeHzPlot(handles); handles = updateHzPlot(handles); linkedzoom([handles.timeplot, handles.specplot],'onx'); place_header(f,handles); set(handles.freqzoom,'Value',1); end case {'playsound', 'playoriginal'} if isfield(handles, 'audiodata') times = get(handles.specplot,'XLim'); switch action case 'playsound' audiodata = handles.audiodata; button = handles.play; case 'playoriginal' audiodata = handles.original; button = handles.playoriginal; end samples = floor(times*audiodata.Fs); if (samples(1) <= 0) samples(1) = 1; end if (samples(2) > length(audiodata.data)) samples(2) = length(audiodata.data); end audiodata.data = audiodata.data(samples(1):samples(2)); if (max(abs(audiodata.data)) > 1.0) audiodata.data = normalize(audiodata.data); end play_audiodata(audiodata, button); end case {'db','inverse','interpolate','colormap','fftdisplay'} if isfield(handles, 'audiodata') updateSpecPlot(handles); set(handles.specplot,'XLim',get(handles.timeplot,'XLim')); pzfilterexpofn 'freqzoom'; end case 'Hz_logf' if get(handles.Hz_logf,'Value') set(handles.Hz_plot,'XScale','log'); else set(handles.Hz_plot,'XScale','linear'); end case 'Hz_dB' axes(handles.Hz_plot); if get(handles.dB,'Value') set(handles.Hz_plot,'YLim',[-80 1]); ylabel('Normalized Attenuation (dB)'); else %set(handles.freq_plot,'YLim',[0 1.05]); %set(handles.freq_plot,'YLimMode','auto'); ylabel('Normalized Attenuation'); end pzfilterexpofn 'plotfreqz' case {'fftsize','window'} if isfield(handles, 'audiodata') contents = get(handles.fftsize,'String'); fftsize = str2double(contents{get(handles.fftsize,'Value')}); contents = get(handles.Window,'String'); shape = contents{get(handles.Window,'Value')}; [handles.spectrum, handles.bin, handles.st] = ... spectrogram(handles.audiodata, fftsize, shape); updateSpecPlot(handles); set(handles.specplot,'XLim',get(handles.timeplot,'XLim')); pzfilterexpofn 'freqzoom'; end case 'normalize' if isfield(handles, 'audiodata') handles.audiodata.data = normalize(handles.audiodata.data); handles = makeTimePlot(handles); contents = get(handles.fftsize,'String'); fftsize = str2double(contents{get(handles.fftsize,'Value')}); contents = get(handles.Window,'String'); shape = contents{get(handles.Window,'Value')}; [handles.spectrum, handles.bin, handles.st] = ... spectrogram(handles.audiodata, fftsize, shape); updateSpecPlot(handles); set(handles.specplot,'XLim',get(handles.timeplot,'XLim')); pzfilterexpofn 'freqzoom'; end case 'freqzoom' if isfield(handles,'audiodata') val = get(handles.freqzoom,'Value'); if val == 0, val = 0.001; end Fs = handles.audiodata.Fs; set(handles.specplot,'YLim',[0 val*Fs/2]) end case 'zoomreset' if isfield(handles,'audiodata') handles = makeTimePlot(handles); set(handles.specplot,'XLim',get(handles.timeplot,'XLim')); linkedzoom([handles.timeplot, handles.specplot],'onx'); end case 'fourier' if isfield(handles,'audiodata') fourierexpogui(handles.audiodata); end case 'addzero' handles = add_coef(handles,'zero'); pzfilterexpofn 'plotfreqz' case 'addpole' handles = add_coef(handles,'pole'); pzfilterexpofn 'plotfreqz' case 'selectpole' handles = select_coef(handles,'pole'); case 'selectzero' handles = select_coef(handles,'zero'); case 'movepole' handles = move_coef(handles); pzfilterexpofn 'plotfreqz' case 'movezero' handles = move_coef(handles); pzfilterexpofn 'plotfreqz' case 'releaseobject' set(gcf,'WindowButtonMotionFcn',''); set(gcf,'WindowButtonUpFcn',''); %set([handles.currentcoef handles.partnercoef],'Selected','off'); pzfilterexpofn 'plotfreqz' case 'plotfreqz' handles = updateHzPlot(handles); case 'loadvowel' axes(handles.pz_plot); cla; delete(findobj(gcf,'Selected','on')) makePZPlot(handles); bws=[0.03 0.07 0.1]; %formant freqs from Rabiner & Juang switch datastruct case 'beet' freqs=[270 2290 3010]; case 'bit' freqs=[390 1990 2550]; case 'bet' freqs=[530 1840 2480]; case 'bat' freqs=[660 1720 2410]; case 'bart' freqs=[730 1090 2440]; case 'bort' freqs=[570 840 2410]; case 'but' freqs=[440 1020 2240]; case 'boot' freqs=[300 870 2240]; case 'bert' freqs=[490 1350 1690]; otherwise end % convert freqs and bws to PZ locations angs=2*pi*freqs/handles.Fs; for fr=1:length(freqs) [x,y]=pol2cart(angs(fr),1-bws(fr)); p1=text('Parent',handles.pz_plot,'Position',[x y],... 'String','x','ButtonDownFcn','pzfilterexpofn selectpole',... 'EraseMode','xor','Tag','Pole','HorizontalAlignment','center'); p2=text('Parent',handles.pz_plot,'Position',[x -y],... 'String','x','ButtonDownFcn','pzfilterexpofn selectpole',... 'EraseMode','xor','Tag','Pole','HorizontalAlignment','center'); set(p1,'UserData',p2); set(p2,'UserData',p1); end handles = updateHzPlot(handles); case 'apply_filter' if isfield(handles, 'audiodata') handles = apply_filter(handles); contents = get(handles.fftsize,'String'); fftsize = str2double(contents{get(handles.fftsize,'Value')}); contents = get(handles.Window,'String'); shape = contents{get(handles.Window,'Value')}; [handles.spectrum, handles.bin, handles.st] = ... spectrogram(handles.audiodata, fftsize, shape); updateSpecPlot(handles); Xlim = get(handles.timeplot,'XLim'); handles = makeTimePlot(handles); set(handles.specplot,'XLim',Xlim); set(handles.timeplot,'XLim',Xlim); pzfilterexpofn 'freqzoom'; end case 'keypressed' % if delete key is pressed, delete any selected object if double(get(gcf,'CurrentCharacter')) == 8 delete(findobj(gcf,'Selected','on')) end pzfilterexpofn 'plotfreqz' case 'save' if isfield(handles.audiodata,'data') save_audiodata(handles.audiodata); end case 'undo' if isfield(handles,'audiodata') handles = undo(handles); updateSpecPlot(handles); Xlim = get(handles.timeplot,'XLim'); handles = makeTimePlot(handles); set(handles.specplot,'XLim',Xlim); set(handles.timeplot,'XLim',Xlim); pzfilterexpofn 'freqzoom'; end case 'convexpo' polepos=findobj(handles.pz_plot,'Tag','Pole'); zeropos=findobj(handles.pz_plot,'Tag','Zero'); pp = []; zz = []; for p=1:length(polepos) ppos=get(polepos(p),'Position'); pp(p)=complex(ppos(1),ppos(2)); end for z=1:length(zeropos) zp=get(zeropos(z),'Position'); zz(z)=complex(zp(1),zp(2)); end [num,den]=zp2tf(zz',pp',1); data.impulse = filter(num, den,[1 zeros(1,99)]); convexpogui(data); case 'pzexpo' polepos=findobj(handles.pz_plot,'Tag','Pole'); zeropos=findobj(handles.pz_plot,'Tag','Zero'); pp = []; zz = []; for p=1:length(polepos) ppos=get(polepos(p),'Position'); pp(p)=complex(ppos(1),ppos(2)); end for z=1:length(zeropos) zp=get(zeropos(z),'Position'); zz(z)=complex(zp(1),zp(2)); end data.polepos = pp; data.zeropos = zz; data.gain = str2num(get(handles.gain,'String')); pzexpogui(data); case 'unselectall' set(findobj(gcf,'Selected','on'),'Selected','off'); case 'print' print_figure(f); case 'close' close_figure(f,figname(1:end-4)); return; end set(f,'UserData',handles); % -------------------------------------------------------------------- function makePZPlot(handles) axes(handles.pz_plot); set(handles.pz_plot, 'DrawMode','fast', 'NextPlot','replacechildren',... 'Box','on', 'XLim', [-1.3 1.3], 'YLim', [-1.3 1.3]); cax=handles.pz_plot; % define a circle th = 0:pi/50:2*pi; xunit = cos(th); yunit = sin(th); rmax=1; tc = get(cax,'xcolor'); % now really force points on x/y axes to lie on them exactly inds = 1:(length(th)-1)/4:length(th); xunit(inds(2:2:4)) = zeros(2,1); yunit(inds(1:2:5)) = zeros(3,1); patch('xdata',xunit*rmax,'ydata',yunit*rmax, ... 'edgecolor',tc,'facecolor',get(gca,'color'),... 'ButtonDownFcn','pzfilterexpofn unselectall'); line([-1.1 1.1],[0 0]); line([0 0],[-1.1 1.1]); axis(rmax*[-1 1 -1.15 1.15]); axis image; axis off; zoom off; function handles = makeHzPlot(handles); if isfield(handles, 'audiodata') Fs = handles.audiodata.Fs; else Fs = handles.Fs; end axes(handles.Hz_plot); cla; handles.freqs=linspace(0,Fs/2,handles.npoints); handles.magline=line(handles.freqs,zeros(size(handles.freqs))); set(handles.magline,'EraseMode','xor'); axis normal; % Strange hack. set(handles.Hz_plot,'XLim',[0 round(Fs/2)]); set(handles.Hz_plot, 'DrawMode','fast', 'NextPlot','replacechildren',... 'Box','off'); xlabel('frequency (Hz)'); ylabel('Attenuation'); % -------------------------------------------------------------------- function handles = makeTimePlot(handles); handles.t = [0:1/handles.audiodata.Fs:(length(handles.audiodata.data)-1)/... handles.audiodata.Fs]; axes(handles.timeplot) plot(handles.t,handles.audiodata.data) maxtime = length(handles.t)/handles.audiodata.Fs; set(handles.timeplot,'XLim',[0 maxtime]); set(handles.timeplot,'YLim',[-1.0 1.0]); grid; xlabel('time (s)'); function handles = makeSpecPlot(handles); axes(handles.specplot); handles.pos = get(gca,'Position'); % Save axes position if (get(handles.interpolate,'Value')) if (get(handles.dBcheckbox,'Value')) pcolor(handles.st,handles.bin,20*log10(abs(handles.spectrum))); else pcolor(handles.st,handles.bin,abs(handles.spectrum)); end shading interp; else if (get(handles.dBcheckbox,'Value')) imagesc(handles.t,handles.bin,20*log10(abs(handles.spectrum))); else imagesc(handles.t,handles.bin,abs(handles.spectrum)); end end axis xy; ylabel('Frequency (Hz)'); colormap('Jet'); set(handles.specplot,'XTickLabel',['']); h = colorbar('vert'); if (get(handles.dBcheckbox,'Value')) set(get(h, 'YLabel'), 'String', 'dB'); else set(get(h, 'YLabel'), 'String', 'Amplitude'); end set(handles.specplot,'Units','Characters'); sonopos = get(handles.specplot,'Position') set(h,'units','Characters', ... 'Position',[sonopos(1)+sonopos(3)+18 sonopos(2) 7 sonopos(4)]) switch computer case {'GLNX86','MAC'} %set(gca,'Position',handles.pos + [0 0.07 0 0]) set(gca,'Position',handles.pos) case 'PCWIN' set(gca,'Position',handles.pos) end handles.xlim_specplot_orig = get(handles.specplot,'XLim'); handles.ylim_specplot_orig = get(handles.specplot,'YLim'); handles.xlim_timeplot_orig = get(handles.timeplot,'XLim'); handles.ylim_timeplot_orig = get(handles.timeplot,'YLim'); handles.xlim_specplot = handles.xlim_specplot_orig; handles.ylim_specplot = handles.ylim_specplot_orig; handles.xlim_timeplot = handles.xlim_timeplot_orig; handles.ylim_timeplot = handles.ylim_timeplot_orig; handles.clim = get(handles.specplot,'CLim'); % -------------------------------------------------------------------- function ud = updateHzPlot(ud) polepos=findobj(ud.pz_plot,'Tag','Pole'); zeropos=findobj(ud.pz_plot,'Tag','Zero'); len=max(length(polepos),length(zeropos)); pp=zeros(1,len); % pp=1e-10*rand(1,len); for p=1:length(polepos) ppos=get(polepos(p),'Position'); pp(p)=ppos(1)+ppos(2)*i; end zz=zeros(1,len); % zz=1e-10*rand(1,len); for z=1:length(zeropos) zp=get(zeropos(z),'Position'); zz(z)=zp(1)+zp(2)*i; end ud.zz=zz;ud.pp=pp; [ud.num,ud.den]=zp2tf(zz',pp',1); [h,w]=freqz(ud.num,ud.den,ud.freqs,ud.Fs); gain = str2num(get(ud.gain,'String')); if get(ud.dB,'Value') % normalise so max = 0 dB logmag=20*log10(abs(h)); mag=logmag-max(logmag); else mag = gain*abs(h)./max(abs(h)); %mag = gain*abs(h); set(ud.Hz_plot,'YLim',[0 max(mag)*1.1]); end set(ud.magline,'YData',mag); function updateTimePlot(handles) axes(handles.timeplot) plot(handles.t,handles.audiodata) set(handles.timeplot,'XLim',handles.xlim_timeplot); set(handles.timeplot,'YLim',handles.ylim_timeplot); xlabel('time (s)'); grid; function updateSpecPlot(handles) axes(handles.specplot); if (get(handles.interpolate,'Value')) if (get(handles.dBcheckbox,'Value')) pcolor(handles.st,handles.bin,20*log10(abs(handles.spectrum))); else pcolor(handles.st,handles.bin,abs(handles.spectrum)); end shading interp; else if (get(handles.dBcheckbox,'Value')) imagesc(handles.t,handles.bin,20*log10(abs(handles.spectrum))); else imagesc(handles.t,handles.bin,abs(handles.spectrum)); end end set(handles.specplot,'XTickLabel',['']); axis xy; ylabel('Frequency (Hz)'); % Get Colormap contents = get(handles.colormap,'String'); cmap = colormap(lower(contents{get(handles.colormap,'Value')})); % Handle Inverse if (get(handles.inverse,'Value')) colormap(flipud(cmap)); else colormap(cmap); end set(handles.specplot,'XLim',handles.xlim_specplot); set(handles.specplot,'YLim',handles.ylim_specplot); set(handles.specplot,'CLim',handles.clim); h = colorbar('vert'); if (get(handles.dBcheckbox,'Value')) set(get(h, 'YLabel'), 'String', 'dB'); else set(get(h, 'YLabel'), 'String', 'Amplitude'); end set(handles.specplot,'Units','Characters'); sonopos = get(handles.specplot,'Position') set(h,'units','Characters', ... 'Position',[sonopos(1)+sonopos(3)+18 sonopos(2) 7 sonopos(4)]) switch computer case {'GLNX86','MAC'} %set(gca,'Position',handles.pos + [0 0.07 0 0]) set(gca,'Position',handles.pos) case 'PCWIN' set(gca,'Position',handles.pos) end % -------------------------------------------------------------------- function [a,b] = designfilter(handles) order = str2double(get(handles.filtorder,'String')); contents = get(handles.filtermenu,'String'); cut1 = str2double(get(handles.cut1,'String')); cut2 = str2double(get(handles.cut2,'String')); cut1 = cut1/(handles.Fs/2); cut2 = cut2/(handles.Fs/2); switch (lower(contents{get(handles.filtermenu,'Value')})) case 'allpass' b = 1; case 'lowpass' b = fir1(order, cut1, 'low'); case 'highpass' b = fir1(order, cut1, 'high'); case 'bandpass' b = fir1(order, [cut1 cut2], 'bandpass'); case 'notch' b = fir1(order, [cut1 cut2], 'stop'); end a = 1; function ud = apply_filter(ud) polepos=findobj(ud.pz_plot,'Tag','Pole'); zeropos=findobj(ud.pz_plot,'Tag','Zero'); gain = str2num(get(ud.gain,'String')); len=max(length(polepos),length(zeropos)); pp=zeros(1,len); % pp=1e-10*rand(1,len); for p=1:length(polepos) ppos=get(polepos(p),'Position'); pp(p)=ppos(1)+ppos(2)*i; end zz=zeros(1,len); % zz=1e-10*rand(1,len); for z=1:length(zeropos) zp=get(zeropos(z),'Position'); zz(z)=zp(1)+zp(2)*i; end ud.zz=zz;ud.pp=pp; [ud.num,ud.den]=zp2tf(zz',pp',1); ud.audiodata2 = ud.audiodata; ud.audiodata.data = gain*filter(ud.num, ud.den, ud.audiodata.data); if max(abs(ud.audiodata.data))>1 ud.audiodata.data = normalize(ud.audiodata.data); end % Store old data for undo ud.spectrum2 = ud.spectrum; ud.bin2 = ud.bin; ud.st2 = ud.st; set(ud.undo,'String','Undo'); function handles = undo(handles) hObject = handles.undo; if (strcmp(get(hObject,'String'),'Undo')) % Store old data for redo handles.spectrum3 = handles.spectrum; handles.bin3 = handles.bin; handles.st3 = handles.st; handles.audiodata3 = handles.audiodata; % Reload old data handles.spectrum = handles.spectrum2; handles.bin = handles.bin2; handles.st = handles.st2; handles.audiodata = handles.audiodata2; set(hObject,'String','Redo'); else handles.spectrum = handles.spectrum3; handles.bin = handles.bin3; handles.st = handles.st3; handles.audiodata = handles.audiodata3; set(hObject,'String','Undo'); end function ud = add_coef(ud,type) switch type case 'zero' string = 'o'; callbak = 'pzfilterexpofn selectzero'; tag = 'Zero'; case 'pole' string = 'x'; callbak = 'pzfilterexpofn selectpole'; tag = 'Pole'; end [x,y]=pol2cart(pi/(2+4*rand(1)),1.0*rand(1)); p1=text('Parent',ud.pz_plot,'Position',[x y],'String',string,... 'ButtonDownFcn',callbak,'EraseMode','xor',... 'Tag',tag,'HorizontalAlignment','center'); p2=text('Parent',ud.pz_plot,'Position',[x -y],'String',string,... 'ButtonDownFcn',callbak, 'EraseMode','xor',... 'Tag',tag,'HorizontalAlignment','center'); set(p1,'UserData',p2); set(p2,'UserData',p1); function ud = select_coef(ud,type) switch type case 'zero' buttonfn = 'pzfilterexpofn movezero'; case 'pole' buttonfn = 'pzfilterexpofn movepole'; end s=get(gcbo,'UserData'); set(gcf,'WindowButtonMotionFcn', buttonfn); set(gcf,'WindowButtonUpFcn','pzfilterexpofn releaseobject'); ud.currentcoef=gcbo; ud.partnercoef=s; set([findobj(gca,'Tag','Pole'); findobj(gca,'Tag','Zero')],'Selected','off'); set([ud.currentcoef ud.partnercoef],'Selected','on'); function ud = move_coef(ud) cp=get(ud.pz_plot,'CurrentPoint'); if (cp(1)*cp(1)+cp(3)*cp(3)) < 1.1 set(ud.currentcoef,'Position',[cp(1) cp(3)]); set(ud.partnercoef,'Position',[cp(1) -cp(3)]); end