//HSS3S02V10 for use with HSS3g hardware. //gijs gieskes 2009/2011, http://gieskes.nl //credits: http://gieskes.nl/instruments/files/hard-soft-synth-3/hss3-credits.html //upload using arduino version 21 only volatile boolean triggerSignal = false; volatile boolean audioInActive = true; volatile byte butSelP = 255; volatile unsigned int butSelVolDel = 0; //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) //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; byte seqCount = 0; //pot array int pot[8] = {0,0,0,0,0,0,0,0}; int potp[8] = {0,0,0,0,0,0,0,0}; byte mcounter = 0; //trigger vars volatile boolean externalTrigger = false; volatile boolean triggerActive = false; volatile boolean audioTrigger = false; //midi library: //http://timothytwillman.com/itp_blog/?page_id=240 #include "Midi.h" //midi sequencing vars byte midiCounter; boolean midiPlay = true; boolean midibool = false; boolean midibools[6] = {0, 0, 0, 0, 0, 0}; class MyMidi : public Midi { public: // Need this to compile; it just hands things off to the Midi class. MyMidi(HardwareSerial &s) : Midi(s) {} void handleControlChange(unsigned int channel, unsigned int controller, unsigned int value) { // if(controller == 20 || 21 || 22 || 23 || 24 || 25 || 26){ midibool = true; } switch(controller){ case 20: midibools[0] = true; pot[0] = 1023-(value<<3); break; case 21: midibools[1] = true; pot[1] = 1023-(value<<3); break; case 22: midibools[2] = true; pot[2] = 1023-(value<<3); break; case 23: midibools[3] = true; pot[3] = 1023-(value<<3); break; case 24: midibools[4] = true; pot[4] = 1023-(value<<3); break; case 25: midibools[5] = true; pot[5] = 1023-(value<<3); break; case 26: pot[6] = 1023-(value<<3); break; //pot[(controller-1)%7] = 1023-(value<<3); } } void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity) { switch(note){ case 0: midiPlay = !midiPlay; break; case 1: triggerNormal(); break; } } void handleSync(){ if(midiPlay){ if(!midiCounter){ triggerActive = true; } midiCounter = cupb(midiCounter, 6); } } void handleStop(){ midiPlay = false; } void handleStart(){ seqCount = 0; //reset sequencer so it starts at 0 oscD = 0; //reset sequencer so it starts at 0 midiCounter = 0; midiPlay = true; externalTrigger = true; } void handleContinue(){ midiCounter = 0; midiPlay = true; } }; MyMidi midi(Serial); byte midichannel = 1; byte scaleSelect = 1; byte SSOct = 0; int avLed = 0; int octaver2 = 0; boolean typeSwitch = 0; //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; byte tvolb1 = 0; byte tvolb2 = 0; int BA = 0; int BB = 0; int tp = 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}; 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; 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; pinMode(8, INPUT); digitalWrite(8, HIGH); delay(100); typeSwitch = !digitalRead(8); if(typeSwitch){ setupPWM(3); for(byte i=0; i<128; i+=8){ sinC[ti] = i; ti++; } for(byte i=0; i<128; i+=8){ sinC[ti] = i; ti++; } resetWavetable(); }else{ 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++; } waveTable[0] = 0xaa; waveTable[1] = 0x66; setupPWM(0); for(byte i=6; i<255; i++){ waveGenartor(pot[3], 0); } } pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(11, OUTPUT); pinMode(12, INPUT); digitalWrite(12, HIGH); pinMode(13, OUTPUT); pinMode(3, OUTPUT); readAnalogs(); resetWavetable(); pinMode(2, INPUT); pinMode(3, INPUT); //digitalWrite(2, HIGH); //set to CHANGE to patch signal direct thrue.. //attachInterrupt(0, triggerOut, CHANGE); //attachInterrupt(1, triggerOut, CHANGE); attachInterrupt(0, triggerNormal, FALLING); attachInterrupt(1, triggerOutB, FALLING); midi.begin(1); } ISR(TIMER0_COMPA_vect) { if(typeSwitch){ droneI3(); }else{ //reset all OSCs on patch change, to prevent overflows.. if(butSelP != butSel){ butSelP = butSel; oscA = 0; oscB = 0; oscC = 0; oscD = 0; oscA2 = 0; oscB2 = 0; oscC2 = 0; oscD2 = 0; seqCount = 0; butSelVolDel = 16320; } if(midiPlay){ 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; midi.poll(); audioInOnOff(); //read potmeters readAnalogs(); if(typeSwitch){ if(!digitalRead(8)){ scaleSelect++; if(scaleSelect > 2){ scaleSelect = 0; SSOct++; if(SSOct > 1){ SSOct = 0; } } while(!digitalRead(8)){} } butSel = pot[5] >> 8; droneL3(); }else{ //start stop controls.. if(!digitalRead(8)){ while(!digitalRead(8)){delay(1);} if(midiPlay){ midi.sendStart(); }else{ midi.sendStop(); } midiPlay = !midiPlay; seqCount = 0; //reset sequencer so it starts at 0 oscD = 0; //reset sequencer so it starts at 0 } butSel = map(pot[5], 0, 1023, 0, 11); 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; } } } inline 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 audioOut(out); //analogWrite(10, out << 2); } inline void droneL0(){ setupPWM(3); waveGenartor(31, (pot[4] >> 4)); if(pot[0] && pot[0] < 1022){ if(!oscB2 && !externalTrigger || triggerActive){ triggerActive = false; ta = !ta; digitalWrite(11, ta); IRsync(); } oscB2++; oscB2 %= pot[0]+1; }else if(pot[0]){ digitalWrite(11, LOW); }else{ digitalWrite(11, HIGH); } analogWrite(10, out); delayMicroseconds((pot[4] >> 2)+10); } inline 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, 1); //mix oscillators out = ((waveTable[oscA])+(waveTable[oscB]*2)+(waveTable[oscC]*2)) >> 3; audioOut(out); } inline void droneL1(){ setupPWM(3); analogWrite(11, ((1023 - pot[0]) >> 2)); waveGenartor2(oscB2); if(pot[3]){ oscB2++; oscB2 %= (pot[3]>> 2)+100; if(!oscB2 && !externalTrigger || triggerActive){ triggerActive = false; IRsync(); } }else{ oscB2 = 150; } delayMicroseconds(12); } inline 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); //mix oscillators out = ((waveTable[oscA])+(waveTable[oscB])+(waveTable[oscC])) >> 2; audioOut(out); } inline void droneL2(){ setupPWM(3); 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, 1); analogWrite(11, ((1023 - pot[0]) >> 2)); waveGenartor2(max(pot[4] >> 1, 8)); delayMicroseconds(12); } inline void teknoI0(){ //techno OCR0A = 255; oscB = cup(oscB, (pot[4]<<1)+500); if(!oscB && !externalTrigger || triggerActive){ triggerActive = false; IRsync(); if(externalTrigger){ oscD = ((1023 - pot[4]) >> 8)+1; }else{ oscD = 4; } ta = true; } oscD2 = cup(oscD2, 3); if(!oscD2){ //sendMidi(oscA2+36, (byte)tvol, 1); //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 tvolb1++; if(tvolb1 > 20 && tvolb2 > 0){ tvolb1 = 0; tvolb2--; } //saw to square so volume stays sort of the same.. out = constrain((oscA<<1), 0, tvolb2); audioOut(out); } inline void teknoL0(){ //nothing needed here (-: setupPWM(3); analogWrite(11, constrain(((tp-44) << 1), 0, 255)); if(ta){ ta = false; //reset to start volume. //tvol = 70; tvolb1 = 0; tvolb2 = 70; //selectpotmeter for next pitch seqCount++; seqCount %= oscD; oscA2 = map(pot[seqCount], 0, 1023, 48, 0); } } inline 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])) >> 2); //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){ audioOut(out); } } inline void hnoiseL0(){ setupPWM(3); 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); } inline void drumsI0(){ //OCR0A = 255;//(pot[3] >> 4)+191; //kick pitch down speed kick += 0.03; kick = min(kick, 500); //pitch oscA = cup(oscA, (byte) (kick)); //convert from float to byte oscB = cup(oscB, (pot[3] >> 3) + 20); //convert from float to byte oscD = cup(oscD, (pot[4])+500); if(!oscD && !externalTrigger || triggerActive){ triggerActive = false; IRsync(); BA = pot[1] >> 2; BB = pot[2] >> 2; tvol = 0; tvol2 = 0; kick = (pot[0] >> 3) + 20; seqCount = cupb(seqCount, 8); } //decay tvol += 0.005; tvol = min(tvol, 8); tvol2 += 0.001; tvol2 = min(tvol2, 8); //mix all together. if(!bitRead(BA, seqCount) && !bitRead(BB, seqCount)){ out = (((waveTable[oscB] >> (byte)tvol)+(waveTable[oscA+255] >> (byte)tvol2)) >> 2); digitalWrite(11, LOW); }else if(!bitRead(BA, seqCount)){ out = ((waveTable[oscA+255] >> (byte)tvol2) >> 1); digitalWrite(11, LOW); }else if(!bitRead(BB, seqCount)){ out = ((waveTable[oscB] >> (byte)tvol) >> 1); digitalWrite(11, HIGH); } audioOut2(); } inline void drumsL0(){ //bas kick and hh noise.. OCR0A = 255; setupPWM(3); oscC = cup(oscC, 16);//pot[4]+2; if(!oscC){ sinAc = cup(sinAc, 255); decayA = cup(decayA, 32); waveTable[sinAc] = random(50, 150); waveTable[sinAc+255] = 255*sinA[decayA]; } delayMicroseconds(10); } inline void arpegiatorI0(){ //2 voice arpegiator OCR0A = 255; oscA = cup(oscA, (scale[major[0][oscL[oscB2]]]) << ta); oscB = cup(oscB, (scale[major[0][oscN[seqCount]]]) << 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; audioOut(out); } inline void arpegiatorL0(){ setupPWM(3); 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; oscC2++; oscC2 %= (pot[1] >> 9)+1; if(!oscD){ oscB2++; oscB2 %= ((pot[0] >> 6)%8)+1;//map(pot[1], 0, 1023, 1, 8); } if(!oscC2){ seqCount++; seqCount %= ((pot[1] >> 6)%8)+1;//map(pot[1], 0, 1023, 1, 8); } digitalWrite(11, HIGH); //reset for atack to prevent click tb = 1; IRsync(); } oscC++; oscC %= 16; if(!oscC){ waveGenartor4(31, ((pot[1] >> 4)+24)); //Serial.println(((pot[1] >> 4)+32), DEC); } delayMicroseconds(8); } inline 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); seqCount = cup(seqCount, (1023 - pot[1]) >> 7); tvolb1 = 0; IRsync(); } //pitch oscA = cup(oscA, (oscL[oscB2] >> ((1023 - pot[0]) >> 7))+2); oscB = cup(oscB, (oscN[seqCount] >> ((1023 - pot[0]) >> 7))+2); if(!oscA || !oscB){ tc = !tc; if(tc){ out = (50) >> tvolb1; }else{ out = pot[4] >> 6; } } //must be here to have less hickups analogWrite(11, oscL[oscB2]); tvolb2++; if(tvolb2 > 100 && tvolb1 < 9){ tvolb2 = 0; tvolb1++; } ////tvol += (((pot[0])+1)*0.00002); //0.1; //fix hier... //tvolb1 += ((oscN[seqCount]+40)*0.00006); //tvolb1 = min(tvolb1, 8); audioOut(out); } inline void clicksL0(){ setupPWM(3); oscC++; oscC %= 16; if(!oscC){ waveGenartor4(31, 64); } } inline 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; audioOut(out); } inline void feedbackL0(){ setupPWM(3); 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); } inline 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; audioOut((byte)(out*0.3)); } inline void remoteL0(){ setupPWM(3); analogWrite(11, ((1023-pot[0])>>2)); delayMicroseconds(20); } inline void arpegiatorI1(){ OCR0A = 255; oscB = cup(oscB, (pot[4]<<1)+500); if(!oscB && !externalTrigger || triggerActive){ triggerActive = false; IRsync(); tb = true; //selectpotmeter for next pitch seqCount = cup(seqCount, map(pot[0], 0, 1023, 8, 1)); oscD = cup(oscD, map(pot[2], 0, 1023, 8, 1)); //reset to start volume. tvolb2 = oscN[oscD]<<2; } oscD2 = cup(oscD2, 3); if(!oscD2){ //sendMidi(major[1][oscL[seqCount]]+36, (byte)tvol, 1); //legato if(tp < (scale[major[1][oscL[seqCount]]])){ tp++; }else if(tp > (scale[major[1][oscL[seqCount]]])){ tp--; } } //oscillators timer oscA = cup(oscA, (tp >> 1)); //decay tvolb1++; if(tvolb1 > 20 && tvolb2 > 0){ tvolb1 = 0; tvolb2--; } //saw to square so volume stays sort of the same.. out = constrain((oscA<<1), 0, tvolb2); audioOut(out); } inline void arpegiatorL1(){ setupPWM(3); //filter analogWrite(11, constrain(((tp-44) << 1), 0, 255)); 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){ //tvolb2 = pot[4]*0.00015; }else{ //tvolb2 = 0.05; } delayMicroseconds(50); } inline 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)); } } audioOut(waveTable[oscA] >> cvol); } inline void remoteL1(){ setupPWM(3); 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, 1); //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; } } } } //needs more works.... inline void droneI3(){ oscA = cup(oscA, scale[major[scaleSelect][oscA2]] << SSOct); oscB = cup(oscB, scale[major[scaleSelect][oscB2]] << SSOct); oscC = cup(oscC, scale[major[scaleSelect][oscC2]] << SSOct); out = ((waveTable[oscA])+(waveTable[oscB])+(waveTable[oscC])) >> 2; //was /7 audioOut2(); } inline void droneL3(){ if(prevSynth != butSel){ prevSynth = butSel; tc = !tc; digitalWrite(4, tc); setupPWM(1); } if(out < avLed){ avLed--; analogWrite(11, max((avLed-22), 0)); } if(out > avLed){ avLed++; avLed = min(avLed, 255); } oscA2 = (1023-pot[1]) >> 6; oscB2 = (1023-pot[2]) >> 6; oscC2 = (1023-pot[3]) >> 6; //sendMidi(major[scaleSelect][oscA2]+35, 100, 1); //sendMidi(major[scaleSelect][oscB2]+35, 100, 2); //sendMidi(major[scaleSelect][oscC2]+35, 100, 3); if(butSel == 0){ //start wave generator octaver = cup(octaver, pot[4] >> 7); if(!octaver){ sinAc2 += (4 << SSOct); if(sinAc2 > 31){ sinAc2 = 0; } } sinAc = cup(sinAc, 255 << SSOct); octaver2 = cup(octaver2, pot[0] >> 7); if(!octaver2){ decayA = cup(decayA, 31); } waveTable[sinAc] = (220*sinA[decayA])*sinA[sinAc2]; }else if(butSel == 1){ //start wave generator sinAc2 += ((1024-pot[0]) >> 6); if(sinAc2 > 128){ sinAc2 = 0; } decayA = cup(decayA, pot[4] >> 3); sinAc = cup(sinAc, 255 << SSOct); waveTable[sinAc] = (min(decayA+sinAc2, 220)); //end wave generator }else if(butSel == 2){ //start wave generator octaver = cup(octaver, pot[4] >> 2); if(!octaver){ ta = !ta; if(ta){ sinAc2 = 70; }else{ sinAc2 = 0; } } sinAc = cup(sinAc, 255 << SSOct); octaver2 = cup(octaver2, (pot[0] >> 2)); if(!octaver2){ tb = !tb; if(tb){ decayA = 70; }else{ decayA = 0; } } waveTable[sinAc] = sinAc2+decayA; //end wave generator }else if(butSel == 3){ //start wave generator sinAc = cup(sinAc, 256 << SSOct); waveTable[sinAc] = random(220); //end wave generator } } ///////// //other// ///////// //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(); }else if(inp == 3){ cli(); //also check the datasheet! TCCR0A = TCCR0A & B11111000 | B00000010; TCCR0B = TCCR0B & B11111000 | B00000010; TIMSK0 = TIMSK0 & B11111000 | B00000010; //Call ISR //set sample rate/frequency OCR0A = 255; sei(); } } } 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 inline void readAnalogs(){ static byte potc = 0; potc = cup(potc, 6); int av = 1023 - analogRead(potc); if(midibools[potc] == false){ //pot[potc] = analogRead(potc); pot[potc] = av; } } //send trigger void trigger(byte inp){ volatile static int tCount = 0; if(!externalTrigger){ tCount = cup(tCount, inp); IRsync(); } } 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 triggerOutB(){ if(audioInActive){ audioTrigger = true; //triggerNormal(); } } void audioInOnOff(){ static boolean butread; if(!bitRead(PINB, 4)){ if(butread){ audioInActive = !audioInActive; butread = false; } }else{ butread = true; } } void triggerOut(){ if(triggerSignal){ triggerNormal(); } triggerSignal = !triggerSignal; IRsync(); } 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); } } */ void sendMidi(byte noteIn, byte volume, byte channel){ static byte noteHolder[3]; if(noteIn != noteHolder[channel]){ midi.sendNoteOff(channel, noteHolder[channel], 0); noteHolder[channel] = noteIn; midi.sendNoteOn(channel, noteIn, volume); } } void sendMidiNoOne(byte noteIn, byte volume){ static int 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; } inline static byte cupb(byte a, byte b){ a++; if(a >= b){ a = 0; } return a; } inline byte audioOut(byte signal){ //Serial.println(signal>>(pot[6]>>7), DEC); //delay(50); //analogWrite(9, constrain(signal>>(pot[6]>>7), 4, 172)); //analogWrite(9, signal>>(pot[6]>>7)); if(butSelVolDel > 1){ butSelVolDel--; analogWrite(9, constrain(signal>>(pot[6]>>7), 10, 170)); }else{ analogWrite(9, min(signal>>(pot[6]>>7), 220)); } analogWrite(10, min(signal << 2, 255)); } inline void audioOut2(){ //Serial.println(signal>>(pot[6]>>7), DEC); //delay(50); //analogWrite(9, constrain(signal>>(pot[6]>>7), 4, 172)); if(butSelVolDel > 1){ butSelVolDel--; analogWrite(9, constrain(out>>(pot[6]>>7), 10, 170)); }else{ analogWrite(9, min(out>>(pot[6]>>7), 220)); } analogWrite(10, min(out << 2, 255)); } void IRsync(){ static boolean irflip; irflip = !irflip; //digitalWrite(13, irflip); //digitalWrite(4, irflip); bitWrite(PORTB, 5, irflip); bitWrite(PORTD, 4, irflip); }