desc:syn_phoneme1 :: ccernn.2009  :: v0.0.1
// phoneme synthesis

slider1:0<0,17,1>phoneme
slider2:90<20,1024,1>freq
slider3:0.5<0,1,0.1>vol
slider4:256<100,10000>xfade

@init

  NUM_FILTERS = 3;

  FILTERS = 1000;
    _a  = 0;
    _b  = 1;
    _c  = 2;
    _y  = 3;
    _z1 = 4;
    _z2 = 5;
    //
    _fm = 6;
    _bw = 7;
    _am = 8;
    //
    _ff = 9;
    _bb = 10;
    _aa = 11;
  F_size = 12;

  PHONEMES = 2000;
    _fm1 = 0;
    _fm2 = 1;
    _fm3 = 2;
    _bw1 = 3;
    _bw2 = 4;
    _bw3 = 5;
    _am1 = 6;
    _am2 = 7;
    _am3 = 8;
    _as  = 9;
    _pl  = 10;  // not used
    _ln = 11;
  P_size = 12;

  saw   = 0;
  freq  = 90;

  xfade = 8000;

  Ta    = 1/srate;
  PiTa  = $pi*Ta;
  PiTa2 = Pita*2;

  //--- phonemes
  P = PHONEMES + (P_size*0); P[_fm1]=700; P[_fm2]=1100; P[_bw1]=60; P[_bw2]=90; P[_am1]=1;   P[_am2]=1;   P[_as]=0; P[_pl]=0; P[_ln]=5000;  // a
  P = PHONEMES + (P_size*1); P[_fm1]=600; P[_fm2]=1800; P[_bw1]=60; P[_bw2]=90; P[_am1]=1;   P[_am2]=1;   P[_as]=0; P[_pl]=0; P[_ln]=4000;  // e
  P = PHONEMES + (P_size*2); P[_fm1]=300; P[_fm2]=2200; P[_bw1]=60; P[_bw2]=90; P[_am1]=1;   P[_am2]=1;   P[_as]=0; P[_pl]=0; P[_ln]=4000;  // i
  P = PHONEMES + (P_size*3); P[_fm1]=610; P[_fm2]=880;  P[_bw1]=60; P[_bw2]=90; P[_am1]=1;   P[_am2]=1;   P[_as]=0; P[_pl]=0; P[_ln]=4000;  // o
  P = PHONEMES + (P_size*4); P[_fm1]=500; P[_fm2]=950;  P[_bw1]=60; P[_bw2]=90; P[_am1]=1;   P[_am2]=1;   P[_as]=0; P[_pl]=0; P[_ln]=10000; // o
  P = PHONEMES + (P_size*5); P[_fm1]=300; P[_fm2]=950;  P[_bw1]=60; P[_bw2]=90; P[_am1]=1;   P[_am2]=1;   P[_as]=0; P[_pl]=0; P[_ln]=5000;  // u
  P = PHONEMES + (P_size*6); P[_fm1]=480; P[_fm2]=1780; P[_bw1]=40; P[_bw2]=300;P[_am1]=0;   P[_am2]=0;   P[_as]=0; P[_pl]=1; P[_ln]=500;   // -
  P = PHONEMES + (P_size*7); P[_fm1]=190; P[_fm2]=760;  P[_bw1]=60; P[_bw2]=90; P[_am1]=1;   P[_am2]=1;   P[_as]=1; P[_pl]=1; P[_ln]=500;   // b
  P = PHONEMES + (P_size*8); P[_fm1]=190; P[_fm2]=2680; P[_bw1]=60; P[_bw2]=150;P[_am1]=0.25;P[_am2]=0.25;P[_as]=1; P[_pl]=0; P[_ln]=500;   // d
  P = PHONEMES + (P_size*9); P[_fm1]=190; P[_fm2]=1480; P[_bw1]=30; P[_bw2]=45; P[_am1]=1;   P[_am2]=1;   P[_as]=1; P[_pl]=0; P[_ln]=1000;  // k
  P = PHONEMES + (P_size*10);P[_fm1]=460; P[_fm2]=1480; P[_bw1]=60; P[_bw2]=90; P[_am1]=1;   P[_am2]=1;   P[_as]=0; P[_pl]=1; P[_ln]=4000;  // l
  P = PHONEMES + (P_size*11);P[_fm1]=480; P[_fm2]=1000; P[_bw1]=40; P[_bw2]=175;P[_am1]=1;   P[_am2]=1;   P[_as]=0; P[_pl]=1; P[_ln]=5000;  // m
  P = PHONEMES + (P_size*12);P[_fm1]=480; P[_fm2]=1780; P[_bw1]=40; P[_bw2]=300;P[_am1]=1;   P[_am2]=0;   P[_as]=0; P[_pl]=1; P[_ln]=5000;  // n
  P = PHONEMES + (P_size*13);P[_fm1]=490; P[_fm2]=1180; P[_bw1]=60; P[_bw2]=90; P[_am1]=1;   P[_am2]=1;   P[_as]=0; P[_pl]=1; P[_ln]=5000;  // r
  P = PHONEMES + (P_size*14);P[_fm1]=2620;P[_fm2]=13000;P[_bw1]=200;P[_bw2]=220;P[_am1]=0.05;P[_am2]=0.15;P[_as]=1; P[_pl]=0; P[_ln]=4000;  // s
  P = PHONEMES + (P_size*15);P[_fm1]=1720;P[_fm2]=14000;P[_bw1]=60; P[_bw2]=90; P[_am1]=0.1; P[_am2]=0.1; P[_as]=1; P[_pl]=0; P[_ln]=5000;  // z
  P = PHONEMES + (P_size*16);P[_fm1]=190; P[_fm2]=2680; P[_bw1]=60; P[_bw2]=150;P[_am1]=0.5; P[_am2]=0.50;P[_as]=1; P[_pl]=0; P[_ln]=500;   // t
  P = PHONEMES + (P_size*17);P[_fm1]=280; P[_fm2]=1420; P[_bw1]=60; P[_bw2]=90; P[_am1]=1;   P[_am2]=1;   P[_as]=1; P[_pl]=0; P[_ln]=1000;  // v
  //---

@slider

  phon  = slider1;
  freq  = slider2;
  vol   = slider3;
  xfade = slider4;

  P  = PHONEMES + (P_size * phon);
  F1 = FILTERS  + (F_size * 0);
  F2 = FILTERS  + (F_size * 1);
  
  F1[_ff] = P[_fm1];
  F1[_bb] = P[_bw1];
  F1[_aa] = P[_am1];

  F2[_ff] = P[_fm2];
  F2[_bb] = P[_bw2];
  F2[_aa] = P[_am2];
  asp     = P[_as];
  pl      = P[_pl];
  ll      = P[_ln];
  
@block
  while (
    midirecv(ts,msg1,msg23) ? (
      m = msg1 & 240;
      (m == 9*16) ? (
        note = msg23 & 127;
        vel = (msg23/256) | 0;
        note < 24 ?
          phon = note;
          P  = PHONEMES + (P_size * phon);
          F1 = FILTERS  + (F_size * 0);
          F2 = FILTERS  + (F_size * 1);
          F1[_ff] = P[_fm1];
          F1[_bb] = P[_bw1];
          F1[_aa] = P[_am1];
          F2[_ff] = P[_fm2];
          F2[_bb] = P[_bw2];
          F2[_aa] = P[_am2];
          asp     = P[_as];
          pl      = P[_pl];
          ll      = P[_ln];
          slider1 = phon;
          sliderchange(slider1);
//        ) :
//        (
//          freq = 440 * pow(2.0,(note-69.0)/12.0);
//          //slider2 = freq;
//          //sliderchange(slider2);
        );
//      (m == 13*16) ? (
//        m_f ? (
//          fbk = (msg23 & 127) / 127;
//          slider2 = fbk;
//          sliderchange(slider2);
//        );
//      );
      midisend(ts,msg1,msg23);
    );
  );


@sample

  pl > 0 ?  mul = 1 : mul = (1/xfade);

  as += (asp-as) * mul;

  //----------

  // osc
  saw += (freq/srate);
  saw > 1 ? saw -= 1;
  src = ((1-as) * (   saw -0.5))
      + (   as  * (rand(1)-0.5));
  // filters
  out = 0;
  i = 0;
  while(
    F = FILTERS + (i*F_size);
    F[_ff] > 0 ? (
      F[_fm] += (F[_ff] - F[_fm]) * mul;
      F[_bw] += (F[_bb] - F[_bw]) * mul;
      F[_am] += (F[_aa] - F[_am]) * mul;
      // init
      x = (-PiTa*F[_bw]);
      r = (pow(2,x*1.442695041));
      c = -r*r;
      b = r*2*cos(PiTa2*F[_fm]);
      a = 1-b-c;
      F[_a] = a;
      F[_b] = b;
      F[_c] = c;
      // iir
      F[_y]  = (F[_a] * (src*F[_am]))
             + (F[_b] * F[_z1])
             + (F[_c] * F[_z2]);
      F[_z2] = F[_z1];
      F[_z1] = F[_y];
      //
      out += F[_y];
    );
    i += 1;
    i < NUM_FILTERS;
  );

  spl0 = out * vol;
  spl1 = spl0;

  //----------

/*
// two filter taps only
// todo: find phoneme table with three filters
 f1   f2      b1  b2    a1  a2    asp   len     bla
 250  1800    60  90    100 100   1     5000    
 480  1780    40  300   0   0     1     500     silence
 550  2000    60  90    0   0     1     500     silence
 300  950     60  90    100 10    1     1       end
 700  1100    60  90    100 100   1     5000    a
 700  1100    60  90    100 100   0     7000    a
 600  1800    60  90    100 100   0     4000    e
 600  1800    60  90    100 100   1     5000    e
 300  2200    60  90    100 100   1     4000    i
 610  880     60  90    100 100   1     4000    o
 610  880     60  90    100 100   0     4000    o
 500  950     60  90    100 100   1     10000   o
 300  950     60  90    100 100   1     5000    u
 190  760     60  90    100 100   255   500     b
 190  760     60  90    200 200   255   1500    b
 190  2680    60  150   25  25    255   500     d
 190  1480    30  45    100 100   255   1000    k
 460  1480    60  90    100 100   1     4000    l
 460  1480    60  90    100 100   0     4000    l
 480  1000    40  175   100 100   1     5000    m
 480  1780    40  300   100 0     1     5000    n
 480  1780    40  300   100 0     0     3000    n
 490  1180    60  90    100 100   1     5000    r
 2620 13000   200 220   5   15    255   4000    s
 190  2680    60  150   50  50    255   500     t
 280  1420    60  90    100 100   255   1000    v
 1720 14000   60  90    10  10    255   5000    z
*/
