// This effect Copyright (C) 2005 and later Cockos Incorporated
// License: GPL - http://www.gnu.org/licenses/gpl.html
desc:single instrument melody player
slider1:/simple_melodies:none:track
slider2:0<-120,12,1>volume (dB)
slider3:120<0,320,1>play speed (bpm)
slider4:1<0,10,1>start/stop trigger
slider5:0<0,1,1{one-shot,loop}>playback mode
slider6:/simple_instruments:none:instrument
slider7:0<-100,100,1>pitch shift (semitones)

@init
isplay=0;
lslider6=-1;
lslider1=-1;
myfile=-1;
lspl0=lspl1=0;
cur_note=cur_left=cur_vol=cur_transt=0;

@template slider1
A=0,B=2,C=3,D=5,E=7,F=8,G=10,SHARP=1,FLAT=-1,OCTAVE=12

# format: note, length (beats), volume (dB), transition time (beats)
A,1,-0,0
B,1,-0,0
C,1,-0,0
B,1,-0,0

@serialize
file_var(0,isplay);

@slider

padj=2^(slider7/12);

lslider1 != slider1 ? 
(
  lslider1 = slider1;
  file_close(myfile);
  myfile=file_open(slider1);
  cur_note=cur_left=cur_vol=cur_transt=0;
);

lslider6 != slider6 ?
(
  lslider6=slider6;
  fh=file_open(slider6);
  fh > 0 ? 
  (
    file_riff(fh,mem_nch,mem_srate);
    playpos=0;
    mem_nch>0?
    (
      act_len=file_avail(fh);
      (act_len > 1048576 && mem_nch == 2) ? 
      (
        act_len *= 0.5;
        act_len = min(act_len|0,1048576);
        mem_nch=1;
        mem_len=act_len;
        i=0;
        loop(mem_len, 
          file_var(fh,i[0]);
          file_var(fh,tmp); // skip right channel
          i+=1;
        );
      )
      :
      (
        act_len = min(act_len,1048576);
        mem_len=act_len/mem_nch;  
        file_mem(fh,0,act_len); 
      ); 
    ) : mem_len=0;
    file_close(fh);  
  );
);

mflen=srate*0.015;
playmix=2 ^ (slider2/6);
trigstart=2 ^ (slider4|0);
playspeed=srate*60/slider3;
doloop=slider5;
playsa=0;
notesc=mem_srate/srate;

@block
  trigger&trigstart ? 
  ( 
    isplay ? (
      isplay=0;
    ) : (
      isplay=1;
      file_rewind(myfile);
      cur_note=cur_left=cur_vol=cur_transt=0;
    );
  );

@sample

isplay && myfile>0 ? (  

   cur_left <= 0 ?
   (
     last_note=cur_note;
     last_vol=cur_vol;
     // read next item from file
     file_var(myfile,cur_note);
     file_var(myfile,cur_left);    
     file_var(myfile,cur_vol);
     file_var(myfile,cur_transt);
     file_avail(myfile) <= 0 && doloop ? 
     (
       file_rewind(myfile); 
       file_var(myfile,cur_note);
       file_var(myfile,cur_left);    
       file_var(myfile,cur_vol);
       file_var(myfile,cur_transt);
     );

     file_avail(myfile) <= 0 ? 
     (
       cur_note=cur_left=cur_vol=cur_transt=0;
       isplay=0;
     ) : (
       cur_vol = 2^(cur_vol/6);
       cur_left *= playspeed;
       cur_note=notesc*(2^(cur_note/12));
       notedelta=1/(1+cur_transt*playspeed);
       deltapos=0;
       fadein=0;
       osc1=0;
     );
   );
 
   isplay ? 
   (
     deltapos=min(deltapos+notedelta,1);

     osc1 < mem_len ? 
     (
        io=osc1|0;
        so=osc1-io;
        mem_nch > 1 ? io+=io;
        s0=io[0]*(1-so) + io[mem_nch]*so;
        s1 = mem_nch > 1 ? io[1]*(1-so) + io[1+mem_nch]*so : s0;      
     ): s0=s1=0;

     sc = cur_left < mflen ? cur_left/mflen : 1;
     fadein < mflen ? ( sc *= fadein/mflen; fadein+=1; );
     cur_left -= 1;

     sc = (cur_vol*deltapos + last_vol*(1-deltapos)) * sc;
     s0 *= sc;
     s1 *= sc;

     osc1+=(cur_note*deltapos+last_note*(1-deltapos))*padj;

     spl0 += s0*playmix;
     spl1 += s1*playmix;
   )
);
