function ceplift(action)
%CEPLIFT A simple demonstration of cepstral-domain liftering
% 
% To start, load a signal using the 'Load' menu.
%
%  Author: Stuart N Wrigley       
%  MAD - Matlab Auditory Demonstrations
%  (c) University of Sheffield 1998
%  Revision 0.05: 30 August 1998
%  Revision 1 by MPC Jan 19 1999 to standardise for release 2
% Revision for v2.1
% MPC 11/6/99

if nargin < 1
  action='init';
end

switch action
  
case 'init'

  f=findobj('Tag','ceplift_fig');
  if ~isempty(f)
    figure(f);
  else    
    ceplift_gui;
    ud=get(gcf,'UserData');        
    ud.signalYLim=[-1.1 1.1];   
    ud.cursor.ratio=[];   
    set(gcf,'UserData',ud); 
    ceplift changeWinSize;
    ceplift changeWinShift;
  end

case 'changeWin'
  ceplift changeWinSize;
  ceplift changeWinShift;
  ceplift spectrogram;
  ceplift refresh;   
  
case 'changeWinSize'
  ud=get(gcf,'UserData');
  ud.window.size=getuicontrolvalue(ud.winSize,'int');
  set(gcf,'UserData',ud);
  ceplift changeWinType;
  
case 'changeWinShift'
  ud=get(gcf,'UserData');
  ud.window.shift=getuicontrolvalue(ud.winShift,'int');
  set(gcf,'UserData',ud);
  
case 'changeWinType'
  ud=get(gcf,'UserData');
  ud.window.type=getuicontrolvalue(ud.winType);
  set(gcf,'UserData',ud);
  
case 'cursor'
  set(gcf,'WindowButtonMotionFcn','ceplift movecursor');
  set(gcf,'WindowButtonUpFcn','ceplift release');
  
case 'release'
  set(gcf,'WindowButtonMotionFcn','');
  set(gcf,'WindowButtonUpFcn','');
  ceplift refresh;
  
case 'movecursor'
  ud=get(gcf,'UserData');
  currentPoint=get(ud.cepAxes,'CurrentPoint');
  ud.cursor.pos=min(ud.cepYLim(2),max(ud.cepYLim(1),ceil(currentPoint(1,2))));
  ud.cursor.ratio=ud.cursor.pos/ud.cepYLim(2);
  set(gcf,'UserData',ud);
  ceplift plotCursor;    
  
case 'plotCursor'
  ud=get(gcf,'UserData');
  set(ud.handle.cepCursor,'XData',ud.cepXLim,'YData',[ud.cursor.pos ud.cursor.pos],'Visible','on','Color','b','Erasemode','xor');
  
  
case 'refresh'
  ceplift smoothandpitch;
  
case 'spectrogram'
  ud=get(gcf,'UserData');
  axes(ud.specAxes);
  [toplot ud.cepdata ud.nfft]=...
    calcspec(ud.signal.vector,ud.signal.fs,ud.window.type,...
    samplestomilli(ud.window.size,ud.signal.fs),...
    samplestomilli(ud.window.shift,ud.signal.fs));
  xscale=[0 ud.signal.samples/ud.signal.fs]; yscale=[0 ud.signal.fs/2];
  imagesc(xscale,yscale,log10(toplot));
  axis xy; colormap(jet); set(gca,'XTick',[],'YTick',[]);
  ylabel('Frequency (Hz)');     
  title('Spectrogram');
  set(gcf,'UserData',ud);
  ceplift cepstrogram;
  
case 'cepstrogram'
  ud=get(gcf,'UserData');
  range=2:round(ud.nfft/2)-1;
  spec_slice=log10(ud.cepdata); 
  ud.cepSlice=ifft(spec_slice,ud.nfft);
  cepPlot=real(ud.cepSlice(range,:));
  cepPlot=exp(cepPlot-min(cepPlot(:))+0.00001);  
  axes(ud.cepAxes)
  xscale=[0 ud.signal.samples/ud.signal.fs]; yscale=[0 ud.signal.fs/2];
  imagesc(xscale,yscale,cepPlot);
  axis xy; colormap(sqrt(1-gray));set(gca,'XTick',[],'YTick',[]);
  ylabel('Quefrency');title('Cepstrogram');
  ud.cepXLim=get(ud.cepAxes,'XLim');
  ud.cepYLim=get(ud.cepAxes,'YLim');
  if isempty(ud.cursor.ratio)
    ud.cursor.ratio=0.1;
  end
  ud.cursor.pos=round(ud.cursor.ratio*ud.cepYLim(2));
  ud.handle.cepCursor=line('XData',ud.cepXLim,'YData',[ud.cursor.pos ud.cursor.pos],'ButtonDownFcn','ceplift cursor');
  set(ud.handle.cepCursor,'Visible','on','Color','b','Erasemode','xor');
  set(gcf,'UserData',ud); 
  
  
case 'smoothandpitch'
  ud=get(gcf,'UserData');
  datasize=size(ud.cepdata);
  seppos=max(1,round(ud.cursor.ratio*(datasize(1)/2)));
  scep_slice=ud.cepSlice; pcep_slice=ud.cepSlice;
  scep_slice(seppos:end-seppos-1,:)=0;
  pcep_slice(1:seppos-1,:)=0; 
  pcep_slice(end-seppos:end,:)=0;
  range=2:round(ud.nfft/2)-1;
  s=real(fft(scep_slice,ud.nfft));
  p=real(fft(pcep_slice,ud.nfft));
  smooth=s(range,:);
  pitch=p(range,:);
  
  axes(ud.envAxes)
  xscale=[0 ud.signal.samples/ud.signal.fs]; yscale=[0 ud.signal.fs/2];
  imagesc(xscale,yscale,smooth); set(gca,'XTick',[],'YTick',[]);
  axis xy; colormap(jet);
  ylabel('Frequency (Hz)');title('Smooth Spectrogram');
  
  axes(ud.pitchAxes)
  xscale=[0 ud.signal.samples/ud.signal.fs]; yscale=[0 ud.signal.fs/2];
  imagesc(xscale,yscale,pitch); set(gca,'XTick',[],'YTick',[]);
  axis xy; colormap(jet);
  ylabel('Frequency (Hz)'); title('Pitch Spectrogram');
  
  set(gcf,'UserData',ud); 
  ceplift plotCursor;
  
  
case 'playSignal'
  ud=get(gcf,'UserData');
  if ~isempty(ud.signal.vector)
    sound(ud.signal.vector,ud.signal.fs,ud.signal.bits);
  end

case 'create'
  [sig,fs,name]=createsig;
  if length(sig)
    ud=get(gcf,'UserData');
    ud.signal.vector=normalise(sig(:));
    ud.name=name; ud.signal.fs=fs;
    set(gcf,'UserData',ud);
    ceplift 'newsig'
  end
  
case 'load'
  ud=get(gcf,'UserData');
  [name,sig,fs]=loadsig(fullfile(madroot,'data','sounds'));
  if length(sig) 
    ud.signal.vector=normalise(sig(:));
    ud.name=name; ud.signal.fs=fs;
    set(gcf,'UserData',ud);
    ceplift 'newsig'
  end

case 'newsig'
  ud=get(gcf,'UserData');
  ud.signal.samples=length(ud.signal.vector);
  ud.signal.winleft=1;
  ud.signal.winright=ud.signal.samples;
  set([ud.winSize ud.winShift ud.winType],'Enable','on');
  set(gcf,'UserData',ud); 
  ceplift spectrogram;
  ceplift refresh;


otherwise
  maduievent('ceplift',action);
  
end

