function sws(action)
%SWS Demonstration of natural and sine-wave speech cocktails.
%
% 
%
% Martin Cooke, May 1998
%  Updated June 1998 for first release of MAD
%  updated July 1999 for v2.1

% Future versions to include
%   better redrawing

if nargin < 1
  action='init';
end

switch action

case 'init'
  % does main figure window exist? If so, bring it to front
  f=findobj('Tag','sws_fig');
  if ~isempty(f)
    figure(f);
  else
    savedir=pwd;  
    sws_gui;		         % otherwise, create one
    ud=get(gcf,'UserData');
    ud.fs=8012;  
    ud.savedir=savedir;
    ud.path=fullfile(madroot,'sws','');
    colormap(hot.*gray);  % a rather fine sepia
  end
  set(gcf,'UserData',ud);
  
case 'load'
  a=get(gcbo,'UserData');  % a defines the axes
  udf=get(gcf,'UserData');
  [swsdata,sig,name]=getswsfile(fullfile(madroot,'data','swstracks','*.ft'));
  if name
    ud=get(a,'UserData');
    ud.sws=swsdata;
    ud.sig=sig;
    ud.fs=ud.sig.fs;
    ud.name=name;
    ud.loaded=1;
    val=get(ud.setnat,'Value');
    str=get(ud.setnat,'String');
    ud.regenopts.ampfreq=deblank(str(val,:));
    ud.regenopts.useleft=get(ud.useleft,'Value');
    ud.regenopts.useright=get(ud.useright,'Value');
    sg=spectrogram(ud.sig.data,ud.sig.fs,30,5);
    axes(a);
    im=imagesc(sg');
    [frames,chans]=size(sg);
    ud.chans=chans;
    set(a,'XLim',[1 frames],'YLim',[1 chans]);      
    set(im,'ButtonDownFcn','sws playsws','UserData',a,'Erasemode','background');
    ud.sws.tracks=drawTracks(swsdata.raw,ud.sig.fs,chans);
    set([ud.setnat ud.amfreqbox ud.useam ud.selectoutput ud.useleft ud.useright],'Enable','on');
    set(a,'UserData',ud);
    sws 'useam'
  end

case 'select'
  t=gcbo;
  tud=get(t,'UserData');
  if tud.selected
    tud.selected=0;
    set(tud.p,'FaceColor','y');
  else
    tud.selected=1;
    set(tud.p,'FaceColor','b');
  end
  set(t,'UserData',tud); 
  a=get(t,'Parent');
  ud=get(a,'UserData');
  ud.swssig=regen(ud.sws,ud.regenopts,ud.sig.fs);
  set(a,'UserData',ud);
  sws 'redomix'
	
case 'useam'
  a=get(gcbo,'UserData');
  ud=get(a,'UserData');
  ud.regenopts.useam=get(ud.useam,'Value');
  % read frequency
  s=get(ud.amfreqbox,'String');
  if strcmp(s,'')
    set(ud.amfreqbox,'String',100);
    s='100';
  end
  ud.regenopts.amfreq=str2num(s);
  ud.swssig=regen(ud.sws,ud.regenopts,ud.sig.fs);
  set(a,'UserData',ud);
  sws 'redomix'
 
case 'useleft'
  a=get(gcbo,'UserData');
  ud=get(a,'UserData');
  ud.regenopts.useleft=get(ud.useleft,'Value');
  set(a,'UserData',ud);
  sws 'redomix'

case 'useright'
  a=get(gcbo,'UserData');
  ud=get(a,'UserData');
  ud.regenopts.useright=get(ud.useright,'Value');
  set(a,'UserData',ud);
  sws 'redomix'
  
case 'amfreqbox'
  a=get(gcbo,'UserData');
  ud=get(a,'UserData');
  if ud.regenopts.useam
    sws 'useam'
  end	

case 'setnat'
  a=get(gcbo,'UserData');
  ud=get(a,'UserData');
  val=get(ud.setnat,'Value');
  str=get(ud.setnat,'String');
  ud.regenopts.ampfreq=deblank(str(val,:));
  ud.swssig=regen(ud.sws,ud.regenopts,ud.sig.fs);
  set(a,'UserData',ud);
  sws 'redomix'
  
case 'selectoutput'
  sws 'redomix'  
  
  
case 'playsws'
  a=get(gcbo,'UserData');
  ud=get(a,'UserData');
  % if natural checked, play that
  val=get(ud.selectoutput,'Value');
  str=get(ud.selectoutput,'String');
  switch deblank(str(val,:))
	case 'natural'	
    soundsc(makebinaural(ud.sig.data,ud.regenopts.useleft,ud.regenopts.useright),ud.sig.fs);
  case 'sws'	
    soundsc(makebinaural(ud.swssig,ud.regenopts.useleft,ud.regenopts.useright),ud.sig.fs);
  case 'silence'
	  warndlg('You have selected silence');
  end  

case 'saveSignal'
	ud=get(gcf,'UserData');
	[f,p] = uiputfile('mix.au','Select filename to save sws mix signal');
	if f
    if isfield(ud,'mix')  % data is loaded
      s=mean(ud.mix);
      s=s./max(abs(s));
	    auwrite(s,ud.fs,[p f]);
    end  
  end

case 'playmix'
  ud=get(gcf,'UserData');
  soundsc(ud.mix,ud.fs);
	
case 'redomix'
  ud=get(gcf,'UserData');
  
  ud1=get(ud.sws1axes,'UserData');
  if ud1.loaded
    val=get(ud1.selectoutput,'Value');
    str=get(ud1.selectoutput,'String');
    switch deblank(str(val,:))
    case 'natural'
      s1=ud1.sig.data;
    case 'sws'	
      s1=ud1.swssig;
    case 'silence'
      s1=zeros(1,length(ud1.sig.data));
    end
    s1=makebinaural(s1,ud1.regenopts.useleft,ud1.regenopts.useright);            
  end

  ud2=get(ud.sws2axes,'UserData');
  if ud2.loaded
    val=get(ud2.selectoutput,'Value');
    str=get(ud2.selectoutput,'String');
    switch deblank(str(val,:))
	  case 'natural'
      s2=ud2.sig.data;
    case 'sws'	
      s2=ud2.swssig;
    case 'silence'
      s2=zeros(1,length(ud2.sig.data));
    end
    s2=makebinaural(s2,ud2.regenopts.useleft,ud2.regenopts.useright);            
  end

  if and(ud1.loaded,ud2.loaded)
    if length(s1) > length(s2)
      ud.mix=s1;
      %ud.mix(:,1:length(s2))=ud.mix(:,1:length(s2))+s2;
      ud.mix(1:length(s2),:)=ud.mix(1:length(s2),:)+s2;
    else	
      ud.mix=s2;
      %ud.mix(:,1:length(s1))=ud.mix(:,1:length(s1))+s1;	
      ud.mix(1:length(s1),:)=ud.mix(1:length(s1),:)+s1;	
    end
    fs=ud1.sig.fs;
  elseif ud1.loaded
    ud.mix=s1;
    fs=ud1.sig.fs;
  elseif ud2.loaded
    ud.mix=s2;
    fs=ud2.sig.fs;
  end

  sg=spectrogram(sum(ud.mix'),fs,30,5);
  axes(ud.mixaxes);
  if isfield(ud,'mixim')
    set(ud.mixim,'CData',sg');
  else  
    ud.mixim=imagesc(sg');
    set(ud.mixim,'ButtonDownFcn','sws playmix','Erasemode','background');
  end 
  [frames,chans]=size(sg);
  ud.chans=chans;
  set(ud.mixaxes,'XLim',[1 frames],'YLim',[1 chans]);       
  set(gcf,'UserData',ud);
	
  
otherwise
  maduievent('sws',action);
  
end

function y=tochans(x,fs,nchans)
y=round(nchans*(2*x)/fs);

%------------------------------------
function s=regen(swsdata,opts,fs)
%REGEN regenerate SWS given data and options

[tracks,tlen]=size(swsdata.fine);
s=zeros(1,tlen);
for t=1:length(swsdata.tracks)
  l=get(swsdata.tracks(t),'UserData');
  if l.selected
    s = s + regen_aux(swsdata.fine(2*t-1,:),swsdata.fine(2*t,:),opts.ampfreq,fs);
  end
end
if opts.useam
  c=sin((2*pi*opts.amfreq*(1:length(swsdata.fine(1,:))))/fs);
  s=s.*(1+c)/2;
end

function s=regen_aux(f,a,af,fs)

tpt=2*pi/fs;

switch af
case 'natural f & a'
	s=a.*sin(tpt*cumsum(f));
case 'constant a'
	s=mean(a).*sin(tpt*cumsum(f));
case 'constant f'
	s=a.*sin(tpt*mean(f)*(1:length(a)));
end	
s=s/max(s);

function [swsdata,sig,f]=getswsfile(swspath)

[f,p]=uigetfile(swspath,'choose a sws file');
if f
  [sig.data,sig.fs,bits]=auread(strrep([p f],'.ft','.au'));
  sig.data=sig.data';
	sig.data=sig.data/max(sig.data);
  swsdata.raw=load([p f]);  % load SWS text file
	swsdata.raw=swsdata.raw';
  [ntracks,l]=size(swsdata.raw);
  t=200/sig.fs;
  ft=1:t:l;
  swsdata.fine=zeros(ntracks,length(ft));
  for i=1:ntracks
    swsdata.fine(i,:)=interp1(1:l,swsdata.raw(i,:),ft);
  end
else
  swsdata=[]; sig=[];
end	


function t=drawTracks(rawdata,fs,nchans)

[tracks,tlen]=size(rawdata);
maxen=max(max(rawdata(2:2:tracks,:)));
norm=10/maxen;
t=[];
for i=1:round(tracks/2);
	f=tochans(rawdata(2*i-1,:),fs,nchans);
	a=rawdata(2*i,:);
  lf=round(f-norm*a);
  hf=round(f+norm*a+1);
  x=1:tlen;
  x=[x fliplr(x(2:tlen-1))];
  y=[lf fliplr(hf(2:tlen-1))];
  p=patch(x,y,'b');
	set(p,'HitTest','off','Erasemode','xor');
  l=line(1:tlen,f);
	set(l,'Visible','on','Color','b','Erasemode','xor');
	tud.p=p;
	tud.selected=1;
  set(l,'UserData',tud,'ButtonDownFcn','sws select');
	t=[t l];
end

%-----------
function y=makebinaural(x,left,right)
%y=zeros(2,length(x));
y=zeros(length(x),2);
if left
  %y(1,:)=x;
  y(:,1)=x';
end
if right
  %y(2,:)=x;
  y(:,2)=x';
end  

