desc:syn_phoneme2 :: ccernn.2009 :: v0.0.1
// phonemes/speech synth

slider1:700<20,10000,0.01>fr.1
slider2:60<0,1000,0.01>bw.1
slider3:0.9<0,01>vol.1
slider4:1100<20,10000,0.01>fr.2
slider5:90<0,1000,0.01>bw.2
slider6:0.9<0,01>vol.2
slider7:0<0,1,0.01>breath
slider8:1<-1,1000,1>len (ms)
slider9:1<0,1,1{pitch,phoneme}>midi note
slider10:0<0,31,1>phoneme
slider11:90<20,440,0.01>pitch
slider12:0<0,1,0.01>vol
slider13:1<0,10,0.01>speed
slider14:0.5<0,1>master volume

@init

  ext_noinit = 1;

  PHONEMES = 2000;
    _f1 = 0;
    _b1 = 1;
    _v1 = 2;
    _f2 = 3;
    _b2 = 4;
    _v2 = 5;
    _n  = 6;
    _l  = 7;
  P_size = 8;

  NUM_PHONEMES = 53;
  P=PHONEMES+(P_size*0 ); P[_f1]= 100; P[_b1]= 60; P[_v1]= 0; P[_f2]=1000; P[_b2]= 90; P[_v2]= 0; P[_n]=0; P[_l]= 1; // space
/*
vowels
(unrounded)
i   300,2250
e   400,2000
E   550,1700
a   850,1500
Q   620,950
A   550,1150
V   400,1100
W   300,1100
+   300,1700
*/
  P=PHONEMES+(P_size*1 ); P[_f1]= 300; P[_b1]= 60; P[_v1]= 1; P[_f2]=2250; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // i
  P=PHONEMES+(P_size*2 ); P[_f1]= 400; P[_b1]= 60; P[_v1]= 1; P[_f2]=2000; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // e
  P=PHONEMES+(P_size*3 ); P[_f1]= 550; P[_b1]= 60; P[_v1]= 1; P[_f2]=1700; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // E
  P=PHONEMES+(P_size*4 ); P[_f1]= 850; P[_b1]= 60; P[_v1]= 1; P[_f2]=1500; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // a
  P=PHONEMES+(P_size*5 ); P[_f1]= 620; P[_b1]= 60; P[_v1]= 1; P[_f2]=950;  P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // Q
  P=PHONEMES+(P_size*6 ); P[_f1]= 550; P[_b1]= 60; P[_v1]= 1; P[_f2]=1150; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // A
  P=PHONEMES+(P_size*7 ); P[_f1]= 400; P[_b1]= 60; P[_v1]= 1; P[_f2]=1100; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // V
  P=PHONEMES+(P_size*8 ); P[_f1]= 300; P[_b1]= 60; P[_v1]= 1; P[_f2]=1100; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // W
  P=PHONEMES+(P_size*9 ); P[_f1]= 300; P[_b1]= 60; P[_v1]= 1; P[_f2]=1700; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // +
/*
(rounded)
y   300,2050
0   400,1750
6   550,1400
G   650,1200
D   620,900
O   550,900
o   400,700
u   300,550
H   300,1300
*/
  P=PHONEMES+(P_size*10); P[_f1]= 300; P[_b1]= 60; P[_v1]= 1; P[_f2]=2050; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // y
  P=PHONEMES+(P_size*11); P[_f1]= 400; P[_b1]= 60; P[_v1]= 1; P[_f2]=1750; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // 0
  P=PHONEMES+(P_size*12); P[_f1]= 550; P[_b1]= 60; P[_v1]= 1; P[_f2]=1400; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // 6
  P=PHONEMES+(P_size*13); P[_f1]= 650; P[_b1]= 60; P[_v1]= 1; P[_f2]=1200; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // G
  P=PHONEMES+(P_size*14); P[_f1]= 620; P[_b1]= 60; P[_v1]= 1; P[_f2]=900;  P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // D
  P=PHONEMES+(P_size*15); P[_f1]= 550; P[_b1]= 60; P[_v1]= 1; P[_f2]=900;  P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // O
  P=PHONEMES+(P_size*16); P[_f1]= 400; P[_b1]= 60; P[_v1]= 1; P[_f2]=700;  P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // o
  P=PHONEMES+(P_size*17); P[_f1]= 300; P[_b1]= 60; P[_v1]= 1; P[_f2]=550;  P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // u
  P=PHONEMES+(P_size*18); P[_f1]= 300; P[_b1]= 60; P[_v1]= 1; P[_f2]=1300; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // H
/*
allophones
w   350, 650
j   250,2000
l   400,1180
L   380,920
1   400,800
J   350,1240
J   350,1100
r   420,1220
*/
  P=PHONEMES+(P_size*19); P[_f1]= 350; P[_b1]= 60; P[_v1]= 1; P[_f2]=  65; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // w
  P=PHONEMES+(P_size*20); P[_f1]= 250; P[_b1]= 60; P[_v1]= 1; P[_f2]=2000; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // j
  P=PHONEMES+(P_size*21); P[_f1]= 400; P[_b1]= 60; P[_v1]= 1; P[_f2]=1180; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // l
  P=PHONEMES+(P_size*22); P[_f1]= 380; P[_b1]= 60; P[_v1]= 1; P[_f2]= 920; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // L
  P=PHONEMES+(P_size*23); P[_f1]= 400; P[_b1]= 60; P[_v1]= 1; P[_f2]= 800; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // 1
  P=PHONEMES+(P_size*24); P[_f1]= 350; P[_b1]= 60; P[_v1]= 1; P[_f2]=1240; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // J
  P=PHONEMES+(P_size*25); P[_f1]= 350; P[_b1]= 60; P[_v1]= 1; P[_f2]=1100; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // J
  P=PHONEMES+(P_size*26); P[_f1]= 420; P[_b1]= 60; P[_v1]= 1; P[_f2]=1220; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; // r
/*
stops & affricates
p/b 250,900
T/D 200,1600
t/d 200,1900
k/g 200,2300
*/
  P=PHONEMES+(P_size*27); P[_f1]= 250; P[_b1]= 60; P[_v1]= 1; P[_f2]= 900; P[_b2]= 90; P[_v2]= 1; P[_n]=1; P[_l]= 0; // p
  P=PHONEMES+(P_size*28); P[_f1]= 250; P[_b1]= 60; P[_v1]= 1; P[_f2]= 900; P[_b2]= 90; P[_v2]= 1; P[_n]=.8;P[_l]= 0; // b
  P=PHONEMES+(P_size*29); P[_f1]= 200; P[_b1]= 60; P[_v1]= 1; P[_f2]=1600; P[_b2]= 90; P[_v2]= 1; P[_n]=1; P[_l]= 0; // T
  P=PHONEMES+(P_size*30); P[_f1]= 200; P[_b1]= 60; P[_v1]= 1; P[_f2]=1600; P[_b2]= 90; P[_v2]= 1; P[_n]=.8;P[_l]= 0; // D
  P=PHONEMES+(P_size*31); P[_f1]= 200; P[_b1]= 60; P[_v1]= 1; P[_f2]=1900; P[_b2]= 90; P[_v2]= 1; P[_n]=1; P[_l]= 0; // t
  P=PHONEMES+(P_size*32); P[_f1]= 200; P[_b1]= 60; P[_v1]= 1; P[_f2]=1900; P[_b2]= 90; P[_v2]= 1; P[_n]=.8;P[_l]= 0; // d
  P=PHONEMES+(P_size*33); P[_f1]= 200; P[_b1]= 60; P[_v1]= 1; P[_f2]=2300; P[_b2]= 90; P[_v2]= 1; P[_n]=1; P[_l]= 0; // k
  P=PHONEMES+(P_size*34); P[_f1]= 200; P[_b1]= 60; P[_v1]= 1; P[_f2]=2300; P[_b2]= 90; P[_v2]= 1; P[_n]=.8;P[_l]= 0; // g
/*
fricatives
f/v 300,1150
8/5 450,1300
s/z 350,1400
S/3 220,1800
c/  350,1650
x/Y 400,1200
 /K 420,1220
*/
  P=PHONEMES+(P_size*35); P[_f1]= 300; P[_b1]= 60; P[_v1]= 1; P[_f2]=1150; P[_b2]= 90; P[_v2]= 1; P[_n]=1; P[_l]= 10; // f
  P=PHONEMES+(P_size*36); P[_f1]= 300; P[_b1]= 60; P[_v1]= 1; P[_f2]=1150; P[_b2]= 90; P[_v2]= 1; P[_n]=.8;P[_l]= 10; // v
  P=PHONEMES+(P_size*37); P[_f1]= 450; P[_b1]= 60; P[_v1]= 1; P[_f2]=1300; P[_b2]= 90; P[_v2]= 1; P[_n]=1; P[_l]= 10; // 8
  P=PHONEMES+(P_size*38); P[_f1]= 450; P[_b1]= 60; P[_v1]= 1; P[_f2]=1300; P[_b2]= 90; P[_v2]= 1; P[_n]=.8;P[_l]= 10; // 5
  P=PHONEMES+(P_size*39); P[_f1]= 350; P[_b1]= 60; P[_v1]= 1; P[_f2]=1400; P[_b2]= 90; P[_v2]= 1; P[_n]=1; P[_l]= 10; // s
  P=PHONEMES+(P_size*40); P[_f1]= 350; P[_b1]= 60; P[_v1]= 1; P[_f2]=1400; P[_b2]= 90; P[_v2]= 1; P[_n]=.8;P[_l]= 10; // z
  P=PHONEMES+(P_size*41); P[_f1]= 220; P[_b1]= 60; P[_v1]= 1; P[_f2]=1800; P[_b2]= 90; P[_v2]= 1; P[_n]=1; P[_l]= 10; // S
  P=PHONEMES+(P_size*42); P[_f1]= 220; P[_b1]= 60; P[_v1]= 1; P[_f2]=1800; P[_b2]= 90; P[_v2]= 1; P[_n]=.8;P[_l]= 10; // 3
  P=PHONEMES+(P_size*43); P[_f1]= 350; P[_b1]= 60; P[_v1]= 1; P[_f2]=1650; P[_b2]= 90; P[_v2]= 1; P[_n]=1; P[_l]= 10; // c
  P=PHONEMES+(P_size*44); P[_f1]= 350; P[_b1]= 60; P[_v1]= 1; P[_f2]=1650; P[_b2]= 90; P[_v2]= 1; P[_n]=.8;P[_l]= 10; //
  P=PHONEMES+(P_size*45); P[_f1]= 400; P[_b1]= 60; P[_v1]= 1; P[_f2]=1200; P[_b2]= 90; P[_v2]= 1; P[_n]=1; P[_l]= 10; // x
  P=PHONEMES+(P_size*46); P[_f1]= 400; P[_b1]= 60; P[_v1]= 1; P[_f2]=1200; P[_b2]= 90; P[_v2]= 1; P[_n]=.8;P[_l]= 10; // Y
  P=PHONEMES+(P_size*47); P[_f1]= 420; P[_b1]= 60; P[_v1]= 1; P[_f2]=1220; P[_b2]= 90; P[_v2]= 1; P[_n]=1; P[_l]= 10; //
  P=PHONEMES+(P_size*48); P[_f1]= 420; P[_b1]= 60; P[_v1]= 1; P[_f2]=1220; P[_b2]= 90; P[_v2]= 1; P[_n]=.8;P[_l]= 10; // K
/*
nasals
m   200,1200
N   200,1350
n   200,1500
9   200,2200
*/
  P=PHONEMES+(P_size*49); P[_f1]= 200; P[_b1]= 60; P[_v1]= 1; P[_f2]=1200; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; //m
  P=PHONEMES+(P_size*50); P[_f1]= 200; P[_b1]= 60; P[_v1]= 1; P[_f2]=1350; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; //N
  P=PHONEMES+(P_size*51); P[_f1]= 200; P[_b1]= 60; P[_v1]= 1; P[_f2]=1500; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; //n
  P=PHONEMES+(P_size*52); P[_f1]= 200; P[_b1]= 60; P[_v1]= 1; P[_f2]=2200; P[_b2]= 90; P[_v2]= 1; P[_n]=0; P[_l]= 10; //9

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

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

@slider

  F1 = FILTERS  + (F_size * 0);
  F2 = FILTERS  + (F_size * 1);
  F1[_ff] = slider1;
  F1[_bb] = slider2;
  F1[_vv] = slider3;
  F2[_ff] = slider4;
  F2[_bb] = slider5;
  F2[_vv] = slider6;
  breath  = slider7;
  len     = slider8;

  midimode= slider9;
  phon != slider10 ? (
    phon   = slider10;
    P  = PHONEMES + (P_size * phon);
    F1 = FILTERS  + (F_size * 0);
    F2 = FILTERS  + (F_size * 1);
    F1[_ff] = P[_f1];
    F1[_bb] = P[_b1];
    F1[_vv] = P[_v1];
    F2[_ff] = P[_f2];
    F2[_bb] = P[_b2];
    F2[_vv] = P[_v2];
    breath  = P[_n];
    len     = P[_l];
  );

  pitch   = slider11;
  vol     = slider12;
  speed   = slider13;
  mastvol = slider14;
  
@block

  while (
    midirecv(ts,msg1,msg23) ? (
      m = msg1 & 240;
      (m == 8*16) ? (
//        isplaying -= 1;
//        isplaying == 0 ? (
          vol = 0;
          slider12 = vol;
          sliderchange(slider10);
//        );
      );
      (m == 9*16) ? (
        vel = (msg23/256) | 0;
        vol = vel / 127;
        slider12 = vol;
        sliderchange(slider12);
        note = msg23 & 127;
//        isplaying += 1;
        midimode == 0 ? (
          pitch = 440 * pow(2.0,(note-69.0)/12.0);
          slider11 = pitch;
          sliderchange(slider11);
        ) :
        midimode == 1 ? (
          phon = note - 36;
          P  = PHONEMES + (P_size * phon);
          F1 = FILTERS  + (F_size * 0);
          F2 = FILTERS  + (F_size * 1);
          F1[_ff] = P[_f1];
          F1[_bb] = P[_b1];
          F1[_vv] = P[_v1];
          F2[_ff] = P[_f2];
          F2[_bb] = P[_b2];
          F2[_vv] = P[_v2];
          breath  = P[_n];
//          // currently playing a plosive sound? len = xfade fast instead of normal fade
//          ((len <= 0) && (isplaying>0)) ? len=0.1 : len  = P[_l];
          slider1 = F1[_ff];
          slider2 = F1[_bb];
          slider3 = F1[_vv];
          slider4 = F2[_ff];
          slider5 = F2[_bb];
          slider6 = F2[_vv];
          slider7 = breath;
          slider8 = len;
          slider10 = phon;
          sliderchange(b0000001011111111);
        );
      );
      midisend(ts,msg1,msg23);
    );
  );

@sample

  out = 0;

//vol > 0.01 ? (

    len <= 0 ? mul = 1 : (
      mul = (1*speed) / (len * (srate/1000));
    );

    // osc

    noise += (breath-noise) * mul;
    saw += (pitch/srate);
    saw > 1 ? saw -= 1;
    src = ((1-noise) * (   saw -0.5))
        + (   noise  * (rand(1)-0.5));

    // filters
    i = 0;
    while(
      F = FILTERS + (i*F_size);
      F[_vv] > 0 ? (
        F[_fr] += (F[_ff] - F[_fr]) * mul;
        F[_bw] += (F[_bb] - F[_bw]) * mul;
        F[_vo] += (F[_vv] - F[_vo]) * mul;
        // init
        x = (-PiTa*F[_bw]);
        r = (pow(2,x*1.442695041));
        c = -r*r;
        b = r*2*cos(PiTa2*F[_fr]);
        a = 1-b-c;
        F[_a] = a;
        F[_b] = b;
        F[_c] = c;
        // iir
        F[_y]  = (F[_a] * (F[_vo]) * src)
               + (F[_b] * F[_z1])
               + (F[_c] * F[_z2]);
        F[_z2] = F[_z1];
        F[_z1] = F[_y];
        //
        out += F[_y];
      );
      i += 1;
      i < NUM_FILTERS;
    );

//);

  out = out * vol * mastvol;
  out > 0.99 ? out = 0.99;
  out < -0.99 ? out = -0.99;
  spl0 = out;
  spl1 = spl0;
