www.gusucode.com > 声音的处理有:LPC,FFT,共振峰,频谱源码程序 > siganlandsystemusingMatlab/SSUM/pzexpo/pzexpofn.m

    function pzexpofn(action,datastruct)
% This code borrows heavily from MAD polezero demonstration
    if nargin < 1
        action='init';
    end

	% Maybe 'apply to white noise' button
	% Send filter to pzfilterexplorer
	% How do you set the plots so that one zooms and the other doesn't????
	% Phase in radians, +- pi
    % Fix impulse response, zoom in...

	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.pz_plot);
			reset(handles.freq_plot);
			reset(handles.phase_plot);
			reset(handles.impulse_plot);
			handles.npoints = 256;
			makePZPlot(handles);
			handles = makePlots(handles);
			set(gcf,'KeyPressFcn','pzexpofn keypressed');
			%linkedzoom([handles.freq_plot, handles.phase_plot],'onx');
		case 'readinput'
			setdefaults;
			reset(handles.pz_plot);
			reset(handles.freq_plot);
			reset(handles.phase_plot);
			reset(handles.impulse_plot);
            handles.Fs = 44100;
			handles.npoints = 256;
			makePZPlot(handles);
			handles = makePlots(handles);
			set(gcf,'KeyPressFcn','pzexpofn keypressed');
            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

			if isfield(datastruct,'zeropos')
                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','pzexpofn selectzero',...
                        'EraseMode','xor','Tag','Zero',...
                        'HorizontalAlignment','center');
					% Don't create two where there should be one
					if y ~= 0
						p2=text('Parent',handles.pz_plot,'Position',[x -y],...
							'String','o','ButtonDownFcn','pzexpofn 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','pzexpofn selectpole',...
                        'EraseMode','xor','Tag','Pole',...
                        'HorizontalAlignment','center');
					% Don't create two where there should be one
					if y ~= 0
						p2=text('Parent',handles.pz_plot,'Position',[x -y],...
							'String','x','ButtonDownFcn','pzexpofn selectpole',...
							'EraseMode','xor','Tag','Pole',...
							'HorizontalAlignment','center');
						set(p1,'UserData',p2);
						set(p2,'UserData',p1);
					end
                end
			end
			handles = updatePlots(handles);
		case 'db'
			axes(handles.freq_plot);
			if get(handles.dB,'Value')
				set(handles.freq_plot,'YLim',[-80 1]);
    			ylabel('Normalized Attenuation (dB)');
			else
				set(handles.freq_plot,'YLim',[0 1.05]);
    			ylabel('Normalized Attenuation');
			end
			pzexpofn 'plotfreqz'
		case 'unwrap'
			if get(handles.unwrap,'Value')
				set(handles.phase_plot,'YLimMode','auto');
			else
				set(handles.phase_plot,'YLim',[-pi pi]);
			end
			pzexpofn 'plotfreqz'
		case 'grid'
			if get(handles.grid,'Value')
				axes(handles.freq_plot);
				grid on;
				axes(handles.phase_plot);
				grid on;
				axes(handles.impulse_plot);
				grid on;
			else
				axes(handles.freq_plot);
				grid off;
				axes(handles.phase_plot);
				grid off;
				axes(handles.impulse_plot);
				grid off;
			end
		case 'logf'
			if get(handles.logf,'Value')
				set(handles.freq_plot,'XScale','log');
				set(handles.phase_plot,'XScale','log');
			else
				set(handles.freq_plot,'XScale','linear');
				set(handles.phase_plot,'XScale','linear');
			end
		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/44100;
            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','pzexpofn selectpole',...
                    'EraseMode','xor','Tag','Pole','HorizontalAlignment','center');
                p2=text('Parent',handles.pz_plot,'Position',[x -y],...
                    'String','x','ButtonDownFcn','pzexpofn selectpole',...
                    'EraseMode','xor','Tag','Pole','HorizontalAlignment','center');
				set(p1,'UserData',p2);
				set(p2,'UserData',p1);
            end     
			pzexpofn 'plotfreqz'
		case 'addzero'
			handles = add_coef(handles,'zero');
			pzexpofn 'plotfreqz'
		case 'addpole'
			handles = add_coef(handles,'pole');
			pzexpofn 'plotfreqz'
		case 'selectpole'
			handles = select_coef(handles,'pole');
		case 'selectzero'
			handles = select_coef(handles,'zero');
		case 'movepole'
			handles = move_coef(handles);
			pzexpofn 'plotfreqz'
		case 'movezero'
			handles = move_coef(handles);
			pzexpofn 'plotfreqz'
		case 'releaseobject'
			set(gcf,'WindowButtonMotionFcn','');
			set(gcf,'WindowButtonUpFcn','');
			pzexpofn 'plotfreqz'
		case 'plotfreqz'
			handles = updatePlots(handles);
			pzexpofn 'timezoom';
		case 'keypressed'
			% if delete key is pressed, delete any selected object
			if double(get(gcf,'CurrentCharacter')) == 8
				delete(findobj(gcf,'Selected','on'))
			end
			pzexpofn 'plotfreqz'
		case 'convexpo'
			data.impulse = get(handles.implot(1),'YData');
			data.impulse = data.impulse(1:100);
			convexpogui(data);
		case 'pzfilterexpo'
			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)=ppos(1)+ppos(2)*j;
			end
			for z=1:length(zeropos)
				zp=get(zeropos(z),'Position');
				zz(z)=zp(1)+zp(2)*j;
			end
			data.polepos = pp;
			data.zeropos = zz;
            data.gain = str2num(get(handles.gain,'String'));
			pzfilterexpogui(data);
		case 'timezoom'
			if isfield(handles,'imp')
                val = get(handles.timezoom,'Value');
                if val == 0,
                    val = 0.001;
                end
                set(handles.impulse_plot,'XLim',[0 val*100])
            end
		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]);

	% define a circle
	th = 0:pi/50:2*pi;
	xunit = [0.2:0.2:1.0]'*cos(th);
	yunit = [0.2:0.2:1.0]'*sin(th);
	rmax=1;
	tc = get(handles.pz_plot,'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(5,:).*rmax,'ydata',yunit(5,:).*rmax, ...
		'edgecolor',tc,'facecolor',get(gca,'color'),...
		'ButtonDownFcn','pzexpofn unselectall');
	hold on;
	for i=1:4,
		plot(yunit(i,:).*rmax, xunit(i,:).*rmax, 'k:')
	end

	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;

function handles = makePlots(handles);
	axes(handles.freq_plot);
	handles.freqs=linspace(0,1,handles.npoints);
	handles.freqline=line(handles.freqs,zeros(size(handles.freqs)));
	set(handles.freqline,'EraseMode','xor');
	axis normal;	% Strange hack.
	set(handles.freq_plot,'XLim',[0 0.5]);
	set(handles.freq_plot, 'DrawMode','fast', 'NextPlot','replacechildren',...
		'Box','off');
	set(handles.freq_plot,'XTick',[],'XTickLabel','');
    ylabel('Normalized Attenuation');
	grid;

	axes(handles.phase_plot);
	handles.phaseline=line(handles.freqs,zeros(size(handles.freqs)));
	set(handles.phaseline,'EraseMode','xor');
	axis normal;	% Strange hack.
	set(handles.phase_plot,'YLim',[-pi pi],'XLim',[0 0.5]);
	set(handles.phase_plot, 'DrawMode','fast', 'NextPlot','replacechildren',...
		'Box','off');
	xlabel('Normalized Frequency ({\varpi})');
    ylabel('Phase (radians)');
	set(handles.freq_plot,'XTick',get(handles.phase_plot,'XTick'));
	grid;

	
	axes(handles.impulse_plot);
	handles.imp = zeros(1,500);
	%handles.implot = plot(handles.imp);
	handles.implot = stem(handles.imp);
	set(handles.implot,'EraseMode','xor');
	set(handles.impulse_plot,'XLim',[-1 100]);
	set(handles.impulse_plot, 'DrawMode','fast', 'NextPlot','replacechildren');
	xlabel('Sample');
	grid;
	%zoom on;
	

% --------------------------------------------------------------------
function ud = updatePlots(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.npoints,'whole');
    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);
	end
    set(ud.freqline,'YData',mag);
    if get(ud.dB,'Value')
    else
        set(ud.freq_plot,'YLim',[0 max(mag)*1.1])
    end
	if get(ud.unwrap,'Value')
	    set(ud.phaseline,'YData',unwrap(angle(h)));
		set(ud.phase_plot,'YLim',[min(unwrap(angle(h)))-1 max(unwrap(angle(h)))+1]);
	else
	    set(ud.phaseline,'YData',angle(h));
	end
	imp = filter(ud.num, ud.den, [1, zeros(1,499)]);	
    set(ud.implot,'YData',imp(1:500));
% 	temp = get(ud.implot(2),'YData');
% 	temp(2:3:end) = imp(1:500);
%     set(ud.implot(2),'YData',temp);
	set(ud.impulse_plot,'YLim',[1.1*min(imp) 1.1*max(imp)]);
	


% --------------------------------------------------------------------
function ud = add_coef(ud,type)
	switch type
		case 'zero'
			string = 'o';
			callbak = 'pzexpofn selectzero';
			tag = 'Zero';
		case 'pole'
			string = 'x';
			callbak = 'pzexpofn selectpole';
			tag = 'Pole';
	end
	freq = rand*22050/2;
	ang = 2*pi*freq/44100;
	[x,y]=pol2cart(ang,1.0*rand);
	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 = 'pzexpofn movezero';
		case 'pole'
			buttonfn = 'pzexpofn movepole';
	end
	s=get(gcbo,'UserData');
	set(gcf,'WindowButtonMotionFcn', buttonfn);
	set(gcf,'WindowButtonUpFcn','pzexpofn 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)) < 2.1
	  set(ud.currentcoef,'Position',[cp(1) cp(3)]);
	  set(ud.partnercoef,'Position',[cp(1) -cp(3)]);
	end

function showImpulse(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
    [b_k,a_k]=zp2tf(zz',pp',1);