//HSS3S01V38 for use with HSS3a, HSS3b, HSS3c, HSS3d, HSS3f hardware.
//gijs gieskes 2009/2010, http://gieskes.nl
//credits: http://gieskes.nl/instruments/files/hard-soft-synth-3/hss3-credits.html

byte prevSynth = 100;

byte triggerDecay = 0;

byte sinAc = 0;
byte sinAc2 = 0;

float tvol = 0.5;
float tvol2 = 0;
float kick = 0;

int BA = 0;
int BB = 0;

int tp = 0;

//oscs
byte oscA = 0;
byte oscB = 0;
byte oscC = 0;
byte oscD = 0;

byte oscA2 = 0;
byte oscB2 = 0;
byte oscC2 = 0;
byte oscD2 = 0;

boolean ta = LOW;
boolean tb = LOW;
boolean tc = LOW;
boolean td = LOW;
boolean te = LOW;

int oscL[8] = {
  264,264,264,264,264,264,264,264};

//noise synth waveform holder
byte oscN[8] = {
  1,1,1,1,1,1,1,1};

unsigned long pitcha = 4;
boolean noisebool = false;

int c = 0;
unsigned long noiselong = 0;

//pot array
int pot[8] = {
  0,0,0,0,0,0,0,0};

float sinA[2][32] = 
{
  {0.6, 0.679, 0.755, 0.825, 0.886, 0.936, 0.972, 0.994, 1, 0.99, 0.965, 0.926, 0.874, 0.811, 0.739, 0.662, 0.583, 0.504, 0.429, 0.361, 0.303, 0.256, 0.222, 0.204, 0.201, 0.214, 0.242, 0.284, 0.339, 0.404, 0.477, 0.554},
  {0.6, 0.679, 0.755, 0.825, 0.886, 0.936, 0.972, 0.994, 1, 0.99, 0.965, 0.926, 0.874, 0.811, 0.739, 0.662, 0.583, 0.504, 0.429, 0.361, 0.303, 0.256, 0.222, 0.204, 0.201, 0.214, 0.242, 0.284, 0.339, 0.404, 0.477, 0.554}
};

byte waveTable[260];

float sinC[41];

byte ti = 0;

int out = 0;
float fout = 0;

//extra outs
boolean Acounter = 0;
boolean Bcounter = 0;

byte selPitch = 0;

byte vibA = 0;
unsigned long mlong[4] = {0,0,0,0};

//trigger vars
boolean externalTrigger = false;
boolean triggerActive = false; 

boolean inLoop = false;

#define FASTADC 0

//defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

void setup(){

#if FASTADC
  //set prescale to 16
  sbi(ADCSRA,ADPS2);
  cbi(ADCSRA,ADPS1);
  cbi(ADCSRA,ADPS0);
#endif

  //setup FAST PWM pin 9 & 10.
  TCCR1B = TCCR1B & 0b11111000 | 0x01;
  TCCR2B = TCCR2B & 0b11111000 | 0x01;

  for(float f=0.5; f<1; f+=0.05){
    sinC[ti] = f;
    ti++;
  }

  for(float f=1; f>0.5; f-=0.05){
    sinC[ti] = f;
    ti++;
  }   

  for(byte f=0; f<32; f++){
    sinA[1][f] = f*0.032;
  }   

  waveTable[0] = 0xaa;
  waveTable[1] = 0x66;

  setupPWM(0);

  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);

  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);

  pinMode(13, OUTPUT);

  pinMode(3, OUTPUT);

  readAnalogs();

  for(byte i=6; i<255; i++){
    waveGenartor(pot[3], 0 , 0);
  }

  pinMode(2, INPUT);
  digitalWrite(2, HIGH);
  
  startupSound();
  attachInterrupt(0, triggerNormal, FALLING);
}

void loop(){
  
  //check if we are in the loop.. (for interupt, pullup resistors).
  inLoop = true;

  //read potmeters
  readAnalogs();

  //button vars
  static byte butSel = 6;
  //select synth (0 to 15).
  butSel = pot[5] >> 6;

  if(butSel == 0){
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
      digitalWrite(11, HIGH);
    }
    setupPWM(1);

    waveGenartor(pot[3], 0, 0);

    oscA2 = max(pot[0] >> 2, 1);

    //detunes oscillators
    oscA++;
    //extra pitch shift up to normal pitch
    oscA += pot[4]>>6;
    oscA %= max(oscA2, 1);
    oscB++;
    oscB %= max(oscA2+1, 2);
    oscC++;
    oscC %= max(oscA2+2, 3);

    //mix oscillators
    out = ((waveTable[oscA]*2)+(waveTable[oscB]*2)+(waveTable[oscC]*2))/6;

    //add vibrato
    if(millis() - mlong[0] > ((pot[2]*4)+512)){
      mlong[0] =  millis();
      vibA++;
      vibA %= ti;
      fout = sinC[vibA]*((pot[1]*0.001)+0.9);
      trigger((ti*2));
    }

    out *= fout;

    out = constrain(out, 0, 127);

    if(!oscA){
      Acounter = !Acounter;
    }

    if(!oscA2){
      Bcounter = !Bcounter;
    }

    analogWrite(5, 20);
    analogWrite(6, 10);
    
    if(oscD > out){
      oscD++;
    }else{
      oscD--;
    }

    analogWrite(9, out);
    analogWrite(10, out);

    delayMicroseconds(oscA2); 

  }
  else if(butSel == 1){
    //reset vars
    if(prevSynth != butSel){
      //fader();
      prevSynth = butSel;
    }
    
    setupPWM(1);

    waveGenartor(pot[3], 0 , 0);

    //detunes oscillators
    oscA++;
    oscA %= (pot[0] >> 4)+1;
    oscB++;
    oscB %= (pot[1] >> 4)+1;
    oscC++;
    oscC %= (pot[2] >> 4)+1;

    //mix oscillators
    out = ((waveTable[oscA]*2)+(waveTable[oscB]*2)+(waveTable[oscC]*2))/7;

    analogWrite(11, (255 - (pot[4] >> 2)));
    
    analogWrite(9, out);
    analogWrite(10, out);
    delayMicroseconds(1); 

  }
  else if(butSel == 2){
    //kick
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
    }
    
    setupPWM(0);

    static unsigned int pitchDecay = 0;

    waveGenartor(pot[3], 0, 0);

    //detunes oscillators
    oscA++;
    //extra pitch shift up to normal pitch
    oscA += ((pot[3]) >> 6);
    oscA %= max(pot[0] >> 3, 1);
    
    oscB++;
    oscB %= max((pot[0] >> 3)+1, 1);
    oscC++;
    oscC %= max((pot[0] >> 3)+2, 1);

    pitchDecay++;
    pitchDecay %= (pot[2]);

    //mix oscillators
    out = ((waveTable[oscA]*2)+(waveTable[oscB]*2)+(waveTable[oscC]*2))/6;

    byte tr0 = (pot[1]/6)+83;
    out = constrain(out, 0, tr0);

    if(!oscA){
      Acounter = !Acounter;
    }

    if(!oscB){
      Bcounter = !Bcounter;
    }

    static byte go = 0;
    go++;
    go %= 256;

    if(!go){
      Acounter = !Acounter;
    }

    if(Acounter){
      analogWrite(6, out);
      digitalWrite(10, LOW);
    }
    else{
      analogWrite(10, out); 
      digitalWrite(6, LOW);
    }

    analogWrite(9, out);

    if(256 % (pitchDecay + 20) == 0){
      trigger(2);
    }
    
    if(!pitchDecay){
      tvol = 255;
    }
    tvol*=0.992;
    max(tvol, 0.1);
    analogWrite(11, (byte(tvol))); 
    
    delayMicroseconds(pitchDecay+20); 

  }
  else if(butSel == 3){
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
      digitalWrite(11, HIGH);
    }
    setupPWM(0);

    //detunes oscillators
    oscA++;
    oscA %= (pot[0] >> 4)+1;
    oscB++;
    oscB %= (pot[0] >> 4)+2;
    oscC++;
    oscC %= (pot[0] >> 4)+3;
    oscD++;
    oscD %= (pot[0] >> 4)+4;

    //detunes oscillators
    oscA2++;
    oscA2 %= (pot[1] >> 4)+1;
    oscB2++;
    oscB2 %= (pot[1] >> 4)+2;
    oscC2++;
    oscC2 %= (pot[1] >> 4)+3;
    oscD2++;
    oscD2 %= (pot[1] >> 4)+4;

    //mix oscillators
    unsigned int outA = ((waveTable[oscA]*2)+(waveTable[oscB]*2)+(waveTable[oscC]*2)+(waveTable[oscD]*2));
    unsigned int outB = ((waveTable[oscA2]*2)+(waveTable[oscB2]*2)+(waveTable[oscC2]*2)+(waveTable[oscD2]*2));

    outA = (outA)*(((pot[2]+1)*0.0005));
    outB = (outB)*(((pot[3]+1)*0.0005));

    if(outA > 255){
      outA -= (outA - 255);  
      trigger(32);
    }

    if(outB > 255){
      outB -= (outB - 255);  
      trigger(32);
    }

    byte out = (outA+outB)/2;

    //oscilloscope(Mout);
    digitalWrite(5, out);
    digitalWrite(6, out);
    analogWrite(9, out);
    analogWrite(10, out);
    analogWrite(11, (pot[4] >> 2));
    delayMicroseconds(1);  

  }
  else if(butSel == 4){
    //techno
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
      oscA = 0;
      selPitch = 0;
      tvol = 0;
      //resetWavetable();
    }
    //setup timers
    setupPWM(0);

    //legato
    if(tp < pot[selPitch]){
      tp++;
    }
    else if(tp > pot[selPitch]){
      tp--; 
    }

    //oscillators timer
    oscA++;
    oscA %= (tp >> 3)+20;

    //display wave..
    analogWrite(10, (tp >> 2));
    analogWrite(11, (tp >> 2));

    //interval
    if(triggerME((pot[4] >> 1)+ 4, 0)){

      //selectpotmeter for next pitch
      selPitch++;
      selPitch %= 4;

      //render waveform
      waveGenartor(1023, ta, ta);

      //pwm sound, changes settings inside the waveGenerator 
      if(!(sinAc % 32)){
        sinAc = 0;
        ta = !ta;
      }

      //reset volume
      tvol = 0.5;

      tc = random(2);

      //no display lines
      digitalWrite(5, 0);
      digitalWrite(6, 0);

      //send trigger
      digitalWrite(3, HIGH);
      digitalWrite(4, HIGH);
      oscA2 = 30;
    }

    oscA2--;
    oscA2 = max(oscA2, 0);
    if(!oscA2){
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
    }

    //fade out
    tvol -= 0.0002;
    tvol = max(tvol, 0.0001);
    out = (waveTable[oscA])*tvol;

    analogWrite(9, out);
    delayMicroseconds(20);  
  }
  else if(butSel == 5){
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
      oscD = 0;
      oscA2 = 2;
      oscB2 = 2;
      oscC2 = 2;
      oscD2 = 0;
      oscL[0] = 0;
      oscL[1] = 0;
      oscL[2] = 0;
    }
    //setup timers
    setupPWM(0);

    oscA++;
    oscA %= oscA2;
    oscB++;
    oscB %= oscB2;
    oscC++;
    oscC %= oscC2;

    //pitch change
    if(triggerME((pot[3] >> 3)+10, 0)){
      
      waveGenartor(1023, 0, 0);

      byte selMode = pot[4] >> 8;

      if(selMode == 0){
        oscA2 = max(pot[0] >> 4, 1);
        oscB2 = max(pot[1] >> 4, 1);
        oscC2 = max(pot[2] >> 4, 1);
      }
      else if(selMode == 1){
        oscA2 = max(pot[1] >> 4, 1);
        oscB2 = max(pot[2] >> 4, 1);
        oscC2 = max(pot[0] >> 4, 1);
      }
      else if(selMode == 2){
        oscA2 = max(pot[2] >> 4, 1);
        oscB2 = max(pot[0] >> 4, 1);
        oscC2 = max(pot[1] >> 4, 1);
      }

      oscL[0]++;
      oscL[0] %= max((pot[0] >> 3)+1, 1);
      oscL[1]++;
      oscL[1] %= max((pot[1] >> 3)+1, 1);
      oscL[2]++;
      oscL[2] %= max((pot[2] >> 3)+1, 1);

      //fade reset
      oscD2 = 240;
    }

    //fade
    oscD2 -= 0.01;
    oscD2 = max(oscD2, 0.0001);

    //reset out
    out = 0;

    //mix
    if(!oscL[0]){
      out += (sinA[1][oscA]*oscD2);
      trigger(2);
    }

    if(!oscL[1]){
      out += (sinA[1][oscB]*oscD2);
      trigger(2);
    }

    if(!oscL[2]){
      out += (sinA[1][oscC]*oscD2);
      trigger(2);
      //reset Effect LED
      oscD = 255;
    }
    
    //fade Efect LED
    oscD--;
    oscD = max(oscD, 1);
    analogWrite(11, oscD);

    out = max(min((out/3), 255), 1);

    analogWrite(9, max(min(out, 100), 1));
    analogWrite(10, out);
    delayMicroseconds(1);  

  }
  else if(butSel == 6){
    //noise
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
    }
    setupPWM(0);

    //switch between up or down fade
    if(triggerME(pot[2]+50, 0)){

      for(byte i=0; i<255; i++){
        waveTable[i] = random(32);
      }

      analogWrite(11, min((waveTable[0]*(pot[3] >> 5)), 255));
      
      ta = !ta;

      //visuals
      analogWrite(5, waveTable[0]);
      analogWrite(6, waveTable[1]);
      digitalWrite(4, HIGH);

      //start trigger
      digitalWrite(3, HIGH);
      digitalWrite(4, HIGH);
      triggerDecay = 30;
    }

    //countdwon trigger and set low..
    triggerDecay--;
    triggerDecay = max(triggerDecay, 0);
    if(!triggerDecay){
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
    }

    //fade
    if(ta == 0){
      kick -= 0.0003;
      if(kick < 0.001){
        kick = 0.95;
      } 
    }
    else if(ta == 1){
      kick += 0.0003;
      if(kick > 0.95){
        kick = 0.0001;
      } 
    }

    //play wave form..
    oscA++;
    oscA %= ((pot[1] >> 3)+2);
    out = min(waveTable[oscA]*kick, 253)+1;
    
    analogWrite(9, out);
    analogWrite(10, out);
    delayMicroseconds((pot[0] << 1)+1); 

  }
  else if(butSel == 7){
    //noise
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
    }
    setupPWM(0);

    
    //analogWrite(11, pot[4] >> 3);
    
    //add up and add new rand vars to array with delay..
    oscA++;
    oscA %= (pot[4] >> 4)+1;
    if(!oscA){
      oscB++;
      oscB %= 8;
      oscN[oscB] = random(90)*kick;
      tc = !tc;
      digitalWrite(7, tc);
    }

    //select active sounds  
    oscA2 = pot[1] >> 5;

    //fade in
    if(bitRead(oscA2, 0)){
      kick += 0.01;
      if(kick > 0.99){
        kick = 0;
      }
    }
    //fade out
    if(bitRead(oscA2, 1)){
      kick -= 0.01;
      if(kick < 0.1){
        kick = 1;
      }
    }
    //oscilate 
    if(bitRead(oscA2, 2)){
      for(int i = 100; i>1; i--){ 
        ta = !ta;
        if(ta){
          analogWrite(9, limiter(pot[1] >> 6)); 
        }
        else{
          analogWrite(9, 5); 
        } 
        delayMicroseconds((pot[0] >> 1)+1); 
      }
    }
    //add empty time..
    if(bitRead(oscA2, 3)){
      //read voor break..
      readAnalogs();
      readAnalogs();
      readAnalogs();
      readAnalogs();
      readAnalogs();
      readAnalogs();
      delay(pot[3] >> 2); 
    }

    for(int i=0; i<((pot[2] >> 4)+1); i++){

      byte t = i % 8;
      out = min((oscN[t]*kick), 128);
      
      analogWrite(11, min((out*3), 255));
      analogWrite(9, limiter(out));      

      tb = !tb;
      digitalWrite(6, tb);

      trigger(pot[2]+4);

      delayMicroseconds((pot[0] >> 1)+1); 
    }

    ta = !ta;
    digitalWrite(5, ta);
    digitalWrite(4, LOW);
    digitalWrite(10, LOW);
  }
  else if(butSel == 8){
    //hypnotoad
    
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
      oscA2 = 0;
      oscB2 = 0;
      oscC2 = 0;
      oscA = 0;
      oscB = 0;
      ta = false;
      tb = false;
      tc = false;
      analogWrite(10, 0);
      analogWrite(5, 0);
      analogWrite(6, 0);
      analogWrite(7, 0);
    }
    
    //setup timers
    setupPWM(1);

    if(millis() - mlong[1] > ((pot[2] >> 1)+2)){
      mlong[1] =  millis();
      
      sinAc++;
      sinAc %= max(pot[0] >> 2, 1);
      waveTable[sinAc]  = random(100);
      
      tb = !tb;
    }
    
    if(millis() - mlong[0] > (pot[3]+128)){
      mlong[0] =  millis();

      trigger(2);
 
      oscC2++;
      oscC2 %= ti;
    }

    ta = !ta;
    
    //oscillators
    oscA++;
    oscA %= max(pot[0] >> 2, 2);
    oscB++;
    oscB %= max(pot[0] >> 2, 3);

    out = (((waveTable[oscA])+(waveTable[oscB]))/3);

    //Serial.println(oscC2, DEC);
    analogWrite(11, (pot[4] >> 2));
    analogWrite(10, oscC2*12);
    analogWrite(5, sinAc);
    analogWrite(6, (255 - sinAc));
    digitalWrite(7, tc);
    analogWrite(9, out);

    delayMicroseconds((((pot[1])+1)*sinC[oscC2])+1);

  }
  else if(butSel == 9){
    //melody bin seq
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
      BA = 0;
      BB = 0;
      tvol = 0;
      tb = true;
    }
    //setup timers
    setupPWM(0);

    if(triggerME(pot[4]+20, 1)){

      BA = pot[2] >> 2;
      BB = pot[3] >> 2;

      waveGenartor(1023, ta, ta);

      oscA2++;
      oscA2 %= 8;
      oscB2++;
      oscB2 %= 8;

      if(!(sinAc % 32)){
        sinAc = 0;
        ta = !ta;
      }

      //no extra visuals
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);

      //tvol = 0.5;
      tb = true;
      
      //start trigger
      digitalWrite(3, HIGH);
      digitalWrite(4, HIGH);
      oscC2 = 30;
    }

    //countdwon trigger and set low..
    oscC2--;
    oscC2 = max(oscC2, 0);
    if(!oscC2){
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
    }

    //pitch
    oscA++;
    oscA %= (pot[0] >> 3)+2;
    oscB++;
    oscB %= (pot[1] >> 3)+2;

    if(bitRead(BA, oscA2) && bitRead(BB, oscB2)){
      out = ((waveTable[oscA]*2)+(waveTable[oscB]*2))*(tvol/3);
      oscD--;
    }
    else if(bitRead(BA, oscA2)){
      out = waveTable[oscA]*tvol;
      oscD++;
    }
    else if(bitRead(BB, oscB2)){
      out = waveTable[oscB]*tvol;
      oscD++;
    }
    
    //oscD %= 255;
    oscD = max(min(oscD, 254), 1);
    analogWrite(11, oscD);
    
    //short attack..
    if(tb){
      if(tvol > 0.8){
        tb = false;
      }
      tvol += (pot[4]+1)*0.00001;//0.005;
    }
    else{
      tvol -= (pot[4]+1)*0.00001;//0.005;
      tvol = max(tvol, 0.0001);
    }

    analogWrite(9, out);
    analogWrite(10, out);

  }
  else if(butSel == 10){
    //4/4 chipy attempt..
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
      digitalWrite(11, HIGH);
    }
    //setup timers
    setupPWM(0);

    if(triggerME(pot[4]+20, 1)){
    //if(millis() - mlong[1] > (pot[4]+20)){
     // mlong[1] =  millis();

      BA = pot[2] >> 2;
      BB = pot[3] >> 2;

      //waveGenartor(1023, ta, ta);
      waveGenartor(1023, 0, 0);

      //reset volume decay
      tvol = 0.5;

      //bit read counters (probably only need one of these..).
      oscA2++;
      oscA2 %= 8;
      oscB2++;
      oscB2 %= 8;

      //change volume with length of long pitch change..
      tvol2 = ((byte) (pot[1]))*0.0035;

      //add some delay (4/4 type) because the analog reads are to unstable..
      oscD2++;
      oscD2 %= 8 << (pot[1] >> 8);
      if(!oscD2){
        for(byte i=0; i<8; i++){
          //multiply and make into byte... melody generation..
          oscL[i] = (byte) (pot[0]*(i+1));
          oscL[i] += 1;
        }
        //melody change 
        oscC2++;
        oscC2 %= 8;
      }

      //phasing..
      if(!(sinAc % 32)){
        sinAc = 0;
        ta = !ta;
      }

      //no extra visuals
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);

      //start trigger
      digitalWrite(3, HIGH);
      digitalWrite(4, HIGH);
      triggerDecay = 30;

      //attack time change.. 
      kick = (oscL[oscA2] >> 2)+1;
    }

    //countdwon trigger and set low..
    triggerDecay--;
    triggerDecay = max(triggerDecay, 0);
    if(!triggerDecay){
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
    }

    //kick pitch down speed
    kick += 0.05; 
    kick = min(kick, 255);

    //pitch
    oscA++;
    oscA %= (byte) (kick); //convert from float to byte
    oscB++;
    oscB %= max((oscL[oscA2] >> 1), 2);

    if(bitRead(BA, oscA2) && bitRead(BB, oscB2)){
      fout = ((waveTable[oscA]*1.3)+(waveTable[oscB]*2))*(tvol/2);
    }
    else if(bitRead(BA, oscA2)){
      fout = waveTable[oscA]*tvol;
    }
    else if(bitRead(BB, oscB2)){
      fout = waveTable[oscB]*tvol;
    }

    tvol -= 0.0003;
    tvol = max(tvol, 0.0001);

    oscD++;
    oscD %= 128;
    if(!oscD){
      tb = !tb;
    }

    oscC++;
    oscC %= oscL[oscC2];

    //mix in with limiter
    out = (byte) min(((fout*2)+(waveTable[oscC]*tvol2))*0.5, 255);

    analogWrite(9, out);
    analogWrite(10, out);

  }
  else if(butSel == 11){
    //clicks
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
    }
    //setup timers
    setupPWM(0);

    if(triggerME(pot[4]+20, 1)){

      //add some delay (4/4 type) because the analog reads are to unstable..
      oscA2++;
      oscA2 %= 16;
      if(!oscA2){
        for(byte i=0; i<8; i++){
          //multiply and make into byte... melody generation..
          oscL[i] = max(((oscL[i]+((byte) (pot[2]*(i+1))))/2), 1);
          oscN[i] = max(((oscN[i]+((byte) (pot[3]*(i+1))))/2), 1);
        }
      }

      //select pitch
      oscB2++;
      oscB2 %= pot[0] >> 7;
      oscC2++;
      oscC2 %= pot[1] >> 7;

      //no extra visuals
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);

      tvol = 2;

      //start trigger
      digitalWrite(3, HIGH);
      digitalWrite(4, HIGH);
      triggerDecay = 30;
    }

    //countdwon trigger and set low..
    triggerDecay--;
    triggerDecay = max(triggerDecay, 0);
    if(!triggerDecay){
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
    }

    //pitch
    oscA++;
    oscA %= (oscL[oscB2] >> 2)+1;
    oscB++;
    oscB %= (oscN[oscC2] >> 2)+1;

    //fade out
    tvol *= 0.9;
    tvol = max(tvol, 0.0001);
    tvol = min(tvol, 2); 

    if(!oscA || !oscB){
      tc = !tc;
      if(tc){
        out = 100*tvol;
        analogWrite(11, (out % 255));
      }
      else{
        out = 0;
      }
    }

    analogWrite(9, out);
    analogWrite(10, out);

  }
  else if(butSel == 12){
    //2 voice arpegiator with fade
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
      
      digitalWrite(11, HIGH);
    }
    //setup timers
    setupPWM(0);

    if(triggerME(pot[4]+20, 1)){

      waveGenartor(pot[1], 0, 0);

      //add some delay (4/4 type) because the analog reads are to unstable..
      oscA2++;
      oscA2 %= 8;
      if(!oscA2){
        for(byte i=0; i<8; i++){
          //multiply and make into byte... melody generation..
          oscL[i] = max(((oscL[i]+((byte) (pot[2]*(i+1))))/2), 1);
          oscN[i] = max(((oscN[i]+((byte) (pot[3]*(i+1))))/2), 1);
        }
      }

      //select pitch
      oscB2++;
      oscB2 %= pot[0] >> 7;
      oscC2++;
      oscC2 %= pot[1] >> 7;

      //no extra visuals
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);

      //phasing..
      if(!(sinAc % 32)){
        sinAc = 0;
        ta = !ta;
      }

      //tvol = 2;
      tb = true;

      //start trigger
      digitalWrite(3, HIGH);
      digitalWrite(4, HIGH);
      triggerDecay = 30;
    }

    //countdwon trigger and set low..
    triggerDecay--;
    triggerDecay = max(triggerDecay, 0);
    if(!triggerDecay){
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
    }

    //short attack..
    if(tb){
      if(tvol >= 2){
        tb = false;
      }
      tvol += 0.03;
    }
    else{
      tvol -= 0.0009;
      tvol = max(tvol, 0.0001);
    }

    //pitch
    oscA++;
    oscA %= max((oscL[oscB2]>>1), 2);
    oscB++;
    oscB %= max((oscN[oscC2]>>1), 2);

    //mix
    out = min(((waveTable[oscA]*tvol)+(waveTable[oscB]*tvol))/4, 255);

    analogWrite(9, out);
    
    //visuals
    analogWrite(10, min((out*2), 255));
    if(out > 50){
      digitalWrite(5, HIGH);
    }else{
      digitalWrite(5, LOW);
    }
    
  }
  else if(butSel == 13){
    //setup timers
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
      //digitalWrite(11, HIGH);
      triggerDecay = 1;
    }
    setupPWM(0);

    //extra reads
    readAnalogs();
    readAnalogs();
    readAnalogs();
    readAnalogs();
    readAnalogs();

    oscA++;
    oscA %= 8;
    oscL[oscA] = max(((oscL[oscA]+((byte) (pot[0]*(oscA+1))))/2), 1);

    //select sounds
    byte tpot = pot[1] >> 8;
    byte tpot2 = pot[2] >> 8;

    //set random or not
    if(pot[3] >> 9){
      tpot = random(4);
      tpot2 = random(4);  
    }

    //effect led
    analogWrite(11, (255 - (pot[4] >> 2)));
    oscD2 = (pot[4] >> 6)+1;
    
    //send trigger
    triggerDecay = !triggerDecay;
    digitalWrite(3, triggerDecay);
    digitalWrite(4, triggerDecay);

    if(tpot == 0){
      //1st one empty
    }
    else if(tpot == 1){
      //no fade, 8 pitches 
      for(byte j=0; j<8; j++){
        for(byte i=0; i<255; i++){
          ta = !ta;
          delayMicroseconds((oscL[j]+1)*oscD2);
          if(ta){
            analogWrite(9, 25); 
          }
          else{
            analogWrite(9, 0); 
          }
        }
      }
    }
    else if(tpot == 2){
      //no fade, 8 pitches 
      for(byte j=0; j<8; j++){
        for(byte i=0; i<255; i++){
          ta = !ta;
          oscB++;
          oscB %= 35;
          delayMicroseconds((oscL[j]+1)*oscD2);
          if(ta){
            analogWrite(9, oscB); 
          }
          else{
            analogWrite(9, (35-oscB)); 
          }
        }
      }
    }
    else if(tpot == 3){
      //fade in and out, 8 pitches 
      for(byte j=0; j<4; j++){
        tvol = 0;  
        for(byte i=0; i<255; i++){
          ta = !ta;
          tvol += 0.0025;
          delayMicroseconds((oscL[j+4]+1)*oscD2);
          if(ta){
            analogWrite(9, 40*tvol); 
          }
          else{
            analogWrite(9, 0); 
          }
        }
        for(byte i=0; i<255; i++){
          ta = !ta;
          tvol -= 0.0025;
          tvol = max(tvol, 0.001);
          delayMicroseconds((oscL[j]+1)*oscD2);
          if(ta){
            analogWrite(9, 40*tvol); 
          }
          else{
            analogWrite(9, 0); 
          }
        }
      }
    }

    //send trigger
    triggerDecay = !triggerDecay;
    digitalWrite(3, triggerDecay);
    digitalWrite(4, triggerDecay);
    
    if(tpot2 == 0){
      //1st one empty
    }
    else if(tpot2 == 1){
      //just a pitch
      for(byte j=0; j<8; j++){
        for(byte i=0; i<((byte)(oscL[oscA]/4)); i++){
          ta = !ta;
          delayMicroseconds((oscL[oscA]+1)*oscD2);
          if(ta){
            analogWrite(9, 16); 
          }
          else{
            analogWrite(9, 0); 
          }
        }
      }
    }
    else if(tpot2 == 2){
      //
      for(byte j=0; j<8; j++){
        tvol = 0;
        for(byte i=0; i<255; i++){
          tvol += 0.0025;
          ta = !ta;
          oscC++;
          oscC %= 3;
          oscB++;
          oscB %= 35;
          delayMicroseconds((oscL[oscA]+1)*oscD2);
          if(ta){
            analogWrite(9, ((oscB*tvol)*oscC)); 
          }
          else{
            analogWrite(9, 0); 
          }
        }
      }
    }
    else if(tpot2 == 3){
      for(byte j=0; j<8; j++){
        for(byte i=0; i<255; i++){
          ta = !ta;
          delayMicroseconds((oscL[oscA]+1)*oscD2);
          if(ta){
            analogWrite(9, random(40)); 
          }
          else{
            analogWrite(9, 0); 
          }
        }
      }
    }

  }
  else if(butSel == 14){

    //bas kick and hh noise..
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(11, HIGH);
    }
    
    //setup timers
    setupPWM(0);

    if(triggerME(pot[4]+20, 1)){

      BA = pot[2] >> 2;
      BB = pot[3] >> 2;

      //waveGenartor(1023, ta, ta);
      waveGenartor(1023, ta, ta);

      //crosfade volume..
      tvol = min(pot[1]*0.001, 0.6);
      tvol2 = min((1023-pot[1])*0.001, 0.6);

      //bit read counters (probably only need one of these..).
      oscA2++;
      oscA2 %= 8;
      oscB2++;
      oscB2 %= 8;

      //phasing..
      if(!(sinAc % 32)){
        sinAc = 0;
        ta = !ta;
      }

      //start trigger
      digitalWrite(3, HIGH);
      digitalWrite(4, HIGH);
      triggerDecay = 30;

      //attack time change.. 
      kick = (pot[0] >> 2)+1;
    }

    //countdwon trigger and set low..
    triggerDecay--;
    triggerDecay = max(triggerDecay, 0);
    if(!triggerDecay){
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
    }

    //kick pitch down speed
    kick += 0.05; 
    kick = min(kick, 255);

    //volume
    tvol -= 0.001;
    tvol = max(tvol, 0.0001);
    tvol2 -= 0.003; 
    tvol2 = max(tvol2, 0.0001);

    //pitch
    oscA++;
    oscA %= (byte) (kick); //convert from float to byte
    oscB++;
    oscB %= (byte) (tvol2); //convert from float to byte

    //reset volume if no beat A
    if(!bitRead(BA, oscA2)){
      tvol = 0.001;
      //analogWrite(11, random(255));
      oscD += (random(10) - 5);
      oscD %= 256; 
      analogWrite(11, oscD);
    }
    //reset volume if no beat B
    if(!bitRead(BB, oscA2)){
      tvol2 = 0.001;
      digitalWrite(11, LOW);
    }

    //mix
    out = (waveTable[oscA]*tvol)+(random(240)*tvol2)/2;

    analogWrite(9, out);
    analogWrite(10, min((out*8), 255));

  }
  else if(butSel == 15){
    //square wave synth..
    
    //reset vars
    if(prevSynth != butSel){
      prevSynth = butSel;
      oscA2 = 10;
      oscB2 = 10;
      oscC2 = 10;
      analogWrite(10, 0);
    }
    setupPWM(0);
    
    //oscillators
    oscA++;
    oscA %= (pot[0]>>4)+8;
    oscB++;
    oscB %= (pot[0]>>4)+9;
    oscC++;
    oscC %= (pot[0]>>4)+10;
    
    //inverse cycle
    if(!oscA){
      ta = !ta;
    }
    if(!oscB){
      tb = !tb;
    }
    if(!oscC){
      tc = !tc;
    }
    
    //reset output volume
    out = 0;
    
    //make wave form, lower volume on low pitch
    if(ta){
      out += 28;
    }
    if(tb){
      out += 28;
    }
    if(tc){
      out += 28;
    }
    
    if(triggerME(pot[4]+10, 1)){
      oscA2++;
      oscA2 %= (pot[2]>>7)+1;
      for(byte i=0; i<8; i++){
        //multiply and make into byte... melody generation.. reverse for low pitch on no arp..
        oscL[i] = 255 - ((byte) ((pot[1]>>2)*((i+1))));
      }
      //start trigger
      digitalWrite(3, HIGH);
      digitalWrite(4, HIGH);
      triggerDecay = 30;
    }

    //countdwon trigger and set low..
    triggerDecay--;
    triggerDecay = max(triggerDecay, 0);
    if(!triggerDecay){
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
    }
    
    out += pot[3]>>4; 
    out = constrain(out, 1, 100); 
    analogWrite(9, out);

    //visuals
    digitalWrite(7, ta);
    digitalWrite(6, tb);
    digitalWrite(5, tc);
    
    analogWrite(11, oscL[oscA2]);
    //overall pitch
    delayMicroseconds(max(oscL[oscA2], 1)); 
  }
}


//read pots, 1 at a time
void readAnalogs(){
  static byte potc = 0;

  potc++;
  potc %= 6;

  pot[potc] = analogRead(potc);
 
}

//setup PWMs: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1235060559
void setupPWM(byte inp){
  static byte prevstate = 255;
  if(inp != prevstate){
    prevstate = inp;
    if(inp == 0){
      //cli();
      TCCR0B = TCCR0B & 0b11111000 | 0x03; 
      //sei();
    }
    else if(inp == 1){
      //cli();
      TCCR0B = TCCR0B & 0b11111000 | 0x01; 
      //sei();
    }
    else if(inp == 2){
     // cli();
      TCCR0B = TCCR0B & 0b11111000 | 0x02; 
      //sei();
    }
  }
}

//send trigger
void trigger(byte inp){
  static unsigned int tCount = 0;

  tCount++;
  tCount %= inp;

  if(!tCount){
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
  }
  else{
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
  }

}

void startupSound(){
  //wait tone
  for(int i=10000; i>0; i--){
    oscA++;
    oscA %= 32;
    out = sinA[0][oscA]*16;
    analogWrite(9, out); 
    delayMicroseconds(68);
  }

  //dial
  for(int j=8; j>0; j--){
    byte rpitch = random(1, 50);
    int rpitcC = (50 - rpitch)*50;
    for(unsigned int i=rpitcC; i>0; i--){
      oscA++;
      oscA %= 32;
      out = sinA[0][oscA]*35;
      analogWrite(9, out); 
      delayMicroseconds(rpitch);
    }
    delay(100);
  }

  delay(1000);
  //part 2..
  oscA = 0;
  for(int i=20000; i>0; i--){
    oscA++;
    oscA %= 32;
    out = sinA[0][oscA]*2;
    analogWrite(9, out); 
    delayMicroseconds(1);
  }
  for(int i=2000; i>0; i--){
    oscA++;
    oscA %= 32;
    out = sinA[0][oscA]*2;
    analogWrite(9, out); 
    delayMicroseconds(70);
  }
  oscA = 0;
  for(int j=7; j>0; j--){
    for(int i=96; i>0; i--){
      oscA++;
      oscA %= 32;
      out = sinA[0][oscA]*12;
      analogWrite(9, out); 
      delayMicroseconds(1);
    }
    delay(6);
  }
  for(int i=200; i>0; i--){
    oscA++;
    oscA %= 32;
    out = sinA[0][oscA]*20;
    analogWrite(9, out); 
    delayMicroseconds(1);
  }
  for(int j=10; j>0; j--){
    byte tv = random(4, 20);
    for(int k=20; k>0; k--){
      for(int i=96; i>0; i--){
        oscA++;
        oscA %= 32;
        out = sinA[0][oscA]*tv;
        analogWrite(9, out); 
        delayMicroseconds(1);
      }
    }
  }
  //noise
  for(unsigned int i=3000; i>0; i--){
    analogWrite(9, random(14));
    delayMicroseconds(1);
  }
  tvol = 20;
  for(unsigned int i=3000; i>0; i--){
    tvol += 0.005;
    oscA++;
    oscA %= 8;
    out = (sinA[1][oscA]*30)+random(tvol)/2;
    analogWrite(9, out);
    delayMicroseconds(1);
  }
  tvol /= 2;
  for(unsigned int i=600; i>0; i--){
    oscA++;
    oscA %= 8;
    out = (sinA[1][oscA]*30)+random(tvol)/2;
    analogWrite(9, out);
    delayMicroseconds(1);
  }
  tvol = 0;
  for(unsigned int i=1000; i>0; i--){
    tvol += 0.002;
    analogWrite(9, (random(20)*tvol));
    delayMicroseconds(1);
  } 
}

//if trigger use trigger, otherwise use millis.. 
boolean triggerME(int mil, byte arr){
  boolean retVal = false;
  if(!externalTrigger){
    if(millis() - mlong[arr] > mil){
      mlong[arr] =  millis();
      retVal = true;
    }
    else{
      retVal = false;
    }
  }
  else if(triggerActive){
    //reset trigger status, for trigger below
    triggerActive = false;
    retVal = true;
  }
  return retVal;
}

void triggerNormal(){
  if(inLoop){
    //set external trigger to true if there is a trigger signal..
    externalTrigger = true;
    //set trigger to active, see above
    triggerActive = true;
  } 
}

void resetWavetable(){
  for(byte i=0; i<100; i++){
    waveTable[i] = 20;
  }
}

byte limiter(byte inp){
  return constrain(inp, 0, 60);
}

void waveGenartor(int inpA, byte inpB, byte inpC){
  static byte decayA = 0;
  sinAc++;
  sinAc %= 256;
  sinAc2++;
  sinAc2 %= 32;
  decayA++;
  //decayA %= (inpA >> 5);
  decayA %= (inpA >> 5)+1;

  waveTable[sinAc] = (255*sinA[inpB][decayA])*sinA[inpC][sinAc2];
}