function intmel(action)
%INTMEL Demonstration of streaming (or peripheral channelling!) using
% the interleaved melody identification task described in Hartmann and
% Johnson (1991), Music Perception, 9(2), 155-184.

% Martin Cooke, April 1998
%   Updated June 1998 for first release of M.A.D.
%   Updated for MAD v2.1
%     mpc 13/6/99 Bergen

if nargin < 1
  action='init';
end

switch action

case 'init'
  % does main figure window exist? If so, bring it to front
  f=findobj('Tag','intmel_fig');
  if ~isempty(f)
    figure(f);
  else  
    intmel_gui
    ud.A=1;
    ud.B=2;
    ud.tonedur=80;
    ud.rate=4;
    ud.overall=1000/ud.rate;
    ud.fs=8192;
    ud.rampsamps=round(ud.fs*20/1000);  % 20ms ramps
    ud.level=60;
    % ud.cond='null';
    s=zeros(10,12);
    % produce scales
    for o=1:10
      c=chromaticscale(o);
      s(o,:)=c(1:12);
    end
    s=s';
    ud.scales=s(:);  
    set(gcf,'UserData',ud);
    colormap(hot.*gray);  % a rather fine sepia
    intmel 'redosigs'
  end

case 'selectTune'
  ud=get(gcf,'UserData');
  m=get(gcbo,'Position');
  if strcmp(get(gcbo,'Checked'),'on')
    set(gcbo,'Checked','off');
    ud.knowntunes = setdiff(ud.knowntunes,m);
  else
    set(gcbo,'Checked','on');
    ud.knowntunes = union(ud.knowntunes,m);
    soundsc(createMelody(ud.melody(m,:),ud.tonedur,ud.rampsamps,59,ud.overall,ud.scales),ud.fs);
  end
  if length(ud.knowntunes) > 1
    set(findobj(gcf,'Tag','nextbutton'),'Enable','on');
  else
    set(findobj(gcf,'Tag','nextbutton'),'Enable','off');
  end   
  set(gcf,'UserData',ud);
  
case 'presentationRateChanged'
  ud=get(gcf,'UserData');
  s=get(gcbo,'Label');
  ud.rate=str2num(get(gcbo,'Label'));
  % work out gap size
  ud.overall=round(1000/ud.rate);
  set(findobj('Tag','rate'),'Checked','off');
  set(gcbo,'Checked','on');
  set(gcf,'UserData',ud);
  intmel 'redosigs'
  
case 'tonedurChanged'
  ud=get(gcf,'UserData');
  s=get(gcbo,'Label');
  ud.tonedur=str2num(get(gcbo,'Label'));
  set(findobj('Tag','tonedur'),'Checked','off');
  set(gcbo,'Checked','on');
  set(gcf,'UserData',ud);
  intmel 'redosigs'

case 'redosigs'
  ud=get(gcf,'UserData');
  % get params
  levelA = 59;
  levelB = levelA+getuicontrolvalue(ud.relativelevel,'int');
  melA = ud.melody(ud.A,:);
  melB = ud.melody(ud.B,:)+getuicontrolvalue(ud.freqsep,'int');
  dur_ratio = getuicontrolvalue(ud.durationratio','int');
  durA = ud.tonedur;
  if dur_ratio
    durB = durA / dur_ratio;
  else
    durB = durA;
  end  
  A = createMelody(melA,durA,ud.rampsamps,levelA,ud.overall,ud.scales);
  rawB = createMelody(melB,durB,ud.rampsamps,levelB,ud.overall,ud.scales);
  % shift B by ud.overall/2
  shift = round((ud.overall/2000)*ud.fs);
  lenB=length(rawB);
  B=zeros(lenB,1);
  B(shift:lenB)=rawB(1:(lenB-shift+1));
  z=zeros(lenB,1);
  if get(findobj(gcf,'Tag','binaural'),'Value')
    ud.sigB = [z';B']';
    ud.sigA = [A';z']';
  else
    ud.sigA = A;
    ud.sigB = B;
  end  
 
  set(findobj(gcf,'Tag','Abutton'),'Enable','on');
  set(findobj(gcf,'Tag','Bbutton'),'Enable','on');
  if length(ud.knowntunes) > 1
    set(findobj(gcf,'Tag','nextbutton'),'Enable','on');
  end
  
  sg=spectrogram(A+B,ud.fs,30,5);
  [frames,chans]=size(sg);
  c2=round(chans/2);
  sg=sg(:,1:c2);
  axes(ud.axes);
  if isfield(ud,'im')
    set(ud.im,'CData',sg');
  else  
    ud.im=imagesc(sg');
    set(ud.im,'Erasemode','background');
  end 
  set(ud.axes,'XLim',[1 frames],'YLim',[1 c2]);  
  set(gcf,'UserData',ud);
  
case 'playA'
  ud=get(gcf,'UserData');
  soundsc(ud.sigA,ud.fs);
  
case 'playB'
  ud=get(gcf,'UserData');
  soundsc(ud.sigB,ud.fs);
  
case 'playAB'
  ud=get(gcf,'UserData');
  soundsc(ud.sigA+ud.sigB,ud.fs);
  
case 'next'
  ud=get(gcf,'UserData');
  % choose from those the user knows   
  ud.A=selectFrom(ud.knowntunes);
  ud.B=selectFrom(setdiff(ud.knowntunes,ud.A));
  set(gcf,'UserData',ud);
  set(findobj(gcf,'Tag','Abutton'),'Enable','off');
  set(findobj(gcf,'Tag','Bbutton'),'Enable','off');
  set(findobj(gcf,'Tag','nextbutton'),'Enable','off');
  intmel 'redosigs'
  intmel 'playAB' 
  
otherwise
  maduievent('intmel',action);
  
end

function y=selectFrom(a)
% select a value of a at random
if length(a)==0
  warndlg(strvcat('Cannot select a tune from an empty set!',...
                   'Please choose at least two melodies'));
  y=0;                 
else
  v=ceil(rand*length(a));
  y=a(v);
end  


%------------------------
function mel=createMelody(melody,duration,rampsamps,level,overall,scales)

% precompute ramp
tlen=length(tone(100,level,duration));
olen=length(tone(100,level,overall));
ramp=window(tlen,'hanning',rampsamps);

mel=zeros(length(melody),olen);
for i=1:length(melody)
  mel(i,1:tlen)=ramp.*tone(scales(melody(i)),level,duration);
end
mel=mel';
mel=mel(:);
