// HSS2020 // Gijs Gieskes, start project == Januari 2008. // March till August 2020 update code. // http://gieskes.nl #include "TimerOne.h" #include //buttons const byte BUTS = 1;//was 1 const byte BUTD = 7;//was 7 const byte BUTA = 5; const byte BUT3 = 3; const byte BUT4 = 4; const byte BUT5 = 5; const byte BUT6 = 6; const byte ARRAYLENGTH = 64; //sequencers unsigned long prevMillis = 0; byte seqArrayA[3][ARRAYLENGTH] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; int seqArrayAnalog[3][ARRAYLENGTH] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; //interupt vars volatile byte seqCounter = 0; volatile byte seqCounterStrict = 0; volatile byte seqLength[3] = {31,31,31}; volatile boolean ledPin = HIGH; volatile boolean newAnalogRecording = false; volatile byte seqCounterNew = false; byte seqBankNew = false; byte seqBank = 0; byte nextSeqBank = 0; int seqSpeed = 600; boolean seqMode = false; boolean seqStart = true; boolean triggeractive = false; //manual play or sequencer byte pMode = 1; //analog in pins byte inputPinA[] = {7,1,0,2}; //analog Read bool boolean anaRTF = false; int analogValue1 = 0; int delV = 0; //sample rate storage byte delVDD = 0; //delay X times int delV2 = 0; //sample rate storage //samples vars int amArr = 350; //sample length byte arrA[351]; //sample store array const int amArrPerm = 350; //sample length permanent int amArrCapptureTeller = 0; //teller voor arrA Functie, opslag byte tcap = 31; //effects //byte waves[351]; //Ring Modulator int valOUT; //virtualDelay int VDFinalT; // analogRead voor. int VDFoptel; // loop door array teller. int VDFSpeed; //virtualDelay int VDFinalTB; // analogRead voor. int VDFoptelB; // loop door array teller. int VDFSpeedB; //synth 1 int S1volume; int S1volumeTemp; int S1out; float S1volumeT = 1; //lookup tables float sinC[2][16] = { {0.5, 0.656, 0.787, 0.873, 0.9, 0.864, 0.77, 0.634, 0.477, 0.323, 0.197, 0.119, 0.102, 0.147, 0.247, 0.388}, //sinus {0.5, 0.557, 0.614, 0.672, 0.729, 0.786, 0.843, 0.9, 0.057, 0.114, 0.172, 0.229, 0.286, 0.343, 0.4, 0.458}//, //triangle //{0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1} //sqw }; byte TSelA = 0; byte TSelB = 0; byte TSelC = 0; byte FrameSelector = 0; //synth 2 int FreqRange; int S2volume; //delay effect int outVAopt; int delayVar; float ibOpt = 0.0001; int aValT; byte ReadPINDa = 0; byte ReadPINDb = 0; byte prevReadPINDa = 0; boolean manualplay = false; boolean readpina1 = false; boolean readpina2 = false; boolean readpina3 = false; boolean readpina1prev = false; boolean readpina2prev = false; boolean readpina3prev = false; boolean pin1state = HIGH; boolean pin7state = HIGH; //trigger variables unsigned long trigMillis = 0; byte triggerOutPin = 18; //PC4 boolean pocketsync = false; boolean readpina1effectselect = false; boolean effects = false; //save unsigned long prevMillisSave = 0; boolean savingnow = false; const byte SEQLENGTH = 64; byte sBSCounter = 0; byte sBSCounterPlay = 0; byte sBSArray[SEQLENGTH] = {0,0,0,0,0,0,0,0,0,0}; boolean holdplay = false; boolean looper = false; void setup() { //setup playback of sequencer Timer1.initialize(250); Timer1.attachInterrupt(timerseq); cli(); //set speed of ADC //http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1208715493/11 and http://vimeo.com/1460684 ADCSRA &= ~B111; ADCSRA |= B101; sei(); pinMode(1, INPUT_PULLUP); pinMode(3, INPUT_PULLUP); pinMode(4, INPUT_PULLUP); pinMode(5, INPUT_PULLUP); pinMode(6, INPUT_PULLUP); pinMode(7, INPUT_PULLUP); pinMode(19, INPUT_PULLUP); //led pin pinMode(17, OUTPUT); digitalWrite(17, ledPin); //DAC outputs DDRB = B111111; loadallfromeeprom(); delay(10); if(!digitalRead(1)){ //is button S pocketsync = !pocketsync; } if(!digitalRead(4)){ //is button 1 readpina1effectselect = !readpina1effectselect; } //hold when button is pressed so it does not record on bootup while(!digitalRead(4)){} setuppocketsync(); attachInterrupt(0, triggerin, RISING); // Serial.begin(9600); } void loop(){ butReadTSelA(); //1-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//- //1-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//- //1-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//- //Synth 1 if(readA(seqArrayA[seqBank][seqCounter]) == 1){ //button 1 VDFinalTB = 0; VDFoptelB = 0; VDFSpeedB = 0; VirtDelFunctionB(15); S1volume = 64; S1volumeT = 1; while(readA(seqArrayA[seqBank][seqCounter]) == 1){ VDFSpeed = (int) (32-(analogReadF(3)/32)); //vibrato speed VirtDelFunction(15); delV = delayF3(); //pitch delV = (int) (delV-(sinC[0][VDFoptel]*32)); VDFSpeedB = (int) 64 - (analogReadF(2)/16); VirtDelFunctionB(15); if(TSelB == 1){ S1volumeT = (sinC[0][VDFoptelB]); }else{ S1volumeT = 1; } for(int i=0; i<16; i++){ S1out = (int) (sinC[TSelA][i]*64); S1out = ((S1out-32) * S1volumeT) + 32; //volume regeling if(TSelC == 1){S1out = ToSQW(S1out);} //convert to SQW aWrite(S1out); int delaytime = 1024 - delV; delayMicroseconds((delaytime >> 1)+(delaytime >> 2)+1); } butReadTSelA(); } //Synth 2 }else if(readA(seqArrayA[seqBank][seqCounter]) == 2){ //button 3 //delay function reset A VDFinalT = 0; VDFoptel = 0; VDFSpeed = 0; VirtDelFunction(16); //delay function reset B VDFinalTB = 0; VDFoptelB = 0; VDFSpeedB = 0; VirtDelFunctionB(15); S2volume = 64; int addTo; int vibRange; while(readA(seqArrayA[seqBank][seqCounter]) == 2){ VDFSpeed = (int) 8 - (analogReadF(3)/128); VirtDelFunction(20); if(VDFoptel == 1){ FreqRange = 1023 - analogReadF(1); delV = (36 + random(FreqRange-32,FreqRange)); VDFSpeedB = random(16); //vibrato speed, 1 is the fastest (vibrato is below here) vibRange = random(7,32); } if(TSelC == 1){ //vibrato on off VirtDelFunctionB(15); delV = (int) (delV+((sinC[0][VDFoptelB]*vibRange)-(vibRange/2))); } addTo = (int) ((analogReadF(2)/128) - 4); //pitch slide pot delV = delV + addTo; //pitch slide delV = max(delV,1); //limiter int range = 15; for(int i=range; i>0; i--){ if(TSelB == 1){ range = amArrPerm; S1out = (int) (arrA[i]); aWrite((int)((arrA[i]-31)+tcap)/2); //mixer chaos tcap = arrA[i]-31; //mixer chaos }else{ range = 15; S1out = (int) (sinC[TSelA][i]*S2volume); aWrite(S1out); } delayMicroseconds((delV >> 1)+1); } butReadTSelA(); } // Noise }else if(readA(seqArrayA[seqBank][seqCounter]) == 3){ //buttons 1+3 VDFinalT = 0; VDFoptel = 0; VDFSpeed = 0; VirtDelFunction(16); //reset alle parameters hierboven en hier.. int captureNoise = 16; while(readA(seqArrayA[seqBank][seqCounter]) == 3){ S2volume = 63; FreqRange = 1023 - analogReadF(1); VDFSpeed = (int) 32 - (analogReadF(3)/32); VirtDelFunction(16); delV = (int) random(1,FreqRange*sinC[0][VDFoptel]); for(int i=0; i<16; i++){ S1out = (int) (sinC[TSelA][i]*S2volume); if(TSelC == 1){ S1out = (int) 31+((31-captureNoise)-(31-S1out)); S1out = max(S1out,0); S1out = min(S1out,63); captureNoise = S1out; } if(TSelB == 1){ aWrite((int)((arrA[i]-31)+tcap)/2); //mixer chaos tcap = arrA[i]-31; //mixer chaos }else{ aWrite(S1out); } delayMicroseconds((delV >> 1)+1); } butReadTSelA(); } //kick }else if(readA(seqArrayA[seqBank][seqCounter]) == 4){ float volume = 1; boolean prevCapBeats1 = 1; float kickDownSpeed; while(readA(seqArrayA[seqBank][seqCounter]) == 4){ butReadTSelA(); kickDownSpeed = (analogReadF(2)*0.004)+0.7; //snelheid van hoe snel de kick down gaat.. volume = (analogReadF(3)*0.0007+0.25); //volumme van 0.18 tot 0.9 delV = delayF3(); //pitch //schakel heen en weer tussen reverse beat en forward beat if(TSelA == 1 && prevCapBeats1 == 1){ TSelC = 1; prevCapBeats1 = !prevCapBeats1; }else if(TSelA == 1 && prevCapBeats1 == 0){ TSelC = 0; prevCapBeats1 = !prevCapBeats1; } //forward of reverse beat if(TSelC == 1){ //vibrato on off delV = 1050 - delV; for(float i2=1; i2<64; i2=i2+kickDownSpeed){ if(delV == 1 || readA(seqArrayA[seqBank][seqCounter]) != 4){break;} for(int i=0; i<16; i++){ S1out = (int) (sinC[TSelB][i]*64); S1out = ((S1out-32) * volume) + 32; //volume regeling S1out = ToSQW(S1out); aWrite(S1out); delayMicroseconds(delV); delV--; //pitch down delV = max(delV,1); if(delV == 1){break;} } butReadTSelA(); volume *= 0.9; volume = max(volume, 0.00001); } }else{ delV = 1024 - delV; for(float i2=32; i2>1; i2=i2-kickDownSpeed){ for(int i=0; i<16; i++){ if(TSelB == 1){ FrameSelector = random(0,16); }else{ FrameSelector = i; } S1out = (int) (sinC[TSelB][FrameSelector]*64); S1out = (int) ((S1out-31) * volume) +31; //volume regeling S1out = ToSQW(S1out); aWrite(S1out); delV++; //pitch down delV = max(delV,1); delayMicroseconds(delV); } if(readA(seqArrayA[seqBank][seqCounter]) != 4){break;} butReadTSelA(); volume *= 0.9; volume = max(volume, 0.00001); } } } //synth3 }else if(readA(seqArrayA[seqBank][seqCounter]) == 5){ //buttons 1+2 VDFinalTB = 0; VDFoptelB = 0; VDFSpeedB = 0; VirtDelFunction(16); int VShiftVar = 0; float volume = 0.4; float phaseVar = 1; int phaseVarRes = 0; int delVTS3; int playbackResolution = 1; int playbackResolutionReverse = 0; aValT = 256; delV = 256; phaseVar = 0.5; while(readA(seqArrayA[seqBank][seqCounter]) == 5){ butReadTSelA(); if(TSelA == 1){ if(volume < 0.001){volume = 1;} volume -= (analogReadF(3)*0.00048+0.001); //volumme van 0.18 tot 0.9 }else{ volume = (analogReadF(3)*0.0007+0.25); //volumme van 0.18 tot 0.9 } if(TSelC == 1){ playbackResolution = (int) (analogReadF(2)/142)+1; }else{ VShiftVar = (int) 64-(analogReadF(2)/16); } if(TSelB == 1){ volume = volume/2; }else{ //nothing.. } //Legato!!! - Legato!!! - Legato!!! - Legato!!! aValT = 512-(analogReadF(1)/2); if(delV == aValT){ delV = delV; }else if(delV > aValT){ delV -= 32; }else if(delV < aValT){ delV += 32; } delV = max(delV, 1); //pulse width modulation... VDFSpeed = 4; VirtDelFunction(16); phaseVar = sinC[0][VDFoptel]; phaseVarRes = (phaseVar*delV); delVTS3 = delV+phaseVarRes; delVTS3 = max(delVTS3, 1); for(int i=0; i<16; i+=playbackResolution){ S1out = (int) (sinC[0][i]*64); S1out = ((S1out-32) * volume) + 32; //volume regeling S1out = ToSQW(S1out); S1out = VShift(S1out, VShiftVar); aWrite(S1out); delayMicroseconds((delVTS3>>1)+1); // 1 keer phase waarde toegevoegd. playbackResolutionReverse++; // tel de hoeveel heid voor pwm, hierbeneden } delayMicroseconds((((delV-phaseVarRes)*playbackResolutionReverse)>>1)+1); // keer 16 om de zelfed pitch te houden playbackResolutionReverse = 0; } //synth4 }else if(readA(seqArrayA[seqBank][seqCounter]) == 6){ //buttons 2+3 int S4phaser = 0; float S4decayValue = 0.2; int S4playtimesA = 4; int S4playtimesB = 4; boolean S4playtimesBOOL = true; int S4phaseSpeed = 100; float S4highPitch = 3; float S4highPitchArray = 4; while(readA(seqArrayA[seqBank][seqCounter]) == 6){ butReadTSelA(); S4highPitchArray = (int) ((analogReadF(3)/180)+1); //wave form playback inkrimpen voor extra hoge pitch, ook octave waarde 1 t/m 6 if(TSelA == 1){ S4phaseSpeed = (int) (128 - (analogReadF(2)/8)); }else{ S4highPitch = 1025 - (analogReadF(2)); //of micro delay instellen } S4decayValue = 1.2; //start volume for(float i2=S4playtimesA; i2>0; i2--){ //playback hoeveel keer for(int i=0; i<16; i += S4highPitchArray){ //zie hierboven S1out = (int) (sinC[TSelB][i]*64); S1out = ((S1out-32) * S4decayValue) + 32; //volume regeling if(TSelC == 1){S1out = ToSQW(S1out);} aWrite(S1out); int newdelay = S4highPitch; delayMicroseconds((newdelay >> 1)+1); } S4decayValue -= 0.999/S4playtimesA; //decay time } delV = max(delV,1); delayMicroseconds(delV); //delayMicroseconds(delV); S4decayValue = 1.2; //start volume for(float i2=S4playtimesB; i2>0; i2--){ for(int i=0; i<16; i += S4highPitchArray){ //zie hierboven S1out = (int) (sinC[TSelB][i]*64); S1out = ((S1out-32) * S4decayValue) + 32; if(TSelC == 1){S1out = ToSQW(S1out);} aWrite(S1out); int newdelay = S4highPitch; delayMicroseconds((newdelay >> 1)+1); } S4decayValue -= 0.999/S4playtimesB; } //schakeld de hoeveelhed keer dat de waveforms afgespeeld worden, //hieroven, als de een 7 keer dan de ander 1, als de een 6 keer dan de ander 2. //alteid bij elkaar opgeteld 8, zodat de pitch bewaard blijft.. en hij gaat ook heen en weer delV = 8192 - delayF()*4; if(S4phaser >= delV){ S4phaser = 1; if(S4playtimesBOOL == true){ S4playtimesA += 1; S4playtimesB -= 1; if(S4playtimesB < 2){ S4playtimesBOOL = false; } }else{ S4playtimesA -= 1; S4playtimesB += 1; if(S4playtimesA < 2){ S4playtimesBOOL = true; } } }else{ S4phaser += S4phaseSpeed; } delV -= S4phaser; S4phaser = max(S4phaser,1); delayMicroseconds(S4phaser); //delayMicroseconds(S4phaser); } //sample synth bleepie }else if(readA(seqArrayA[seqBank][seqCounter]) == 7){ //buttons 1+2+3 int i2teller = 9; int delVopteller = 9; while(readA(seqArrayA[seqBank][seqCounter]) == 7){ delV = 1025 - (analogReadF(1)); amArr = (int) ((analogReadF(2)/3)+8); if(TSelC == 1){ i2teller = (int) (analogReadF(3)/64)+1; }else{ delVopteller = (int) (analogReadF(3)/64)-8; } for(int i2=0; i2> 2)+1); } } } //SAMPLE AND OUTPUT / play thrue }else{ //DELAY if(readB(seqArrayA[seqBank][seqCounter]) == 3 && !ReadPINDa && !readA(seqArrayA[seqBank][seqCounter])){ static byte counter; counter++; if(counter > map(analogReadF(3), 0, 1023, 4, amArrPerm)){ counter = 0; } aWrite2(arrA[counter]); int AV0T = ((analogReadF(0) >> 3) - 32); AV0T = constrain(AV0T, 0, 63); arrA[counter] = (AV0T + (int) arrA[counter]) >> 1; delayMicroseconds(((1023 - analogReadF(1))>>2)+((1023 - analogReadF(2))>>2)+1); //PITCH SHIFT }else if(readB(seqArrayA[seqBank][seqCounter]) == 2){ static byte counter; counter++; if(counter > amArrPerm){ counter = 0; } static byte counter2; counter2 += (analogReadF(1)>>6)+(analogReadF(2)>>6)+1; if(counter2 > amArrPerm){ counter2 = 0; } aWrite2(arrA[counter2]); int AV0T = ((analogReadF(0) >> 3) - 32); AV0T = constrain(AV0T, 0, 63); arrA[counter] = AV0T; //arrA[counter] = analogReadF(0)/5; delayMicroseconds((analogReadF(3) >> 4)+1); }else if(readB(seqArrayA[seqBank][seqCounter]) == 1){// play throu and rec while(readB(seqArrayA[seqBank][seqCounter]) == 1 && !ReadPINDa && !readA(seqArrayA[seqBank][seqCounter])){ delVDD = (int) ((analogReadF(2) / 32)+1); delV2 = delayF2(); for(int i=0; i> 3) - 32); AV0T = constrain(AV0T, 0, 63); arrA[i] = AV0T; aWrite2(arrA[i]); delayMicroseconds(((1023 - delV2) >> 1)+1); butReadTSelA(); } for(int ib=0; ib> 1)+1); butReadTSelA(); } if(readA(seqArrayA[seqBank][seqCounter]) != 0){break;} } butReadTSelA(); } }else{ //aWrite2(31); } } //END-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//- //END-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//- //END-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//- }//LOOP ENDS HERE!!! //effect controle buttons void butReadTSelA(){ sequenceinloop(); bitWrite(ReadPINDa, 0, !bitRead(PIND, BUT4)); bitWrite(ReadPINDa, 1, !bitRead(PIND, BUT5)); bitWrite(ReadPINDa, 2, !bitRead(PIND, BUT6)); bitWrite(ReadPINDb, 0, !bitRead(PINC, BUTA)); bitWrite(ReadPINDb, 1, !bitRead(PIND, BUT3)); pin1state = bitRead(PIND, BUTS);//digitalRead(1); pin7state = bitRead(PIND, BUTD);//digitalRead(7); //hold state while operations. static byte holdStatePINDb = 0; static boolean sBSCounterPrev = false; if(pin1state == HIGH){ if(pin7state == HIGH){ //record pins 2,3,4 if(ReadPINDa != 0 || pMode == 0){ seqArrayA[seqBank][seqCounter] = writeA(seqArrayA[seqBank][seqCounter], ReadPINDa); seqArrayA[seqBank][seqCounter] = writeB(seqArrayA[seqBank][seqCounter], 0); //if(newAnalogRecording){ // newAnalogRecording = false; seqArrayAnalog[seqBank][seqCounter] = analogRead(inputPinA[1]); //analog pot 1 animation //} anaRTF = true; } //record pins 5,6 if(ReadPINDb != 0 || pMode == 0){ seqArrayA[seqBank][seqCounter] = writeB(seqArrayA[seqBank][seqCounter], ReadPINDb); //seqArrayB[seqBank][seqCounter] = ReadPINDb; if(!readA(seqArrayA[seqBank][seqCounter])){ //write only when no effects are recorded //if(newAnalogRecording){ //newAnalogRecording = false; seqArrayAnalog[seqBank][seqCounter] = analogRead(inputPinA[1]); //analog pot 1 animation //int dummy = analogRead(inputPinA[1]); //} } anaRTF = true; } //reset manual play readpina1 = false; readpina2 = false; readpina3 = false; }else{ //manual playmode if(ReadPINDa){ if(bitRead(ReadPINDa, 0) && readpina1prev){ readpina1prev = false; readpina1 = !readpina1; } if(bitRead(ReadPINDa, 2) && readpina2prev){ readpina2prev = false; readpina2 = !readpina2; } if(bitRead(ReadPINDa, 1) && readpina3prev){ readpina3prev = false; readpina3 = !readpina3; } }else{ readpina1prev = true; readpina2prev = true; readpina3prev = true; } //delete sequences if(bitRead(ReadPINDb, 0)){ //erase A,B butttons seqArrayA[seqBank][seqCounter] = writeB(seqArrayA[seqBank][seqCounter], 0); //never erase the pitch changes // if(readB(seqArrayA[seqBank][seqCounter]) && !readA(seqArrayA[seqBank][seqCounter])){ // seqArrayAnalog[seqBank][seqCounter] = 0; // } } if(bitRead(ReadPINDb, 1)){ //erase 1,2,3 butttons seqArrayA[seqBank][seqCounter] = writeA(seqArrayA[seqBank][seqCounter], 0); //never erase the pitch changes // if(readA(seqArrayA[seqBank][seqCounter])){ // seqArrayAnalog[seqBank][seqCounter] = 0; // } } } sBSCounterPrev = true; //reset states for below; holdStatePINDb = 0; }else{ //update when greater then 0 (if button is pressed) so it holds the value if(ReadPINDb){ holdStatePINDb = ReadPINDb; } //sequencer playback settings if(ReadPINDa){ if(prevReadPINDa){ //only read one time per click prevReadPINDa = false; //reset on new recording if(sBSCounterPrev){ sBSCounter = 0; sBSCounterPrev = false; }else{ //increase only after second pass sBSCounter++; sBSCounter = min(sBSCounter, SEQLENGTH); } switch(ReadPINDa){ case 1:{ sBSArray[sBSCounter] = 0; //seqBank = 0; break; } case 2:{ sBSArray[sBSCounter] = 1; //seqBank = 1; break; } case 4:{ sBSArray[sBSCounter] = 2; //seqBank = 2; break; } } } }else{ prevReadPINDa = true; } //select bank with recorded sequence switch(holdStatePINDb){ case 1:{ seqSpeed = map(analogRead(inputPinA[1]), 0, 1023, 2035, 300);//, 0, 1023, 1023, 31); //playback speed select if(seqSpeed > 2031){ //switch to manul play seqMode = true; }else{ seqMode = false; } //Serial.println(seqSpeed, DEC); anaRTF = true; break; } case 2:{ int vt = analogRead(inputPinA[1]); anaRTF = true; vt = map(vt, 0, 1023, 6, 0); seqLength[seqBank] = 127 >> vt; break; } } } static boolean prevpin1statesave = 0; static byte savecounter = 0; //save to eeprom if(!pin7state){ if(!pin1state){ //reset sequencer variables prevMillis = millis(); sBSCounterPlay = 0; //bank reset seqBankNew = sBSArray[sBSCounterPlay]; //update bank seqCounterStrict = 0; //platback position reset seqCounterNew = seqCounterStrict; holdplay = true; if(prevpin1statesave){ prevpin1statesave = false; savecounter++; } }else{ prevMillisSave = millis(); prevpin1statesave = true; holdplay = false; } if(savecounter == 4){ if(millis() - prevMillisSave > 4000){ //hold both button for 4 seconds to save prevMillisSave = millis(); savecounter = 5;//increase so there is no resave //save to eeprom? savealltoeeprom(); } } }else{ savecounter = 0; holdplay = false; } if(readB(seqArrayA[seqBank][seqCounter]) == 1){TSelA = 1;}else{TSelA = 0;} if(readB(seqArrayA[seqBank][seqCounter]) == 2){TSelB = 1;}else{TSelB = 0;} if(readB(seqArrayA[seqBank][seqCounter]) == 3){TSelC = 1;}else{TSelC = 0;} //fix for recording out of pitch.. if(!anaRTF){ //use analogRead here as timee for delay (analogRead above makes it out of pitch) //if(!effects){ analogValue1 = analogRead(inputPinA[1]); //} } anaRTF = false; } //smooth pitch changes (still needs some change.. look at "-= 1 and +=1, change to ++ and constrain.. no ifs) unsigned long legatoPrM = 0; int analogTstorage[] = {10,10,10}; int analogTstorage2[] = {10,10,10}; void legatoFMaster(){ //removed legato here if(readA(seqArrayA[seqBank][seqCounter]) == 1){ if(micros() - legatoPrM > 300){ legatoPrM = micros(); if(seqArrayAnalog[seqBank][seqCounter] < analogTstorage2[seqBank]){ analogTstorage2[seqBank] -= 1; }else if(seqArrayAnalog[seqBank][seqCounter] > analogTstorage2[seqBank]){ analogTstorage2[seqBank] += 1; } analogTstorage[seqBank] = constrain(analogTstorage2[seqBank], 0, 1023); } }else{ analogTstorage[seqBank] = seqArrayAnalog[seqBank][seqCounter]; } } byte prevSeqCount = 0; int analogReadF(byte input){ if(input == 1){ return analogTstorage[seqBank]; }else{ return analogRead(inputPinA[input]); } } unsigned long timerseqcounter; unsigned long groovetimer; unsigned long counter; boolean masterclock = 0; void timerAll(){ //display LED out and pocketsync out //moet als eerste om geen sync te missen if(counter == 0){ digitalWrite(17, HIGH); if(pocketsync){ //add half clock speed sync out for pocket operator //also helps create higher resolution for HSS2 static boolean flip; flip = !flip; if(flip){ digitalWrite(triggerOutPin, HIGH); } } }else if(counter == 13){ if(seqCounterStrict){ digitalWrite(17, LOW); } if(pocketsync){ digitalWrite(triggerOutPin, LOW); } } timerseqcounter++; counter++; if(counter >= groovetimer && masterclock){ masterclock = false; counter = 0; sequence(); } if(!seqMode){ if(timerseqcounter > seqSpeed){ resettimerseqcounter(); } } } void resettimerseqcounter(){ sequence(); //below is for extra step for pocket sync masterclock = true; groovetimer = timerseqcounter >> 1; //store time between external clock pulses, devide by 2 timerseqcounter = 0; counter = 0; digitalWrite(17, HIGH); //led on when reset position to zero with extrnal trigger } void triggerin(){ if(seqMode){ resettimerseqcounter(); } } byte seqCountEffect; void sequence(){ if(!holdplay){ //increase counter seqCounterStrict++; if(seqCounterStrict > seqLength[seqBank]){ seqCounterStrict = 0; sBSCounterPlay++; if(sBSCounterPlay > sBSCounter){ sBSCounterPlay = 0; } seqBankNew = sBSArray[sBSCounterPlay]; } if(!readpina2){ if(readpina1 && readpina1effectselect){ //playback effect for seq length seqCountEffect++; if(seqCountEffect > map(analogValue1, 0, 1023, 0, seqLength[seqBank])){ seqCountEffect = 0; } seqCounterNew = seqCountEffect; }else{ seqCounterNew = seqCounterStrict; seqCountEffect = seqCounterStrict; } } } //newAnalogRecording = true; } void sequenceinloop(){ //update in loop so there is seqBank = seqBankNew; seqCounter = seqCounterNew; } //sample rate / pitch int delayF(){ return (int) ((analogReadF(1)*2)+1); } int delayF2(){ return (int) (analogReadF(1)+1); //sample rate } int delayF3(){ return analogReadF(1); } void aWrite(byte i){ amArrCappture(i); sampleratefilter(i); } //output to audio void aWrite1(byte i){ //i = constrain(i, 0, 63); //sampleratefilter(i); PORTB = PORTB & B000000; PORTB = PORTB | i; legatoFMaster(); } //output to audio void aWrite2(byte i){ sampleratefilter(i); } //Vertical Shift int VShift(int input, int input2){ //input 0>64, input2 input += input2; if(input > 64){ input -= 64; } return input; } //convert to square, input 0>64 int ToSQW(int inputSQW){ int outputSQW; inputSQW *= 4; if(inputSQW > 159){ outputSQW = 63; }else if(inputSQW < 97){ outputSQW = 0; }else{ outputSQW = inputSQW - 97; } return outputSQW; } void amArrCappture(byte input){ if(amArrCapptureTeller > amArrPerm){amArrCapptureTeller = 0;} arrA[amArrCapptureTeller] = input; amArrCapptureTeller++; } //virtual delay function A void VirtDelFunction(int VDFlenghtOptel){ if(VDFinalT < VDFSpeed){ // analogRead voor. VDFinalT++; }else{ if(VDFoptel > VDFlenghtOptel){ // als het einde van de array bereikt is.. ga begin dan overnieuw. VDFoptel=0; }else{ VDFoptel++; // loop door array teller. } VDFinalT=0; // reset de virtuele delay. } } //virtual delay function B void VirtDelFunctionB(int VDFlenghtOptelB){ if(VDFinalTB < VDFSpeedB){ // analogRead voor. VDFinalTB++; }else{ if(VDFoptelB > VDFlenghtOptelB){ // als het einde van de array bereikt is.. ga begin dan overnieuw. VDFoptelB=0; }else{ VDFoptelB++; // loop door array teller. } VDFinalTB=0; // reset de virtuele delay. } } void setuppocketsync(){ if(pocketsync){ //set volume to maximum for the sync pin pinMode(triggerOutPin, OUTPUT); }else{ //floating the pin so the volume potmeter is used digitalWrite(triggerOutPin, LOW); pinMode(triggerOutPin, INPUT); } } void savealltoeeprom() { //save all data to EEPROM savingnow = true; int eepromcounter = 0; EEPROM.write(eepromcounter, 1); eepromcounter++; EEPROM.write(eepromcounter, pocketsync); eepromcounter++; EEPROM.write(eepromcounter, readpina1effectselect); eepromcounter++; EEPROM.write(eepromcounter, seqBank); eepromcounter++; EEPROM.write(eepromcounter, highByte(seqSpeed)); eepromcounter++; EEPROM.write(eepromcounter, lowByte(seqSpeed)); eepromcounter++; EEPROM.write(eepromcounter, seqMode); eepromcounter++; EEPROM.write(eepromcounter, seqLength[0]); eepromcounter++; EEPROM.write(eepromcounter, seqLength[1]); eepromcounter++; EEPROM.write(eepromcounter, seqLength[2]); eepromcounter++; for (byte i = 0; i <= ARRAYLENGTH; i++) { EEPROM.write(eepromcounter, seqArrayA[0][i]); eepromcounter++; EEPROM.write(eepromcounter, seqArrayA[1][i]); eepromcounter++; EEPROM.write(eepromcounter, seqArrayA[2][i]); eepromcounter++; EEPROM.write(eepromcounter, highByte(seqArrayAnalog[0][i])); eepromcounter++; EEPROM.write(eepromcounter, lowByte(seqArrayAnalog[0][i])); eepromcounter++; EEPROM.write(eepromcounter, highByte(seqArrayAnalog[1][i])); eepromcounter++; EEPROM.write(eepromcounter, lowByte(seqArrayAnalog[1][i])); eepromcounter++; EEPROM.write(eepromcounter, highByte(seqArrayAnalog[2][i])); eepromcounter++; EEPROM.write(eepromcounter, lowByte(seqArrayAnalog[2][i])); eepromcounter++; } for (byte i = 0; i <= SEQLENGTH; i++) { EEPROM.write(eepromcounter, sBSArray[i]); eepromcounter++; } EEPROM.write(eepromcounter, sBSCounter); eepromcounter++; savingnow = false; } void loadallfromeeprom(){ //read stored song data int eepromcounter = 0; //check if something has been saved before, if so load it if(EEPROM.read(eepromcounter) == 1){ //advance to skip first for check eepromcounter++; pocketsync = EEPROM.read(eepromcounter); eepromcounter++; readpina1effectselect = EEPROM.read(readpina1effectselect); eepromcounter++; seqBank = EEPROM.read(eepromcounter); eepromcounter++; seqSpeed = word(EEPROM.read(eepromcounter), EEPROM.read(eepromcounter+1)); eepromcounter+=2; seqMode = EEPROM.read(eepromcounter); eepromcounter++; seqLength[0] = EEPROM.read(eepromcounter); eepromcounter++; seqLength[1] = EEPROM.read(eepromcounter); eepromcounter++; seqLength[2] = EEPROM.read(eepromcounter); eepromcounter++; for (byte i = 0; i <= ARRAYLENGTH; i++) { seqArrayA[0][i] = EEPROM.read(eepromcounter); eepromcounter++; seqArrayA[1][i] = EEPROM.read(eepromcounter); eepromcounter++; seqArrayA[2][i] = EEPROM.read(eepromcounter); eepromcounter++; seqArrayAnalog[0][i] = word(EEPROM.read(eepromcounter), EEPROM.read(eepromcounter+1)); eepromcounter+=2;//needs to be 2 because two bytes are used for the above. seqArrayAnalog[1][i] = word(EEPROM.read(eepromcounter), EEPROM.read(eepromcounter+1)); eepromcounter+=2; seqArrayAnalog[2][i] = word(EEPROM.read(eepromcounter), EEPROM.read(eepromcounter+1)); eepromcounter+=2; } for (byte i = 0; i <= SEQLENGTH; i++) { sBSArray[i] = EEPROM.read(eepromcounter); eepromcounter++; } sBSCounter = EEPROM.read(eepromcounter); eepromcounter++; } } byte readA(byte inp){ return inp & B00000111; } byte readB(byte inp){ //shift out buuton a reads return inp >> 3; } byte writeA(byte arr, byte inp){ bitWrite(arr, 0, bitRead(inp, 0)); bitWrite(arr, 1, bitRead(inp, 1)); bitWrite(arr, 2, bitRead(inp, 2)); return arr; } byte writeB(byte arr, byte inp){ bitWrite(arr, 3, bitRead(inp, 0)); bitWrite(arr, 4, bitRead(inp, 1)); return arr; } static byte count = 0; //modify for HSS2020 from NV/ER void sampleratefilter(byte i) { //lowpass filter i = lowpassfilter(i); //sampe rate reduction filter if(!readpina1effectselect){ count++; if (count >= (1023-analogValue1 >> 7) || !readpina1) { count = 0; i = constrain(i, 0, 63); PORTB = PORTB & B000000; PORTB = PORTB | i; legatoFMaster(); } }else{ i = constrain(i, 0, 63); PORTB = PORTB & B000000; PORTB = PORTB | i; legatoFMaster(); } } byte lowpassfilter(byte i){ static char prevbuff; static byte filterset; filterset = (1023-analogValue1 >> 7)+1; //lowpass filter //always fade out signal volume, slower fade out speed makes lower frequency pass thru. if (filterset > 1 && readpina3) { //low pass filter //byte filter = 10-filterset; //invert input setting if (i > prevbuff) { //count up fast will give less filter then count up slow prevbuff += (256 >> filterset)+8; //tuned ok if (prevbuff > i) prevbuff = i; //prevbuff = min(prevbuff, inp); } else if (i < prevbuff) { prevbuff -= (256 >> filterset)+8; if (prevbuff < i) prevbuff = i; //prevbuff = max(prevbuff, inp); } else { prevbuff = i; } return prevbuff; } else { prevbuff = i; return prevbuff; } } void timerseq() { if(savingnow){ //make audio continue from buffer when saving if(amArrCapptureTeller > amArrPerm){amArrCapptureTeller = 0;} byte i = arrA[amArrCapptureTeller]; amArrCapptureTeller++; sampleratefilter(i); } timerAll(); }