// This effect Copyright (C) 2005 and later Cockos Incorporated
// License: GPL - http://www.gnu.org/licenses/gpl.html
desc:simple 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:0<0,32,1>synth squareness
slider7:0<-100,100,1>pitch shift (semitones)

@init
isplay=0;
lslider1=-1;
myfile=-1;
lspl0=lspl1=0;
cur_note=cur_left=cur_vol=cur_transt=0;
notesc=440*$pi/srate;

@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;
);

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

@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;
     );
   );
 
   isplay ? 
   (
     deltapos=min(deltapos+notedelta,1);
     s=sin(osc1);
     slider6 > 31 ? s=sign(s) : 
     (
       d=3;
       loop(slider6, s+=sin(osc1*d)/d; d+=2; ); 
     );

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

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

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

     spl0 += s*playmix;
     spl1 += s*playmix;
   )
);
