function fourierworkshop(action,in1,in2);
% FOURIERWORKSHOP: Self-contained module that puts up a window. Try it!
%   Version 1.2 (Dec 97). See file "fourierworkshop.m" for more info.

% Author:
%   Alexander Russell Perlis
%   SouthWest Regional Institute in the Mathematical Sciences
%   c/o Department of Mathematics
%   The University of Arizona
%   Tucson, AZ 85721
%   (520) 621-2137
%   aprl@math.arizona.edu
%
% Obtain the latest version of this software from:
%   http://www.math.arizona.edu/~rims/workshops/fourier/softwareMATLAB
%
% Bugs/problems/ideas:
%   None.
%
% Change history:
%   May 1997  1.0  Original version, for Matlab4
%   Oct 1997  1.1  Modified to run under Matlab5
%   Dec 1997  1.2  Runs under either Matlab4 or Matlab5

%----------------------------------------------------------------------------

% Possible actions:
%  'initialize' : this is the default when fourierworkshop is called
%                 with no argument
%
%  'record_popup' : item in this popup was clicked
%  'revert_button' : puts orig sample back in top plot, resets period to full
%  'load_popup'
%  'selection_changed' | 'top_plot_changed'
%  'edit_popup'
%  'top_play_popup'
%
%  'top_plot_click'
%
%  'info_button'
%  'close_button'
%
%
%  'down'
%  'move'
%  'up'
%  'redraw'
%  'done'
%  'setfreq'
%  'setwindow'
%  'showwind'


% Choice of colors can be changed:
periodColor = 'yellow';  % Period start bar, end bar, period edit text
sampleColor = 'magenta';
fourierColor = 'red';
cosineColor = 'cyan';
sineColor = 'green';
    

if nargin<1,
    action='initialize';
end;

global FWGD;  % This is a vector of global data; entries defined below.
global FWmatlabVersion;  % First number of matlab version number
global FWdepth;
global FWorig;  % The original sampled data (may be different from what
                % is currently being viewed and played with)
%% List of handles to make visible/invisible depending on spectrum:
global FWharm_vis;
global FWharm0; % The constant term Fourier coefficient a_0
global FWharm;  % Matrix (2 x max_harmonic) of Fourier coefficients
                %   [ a_1  a_2  a_3  a_4  ... ]
                %   [ b_1  b_2  b_3  b_4  ... ]
max_harmonic = 50; % Max number of harmonics (Fourier coefficients) that
                   % will be computed.

% FWGD is a vector. Here are the entries:
main_fig = 1;
load_popup = 2;
record_popup = 3;
generate_popup = 4;
period_start_field = 5;
period_end_field = 6;
top_axes = 7;
mid_axes = 8;
bot_axes = 9;
top_plot = 10;
period_start_line = 11;
period_end_line = 12;
mid_plot = 13;
mid_fourier = 14;
spectrum_checkbox = 15;
period_popup = 16;
drag_anchor = 17;
FWGD_size = 17;

%% Need to keep:
% Original data
% Clipped data
% From clipped data and period obtain period data
% From period data, repeat it 2 or 3 times,

if strcmp(action,'initialize'),
    % Initialize global variable
    FWmatlabVersion=version;
    FWmatlabVersion=str2num(FWmatlabVersion(1));

    if (FWmatlabVersion < 4) | (FWmatlabVersion > 5),
      disp('FOURIERWORKSHOP is unfamiliar with this version of MATLAB.')
      return
    end

    FWGD = zeros(size(1:FWGD_size));
    FWharm_vis = [];
    FWorig = 0;
    % Create a new figure window
    FWGD(main_fig) = ...
      figure('BackingStore','off','Units','normalized','Visible','off',...
      'NumberTitle','off','Resize','on',...
      'Name','SWRIMS Fourier Workshop');
    set(gcf,'Position',[0.025,0.2,0.95,0.7]);
%    set(gcf,'Position',[0.025,0.45,0.5,0.5]);
    set(gcf,'Visible','on');
    set(gcf,'Pointer','watch');

    %----------------------------------------------------------
    % Define "load_popup_names" and "load_popup_values" now
    % to avoid cluttering the code later on.
    %
    % Matlab only supports 10 names per list --- STUPID!
    sampleList=str2mat('Bird chirps','Chinese Gong','Hallelujah',...
        'Dropping Egg','Train Whistle','Laughter');
    toneList1=str2mat(...
        'Touchtone 1','Touchtone 2','Touchtone 3',...
        'Touchtone 4','Touchtone 5','Touchtone 6',...
        'Touchtone 7','Touchtone 8','Touchtone 9');
    toneList2=str2mat(...,
        'Touchtone *','Touchtone 0','Touchtone #','Dialtone');
    load_popup_names=str2mat('Load sound sample',...
        sampleList,toneList1,toneList2);

    sampleList=str2mat('file:chirp','file:gong','file:handel',...
        'file:splat','file:train','file:laughter');
    toneList1=str2mat(...
        'tones:1','tones:2','tones:3',...
        'tones:4','tones:5','tones:6',...
        'tones:7','tones:8','tones:9');
    toneList2=str2mat(...
        'tones:10','tones:11','tones:12','tones:13');
    load_popup_values=str2mat(' ',...
        sampleList,toneList1,toneList2);


    %====================================
    % Information for all buttons

    %% Following are adjustable:
    outSpc=0.05; %% Spacing between window and frames and axes
    inSpc=0.015; %% Spacing between buttons in frame
    btnWd=0.1; %% Width of buttons
    btnHt=0.035; %% Height of buttons
    btnClr=0.75*[1 1 1]; %% Color of buttons
    frmClr=0.5*[1 1 1]; %% Color of frame (behind buttons)

    %% Following are automatically calculated:
    dblBtnWd=2*btnWd+inSpc;
    frmWd=dblBtnWd+2*inSpc;
    frmLt=1.0-outSpc-frmWd;
    axesHt=(1.0-4*outSpc)/3;
    axesWd=1.0-3*outSpc-frmWd;
    btnPos=[0 0 btnWd btnHt]; % First two entries fixed later
    btnGoDn=[0 -(inSpc+btnHt) 0 0];
    btnGoRt=[inSpc+btnWd 0 0 0];
    btnGoWd=[0 0 inSpc+btnWd 0];


    % Defaults for stuff to come:
    set(gcf,'DefaultAxesFontSize',9);
    set(gcf,'DefaultUIControlBackgroundColor',btnClr);

    %====================================
    % The TOP frame

    frmPos=[frmLt 1.0-outSpc-axesHt-btnHt-inSpc frmWd axesHt+btnHt+inSpc];
    uicontrol('Style','frame','Units','normalized','Position',frmPos, ...
        'BackgroundColor',frmClr);
    btnPos(1:2)=[frmPos(1)+inSpc frmPos(2)+frmPos(4)];

    % The RECORD popup
    btnPos=btnPos+btnGoDn;
    callbackString='fourierworkshop(''record_popup'')';
    nameList=str2mat('Rec 0.5s','Rec 1.0s',...
        'Rec 1.5s','Rec 2.0s',...
        'Rec 2.5s','Rec 3.0s','Rec 3.5s','Rec 4.0s','Rec 4.5s','Rec 5.0s');
    FWGD(record_popup) = ...
      uicontrol('Style','popupmenu','Units','normalized','Position',btnPos,...
      'String',nameList,'HorizontalAlignment','left',...
      'Callback',callbackString);
    
    % The GENERATE popup
    btnPos=btnPos+btnGoRt;
    callbackString='fourierworkshop(''generate_popup'')';
    nameList=str2mat('Generate',...
        'Square Wave',...
        'Triangle Wave',...
        'Mystery Function');
    FWGD(generate_popup) = ...
      uicontrol('Style','popupmenu','Units','normalized','Position',btnPos,...
      'String',nameList,'HorizontalAlignment','left',...
      'Callback',callbackString);
    
    % The LOAD SOUND popup button
    btnPos=btnPos+btnGoDn-btnGoRt+btnGoWd;
    callbackString='fourierworkshop(''load_popup'');';
    % Variables "load_popup_names" and "load_popup_values" were
    % defined earlier.
    FWGD(load_popup) = ...
        uicontrol('Style','popupmenu','Units','normalized',...
        'Position',btnPos, ...
        'String',load_popup_names,'HorizontalAlignment','left',...
        'Callback',callbackString, ...
        'UserData',load_popup_values);

    % The EDIT popup
    btnPos=btnPos+btnGoDn-btnGoWd;
    callbackString = 'fourierworkshop(''edit_popup'')';
    nameList = str2mat('Edit','Keep Selection','Delete Selection',...
        'Scale Signal',...
        'Clip 5% Noise','Clip 10% Noise','Clip 15% Noise','Clip 20% Noise',...
        'Clip 25% Noise','Clip 30% Noise','Clip 35% Noise');
    uicontrol('Style','popupmenu','Units','normalized',...
        'Position',btnPos, ...
        'String',nameList,'HorizontalAlignment','left',...
        'Callback',callbackString);

    % The REVERT button
    btnPos=btnPos+btnGoRt;
    callbackString='fourierworkshop(''revert_button'')';
    uicontrol('Style','pushbutton','Units','normalized','Position',btnPos,...
        'String','Revert',...
        'Callback',callbackString);

    % The PERIOD START and PERIOD END strings
    btnPos=btnPos-btnGoRt+btnGoDn;
    uicontrol('Style','text','Units','normalized','Position',btnPos,...
        'BackgroundColor',frmClr,'ForegroundColor',periodColor, ...
        'HorizontalAlignment','right','String','Period start:');
    btnPos=btnPos+btnGoDn;
    uicontrol('Style','text','Units','normalized','Position',btnPos,...
        'BackgroundColor',frmClr,'ForegroundColor',periodColor, ...
        'HorizontalAlignment','right','String','Period end:');

    % The PERIOD START and PERIOD END editable text boxes
    btnPos=btnPos-btnGoDn+btnGoRt;
    callbackString = 'fourierworkshop(''selection_changed'')';
    FWGD(period_start_field) = ...
        uicontrol('Style','edit','Units','normalized','Position',btnPos, ...
        'String','0',...
        'CallBack',callbackString);
    btnPos=btnPos+btnGoDn;
    FWGD(period_end_field) = ...
        uicontrol('Style','edit','Units','normalized','Position',btnPos,...
        'String','0',...
        'CallBack',callbackString);

    % The PLAY button
    btnPos=btnPos+btnGoDn-btnGoRt+btnGoWd;
    callbackString = 'fourierworkshop(''top_play_popup'')';
    nameList = str2mat('Play Original','Play Visible','Play Selection');
    uicontrol('Style','popup','Units','normalized','Position',btnPos,...
        'String',nameList,'HorizontalAlignment','left',...
        'Callback',callbackString);
    btnPos=btnPos-btnGoWd;


    %====================================
    % The MIDDLE frame

    frmPos=[frmLt 2*outSpc+axesHt frmWd axesHt-btnHt-inSpc];
    uicontrol('Style','frame','Units','normalized','Position',frmPos, ...
        'BackgroundColor',frmClr);
    btnPos(1:2)=[frmPos(1)+inSpc frmPos(2)+frmPos(4)];

%    % DEPTH SLIDER
%    btnPos=btnPos+btnGoDn+btnGoWd;
%    callbackString='fourierworkshop(''depth_slider'')';
%    FWGD(depth_slider) = ...
%      uicontrol('Style','slider','Units','normalized',...
%      'Position',btnPos,'String','Slide it baby',...
%      'Callback',callbackString,'Min',1,'Max',25,'Value',3);

    % The PERIOD popup
    btnPos=btnPos+btnGoDn+btnGoWd;
    callbackString='fourierworkshop(''period_popup'')';
    nameList = str2mat('Show 1 Period','Show 2 Periods','Show 3 Periods');
    FWGD(period_popup) = ...
      uicontrol('Style','popupmenu','Units','normalized',...
      'Position',btnPos,'String',nameList,'HorizontalAlignment','left',...
      'Callback',callbackString);

    % ORIGINAL text
    btnPos=btnPos+btnGoDn-btnGoWd;
    uicontrol('Style','text','Units','normalized','Position',btnPos,...
      'BackgroundColor',frmClr,'ForegroundColor',sampleColor,...
      'HorizontalAlignment','right','String','Original:');

    % The PLAYORIG popup
    btnPos=btnPos+btnGoRt;
    callbackString='fourierworkshop(''play_orig_popup'')';
    nameList = str2mat('Play 1 Period','Play 5 Periods',...
          'Play 10 Periods','Play 50 Periods');
    uicontrol('Style','popupmenu','Units','normalized',...
      'Position',btnPos,'String',nameList,'HorizontalAlignment','left',...
      'Callback',callbackString);

    % FOURIER text
    btnPos=btnPos+btnGoDn-btnGoRt;
    h=uicontrol('Style','text','Units','normalized','Position',btnPos,...
      'BackgroundColor',frmClr,'ForegroundColor',fourierColor,...
      'HorizontalAlignment','right','String','Fourier:','Visible','off');
    FWharm_vis = [FWharm_vis,h];

    % PLAYFOURIER popup
    btnPos=btnPos+btnGoRt;
    callbackString='fourierworkshop(''play_fourier_popup'')';
    nameList = str2mat('Play 1 Period','Play 5 Periods',...
          'Play 10 Periods','Play 50 Periods');
    h=uicontrol('Style','popupmenu','Units','normalized',...
      'Position',btnPos,'String',nameList,'HorizontalAlignment','left',...
      'Callback',callbackString,'Visible','off');
    FWharm_vis = [FWharm_vis,h];

    % return btnPos
    btnPos=btnPos-btnGoRt;

    %====================================
    % The BOTTOM frame

    frmPos=[frmLt outSpc frmWd axesHt];
    uicontrol('Style','frame','Units','normalized','Position',frmPos, ...
        'BackgroundColor',frmClr);
    btnPos(1:2)=[frmPos(1)+inSpc frmPos(2)+frmPos(4)];

    % COMPUTE HARMONICS checkbox
    btnPos=btnPos+btnGoDn+btnGoWd;
    callbackString='fourierworkshop(''spectrum_checkbox'')';
    FWGD(spectrum_checkbox) = ...
      uicontrol('Style','checkbox','Units','normalized','Position',btnPos,...
      'String','Compute the spectrum','HorizontalAlignment','left',...
      'Callback',callbackString);

    % TURN ON ALL HARMONICS popup
    btnPos=btnPos+btnGoDn;
    callbackString='fourierworkshop(''full_depth_popup'')';
    nameList = str2mat('Turn on all harmonics',...
      'Turn on all harmonics (animate)');
    % Made pushbutton for now
    h=uicontrol('Style','pushbutton','Units','normalized','Position',btnPos,...
      'String','Turn on all harmonics','Visible','off',...
      'Callback',callbackString);
    FWharm_vis = [FWharm_vis,h];

    % TURN OFF ALL HARMONICS popup
    btnPos=btnPos+btnGoDn;
    callbackString='fourierworkshop(''no_depth_popup'')';
    nameList = str2mat('Turn off all harmonics',...
      'Turn off all harmonics (animate)');
    % Made pushbutton for now
    h=uicontrol('Style','pushbutton','Units','normalized','Position',btnPos,...
      'String','Turn off all harmonics','Visible','off',...
      'Callback',callbackString);
    FWharm_vis = [FWharm_vis,h];

    % SINE and COSINE text
    btnPos=btnPos+btnGoDn-btnGoWd;
    h=uicontrol('Style','text','Units','normalized','Position',btnPos,...
      'String','Cosine','BackgroundColor',frmClr,...
      'ForegroundColor',cosineColor,'Visible','off');
    FWharm_vis = [FWharm_vis,h];
    btnPos=btnPos+btnGoDn;
    h=uicontrol('Style','text','Units','normalized','Position',btnPos,...
      'String','Sine','BackgroundColor',frmClr,...
      'ForegroundColor',sineColor,'Visible','off');
    FWharm_vis = [FWharm_vis,h];

    % The INFO button
    btnPos=btnPos+btnGoRt-btnGoDn;
    callbackString='fourierworkshop(''info_button'')';
    uicontrol('Style','pushbutton','Units','normalized','Position',btnPos,...
        'String','Info', ...
        'Callback',callbackString);

    % The CLOSE button
    btnPos=btnPos+btnGoDn;
    callbackString='fourierworkshop(''close_button'')';
    uicontrol('Style','pushbutton','Units','normalized','Position',btnPos,...
        'Callback',callbackString,'String','Close');

   %====================================
   % The TOP axes

   axesPos=[outSpc 1.0-outSpc-axesHt axesWd axesHt];
   callbackString='fourierworkshop(''top_plot_click'')';
   FWGD(top_axes) = ...
     axes('Position',axesPos,'DrawMode','normal','YLim',[-1 1],...
     'ButtonDownFcn',callbackString,'DefaultLineButtonDownFcn',callbackString);
   hold on;
   grid on;
   FWGD(top_plot) = plot(0,0,sampleColor);
%   FWGD(top_period_plot) = ...
%     plot(0);
   FWGD(period_start_line) = ...
     line('Xdata',[1 1],'Ydata',[-1 1],'Zdata',[1 1],...
     'EraseMode','xor','Color',periodColor,'LineWidth',1,...
     'ButtonDownFcn',callbackString);
   FWGD(period_end_line) = ...
     line('Xdata',[1 1],'Ydata',[-1 1],'Zdata',[1 1],...
     'EraseMode','xor','Color',periodColor,'LineWidth',1,...
     'ButtonDownFcn',callbackString);

   %====================================
   % The MIDDLE axes

   axesPos=[outSpc 2*outSpc+axesHt axesWd axesHt];
   FWGD(mid_axes) = ...
     axes('Position',axesPos,'YLim',[-1 1]);
   hold on;
   grid on;
   FWGD(mid_plot) = plot(0,0,sampleColor);
   set(gca,'DefaultLineEraseMode','xor');
%'DefaultLineLineWidth',2);
   FWGD(mid_fourier) = plot(0,0,fourierColor);
   set(gca,'DefaultLineEraseMode','remove','DefaultLineLineWidth','remove');

   %====================================
   % The BOTTOM axes

   axesPos=[outSpc outSpc axesWd axesHt];
   callbackStr = 'fourierworkshop(''bot_plot_click'')';
   FWGD(bot_axes) = ...
     axes('Position',axesPos,'YGrid','on',...
     'XLim',[1 max_harmonic],'XTick',1:2:max_harmonic,...
     'DefaultLineButtonDownFcn',callbackStr);
   hold on;
   FWdepth = zeros(max_harmonic,1);
   fourierworkshop('create_depth_marks');

   %------------------------------------
   currentpath = pwd;
   cd ~/matlab;
   FWorig = 0;
   fp = fopen('welcomeToFourier.au', 'r');
   if (fp >= 0),  %% if the file exists, close it and load the sound
     fclose(fp);
     FWorig = auread('welcomeToFourier.au');
   end;
   cd(currentpath);
   fourierworkshop('revert_button');
   drawnow;
   set(gcf,'Pointer','arrow');
%   fourierworkshop('top_play_popup');

elseif strcmp(action,'generate_popup'),
  value=get(FWGD(generate_popup),'Value');
  if value>1,
    set(FWGD(load_popup),'Value',1);
    if value==2,
      FWorig = 0.75 * [ones(40,1);-1*ones(40,1)];
      FWorig = [FWorig;FWorig;FWorig;FWorig;FWorig];
    elseif value==3,
      FWorig = [1:400,399:-1:-400,-399:0];
      FWorig = FWorig';
      FWorig = 0.75 * FWorig / max(abs(FWorig));
      FWorig = [FWorig;FWorig;FWorig;FWorig;FWorig];
    elseif value==4,
      %% Mystery Function is really the following:
      x = [-pi:0.1:pi]';
      %x = [0:0.1:2*pi]';
      FWorig = 5.123 * ones(length(x),1);
      FWorig = FWorig - 45.34*cos(x) + 3.489*sin(x);
      FWorig = FWorig + 15.23*cos(2*x) - 12.375*sin(2*x);
      FWorig = FWorig / 100;
      %FWorig = [FWorig;FWorig;FWorig;];
    end
    fourierworkshop('revert_button');
  end

elseif strcmp(action,'load_popup'),
  value=get(FWGD(load_popup),'Value');
  names=get(FWGD(load_popup),'UserData');
  choice=names(value,:);
  if value==1,
    oldpath = pwd;
    cd ~/sounds;
    [filename, pathname] = uigetfile('*.au','Pick a sound...');
    cd(oldpath);
    FWorig=auread([pathname,filename]);
    FWorig=FWorig/max(abs(FWorig));
    fourierworkshop('revert_button');
  elseif value>1,
    set(FWGD(generate_popup),'Value',1);
    if strcmp(choice(1:4),'file'),
      s=size(choice(:),1);
      filename=choice(6:s);
      filename(filename==' ')=[];  %% strip blanks
      load(filename);
      % Sets Fs to the freq (usu.8000) and y to snd vector
      %Normalize:
      y=y/max(abs(y));
      FWorig=y;
    elseif strcmp(choice(1:5),'tones'),
      s=size(choice(:),1);
      n=str2num(choice(7:s));
      switch FWmatlabVersion
        case 4, load tones, FWorig=tones(:,n);
        case 5, load ptones, FWorig=tones1(:,n);
      end
    end
    fourierworkshop('revert_button');
  end

elseif strcmp(action,'record_popup'),
    set(FWGD(load_popup),'Value',1);
    set(FWGD(generate_popup),'Value',1);
    duration=4096*get(FWGD(record_popup),'Value');
    FWorig=record(duration);
%    FWorig=FWorig/max(abs(FWorig));
    fourierworkshop('revert_button');

elseif strcmp(action,'revert_button'),
    set(FWGD(top_plot),'Xdata',1:length(FWorig),'Ydata',FWorig);
%    set(FWGD(period_start_field),'String','1');
%    set(FWGD(period_end_field),'String',num2str(length(FWorig)));
    fourierworkshop('top_plot_changed');

elseif strcmp(action,'top_plot_changed') | strcmp(action,'selection_changed'),
    pstart=str2num(get(FWGD(period_start_field),'String'));
    pend=str2num(get(FWGD(period_end_field),'String'));
    xdatasize=length(get(FWGD(top_plot),'Xdata'));
    if pstart<1 | pstart>=xdatasize,
       pstart=1;
       set(FWGD(period_start_field),'String',num2str(pstart));
    end
    if pend<1 | pend>xdatasize,
       pend=xdatasize;
       set(FWGD(period_end_field),'String',num2str(pend));
    end
    if pend<pstart,
       pend=pstart;
       set(FWGD(period_end_field),'String',num2str(pend));
    end
    set(FWGD(period_start_line),'Xdata',[pstart pstart]);
    set(FWGD(period_end_line),'Xdata',[pend pend]);

    %% Turn off the spectrum if the computations are too intense
    if pend-pstart > 400,
      set(FWGD(spectrum_checkbox),'Value',0);
    end
    %% Calling "spectrum_checkbox" does any necessary hiding
    %% or showing of controls, and then calculates the spectrum.
    fourierworkshop('spectrum_checkbox');

elseif strcmp(action,'spectrum_checkbox'),
  %% Since this is called even when there is no mouseclick,
  %% we cannot use "gco" below.
  if get(FWGD(spectrum_checkbox),'Value')==0,
    for k=FWharm_vis,
      set(k,'Visible','off');
    end
  else
    for k=FWharm_vis,
      set(k,'Visible','on');
    end
  end
  fourierworkshop('calc_spectrum');

elseif strcmp(action,'calc_spectrum'),
    %% Only calculate it if that is enabled
    if get(FWGD(spectrum_checkbox),'Value')==1,
      set(gcf,'Pointer','watch');
      pstart=str2num(get(FWGD(period_start_field),'String'));
      pend=str2num(get(FWGD(period_end_field),'String'));
      p = pend-pstart+1;
      x = pstart:pend;
      y = get(FWGD(top_plot),'Ydata');
      y = y(pstart:pend);
      FWharm0 = sum(y)/p;
      FWharm = zeros(2,max_harmonic);
      x=2*pi/p*x;
      for k=1:max_harmonic,
        FWharm(1,k) = cos(k*x)*y';
        FWharm(2,k) = sin(k*x)*y';
      end
      FWharm = 2/p * FWharm;
      set(gcf,'Pointer','arrow');
    end
    fourierworkshop('redraw_spectrum');
    % Now move the data from top plot to middle plot:
    fourierworkshop('num_periods_changed');

elseif strcmp(action,'redraw_spectrum'),
    axes(FWGD(bot_axes));
    for k=get(gca,'Children'),
      delete(k);
    end
    if get(FWGD(spectrum_checkbox),'Value')==1,
      axes(FWGD(bot_axes));
      set(gca,'YLimMode','auto');
      set(gca,'DefaultLineMarkerSize',2);
      xx = [1:max_harmonic;1:max_harmonic;nan*ones(1,max_harmonic)];
      yy = [zeros(1,max_harmonic);FWharm(1,:);nan*ones(1,max_harmonic)];
      plot(1:max_harmonic,FWharm(1,:),'co',xx,yy,cosineColor);
      xx = [1:max_harmonic;1:max_harmonic;nan*ones(1,max_harmonic)];
      yy = [zeros(1,max_harmonic);FWharm(2,:);nan*ones(1,max_harmonic)];
      plot(1:max_harmonic,FWharm(2,:),'go',xx,yy,sineColor);
      ylim = get(gca,'YLim');
      m = max(abs(ylim));
      ylim = [-m m];
      set(gca,'YLim',ylim);
      % Create the depth marks
      fourierworkshop('create_depth_marks');
    end
    drawnow;

elseif strcmp(action,'num_periods_changed') | strcmp(action,'period_popup'),
  pstart=str2num(get(FWGD(period_start_field),'String'));
  pend=str2num(get(FWGD(period_end_field),'String'));
  n = get(FWGD(period_popup),'Value');
  y = get(FWGD(top_plot),'Ydata');
  x = pstart:pstart+n*(pend-pstart+1)-1;
  y = y(pstart:pend);
  if n==2,
    y = [y y];
  elseif n==3,
    y = [y y y];
  end
  % Now redraw the middle plot:
  set(FWGD(mid_plot),'Xdata',x,'Ydata',y);
  fourierworkshop('depth_changed');

elseif strcmp(action,'create_depth_marks'),
  axes(FWGD(bot_axes));
  for k=1:max_harmonic,
    if FWdepth(k)==1,
      line('Xdata',k,'Ydata',0,'Zdata',1,'EraseMode','xor',...
      'Color',fourierColor,'MarkerSize',7,'LineWidth',2,...
      'LineStyle','+','UserData',k);
    end
  end

elseif strcmp(action,'bot_plot_click'),
  axes(FWGD(bot_axes));
  pt=get(gca,'currentpoint');
  x=round(pt(1,1));
  if 1<=x & x<=max_harmonic,
    fourierworkshop('flip_depth',x);
    fourierworkshop('depth_changed');
  end

elseif strcmp(action,'flip_depth'),
  %% fourierworkshop('flip_depth',5) turns harmonic 5 on or off
  %% It is the caller's responsibility to call 'depth_changed'
  FWdepth(in1) = 1-FWdepth(in1);
  if FWdepth(in1)==1,
    %% Now on, so create it!
    axes(FWGD(bot_axes));
    line('Xdata',in1,'Ydata',0,'Zdata',1,'EraseMode','xor',...
    'Color',fourierColor,'MarkerSize',7,'LineWidth',2,...
    'LineStyle','+','UserData',in1);
  else
    %% Now off, so remove it!
    h = findobj(FWGD(bot_axes),'Type','line','UserData',in1);
    delete(h);
  end

elseif strcmp(action,'full_depth_popup'),
  animation = get(gco,'Value');
  if animation==2,
    for k=1:max_harmonic,
      if FWdepth(k)==0,
        fourierworkshop('flip_depth',k);
        fourierworkshop('depth_changed');
      end
    end
  else
    FWdepth = ones(max_harmonic,1);
    fourierworkshop('redraw_spectrum');
    fourierworkshop('depth_changed');
  end

elseif strcmp(action,'no_depth_popup'),
  animation = get(gco,'Value');
  if animation==2,
    for k=max_harmonic:-1:1,
      if FWdepth(k)==1,
        fourierworkshop('flip_depth',k);
        fourierworkshop('depth_changed');
      end
    end
  else
    FWdepth = zeros(max_harmonic,1);
    fourierworkshop('redraw_spectrum');
    fourierworkshop('depth_changed');
  end

elseif strcmp(action,'depth_changed'),
  if get(FWGD(spectrum_checkbox),'Value')==1,
    set(gcf,'Pointer','watch');
    x = get(FWGD(mid_plot),'Xdata');
    p = length(x(:)) / get(FWGD(period_popup),'Value');
    y = FWharm0*ones(size(x));
    for k=1:max_harmonic,
      if FWdepth(k)==1,
        y = y + FWharm(1,k)*cos(2*k*pi/p*x);
        y = y + FWharm(2,k)*sin(2*k*pi/p*x);
      end
    end
    set(gcf,'Pointer','arrow');
  else
    x=NaN;
    y=NaN;
  end
  set(FWGD(mid_fourier),'Xdata',x,'Ydata',y);

elseif strcmp(action,'play_orig_popup'),
  % Grab 1 period of the y data
  y = get(FWGD(mid_plot),'Ydata');
  p = length(y(:)) / get(FWGD(period_popup),'Value');
  y = y(1:p);
  % Now repeat it if necessary
  if get(gco,'Value')>1,
    y = [y y y y y];
  end
  if get(gco,'Value')>2,
    y = [y y];
  end
  if get(gco,'Value')>3,
    y = [y y y y y];
  end
  sound(y);

elseif strcmp(action,'play_fourier_popup')
  % Grab 1 period of the y data
  y = get(FWGD(mid_fourier),'Ydata');
  p = length(y(:)) / get(FWGD(period_popup),'Value');
  y = y(1:p);
  % Now repeat it if necessary
  if get(gco,'Value')>1,
    y = [y y y y y];
  end
  if get(gco,'Value')>2,
    y = [y y];
  end
  if get(gco,'Value')>3,
    y = [y y y y y];
  end
  sound(y);


elseif strcmp(action,'edit_popup'),
    value=get(gco,'Value');
    set(gco,'Value',1);
    if value>1,
      y=get(FWGD(top_plot),'Ydata');
      if value==2 | value==3,
        pstart=str2num(get(FWGD(period_start_field),'String'));
        pend=str2num(get(FWGD(period_end_field),'String'));
        xdatasize=length(get(FWGD(top_plot),'Xdata'));
        if pstart<=pend,
          if value==2,
            y=y(pstart:pend);
          elseif value==3,
            y(pstart:pend)=[];
          end
          set(FWGD(period_start_field),'String','0');
          set(FWGD(period_end_field),'String','0');
        end
      elseif value==4,
        y = y / max(abs(y));
      else
        % Strip noise in 5% increments, depending on menu choice
        y=stripnoise(y,(value-4)*0.05);
      end
      set(FWGD(top_plot),'Xdata',1:length(y(:)),'Ydata',y);
      fourierworkshop('top_plot_changed');
    end

elseif strcmp(action,'top_play_popup'),
  value=get(gco,'Value');
  if value==1,
    sound(FWorig);
  else
    data=get(FWGD(top_plot),'Ydata');
    if value==3,
      pstart=str2num(get(FWGD(period_start_field),'String'));
      pend=str2num(get(FWGD(period_end_field),'String'));
      data = data(pstart:pend);
    end
    sound(data);
  end

elseif strcmp(action,'top_plot_click')
  axes(FWGD(top_axes));
  pstart=str2num(get(FWGD(period_start_field),'String'));
  pend=str2num(get(FWGD(period_end_field),'String'));
  pt=get(gca,'currentpoint');
  xdatasize=length(get(FWGD(top_plot),'Xdata'));
  x=round(pt(1,1));
  tol=round(0.08*xdatasize);
  if 1<=x & x<=xdatasize,
    if abs(x-pstart) < abs(x-pend) & abs(x-pstart) < tol,
      FWGD(drag_anchor) = pend;
    elseif abs(x-pstart) >= abs(x-pend) & abs(x-pend) < tol,
      FWGD(drag_anchor) = pstart;
    else
      FWGD(drag_anchor) = x;
    end
    set(gcf,'WindowButtonMotionFcn','fourierworkshop(''top_mouse_move'')');
    set(gcf,'WindowButtonUpFcn','fourierworkshop(''top_mouse_up'')');
    fourierworkshop('top_mouse_move');
  end

elseif strcmp(action,'top_mouse_move'),
    xdatasize=length(get(FWGD(top_plot),'Xdata'));
    axes(FWGD(top_axes));
    pt=get(gca,'currentpoint');
    x=round(pt(1,1));
    if x<1,
      x=1;
    end
    if x>xdatasize,
      x=xdatasize;
    end
    if x<FWGD(drag_anchor),
      pstart=x;
      pend=FWGD(drag_anchor);
    else
      pend=x;
      pstart=FWGD(drag_anchor);
    end
    set(FWGD(period_start_line),'Xdata',[pstart pstart]);
    set(FWGD(period_end_line),'Xdata',[pend pend]);

elseif strcmp(action,'top_mouse_up'),
    fourierworkshop('top_mouse_move');
    pstart = get(FWGD(period_start_line),'Xdata');
    pend = get(FWGD(period_end_line),'Xdata');
    set(FWGD(period_start_field),'String',num2str(pstart(1)));
    set(FWGD(period_end_field),'String',num2str(pend(1)));
    set(gcf,'WindowButtonMotionFcn','');
    set(gcf,'WindowButtonUpFcn','');
    fourierworkshop('selection_changed');

elseif strcmp(action,'close_button'),
    delete(FWGD(main_fig));
    clear global FWGD;
    clear global FWorig;
    clear global FWharm_vis;
    clear global FWharm;
    clear global FWharm0;
    clear global FWdepth;

elseif strcmp(action,'info_button'),
    ttlStr = 'Fourier Workshop Info';

    hlpStr1= ...
        ['                                                '
         ' Fourier Workshop by Alexander Russell Perlis.  '
         '                                                '
         ' See source file "fourierworkshop.m" for more.  '];

     helpfun(ttlStr, hlpStr1);

end

% [eof]
