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

//infra red 
#define BITS_PER_MESSAGE 12    
#define B_1 900       
#define B_0 1400 
#define START_BIT 2000
#define IR_PIN 2
 
//find the threshold time b/w the two pulse sizes
#define BIT_THRESH B_0+((B_1-B_0)/2)

//midi library:
//http://timothytwillman.com/itp_blog/?page_id=240
#include "Midi.h"

class MyMidi : public Midi {
  public:
  
  // Need this to compile; it just hands things off to the Midi class.
  MyMidi(HardwareSerial &s) : Midi(s) {}
  
  void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity)
  {
    //midiHandler(channel, note, true);
  }

  void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity)
  {
    //midiHandler(channel, note, false);
  }

};

MyMidi midi(Serial);

byte midichannel = 1;

//pots mounted on top == true, bottom == false;
boolean reverse = false;

//wave generator values
static byte decayA = 0;
static int octaver = 0;

byte butSel = 0;
byte prevSynth = 100;

byte triggerDecay = 0;

int sinAc = 0;
byte sinAc2 = 0;

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

int BA = 0;
int BB = 0;

int tp = 0;

//oscs
unsigned int oscA = 0;
unsigned int oscB = 0;
unsigned int oscC = 0;
unsigned int oscD = 0;

unsigned int oscA2 = 0;
unsigned int oscB2 = 0;
unsigned int oscC2 = 0;
unsigned int oscD2 = 0;

boolean ta = LOW;
boolean tb = LOW;
boolean tc = 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};

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

float sinA[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};

byte waveTable[512];

/*
int major[] = 
{253, 238, 212, 189, 179, 159, 141, 126, 119, 106, 94, 89, 79, 70, 63, 59, 53, 47, 44, 39, 35, 31, 29, 26, 23};

byte major[2][26] =  {
     {239, 213, 190, 160, 142, 127, 120, 107, 95, 89, 80, 71, 64, 60, 53, 47, 45, 40, 36, 32, 32, 30, 27, 24, 22, 20}, //C major
     {213, 190, 169, 160, 142, 127, 113, 107, 95, 84, 80, 71, 64, 56, 53, 47, 42, 40, 36, 32, 28, 27, 24, 21, 22, 20}  //D major
};
*/

byte major[3][25] =  {
//{239, 213, 190, 160, 142, 127, 120, 107, 95, 89, 80, 71, 64, 60, 53, 47, 45, 40, 36, 32, 32, 30, 27, 24, 22}, //C major
  {  0,   2,   4,   5,   7,   9,  11,  12, 14, 16, 17, 19, 21, 23, 24, 26, 28, 29, 31, 35, 36, 38, 40, 41, 43}, //C major

//{213, 190, 169, 160, 142, 127, 113, 107, 95, 84, 80, 71, 64, 56, 53, 47, 42, 40, 36, 32, 28, 27, 24, 21, 22}, //D major
  {  2,   4,   6,   7,   9,  11,  14,  16, 18, 19, 21, 23, 26, 28, 30, 31, 33, 36, 39, 41, 43, 44, 46, 48, 48}, //D major
  
//{226, 201, 190, 169, 150, 134, 127, 113,100, 95, 84, 75, 67, 64, 56, 50, 47, 42, 38, 34, 32, 28, 25, 24, 21}  //B major
  {  1,   3,   4,   6,   8,  10,  11,  13, 15, 16, 18, 20, 22, 23, 25, 27, 28, 30, 32, 34, 33, 35, 37, 38, 40}  //B major
};

byte scale[49] = {
//0    1    2    3    4    5    6    7    8    9   10   11
239, 226, 213, 201, 190, 179, 169, 160, 150, 142, 134, 127, 

//12  13   14   15   16   17   18   19   20   21   22   23
120, 113, 107, 100,  95,  89,  84,  80,  75,  71,  67,  64, 

//24  25   26   27   28   29   30   31   32   33   34   35
 60,  56,  53,  50,  47,  45,  42,  40,  38,  36,  34,  32,
 
//36  37   38   39   40   41   42   43   44   45   46   47
 30,  28,  27,  25,  24,  22,  21,  19,  18,  17,  16,  16,
 
//48
 15
};

//if OCR0A == 255
//6:                                                                        c=15
//5: b=16  a#=17  a=18  g#=19  g=20  f#=21  f=22  e=24  d#=25  d=27  c#=28  c=30
//4: b=32  a#=34  a=36  g#=38  g=40  f#=42  f=45  e=47  d#=50  d=53  c#=56  c=60
//3: b=64  a#=67  a=71  g#=75  g=80  f#=84  f=89  e=95  d#=100 d=107 c#=113 c=120
//2: b=127 a#=134 a=142 g#=150 g=160 f#=169 f=179 e=190 d#=201 d=213 c#=226 c=239


float sinC[41];

byte ti = 0;

int out = 0;

byte selPitch = 0;

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

volatile boolean inLoop = false;

byte sampleRate = 255;

void setup(){
  //TIMER SETUP
  cli();
  
  TCCR1B = TCCR1B & B11111000 | B00000001;
  TCCR2B = TCCR2B & B11111000 | B00000001;
  
  //also check the datasheet!
  TCCR0A = TCCR0A & B11111000 | B00000010;
  TCCR0B = TCCR0B & B11111000 | B00000010;  
  TIMSK0 = TIMSK0 & B11111000 | B00000010; //Call ISR
  
  //set sample rate/frequency
  OCR0A = sampleRate;
  
  sei();

  for(byte i=0; i<128; i+=8){
    sinC[ti] = i;
    ti++;
  }

  for(byte i=0; i<128; i+=8){
    sinC[ti] = i;
    ti++;
  }
  
  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();

  resetWavetable();

  pinMode(2, INPUT);
  digitalWrite(2, HIGH);
  
  //set to CHANGE to patch signal direct thrue..
  attachInterrupt(0, triggerOut, CHANGE);
  
  midi.begin(0);
  //Serial.begin(9600);
}

//From TIMSK2
ISR(TIMER0_COMPA_vect) {
  
  switch (butSel){
    case 0:
      droneI0();
      break; 
    case 1:
      droneI1();
      break; 
    case 2:
      droneI2();
      break; 
    case 3:
      teknoI0();
      break; 
    case 4:
      arpegiatorI1();
      break; 
    case 5:
      drumsI0();
      break; 
    case 6:
      arpegiatorI0();
      break; 
    case 7:
      hnoiseI0();
      break; 
    case 8:
      clicksI0();
      break; 
    case 9:
      feedbackI0();
      break; 
    case 10:
      remoteI0();
      break; 
    case 11:
      remoteI1();
      break; 
    
  }
}

void loop(){
  //check if we are in the loop.. (for interupt, pullup resistors).
  inLoop = true;
  
  butSel = map(pot[5], 0, 1023, 0, 11);
  
  //read potmeters
  readAnalogs();
  
  switch (butSel){
    case 0:
      droneL0();
      break; 
    case 1:
      droneL1();
      break; 
    case 2:
      droneL2();
      break; 
    case 3:
      teknoL0();
      break; 
    case 4:
      arpegiatorL1();
      break; 
    case 5:
      drumsL0();
      break; 
    case 6:
      arpegiatorL0();
      break; 
    case 7:
      hnoiseL0();
      break; 
    case 8:
      clicksL0();
      break; 
    case 9:
      feedbackL0();
      break; 
    case 10:
      remoteL0();
      break; 
    case 11:
      remoteL1();
      break; 
    
  }
}

void droneI0(){
  OCR0A = 180;//sampleRate;
    
  oscA = cup(oscA, max((pot[1] >> 1), 1));
  oscB = cup(oscB, max((pot[2] >> 1), 1));
  oscC = cup(oscC, max((pot[3] >> 1), 1));
  
  //mix oscillators
  out = ((waveTable[oscA]*2)+(waveTable[oscB]*2)+(waveTable[oscC]*2)) >> 2; //was /7
  
  analogWrite(9, out); 
}

void droneL0(){
  
  waveGenartor(31, (pot[4] >> 4));
    
  if(pot[0] && pot[0] < 1022){ 
    if(!oscB2 && !externalTrigger || triggerActive){
      triggerActive = false;
      ta = !ta;
      digitalWrite(11, ta);
      trigger(2);
    }
    oscB2++;
    oscB2 %= pot[0]+1;
  }else if(pot[0]){
    digitalWrite(11, LOW);
  }else{
    digitalWrite(11, HIGH);
  }
    
  analogWrite(10, out);
    
  delayMicroseconds(30); 
}

void droneI1(){ 
  //fixed, if not it will slow down..
  OCR0A = 255;
    
  oscA2 = map(pot[1], 0, 1023, 16, 0);

  //detunes oscillators 
  oscA++;
  oscA += (1023 - pot[4])>>7;

  oscA %= (scale[major[1][oscA2]]);
  oscB = cup(oscB, (scale[major[1][oscA2]])-1);
  oscC = cup(oscC, (scale[major[1][oscA2]])-2);
  
  sendMidi(major[1][oscA2]+36, 100);
  
  //mix oscillators
  out = ((waveTable[oscA])+(waveTable[oscB]*2)+(waveTable[oscC]*2)) >> 3;

  analogWrite(9, out);
}

void droneL1(){
    
  analogWrite(11, ((1023 - pot[0]) >> 2));

  waveGenartor2(oscB2);

  if(pot[3]){ 
    oscB2++;
    oscB2 %= (pot[3]>> 2)+100;
    if(!oscB2 && !externalTrigger || triggerActive){
      triggerActive = false;
      trigger(2);
    }
  }else{
    oscB2 = 150;
  }
    
  delayMicroseconds(12);
}


void droneI2(){ 
  //fixed, if not it will slow down..
  OCR0A = 255;
  
  oscA = cup(oscA, scale[oscA2] >> 1);
  oscB = cup(oscB, scale[oscB2] >> 1);
  oscC = cup(oscC, scale[oscC2] >> 1);
  
  /*
  oscA++;
  oscA %= (scale[oscA2] >> 1);
  oscB++;
  oscB %= (scale[oscB2] >> 1);
  oscC++;
  oscC %= (scale[oscC2] >> 1);
  */
  //mix oscillators
  out = ((waveTable[oscA])+(waveTable[oscB])+(waveTable[oscC])) >> 1;

  analogWrite(9, out);
}

void droneL2(){
  
  oscA2 = map(pot[1], 0, 1023, 48, 0);
  oscB2 = map(pot[2], 0, 1023, 48, 0);
  oscC2 = map(pot[3], 0, 1023, 48, 0);
  
  sendMidi(oscA2+36, 100);
    
  analogWrite(11, ((1023 - pot[0]) >> 2));

  waveGenartor2(max(pot[4] >> 1, 8));
    
  delayMicroseconds(12);
}


void teknoI0(){
  //techno
  OCR0A = 255;
  
  oscB = cup(oscB, (pot[4]<<1)+500);
  
  if(!oscB && !externalTrigger || triggerActive){
    triggerActive = false;
    trigger(2);
    
    if(externalTrigger){
      oscD = ((1023 - pot[4]) >> 8)+1;
    }else{
      oscD = 4;
    }
    
    ta = true;
  }
  
  oscD2 = cup(oscD2, 3);
  if(!oscD2){
    sendMidi(oscA2+36, (byte)tvol);
    //legato
    if(tp < (scale[oscA2])){
      tp++;
    }else if(tp > (scale[oscA2])){
      tp--; 
    }
  }
  
  //oscillators timer
  oscA = cup(oscA, (tp >> 1));
  
  analogWrite(11, constrain(((tp-44) << 1), 0, 255));
  
  //decay
  tvol-= 0.05;
  tvol = max(tvol, 0);
  
  //saw to square so volume stays sort of the same..
  out = constrain((oscA<<1), 0, (byte)tvol);
  
  analogWrite(9, out);

}

void teknoL0(){ 
  //nothing needed here (-:
  
  if(ta){
    ta = false;
    
    //reset to start volume.
    tvol = 70;
    
    //selectpotmeter for next pitch
    selPitch++;
    selPitch %= oscD;
    oscA2 = map(pot[selPitch], 0, 1023, 48, 0);
  }
}

void hnoiseI0(){
  OCR0A = (pot[3] >> 4)+191;
  
  //oscillators
  oscA = cup(oscA, max(pot[1] >> 1, 3));
  oscB = cup(oscA, max((pot[1] >> 1)+1, 4));

  out = (((waveTable[oscA])+(waveTable[oscB])) >> 1);
  
  //amplitude modulation trick... a bit noisy but it works..
  if(pot[2]){
    oscA2 = cup(oscA2, 255);
    if(!oscA2){ 
      ta = !ta;
    }
    oscB2 = cup(oscB2, (((pot[2]) >> 2) + 255));
    if(!oscB2){ 
      ta = !ta;
    }
  }else{
    byte i = 0;
    ta = true;
  }

  if(ta){
    analogWrite(9, out);
  }
}

void hnoiseL0(){

  oscC++;
  oscC %= 64;
  if(!oscC){
    
    sinAc++;
    sinAc %= max(pot[1] >> 1, 2);
    
    if(tb){
      waveTable[sinAc]  = random(70);
    }else{
      waveTable[sinAc]  = 40;
    }
      
  }
  
  oscD++;
  oscD %= pot[4]+2;
  if(!oscD){
    tb = !tb;
  }

  analogWrite(11, (pot[0] >> 2));
  
  delayMicroseconds(100);
}

void drumsI0(){
   
  OCR0A = 255;//(pot[3] >> 4)+191;
  
  //kick pitch down speed
  kick += 0.02; 
  kick = min(kick, 255);

  //pitch
  oscA++;
  oscA %= (byte) (kick); //convert from float to byte
  oscB++;
  oscB %= (pot[3] >> 3) + 20; //convert from float to byte

  oscD++;
  oscD %= (pot[4])+500;
  
  if(!oscD && !externalTrigger || triggerActive){
    triggerActive = false;
    
    trigger(2);
    
    BA = pot[1] >> 2;
    BB = pot[2] >> 2;
    
    tvol = 0;
    tvol2 = 0;
    
    kick = (pot[0] >> 3) + 20;
    
    oscA2++;
    oscA2 %= 8;
  }
  
  //decay
  tvol += 0.01;
  tvol = min(tvol, 8);
  
  tvol2 += 0.001;
  tvol2 = min(tvol2, 8);
  
  //mix all together.
  if(!bitRead(BA, oscA2) && !bitRead(BB, oscA2)){
    out = (((waveTable[oscB] >> (byte)tvol)+(waveTable[oscA+255] >> (byte)tvol2)) >> 2);
    digitalWrite(11, LOW);
  }else if(!bitRead(BA, oscA2)){
    out = ((waveTable[oscA+255] >> (byte)tvol2) >> 1);
    digitalWrite(11, LOW);
  }else if(!bitRead(BB, oscA2)){
    out = ((waveTable[oscB] >> (byte)tvol) >> 1);
    digitalWrite(11, HIGH);
  }

  analogWrite(9, out);
}

void drumsL0(){
  //bas kick and hh noise..

  oscC++;
  oscC %= 16;//pot[4]+2;
  if(!oscC){
    sinAc++;
    sinAc %= 255;
    
    decayA++;
    decayA %= 32;
    
    waveTable[sinAc] = random(50, 150);
    waveTable[sinAc+255] = 255*sinA[decayA];
  }
  delayMicroseconds(10);
}

void arpegiatorI0(){
  //2 voice arpegiator
  OCR0A = 255;
  
  oscA = cup(oscA, (scale[major[0][oscL[oscB2]]]) << ta);
  oscB = cup(oscB, (scale[major[0][oscN[oscC2]]]) << ta);
  
  //saw to square so volume stays sort of the same..
  out = constrain((oscA<<1), 0, (byte)tvol);
  
  //mix
  out = min((waveTable[oscA]+waveTable[oscB]) >> 2, 255);
  
  if(tb){
    //atack
    tvol+= 0.05;
    if(tvol > 1){
      tb = 0;   
    }
  }else{
    //decay
    tvol-= 0.0005;
    tvol = max(tvol, 0);
  }
  
  //prevent clipping when switching between instruments..
  tvol = min(tvol, 1.06);
  
  out *= tvol; 

  analogWrite(9, out);
}

void arpegiatorL0(){
  
  oscD2++;
  oscD2 %= pot[4]+200;
  if(!oscD2 && !externalTrigger || triggerActive){
    triggerActive = false;
    
    //if there is externa trigger signals.. 
    if(externalTrigger){
      ta = (pot[4]) >> 8;
    }else{
      ta = 1;
    }

    for(byte i=0; i<8; i++){
      //multiply and make into byte... melody generation..
      oscL[i] = map(((byte) (pot[2]*(i+1)) >> 4), 0, 64, 24, 0);
      //oscN[i] = map(((oscN[i]+((byte) (pot[3]*(i+1)))) >> 2), 0, 255, 24, 0);
      oscN[i] = map(((byte) (pot[3]*(i+1)) >> 4), 0, 64, 24, 0);
    }
     
    //select pitch
    oscD++;
    oscD %= (pot[0] >> 9)+1;
    oscC++;
    oscC %= (pot[1] >> 9)+1;
    
    if(!oscD){
      oscB2++;
      oscB2 %= ((pot[0] >> 6)%8)+1;//map(pot[1], 0, 1023, 1, 8);
    }
    
    if(!oscC){
      oscC2++;
      oscC2 %= ((pot[1] >> 6)%8)+1;//map(pot[1], 0, 1023, 1, 8);
    }
    
    digitalWrite(11, HIGH);
    
    //reset for atack to prevent click
    tb = 1;
    
    trigger(2);
  }
  
  oscC++;
  oscC %= 16;
  if(!oscC){
    waveGenartor4(31, ((pot[1] >> 4)+24));
    //Serial.println(((pot[1] >> 4)+32), DEC);
  }
  
  delayMicroseconds(8);
}

void clicksI0(){
  OCR0A = 255;
  
  oscD = cup(oscD, (pot[4] << 1)+500);
  if(!oscD && !externalTrigger || triggerActive){
    triggerActive = false;
  
    for(byte i=0; i<8; i++){
      //multiply and make into byte... melody generation..
      //oscL[i] = map(((byte) (pot[2]*(i+1)) >> 2), 0, 64, 24, 0);
          
      //oscN[i] = map(((byte) (pot[3]*(i+1)) >> 2), 0, 64, 24, 0);
      oscL[i] = max(((oscL[i]+((byte) (pot[2]*(i+1)))) >> 1), 1);
      oscN[i] = max(((oscN[i]+((byte) (pot[3]*(i+1)))) >> 1), 1);
    }

    //select pitch
    oscB2 = cup(oscB2, pot[1] >> 7);
    oscC2 = cup(oscC2, (1023 - pot[1]) >> 7);

    tvol = 0;
    
    trigger(2);
  }

  //pitch
  oscA = cup(oscA, (oscL[oscB2] >> ((1023 - pot[0]) >> 7))+2);
  oscB = cup(oscB, (oscN[oscC2] >> ((1023 - pot[0]) >> 7))+2);

  if(!oscA || !oscB){
    tc = !tc;
    if(tc){
      out = (50) >> (byte)tvol;
    }else{
      out = pot[4] >> 6;
    }
  }
  
  //must be here to have less hickups
  analogWrite(11, oscL[oscB2]);
    
  //tvol += (((pot[0])+1)*0.00002);  //0.1; //fix hier...
  tvol += ((oscN[oscC2]+40)*0.00006); 
  tvol = min(tvol, 8);
  
  analogWrite(9, out);
}

void clicksL0(){
  oscC++;
  oscC %= 16;
  if(!oscC){
    waveGenartor4(31, 64);
  }
}

void feedbackI0(){
  //fixed, if not it will slow down..
  OCR0A = 255;

  //wavtable length
  oscA = cup(oscA, (pot[1] >> 1)+1);
  //decay
  waveTable[oscA] -= (pot[2] >> 4)+32;
  
  //tone
  oscB = cup(oscB, (pot[3]>>4)+1);
  if(!oscB){
    oscB2 = cup(oscB2, (pot[3]%32)+1);
  }
  waveTable[oscA] += 110*sinA[oscB2];
  
  //amplitude modulation
  oscC = cup(oscC, (pot[4])+8);
  if(!oscC && !externalTrigger || triggerActive){
    triggerActive = false;
    
    oscC2 = cup(oscC2, 32);
    
    //make sure the trigger is not slowing down to much..
    trigger(32);
  }
  if(pot[4]){ //disable if 0
    waveTable[oscA] *= sinA[oscC2];
  }else{
    waveTable[oscA] *= 0.8;
  }
  
  out = waveTable[oscA]>>2;
  
  analogWrite(9, out);
}

void feedbackL0(){
  
  oscD = cup(oscD, (pot[0]>>1)+8);
  if(!oscD){
    oscD2 = cup(oscD2, 32);
    if(pot[0] < 1023 && pot[0] > 0){
      analogWrite(11, 255*sinA[oscD2]);
    }else if(pot[0] < 1){
      digitalWrite(11, HIGH);
    }else if(pot[0] > 1022){
      digitalWrite(11, LOW);
    }
  }
  delayMicroseconds(4);
}

void remoteI0(){
  //fixed, if not it will slow down..
  OCR0A = 255;

  //oscA2;
  oscA2 = cup(oscA2 ,(pot[4]>>1)+1);
  
  //tone decay.
  tvol += ((pot[1]+200)*0.000005);
  tvol = min(tvol, 8);
  
  if(triggerActive){
    triggerActive = false;
    
    //rest volume
    tvol = 0;
  }
  
  oscA++;
  oscA %= (pot[2]>>3)+2;
  if(oscA){
    ta = !ta;
    if(ta){
      out = (80 >> (byte)tvol);
    }else{
      out = 0;
    }
  }
  
  tvol2 = ((1050-pot[3])*0.0008);
  
  out += waveTable[oscA2]*tvol2;
  
  waveTable[oscA2] = out;
  
  analogWrite(9, (byte)(out*0.3));
}
 
void remoteL0(){
  
  analogWrite(11, ((1023-pot[0])>>2));
  
  delayMicroseconds(20);
}

void arpegiatorI1(){

  OCR0A = 255;
  
  oscB = cup(oscB, (pot[4]<<1)+500);
  
  if(!oscB && !externalTrigger || triggerActive){
    triggerActive = false;
    trigger(2);
    
    tb = true;
    
    //selectpotmeter for next pitch
    oscC = cup(oscC, map(pot[0], 0, 1023, 8, 1));
    
    oscD = cup(oscD, map(pot[2], 0, 1023, 8, 1));
    
    //reset to start volume.
    tvol = oscN[oscD]<<2;
    
  }
  
  oscD2 = cup(oscD2, 3);
  if(!oscD2){
    sendMidi(major[1][oscL[oscC]]+36, (byte)tvol);
    //legato
    if(tp < (scale[major[1][oscL[oscC]]])){
      tp++;
    }else if(tp > (scale[major[1][oscL[oscC]]])){
      tp--; 
    }
  }
  
  //oscillators timer
  oscA = cup(oscA, (tp >> 1));
  
  //filter
  analogWrite(11, constrain(((tp-44) << 1), 0, 255));
  
  //decay
  tvol-= tvol2;
  tvol = max(tvol, 0);
  
  //saw to square so volume stays sort of the same..
  out = constrain((oscA<<1), 0, (byte)tvol);
  
  analogWrite(9, out);

}

void arpegiatorL1(){ 
  
  if(tb){
    tb = false;
    for(byte i=0; i<8; i++){
      //convert to range 0 to 24.
      oscL[i] = (((1023-pot[1])*0.0244)*(i+1));
      oscL[i] %= 25;
      oscN[i] = (((1023-pot[3])*0.0244)*(i+1));
      oscN[i] %= 25;
    }
  }
  
  if(externalTrigger){
    tvol2 = pot[4]*0.00015;
  }else{
    tvol2 = 0.05;
  }
  
  delayMicroseconds(50);
  
}

void remoteI1(){
  //fixed, if not it will slow down..
  OCR0A = 255;

  //oscillators timer
  oscA = cup(oscA, tp);
  
  //volume envelope
  oscA2 = cup(oscA2, 255);
  if(!oscA2){
    if(!ta){
      cvol++;
      cvol = min(cvol, 9);
      //analogWrite(11, (cvol << 3));
    }
  }
  
  analogWrite(9, waveTable[oscA] >> cvol);
}
 
void remoteL1(){
  unsigned int code = 0x00;
 
  //block until start pulse
  if(digitalRead(IR_PIN) == LOW){
    
    //http://www.gumbolabs.org/2010/05/29/radioshack-infrared-receiver-arduino/comment-page-1/
    while(pulseIn(IR_PIN, LOW) < START_BIT) {}
    
    //read in next 12 bits shifting and masking them into the unsigned int 'code'
    //remeber boolean is basically 0 [false] or 1 [true]
    for(byte i = 0; i < BITS_PER_MESSAGE; i++) {
      code |= (pulseIn(IR_PIN, LOW) > BIT_THRESH) << i;  
    }
  
    if(code < 138 && code > 127){
      oscL[1] = constrain(oscL[1], 96, 128);
      tp = scale[code - oscL[1]];
      midi.sendNoteOn(midichannel, ((code - oscL[1])+36), 100); //midi
      //sendMidi((code - oscL[1])+36, 100);                     //midi..
      oscD = code;
      cvol = 2;
    }else if(code == 144){       //(PROG) +
      oscL[0] += 8;
      oscL[0] = min(255, oscL[0]);
      analogWrite(11, oscL[0]);
    }else if(code == 145){       //(PROG) -
      oscL[0] -= 8;
      oscL[0] = max(0, oscL[0]);
      analogWrite(11, oscL[0]);
    }else if(code == 147){       //up (VOL)
      oscL[1]++;
      oscL[1] = min(128, oscL[1]);
      tp = scale[oscD - oscL[1]];
      midi.sendNoteOn(midichannel, ((oscD - oscL[1])+36), 100); //midi
      cvol = 2;
    }else if(code == 146){       //down (VOL)
      oscL[1]--;
      oscL[1] = max(96, oscL[1]);
      tp = scale[oscD - oscL[1]];//oscD holds last note..
      midi.sendNoteOn(midichannel, ((oscD - oscL[1])+36), 100); //midi
      cvol = 2;
    }else if(code == 148){       //hold (MUTE)
      ta = !ta;
    }else if(code == 149){       //no sound(STANDBY)
      cvol = 8;
    }else{
      oscB = cup(oscB, tp);
      if(bitRead(code, (oscB % 8))){
        waveTable[oscB] = code % 200;
      }else{
        waveTable[oscB] = 20;
      }
    }
  }
}

/////////
//other//
/////////
void waveGenartor(int inpA, int inpD){

  octaver = cup(octaver, inpD+16);
  
  if(!octaver){
    sinAc2 = cup(sinAc2, 32);
  }
  
  sinAc = cup(sinAc, 512);
  
  decayA = cup(decayA, (inpA >> 5)+1);
  
  waveTable[sinAc] = (255*sinA[decayA])*sinA[sinAc2];
}

//nice smooth sound!! with droneL0
void waveGenartor4(int inpA, int inpD){

  octaver = cup(octaver, inpD);
  
  if(!octaver){
    sinAc2 = cup(sinAc2, 32);
  }
  
  sinAc = cup(sinAc, inpD>>4); //stange but it sounds nice..
  
  decayA = cup(decayA, (inpA >> 5)+1);
  
  waveTable[sinAc] = (255*sinA[decayA])*sinA[sinAc2];
}

void waveGenartor2(int inpA){
  
  sinAc = cup(sinAc, 512);
  
  decayA = cup(decayA, 32);
  
  waveTable[sinAc] = constrain((inpA*sinA[decayA]), 2, 128);
}

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

  potc = cup(potc, 6);

  if(reverse){
    pot[potc] = analogRead(potc);
  }else{
    pot[potc] = 1023 - analogRead(potc);
  }
}

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

  if(!externalTrigger){
    tCount = cup(tCount, inp);
    
    digitalWrite(3, tCount);
    digitalWrite(4, tCount);
  }
}

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 triggerOut(){
  volatile static boolean triggerSignal = 1;
  
  if(triggerSignal){
    triggerNormal();
  }
    
  triggerSignal = !triggerSignal;
    
  digitalWrite(3, triggerSignal);
  digitalWrite(4, triggerSignal);
  
}

void resetWavetable(){
  for(int i=0; i<512; i++){
    waveTable[i] = 0;
  }
}

void sendMidi(byte noteIn, byte volume){
  static int noteHolder;
  if(noteIn != noteHolder){
    midi.sendNoteOff(midichannel, noteHolder, 0);
    noteHolder = noteIn;
    midi.sendNoteOn(midichannel, noteIn, volume);
  }
}

inline static int cup(int a, int b){
  a++;
  if(a >= b){
    a = 0;
  }
  return a;
}