function bm(action)
%BM Simple animation of a linear, passive, basilar membrane.

% Martin Cooke, October 1998

% Version 2.1
% MPC 11/6/99

% Work required for V3
%   proper axis labelling
%   frequency mapping
%   help on loading signal

if nargin < 1
  action='init';
end

switch action
case 'init'
  
  f=findobj('Tag','bm_fig');
  if ~isempty(f)
    figure(f);
  else     
    bm_gui;
    ud=get(gcf,'UserData');
    ud.fs=8012;
    ud.fb=initgammatones(100,4000,200,ud.fs);	% reset filterbank
    ud.sig=zeros(1,1000);
    set(ud.wavAxes,'YLim',[-1.1 1.1]);
    ud.sigline=line(1:length(ud.sig),ud.sig);
    ud.cursor=line([1 1],[-1.1 1.1],'Color','r');	% draw cursor
    set(ud.cursor,'EraseMode','xor');
    axes(ud.bmAxes);
    set(ud.bmAxes,'YLim',[-2 2]);
    ud.bmline=line(1:200,zeros(1,200));
    ud.maxline=line(1:200,zeros(1,200));
    set(ud.bmline,'EraseMode','background');
    set(ud.maxline,'EraseMode','background','Color','r');
    set(gcf,'UserData',ud,'Name','basilar membrane - [no data loaded]');
  end

case 'create'
  [sig,fs,name]=createsig;
  if length(sig)
    ud=get(gcf,'UserData');
    ud.sig=sig; ud.name=name; ud.fs=fs;
    set(gcf,'UserData',ud);
    bm 'newsig'
  end
  
case 'load'
  ud=get(gcf,'UserData');
  [name,sig,fs]=loadsig(fullfile(madroot,'data','sounds'));
  if length(sig) 
    ud.sig=sig; ud.name=name; ud.fs=fs;
    set(gcf,'UserData',ud);
    bm 'newsig'
  end
  
case 'newsig'
  ud=get(gcf,'UserData');
  ud.sig=normalise(ud.sig);
  set(ud.control,'Enable','on');
  set(ud.sigline,'XData',1:length(ud.sig),'YData',ud.sig);
  set(ud.wavAxes,'XLim',[1 length(ud.sig)]);
  set(gcf,'UserData',ud,'Name',ud.name);
  ud.fb=initgammatones(100,4000,200,ud.fs);	% reset filterbank
  bm 'redrawSignal'
  
case 'redrawSignal'
  ud=get(gcf,'UserData');
  set(ud.sigline,'YData',ud.sig);
  set(gcf,'UserData',ud);
     
case 'start'
  ud=get(gcf,'UserData');
  set(ud.control,'String','stop','Callback','bm stop');
  % start simulation
  fb=ud.fb;
  i = 0;
  siglen=length(ud.sig);
  maxline=zeros(1,length(ud.fb.gain));
  set(ud.maxline,'YData',maxline);
  while and(strcmp('stop',get(ud.control,'String')),i<siglen)
    i = i + 1;
    fb=gammatones(ud.sig(i),fb);
    bmout=fb.bm;
    set(ud.bmline,'YData',bmout);		% animate bm
    maxline=max(maxline,bmout); 
    set(ud.maxline,'YData',maxline);
    set(ud.cursor,'XData',[i i]);		% move cursor along waveform
    if rem(i,100)
      drawnow;
    end  
  end
  set(ud.control,'String','run','Callback','bm start');
  set(gcf,'UserData',ud);
  bm 'redrawSignal'

case 'stop'
  ud=get(gcf,'UserData');
  set(ud.control,'String','halt');
  set(gcf,'UserData',ud);
  
case 'setbm'
  answer=inputdlg({'lowest frequency (Hz)','highest frequency (Hz)','number of points'},...
			'supply BM details',...
			1,...
			{'100','4000','200'});
  if ~isempty(answer)
    ud=get(gcf,'UserData');
    ud.fb=initgammatones(str2num(answer{1}),str2num(answer{2}),str2num(answer{3}),8012);
    fbsize=str2num(answer{3});
    set(ud.bmAxes,'XLim',[1 fbsize]);
    set(ud.bmline,'XData',1:fbsize,'YData',zeros(1,fbsize));
    set(ud.maxline,'XData',1:fbsize,'YData',zeros(1,fbsize));
    set(gcf,'UserData',ud);
  end

otherwise
  maduievent('bm',action);

end
