home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l460 / 3.ddi / DEMOS.DI$ / SIGDEMO1.M < prev    next >
Encoding:
Text File  |  1993-03-07  |  11.5 KB  |  369 lines

  1. function sigdemo1(action,in1,in2);
  2. %SIGDEMO1 Interactive signal demo - 1 : DFT of a signal
  3. %    Demonstrates MATLAB's graphic user interface using Handle Graphics
  4. %       while illustrating some basic signal processing concepts, such as 
  5. %    sampling, aliasing, and windowing.
  6.  
  7. %    Author: T. Krauss
  8. %     11/3/92, updated 2/9/93
  9. %    (c) Copyright 1984-93, by The MathWorks, Inc.
  10.  
  11. %    possible actions:
  12. %      'start'
  13. %      'down'
  14. %      'move'
  15. %      'up'
  16. %      'redraw'
  17. %      'done'
  18. %      'setwindow'
  19. %      'showwind'
  20.  
  21. if nargin<1,
  22.     action='start';
  23. end;
  24.  
  25. global SIGDEMO1_DAT
  26.  
  27. if strcmp(action,'start'),
  28. % graphics initialization
  29.     clf reset;
  30.     set(gcf,'Units','normalized','backingstore','off');
  31.  
  32.     popup=uicontrol('Style','Popup','String','cosine|square|sawtooth',...
  33.         'Position',[.03 .02 .2 .08],'Units','normalized',...
  34.         'CallBack','sigdemo1(''redraw'')');
  35.  
  36.     if exist('freqz')==2,
  37.         wind_menu=uimenu('Label','Window');
  38.         w1=uimenu(wind_menu,'Label','rectangular','Callback',...
  39.                   'sigdemo1(''setwindow'',1)');
  40.         w2=uimenu(wind_menu,'Label','triangular','Callback',...
  41.                   'sigdemo1(''setwindow'',2)');
  42.         w3=uimenu(wind_menu,'Label','hanning','Callback',...
  43.                   'sigdemo1(''setwindow'',3)');
  44.         w4=uimenu(wind_menu,'Label','hamming','Callback',...
  45.                   'sigdemo1(''setwindow'',4)');
  46.         w5=uimenu(wind_menu,'Label','chebyshev');
  47.         w5_20=uimenu(w5,'Label','20 dB atten.','Callback',...
  48.                   'sigdemo1(''setwindow'',5,20)');
  49.         w5_30=uimenu(w5,'Label','30 dB atten.','Callback',...
  50.                   'sigdemo1(''setwindow'',5,30)');
  51.         w5_40=uimenu(w5,'Label','40 dB atten.','Callback',...
  52.                   'sigdemo1(''setwindow'',5,40)');
  53.         w6=uimenu(wind_menu,'Label','kaiser');
  54.         w6_1=uimenu(w6,'Label','parameter = 1','callback',...
  55.                   'sigdemo1(''setwindow'',6,1)');
  56.         w6_15=uimenu(w6,'Label','parameter = 4','callback',...
  57.                   'sigdemo1(''setwindow'',6,4)');
  58.         w6_2=uimenu(w6,'Label','parameter = 9','callback',...
  59.                   'sigdemo1(''setwindow'',6,9)');
  60.         w7=uimenu(wind_menu,'Label','Show window...',...
  61.                      'Callback','sigdemo1(''showwind'');');
  62.     end;  % if statement
  63.  
  64.     freq_text=uicontrol('Style','text','Position',[.33 .02 .28 .08],...
  65.         'Units','normalized','BackgroundColor','black',...
  66.         'ForegroundColor','white','String','Fundamental (Hertz):',...
  67.         'HorizontalAlignment','right');
  68.  
  69.     freq_field=uicontrol('Style','edit','Position',[.63 .02 .12 .08],...
  70.         'Units','normalized','String','5',...
  71.         'CallBack','sigdemo1(''setfreq''); sigdemo1(''redraw'')');
  72.  
  73.     done_button=uicontrol('Style','Pushbutton','Position',[.85 .02 ...
  74.         .12 .08],'Units','normalized','Callback',...
  75.         'sigdemo1(''done'')','String','Done');
  76.  
  77.     help sig1help    % show help in command window
  78.  
  79.     % Create intial signal
  80.     N=201;     % number of samples
  81. %    N=21;
  82.     amp=0.5;
  83.     freq=5;    % hertz
  84.     t0=0;      % seconds
  85.     t1=1;      % seconds
  86.     t=linspace(t0,t1,N)';
  87.     T=(t1-t0)/N;            % sampling rate in seconds
  88.     M=256;     % length of fft
  89.     window=ones(N,1);    % use window to lower side-lobes in the freq. domain
  90.                              % (makes peaks wider)
  91.  
  92.     min_dB = -40; % freq. domain lower axis limit
  93.  
  94.     % create axes for time domain and frequency domain plot
  95.     ax_freq=axes('Position',[.15 .2 .8 .3],'XLim',...
  96.              [0 1/(2*T)],'YLim',[min_dB 50]);
  97.     
  98.     % time domain
  99.     val = get(popup,'Value');
  100.     if (val == 1),
  101.         f=amp*cos(freq*t*2*pi);
  102.     elseif (val == 2),   % square wave
  103.         tt=freq*t*2*pi;
  104.         tmp=rem(tt,2*pi);
  105.         f=amp*(2*rem((tt<0)+(tmp>pi | tmp<-pi)+1,2)-1);
  106.     elseif (val == 3),   % sawtooth
  107.         tt=freq*t*2*pi;
  108.         f=amp*((tt < 0) + rem(tt,2*pi)/2/pi - .5)*2;
  109.     end;
  110.  
  111.     % frequency domain
  112.     F=fft(window.*f,2*M);
  113.     F=F(1:M);
  114.     w=(0:M-1)*pi/M;
  115.     FF=20*log10(abs(F));
  116.     ind=find(FF<min_dB);
  117.     FF(ind)=NaN*ones(size(ind)); % put NaN's in where
  118.          % min_dB shows up - this is to work around no clipping in xor mode
  119.     freq_line=plot(w/2/pi/T,FF,'EraseMode','xor');
  120.     axis([0 1/(2*T)  min_dB 50]);
  121.     grid;
  122.     ylabel('Magnitude (dB)');
  123.     xlabel('Frequency (Hertz)');
  124.  
  125.     ax_time=axes('Position',[.15 .62 .8 .3],'XLim',[t0 t1],'YLim',[-1 1]);
  126.     time_line=plot(t,f,'EraseMode','xor');
  127.     axis([t0 t1 -1 1]);
  128.     % (set to xor mode to prevent re-rendering, that is, for speed)
  129.     grid;
  130.     ylabel('Waveform');
  131.     xlabel('Time (Seconds)');
  132.     title('Click and drag waveform to change fundamental and amplitude');
  133.  
  134.     set(time_line,'ButtonDownFcn','sigdemo1(''down'')');
  135.     SIGDEMO1_DAT = [freq; amp; N; M; min_dB; 0; 0; ...
  136.          time_line; freq_line; freq_field; popup; -1; gcf; t(:); window(:)];
  137.  
  138. elseif strcmp(action,'down'),
  139.     % assumes that a line was clicked 
  140.     time_line=SIGDEMO1_DAT(8);    
  141.     axes(get(time_line,'parent'));     % set the right axes
  142.  
  143.     % Obtain coordinates of mouse click location in axes units
  144.     pt=get(gca,'currentpoint');
  145.     x=pt(1,1);
  146.     y=pt(1,2);
  147.  
  148.  
  149. % find closest vertex of line to mouse click location (call it fixed_x, fixed_y)
  150.  
  151.     line_x=get(time_line,'XData');
  152.     line_y=get(time_line,'YData');
  153.     set(gca,'units','pixels');     % distance must bein pixels
  154.     p=get(gca,'pos');
  155.     xa=get(gca,'xlim');
  156.     ya=get(gca,'ylim');
  157.     
  158.     dist=((line_x-x)*p(3)/(xa(2)-xa(1))).^2 + ...
  159.          ((line_y-y)*p(4)/(ya(2)-ya(1))).^2;
  160.     [temp,i]=min(dist);
  161.     fixed_x=line_x(i);
  162.     fixed_y=line_y(i);
  163.     set(time_line,'LineStyle','--');
  164.  
  165.     SIGDEMO1_DAT(6)=fixed_x;
  166.     SIGDEMO1_DAT(7)=fixed_y;
  167.  
  168.     set(gcf,'WindowButtonMotionFcn', 'sigdemo1(''move'')');
  169.     set(gcf,'WindowButtonUpFcn', 'sigdemo1(''up'')');
  170.     % set(gcf,'userdata',u);
  171.  
  172. elseif strcmp(action,'move'),
  173.     % u = get(gcf,'userdata');
  174.     freq=SIGDEMO1_DAT(1);
  175.     amp=SIGDEMO1_DAT(2);
  176.     N=SIGDEMO1_DAT(3);
  177.     M=SIGDEMO1_DAT(4);
  178.     min_dB=SIGDEMO1_DAT(5);
  179.     fixed_x=SIGDEMO1_DAT(6);
  180.     fixed_y=SIGDEMO1_DAT(7);
  181.     time_line=SIGDEMO1_DAT(8);
  182.     freq_line=SIGDEMO1_DAT(9);
  183.     freq_field=SIGDEMO1_DAT(10);
  184.     popup=SIGDEMO1_DAT(11);
  185.     t=SIGDEMO1_DAT(14:14+N-1);
  186.     window=SIGDEMO1_DAT(14+N:14+N+N-1);
  187.  
  188.     pt=get(gca,'currentpoint');
  189.     x=pt(1,1);
  190.     y=pt(1,2);
  191.  
  192.     amp1=y/fixed_y*amp;
  193.     if (abs(amp1)>1.0),
  194.        amp1=1.0*sign(amp1);
  195.     end;
  196.     if (abs(amp1)<0.05),
  197.        amp1=0.05*sign(amp1);
  198.     end;
  199.     freq1=fixed_x/x*freq;
  200.  
  201.     val = get(popup,'Value');
  202.     if (val == 1),
  203.         f=amp1*cos(freq1*t*2*pi);
  204.     elseif (val == 2),   % square wave
  205.         tt=freq1*t*2*pi;
  206.         tmp=rem(tt,2*pi);
  207.         f=amp1*(2*rem((tt<0)+(tmp>pi | tmp<-pi)+1,2)-1);
  208.     elseif (val == 3),   % sawtooth
  209.         tt=freq1*t*2*pi;
  210.         f=amp1*((tt < 0) + rem(tt,2*pi)/2/pi - .5)*2;
  211.     end;
  212.     set(time_line,'YData',f);
  213.     F=fft(window.*f,2*M);
  214.     F=F(1:M);
  215.     w=(0:M-1)*pi/M;
  216.     FF=20*log10(abs(F));
  217.     ind=find(FF<min_dB);
  218.     FF(ind)=NaN*ones(size(ind)); % put NaN's in where
  219.              % min_dB shows up - this is to work around no clipping in xor mode
  220.     set(freq_line,'YData',FF);
  221.     set(freq_field,'String',num2str(freq1));
  222.  
  223. elseif strcmp(action,'up'),
  224.     pt=get(gca,'currentpoint');
  225.     x=pt(1,1);
  226.     y=pt(1,2);
  227.  
  228.     set(gcf,'WindowButtonMotionFcn','');
  229.     set(gcf,'WindowButtonUpFcn','');
  230.  
  231.     % u=get(gcf,'userdata');
  232.     freq=SIGDEMO1_DAT(1);
  233.     amp=SIGDEMO1_DAT(2);
  234.     fixed_x=SIGDEMO1_DAT(6);
  235.     fixed_y=SIGDEMO1_DAT(7);
  236.  
  237.     amp1=y/fixed_y*amp;
  238.     if (abs(amp1)>1.0),
  239.        amp1=1.0*sign(amp1);
  240.     end;
  241.     if (abs(amp1)<0.05),
  242.        amp1=0.05*sign(amp1);
  243.     end;
  244.     freq1=fixed_x/x*freq;
  245.  
  246.     set(SIGDEMO1_DAT(8),'linestyle','-');
  247.     SIGDEMO1_DAT(1)=freq1;  % set amplitude and frequency
  248.     SIGDEMO1_DAT(2)=amp1;
  249.     % set(gcf,'userdata',u);
  250.     sigdemo1('redraw');
  251.  
  252. elseif strcmp(action,'done'),
  253.     % close the figure window that is showing the window fnction:
  254.     % u = get(gcf,'userdata');
  255.     if (SIGDEMO1_DAT(12)~=-1),
  256.         close(SIGDEMO1_DAT(12));
  257.     end;
  258.     clf reset;
  259.     clear global SIGDEMO1_DAT
  260.  
  261. elseif strcmp(action,'redraw'),
  262.     % recomputes time and frequency waveforms and updates display
  263.     % u = get(gcf,'userdata');
  264.     freq=SIGDEMO1_DAT(1);
  265.     amp=SIGDEMO1_DAT(2);
  266.     N=SIGDEMO1_DAT(3);
  267.     M=SIGDEMO1_DAT(4);
  268.     min_dB=SIGDEMO1_DAT(5);
  269.     time_line=SIGDEMO1_DAT(8);
  270.     freq_line=SIGDEMO1_DAT(9);
  271.     freq_field=SIGDEMO1_DAT(10);
  272.     popup=SIGDEMO1_DAT(11);
  273.     t=SIGDEMO1_DAT(14:14+N-1);
  274.     window=SIGDEMO1_DAT(14+N:14+N+N-1);
  275.     val = get(popup,'Value');
  276.     if (val == 1),
  277.         f=amp*cos(freq*t*2*pi);
  278.     elseif (val == 2),   % square wave
  279.         tt=freq*t*2*pi;
  280.         tmp=rem(tt,2*pi);
  281.         f=amp*(2*rem((tt<0)+(tmp>pi | tmp<-pi)+1,2)-1);
  282.     elseif (val == 3),   % sawtooth
  283.         tt=freq*t*2*pi;
  284.         f=amp*((tt < 0) + rem(tt,2*pi)/2/pi - .5)*2;
  285.     end;
  286.     set(time_line,'YData',f);
  287.     F=fft(window.*f,2*M);
  288.     F=F(1:M);
  289.     w=(0:M-1)*pi/M;
  290.     FF=20*log10(abs(F));
  291.     ind=find(FF<min_dB);
  292.     FF(ind)=NaN*ones(size(ind)); % put NaN's in where
  293.              % min_dB shows up - this is to work around no clipping in xor mode
  294.     set(freq_line,'YData',FF);
  295.     set(freq_field,'String',num2str(freq));
  296.  
  297.     drawnow;
  298.  
  299. elseif strcmp(action,'setwindow'),
  300.     % u = get(gcf,'userdata');
  301.     N=SIGDEMO1_DAT(3);
  302.     if (in1==1),
  303.         window = boxcar(N);
  304.     elseif (in1==2),
  305.         window = triang(N);
  306.     elseif (in1==3),
  307.         window = hanning(N);
  308.     elseif (in1==4),
  309.         window = hamming(N);
  310.     elseif (in1==5),
  311.         window = chebwin(N,in2);
  312.     elseif (in1==6),
  313.         window = kaiser(N,in2);
  314.     end;
  315.     SIGDEMO1_DAT(14+N:14+N+N-1)=window;
  316.     % set(gcf,'userdata',u);
  317.     sigdemo1('redraw');
  318.     if (SIGDEMO1_DAT(12)~=-1),
  319.         sigdemo1('showwind');
  320.     end;
  321.  
  322. elseif strcmp(action,'showwind'),
  323.     % u=get(gcf,'userdata');
  324.     oldfig=gcf;
  325.     N=SIGDEMO1_DAT(3);
  326.     t=SIGDEMO1_DAT(14:14+N-1);
  327.     window=SIGDEMO1_DAT(14+N:14+N+N-1);
  328.     if (SIGDEMO1_DAT(12)==-1),
  329.         SIGDEMO1_DAT(12)=figure;
  330.  
  331.         axes('Position',[.15 .62 .8 .3]);
  332.         line1=plot(t,window); 
  333.         title('Window function');
  334.         xlabel('time (seconds)');
  335.         grid;
  336.         ylabel('Window');
  337.  
  338.         axes('Position',[.15 .2 .8 .3]);
  339.         W=fft(window,1024);
  340.         line2=plot((0:(1/1024):(.5-(1/1024)))*N,20*log10(abs(W(1:512)))); 
  341.         set(gca,'xlim',[0 N/2]);
  342.         xlabel('Frequency (Hz)');
  343.         ylabel('Magnitude (dB)');
  344.         grid;
  345.         windclose=uicontrol('Style','Pushbutton','Position',[.85 .02 ...
  346.             .12 .08],...
  347.             'Units','normalized','Callback',['THEHAND=get(gcf,''userdata'');'...
  348.             'close; figure(THEHAND(1)); global SIGDEMO1_DAT, '...
  349.             'SIGDEMO1_DAT(12)=-1; clear THEHAND SIGDEMO1_DAT'],'String','Close');
  350.         set(gcf,'userdata',[oldfig line1 line2]);
  351.         % set(oldfig,'userdata',u);
  352.         
  353.     else
  354.         figure(SIGDEMO1_DAT(12));
  355.         lines=get(gcf,'userdata');
  356.         set(lines(2),'ydata',window);
  357.         W=fft(window,1024);
  358.         set(lines(3),'ydata',20*log10(abs(W(1:512))));
  359.         drawnow
  360.     end
  361.  
  362. elseif strcmp(action,'setfreq'),
  363.     % u = get(gcf,'userdata');
  364.     SIGDEMO1_DAT(1)=str2num(get(SIGDEMO1_DAT(10),'string'));
  365.     % set(gcf,'userdata',u);
  366.  
  367. end
  368.  
  369.