function [sig,fs] = splay3(action,param,param2)

if ((nargin == 0) | ((nargin == 1) & ~isstr(action)))

  callauto = ['ud = get(gcbf,''userdata'');',...
              '[ud.sig,ud.fs] = splay3(''auto'',get(gcbo,''value''),gcbf);',...
              'if size(ud.sig,2) == 1,ud.sig = ud.sig'';end,',... 
              'ud.dft = fft(ud.sig);',...
              'ud.ldft = length(ud.dft);',...
              'set(gcbf,''userdata'',ud);',...
              'splay3(''refresh'',gcbf);'];

  callws = ['ud = get(gcbf,''userdata'');',...
            'var = get(gcbo,''string'');',...
             'evalin(''base'',[''ud.sig = '',var,''+0;'']);',...
             'if size(ud.sig,2) == 1,ud.sig = ud.sig'';end,',... 
             'ud.dft = fft(ud.sig);',...
             'ud.ldft = length(ud.dft);',...
             'set(gcbf,''userdata'',ud);',...
             'splay3(''refresh'',gcbf);'];

  callfs = ['ud = get(gcbf,''userdata'');',...
            'ud.fs = str2num(get(gcbo,''string''));',...
            'set(gcbf,''userdata'',ud);',...
            'splay3(''refresh'',gcbf);'];

  callrfs = ['ud = get(gcbf,''userdata'');',...
            'ud.sfactor = str2num(get(gcbo,''string''));',...
            'set(gcbf,''userdata'',ud);',...
            'splay3(''refresh'',gcbf);'];

  callhold = ['ud = get(gcbf,''userdata'');',...
            'ud.hold = get(gcbo,''value'');',...
            'set(gcbf,''userdata'',ud);',...
            'splay3(''refresh'',gcbf);'];


  if (nargin == 0)
    ud.sig = [];
    ud.rsig = [];
  else
    ud.sig = action;
    ud.rsig = action;
  end

  ud.fs = 10000;
  ud.sfactor = 10;

  ud.dft = fft(ud.sig);

  ud.ldft = length(ud.dft);

  ud.hold = 1;

  h0 = figure('Color',[0.8 0.8 0.8], ...
 	'MenuBar','none', ...
	'Name','ELE 201 Signal Viewer and Audio Player: Now with Sampling and Reconstruction!', ...
	'NumberTitle','off', ...
	'Position',[200 300 619 493], ...
	'Tag','Fig1');

  h1 = axes('Parent',h0, ...
	'Units','pixels', ...
	'CameraUpVector',[0 1 0], ...
	'CameraUpVectorMode','manual', ...
	'Color',[1 1 1], ...
	'Position',[66 271 367 190], ...
	'Tag','Axes1', ...
	'XColor',[0 0 0], ...
	'YColor',[0 0 0], ...
	'ZColor',[0 0 0]);

  ud.tax = h1;

  h2 = text('Parent',h1, ...
	'Color',[0 0 0], ...
	'HandleVisibility','off', ...
	'HorizontalAlignment','center', ...
	'Position',[0.4973   -0.1217    9.1603], ...
	'Tag','Axes1Text4', ...
	'VerticalAlignment','cap');
  set(get(h2,'Parent'),'XLabel',h2);
  h2 = text('Parent',h1, ...
	'Color',[0 0 0], ...
	'HandleVisibility','off', ...
	'HorizontalAlignment','center', ...
	'Position',[-0.07923497267759563 0.4920634920634921 9.160254037844386], ...
	'Rotation',90, ...
	'Tag','Axes1Text3', ...
	'VerticalAlignment','baseline');
  set(get(h2,'Parent'),'YLabel',h2);
  h2 = text('Parent',h1, ...
	'Color',[0 0 0], ...
	'HandleVisibility','off', ...
	'HorizontalAlignment','right', ...
	'Position',[-0.180327868852459 1.169312169312169 9.160254037844386], ...
	'Tag','Axes1Text2', ...
	'Visible','off');
  set(get(h2,'Parent'),'ZLabel',h2);
  h2 = text('Parent',h1, ...
	'Color',[0 0 0], ...
	'HandleVisibility','off', ...
	'HorizontalAlignment','center', ...
	'Position',[0.4973    1.0317    9.1603], ...
	'Tag','Axes1Text1', ...
	'VerticalAlignment','bottom');
  set(get(h2,'Parent'),'Title',h2);
  h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[1 1 1], ...
	'Callback',callfs, ...
	'ListboxTop',0, ...
	'Position',[402 171.75 31.5 16.5], ...
	'Style','edit', ...
	'Tag','EditText1');

  ud.fsbox = h1;

  h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'ListboxTop',0, ...
	'Position',[351 164.25 45 33], ...
	'String',{'Original' 'Sampling' 'Frequency'}, ...
	'Style','text', ...
	'Tag','StaticText1');

  h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'Callback','ud = get(gcbf,''userdata'');if ~isempty(ud.sig),sound(ud.sig,ud.fs);end', ...
	'ListboxTop',0, ...
	'Position',[363.75 204 57.75 28.5], ...
	'String','Play Original', ...
	'Tag','Pushbutton1');

  ud.autos = str2mat(' Tiny sine',' Dial Tone',' Busy Signal',' Phone Ring',...
         ' R E S');

  h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'Callback',callauto, ...
	'ListboxTop',0, ...
	'Position',[361.5 294.75 60.75 24], ...
	'String',ud.autos, ...
	'Style','popupmenu', ...
	'Tag','PopupMenu1', ...
	'Value',1);

  h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'ListboxTop',0, ...
	'Position',[351.75 321.75 79.5 12], ...
	'String','Built-in signals', ...
	'Style','text', ...
	'Tag','StaticText2');
  h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[1 1 1], ...
	'Callback',callws, ...
	'ListboxTop',0, ...
	'Position',[402.75 270.75 36 15], ...
	'Style','edit', ...
	'Tag','EditText2');

  h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'ListboxTop',0, ...
	'Position',[344.25 267 55.5 22.5], ...
	'String','Workspace Variable', ...
	'Style','text', ...
	'Tag','StaticText3');
  
  h1 = axes('Parent',h0, ...
	'Units','pixels', ...
	'CameraUpVector',[0 1 0], ...
	'CameraUpVectorMode','manual', ...
	'Color',[1 1 1], ...
	'Position',[69 33 367 190], ...
	'Tag','Axes1', ...
	'XColor',[0 0 0], ...
	'YColor',[0 0 0], ...
	'ZColor',[0 0 0]);
  
  ud.fax = h1;
 
  h2 = text('Parent',h1, ...
	'ButtonDownFcn','ctlpanel SelectMoveResize', ...
	'Color',[0 0 0], ...
	'HandleVisibility','off', ...
	'HorizontalAlignment','center', ...
	'Interruptible','off', ...
	'Position',[0.4973   -0.1217    9.1603], ...
	'Tag','Axes1Text4', ...
	'VerticalAlignment','cap');
  set(get(h2,'Parent'),'XLabel',h2);
  h2 = text('Parent',h1, ...
	'ButtonDownFcn','ctlpanel SelectMoveResize', ...
	'Color',[0 0 0], ...
	'HandleVisibility','off', ...
	'HorizontalAlignment','center', ...
	'Interruptible','off', ...
	'Position',[-0.07923497267759565 0.4920634920634919 9.160254037844386], ...
	'Rotation',90, ...
	'Tag','Axes1Text3', ...
	'VerticalAlignment','baseline');
  set(get(h2,'Parent'),'YLabel',h2);
  h2 = text('Parent',h1, ...
	'ButtonDownFcn','ctlpanel SelectMoveResize', ...
	'Color',[0 0 0], ...
	'HandleVisibility','off', ...
	'HorizontalAlignment','right', ...
	'Interruptible','off', ...
	'Position',[-0.1885245901639344 2.428571428571428 9.160254037844386], ...
	'Tag','Axes1Text2', ...
	'Visible','off');
  set(get(h2,'Parent'),'ZLabel',h2);
  h2 = text('Parent',h1, ...
	'ButtonDownFcn','ctlpanel SelectMoveResize', ...
	'Color',[0 0 0], ...
	'HandleVisibility','off', ...
	'HorizontalAlignment','center', ...
	'Interruptible','off', ...
	'Position',[0.4973    1.0317    9.1603], ...
	'Tag','Axes1Text1', ...
	'VerticalAlignment','bottom');
  set(get(h2,'Parent'),'Title',h2);
  h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'Callback','ud = get(gcbf,''userdata'');if ~isempty(ud.rsig),sound(ud.rsig,ud.fs);end', ...
	'ListboxTop',0, ...
	'Position',[349.5 104.25 86.25 28.5], ...
	'String','Play Reconstructed', ...
	'Tag','Pushbutton1');
  h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'ListboxTop',0, ...
	'Position',[348.75 69 52.5 21], ...
	'String',{'Subsampling' 'Factor'}, ...
	'Style','text', ...
	'Tag','StaticText1');
  h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[1 1 1], ...
	'Callback',callrfs, ...
	'ListboxTop',0, ...
	'Position',[403.5 72 31.5 16.5], ...
	'Style','edit', ...
	'Tag','EditText1');

  ud.rfsbox = h1;

  h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'ListboxTop',0, ...
	'Position',[345 48.75 96 12], ...
	'String','Reconstruction method', ...
	'Style','text', ...
	'Tag','StaticText2');
  h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'Callback',callhold,...
	'ListboxTop',0, ...
	'Position',[357.75 24 77.25 20.25], ...
	'String',{'Zero-order hold' 'First-order hold' 'Sinc interpolation'}, ...
	'Style','popupmenu', ...
	'Tag','PopupMenu1', ...
	'Value',1);

  ud.holdbox = h1; 

  h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'ListboxTop',0, ...
	'Position',[122.25 349.5 138.75 12], ...
	'String','Signal samples in the time domain', ...
	'Style','text', ...
	'Tag','StaticText4');
  h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'ListboxTop',0, ...
	'Position',[107.25 170.25 168 12.75], ...
	'String','DFT of original (blue) and subsampled (green)', ...
	'Style','text', ...
	'Tag','StaticText5');

  set(h0,'userdata',ud);

  if (nargin == 1)
    splay3('refresh');
  end

  sig = [];
  fs = [];

elseif strcmp(action,'refresh')

  ud = get(param,'userdata');

  l = length(ud.sig);
  tout = [1:l]/ud.fs;
  tin = tout(1:ud.sfactor:end);
  yin = ud.sig(1:ud.sfactor:end);

  set(ud.fsbox,'string',num2str(ud.fs));
  set(ud.rfsbox,'string',num2str(ud.sfactor));

  if (ud.hold == 1)
     ud.rsig = zohint(tin,yin,tout,ud.fs,ud.sfactor);
  elseif (ud.hold == 2)
     ud.rsig = fohint(tin,yin,tout,ud.fs,ud.sfactor);
  elseif (ud.hold == 3)
     ud.rsig = sincint(tin,yin,tout,ud.fs,ud.sfactor);
  end

  ud.rdft = fft(ud.rsig);

  axes(ud.tax);
  cla
  hold on

 if (l <= 300) & ((l-1)/ud.sfactor == floor((l-1)/ud.sfactor))
     plot(tout,ud.sig,'b');
     plot(tout,ud.rsig,'g');
     plot(tin,yin,'go');
  else
     plot(ud.sig,'b');
     plot(ud.rsig,'g');
  end
  axis tight
  zoom on
  hold off

  axes(ud.fax);
  cla
  hold on
  plot([1:round(ud.ldft/2)]/ud.ldft*ud.fs,abs(ud.dft(1:round(ud.ldft/2))),'b');
  plot([1:round(ud.ldft/2)]/ud.ldft*ud.fs,abs(ud.rdft(1:round(ud.ldft/2))),'g');
  axis tight
  hold off
  zoom on

  set(param,'userdata',ud);

elseif strcmp(action,'auto');

  ud = get(param2,'userdata');

  fs = 8192;
  file = ud.autos(param,:);
  file(file == ' ') = [];      % get rid of extra blanks in filename
  [sig,fs] = wavread(file);
  ud.sig = sig/max(abs(sig));
  ud.fs = fs;

  set(param2,'userdata',ud);

end  


