// HSS2e // Script V24 // Gijs Gieskes 2010 (start project januari 2008) // http://gieskes.nl #include byte hssMode = 0; byte lsdjsync = 0; byte nanoPin = 11; boolean nanoclock = HIGH; //midi keyboard unsigned long tmills = 0; unsigned long noteEraseTimer = 0; unsigned long vibratoLong = 0; byte mainchannel = 1; unsigned long timeArp = 0; byte frequency = 80; boolean arpMode = 0; boolean FF = false; byte tp = 0; int oscA, oscB, oscC; float tvol = 80; byte tvolb = 100; float decay = 0.05; byte out = 0; boolean ta; boolean reset = true; boolean tekSeqMode = 0; char seqPos = 0; byte prevAV1 = 0; byte AV1 = 0; byte prevAV2 = 0; byte AV2 = 0; 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 }; //sequencers unsigned long prevMillis = 0; byte seqArray[3][32] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; byte seqArrayB[3][32] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; byte seqArrayC[3][32] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,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][32] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,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 char seqCounter = 0; volatile byte seqLength = 31; byte sampleRate = 255; byte vibdepth = 255; byte vibdepthCounter = 0; byte seqBank = 0; byte newSeqBank = 0; int seqSpeed = 100; byte midiClockCounter = 0; boolean seqMode = false; boolean seqStart = true; //manual play or sequencer byte pMode = 1; //analog in pins byte inputPinA[] = {4,1,2,3}; //analog Read bool boolean anaRTF = false; int delV = 0; //sample rate storage byte delVDD = 0; //delay X times //samples vars int amArr = 350; //sample length byte arrA[351]; //sample store array int amArrPerm = 350; //sample length permanent int amArrCapptureTeller = 0; //teller voor arrA Functie, opslag byte tcap = 31; //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 }; byte TSelA = 0; byte TSelB = 0; byte TSelC = 0; byte TSelD = 0; byte FrameSelector = 0; //synth 2 int FreqRange; int S2volume; //delay effect int outVAopt; int delayVar; float ibOpt = 0.0001; int aValT; byte ReadPINDa; byte ReadPINDb; boolean pin1state = HIGH; boolean pin8state = HIGH; //trigger variables unsigned long trigMillis = 0; byte triggerOutPin = 13; boolean inLoop = false; //midi library: //http://timothytwillman.com/itp_blog/?page_id=240 #include "Midi.h" byte midiCounter = 0; boolean midiPlay = false; class MyMidi : public Midi{ public: // Need this to compile; it just hands things off to the Midi class. MyMidi(HardwareSerial &s) : Midi(s) {} void handleSync(){ if(midiPlay){ if(!midiCounter){ sequence(); } midiCounter = cup(midiCounter, 6); //reset lsdj sync lsdjsync = 16; //nanoloop nanoclock = !nanoclock; digitalWrite(nanoPin, nanoclock); } } void handleStop(){ midiPlay = false; digitalWrite(10, LOW); //sync 24 start stop //reset nano clock signals nanoclock = HIGH; digitalWrite(nanoPin, nanoclock); } void handleStart(){ midiCounter = 0; seqCounter = 0; midiPlay = true; seqMode = true; digitalWrite(10, HIGH); //sync 24 start stop } void handleContinue(){ midiCounter = 0; midiPlay = true; digitalWrite(10, HIGH); //sync 24 start stop } void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity){ hssMode = 4; midiHandler(channel, note, true); } void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity){ midiHandler(channel, note, false); } }; MyMidi midi(Serial); void setup() { analogReference(INTERNAL); //TIMER SETUP cli(); TCCR1B = TCCR1B & 0b11111000 | 0x01; TCCR2A = TCCR2A & B11111000 | B00000010; TCCR2B = TCCR2B & B11111000 | B00000010; TIMSK2 = TIMSK2 & B11111000 | B00000010; OCR2A = sampleRate; sei(); //fill for bonus for(int i=0; i0; 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); } butReadTSelA(); } // Noise }else if(seqArray[seqBank][seqCounter] == 3){ VDFinalT = 0; VDFoptel = 0; VDFSpeed = 0; VirtDelFunction(16); //reset alle parameters hierboven en hier.. int captureNoise = 16; while(seqArray[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); } butReadTSelA(); } //kick }else if(seqArray[seqBank][seqCounter] == 4){ float volume = 1; boolean prevCapBeats1 = 1; float kickDownSpeed; while(seqArray[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 = delayF(); //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 = 2165 - delV; for(float i2=1; i2<64; i2=i2+kickDownSpeed){ if(delV == 1 || seqArray[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 = 2048 - 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); delayMicroseconds(delV); delV++; //pitch down delV = max(delV,1); } if(seqArray[seqBank][seqCounter] != 4){break;} butReadTSelA(); volume *= 0.9; volume = max(volume, 0.00001); } } } //synth3 }else if(seqArray[seqBank][seqCounter] == 5){ 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(seqArray[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; 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 keer phase waarde toegevoegd. playbackResolutionReverse++; // tel de hoeveel heid voor pwm, hierbeneden } delayMicroseconds((delV-phaseVarRes)*playbackResolutionReverse); // keer 16 om de zelfed pitch te houden playbackResolutionReverse = 0; } //synth4 }else if(seqArray[seqBank][seqCounter] == 6){ 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(seqArray[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); delayMicroseconds(S4highPitch); } 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); delayMicroseconds(S4highPitch); } 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(seqArray[seqBank][seqCounter] == 7){ int i2teller = 9; int delVopteller = 9; while(seqArray[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 aValT){ delV -= 32; }else if(delV < aValT){ delV += 32; } delV = max(delV, 1); delayMicroseconds(delV); //RING MODULATOR }else if(seqArrayB[seqBank][seqCounter] == 2){ VDFSpeed = 0; VDFoptel = 0; VirtDelFunction(16); while(seqArrayB[seqBank][seqCounter] == 2){ VDFSpeed = (int) ((analogReadF(3)/4)+2); delV = delayF(); for(int i=0; i> 3; ReadPINDa = ~ReadPINDa; ReadPINDb = (ReadPINDa >> 3) & 3; ReadPINDa = ReadPINDa & 7; //Serial.println(seqLength, DEC); if(!seqMode){ standAlone(); } triggerPulse(); //pin states pin1state = digitalRead(1); pin8state = digitalRead(8); if(pin1state == HIGH){ if(pin8state == HIGH){ //record pins 2,3,4 if(ReadPINDa != 0 || pMode == 0){ seqArray[seqBank][seqCounter] = ReadPINDa; seqArrayAnalog[seqBank][seqCounter] = analogRead(1); //analog pot 1 animation anaRTF = true; } //record pins 5,6 if(ReadPINDb != 0 || pMode == 0){ seqArrayB[seqBank][seqCounter] = ReadPINDb; seqArrayAnalog[seqBank][seqCounter] = analogRead(1); //analog pot 1 animation anaRTF = true; } }else{ //erase pins 2,3,4 if(ReadPINDa != 0){ seqArray[seqBank][seqCounter] = 0; } //erase pins 2,3,4 if(ReadPINDb != 0){ seqArrayB[seqBank][seqCounter] = 0; } //erase pot when both keys are presed if(ReadPINDb != 0 && ReadPINDa != 0){ seqArrayAnalog[seqBank][seqCounter] = 0; } } }else{ //sequencer playback settings switch(ReadPINDa){ case 1:{ seqSpeed = map(analogRead(1), 0, 1023, 512, 16); //playback speed select if(seqSpeed > 500){ //switch to manul play seqMode = true; }else{ seqMode = false; } //Serial.println(seqSpeed, DEC); anaRTF = true; break; } case 2:{ int vt = analogRead(1); anaRTF = true; vt = map(vt, 0, 1023, 4, 0); seqLength = 31 >> vt; break; } case 4:{ //sequence or no sequence pMode = analogRead(1) >> 8; //shift to make 0 or 1 anaRTF = true; break; } } //select bank with recorded sequence switch(ReadPINDb){ case 1: seqBank = 0; break; case 2: seqBank = 1; break; } } if(seqArrayB[seqBank][seqCounter] == 1){TSelA = 1;}else{TSelA = 0;} if(seqArrayB[seqBank][seqCounter] == 2){TSelB = 1;}else{TSelB = 0;} if(seqArrayB[seqBank][seqCounter] == 3){TSelC = 1;}else{TSelC = 0;} //fix for recording out of pitch.. if(!anaRTF){ delayMicroseconds(110); } 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}; void legatoFMaster(){ if(micros() - legatoPrM > 500){ legatoPrM = micros(); if(seqArrayAnalog[seqBank][seqCounter] < analogTstorage[seqBank]){ analogTstorage[seqBank] -= 1; }else if(seqArrayAnalog[seqBank][seqCounter] > analogTstorage[seqBank]){ analogTstorage[seqBank] += 1; } analogTstorage[seqBank] = constrain(analogTstorage[seqBank], 0, 1023); } } byte prevSeqCount = 0; int analogReadF(byte input){ if(input == 1 && seqArrayAnalog[seqBank][seqCounter] != 0){ return analogTstorage[seqBank]; }else{ return analogRead(inputPinA[input]); } } void standAlone(){ if(millis() - prevMillis > seqSpeed){ prevMillis = millis(); sequence(); } } void triggerNormal(){ if(inLoop){ sequence(); } } void sequence(){ ta = true; //led pin on off. //ledPin = !ledPin; //digitalWrite(19, ledPin); //increase counter seqCounter++; if(seqCounter > seqLength){ seqCounter = 0; } //reset trigger, so it will send pulse for 8ms trigMillis = millis(); digitalWrite(triggerOutPin, HIGH); digitalWrite(19, HIGH); } void triggerPulse(){ //send trigger pulse for 8 milliseconds.. (see above (sequence();) for rest). if(millis() - trigMillis > 4){ digitalWrite(triggerOutPin, LOW); digitalWrite(19, LOW); } } //sample rate / pitch int delayF(){ return (int) ((analogReadF(1)*2)+1); //sample rate } //output to audio void aWrite(byte i){ amArrCappture(i); i = constrain(i, 0, 63); analogWrite(9,i); legatoFMaster(); } //output to audio void aWrite1(byte i){ analogWrite(9,i); legatoFMaster(); } //output to audio void aWrite2(byte i){ i = constrain(i, 0, 63); analogWrite(9,i); legatoFMaster(); } //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. } } //mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, //mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, //mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, //mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, mode 1, ISR(TIMER2_COMPA_vect) { lsdj(); if(hssMode == 1){ bonus3I0(); }else if(hssMode == 2){ bonus4I0(); }else if(hssMode == 3){ bonus5I0(); }else if(hssMode == 4){ midiNotesI0(); } } inline void lsdj(){ static boolean lsdjc = HIGH; static byte lsdjd = 0; if(lsdjsync > 0){ lsdjsync--; lsdjc = !lsdjc; digitalWrite(12, lsdjc); } } inline void bonus3I0(){ //tekno oscB = cup(oscB, 16); //delay for slide/legato if(!oscB){ if(!seqArrayB[seqBank][seqCounter]){ tp = scale[seqArray[seqBank][seqCounter]]; }else{ //legato if(tp < scale[seqArray[seqBank][seqCounter]]){ tp++; }else if(tp > scale[seqArray[seqBank][seqCounter]]){ tp--; } } } //oscillators timer oscA = cup(oscA, (tp >> 1)); //decay tvol-= decay; tvol = max(tvol, 0); //saw to square so volume stays sort of the same.. out = constrain((oscA<<1), 0, (byte)tvol); analogWrite(9, out); } inline void bonus4I0(){ //beats static float kick = 0; if(reset){ reset = false; kick = scale[seqArray[seqBank][seqCounter]]; } if(seqArrayB[seqBank][seqCounter]){ kick -= 0.08; }else{ kick += 0.08; } kick = constrain(kick, 0, 255); //oscillators timer oscA = cup(oscA, (((byte) kick) >> 1)); //decay tvol-= decay; tvol = max(tvol, 0); //saw to square so volume stays sort of the same.. out = constrain((oscA<<1), 0, (byte)tvol); analogWrite(9, out); } inline void bonus5I0(){ //chip style arpegiator static boolean arpcounter = false; static byte newPos = 0; //als het volume 0 is hou dan de laatste arp sequence positie. if(seqArrayAnalog[seqBank][seqCounter] == 1){ newPos = seqCounter; } oscB = cup(oscB, ((seqArrayC[seqBank][newPos] << 1)+1)); if(!oscB){ arpcounter = !arpcounter; if(arpcounter){ tp = scale[seqArray[seqBank][newPos]]; }else{ tp = scale[seqArrayB[seqBank][newPos]]; } } //seqArrayC[seqBank][seqCounter] > 0 //oscillators timer oscA = cup(oscA, (tp >> 1)); //decay tvol-= decay; tvol = max(tvol, 0); //saw to square so volume stays sort of the same.. out = constrain((oscA<<1), 0, (byte)tvol); analogWrite(9, out); } inline void bonusL0(){ //sequencer mode record or playback if(!digitalRead(8)){ tekSeqMode = !tekSeqMode; seqCounter = 0; while(!digitalRead(8)){}; } //sequencer if(tekSeqMode){ //sequence recorder //loop door sequence if(!digitalRead(7)){ seqCounter++; seqCounter %= 32; setVol(); while(!digitalRead(7)){}; } if(!digitalRead(6)){ seqCounter--; if(seqCounter < 0){ seqCounter = 32; } setVol(); while(!digitalRead(6)){}; } if(hssMode == 1 || hssMode == 2){ //hssMode 1 en 2 //set pitch if(!digitalRead(3)){ AV1 = map(analogRead(1), 0, 1023, 0, 47); if(AV1 != prevAV1){ prevAV1 = AV1; setVol(); } seqArray[seqBank][seqCounter] = AV1; } if(!digitalRead(5)){ seqArrayB[seqBank][seqCounter] = !seqArrayB[seqBank][seqCounter]; setVol(); while(!digitalRead(5)){}; } //set volume if(!digitalRead(4)){ if(seqArrayAnalog[seqBank][seqCounter] == 0){ seqArrayAnalog[seqBank][seqCounter] = 1; }else if(seqArrayAnalog[seqBank][seqCounter] == 1){ seqArrayAnalog[seqBank][seqCounter] = 2; }else{ seqArrayAnalog[seqBank][seqCounter] = 0; } setVol(); while(!digitalRead(4)){}; } }else{ //hssMode 3 //set pitch if(!digitalRead(3) || !digitalRead(4)){ AV1 = map(analogRead(1), 0, 1023, 0, 47); setVol(); if(!digitalRead(3)){ seqArray[seqBank][seqCounter] = AV1; } if(!digitalRead(4)){ seqArrayB[seqBank][seqCounter] = AV1; } } if(!digitalRead(5)){ AV2 = analogRead(1) >> 2; setVol(); if(AV2 == 0){ seqArrayAnalog[seqBank][seqCounter] = 0; }else{ seqArrayAnalog[seqBank][seqCounter] = 1; } seqArrayC[seqBank][seqCounter] = AV2; } } delay(40); }else{ //sequencer playback decay = ((1023 - analogRead(3))+50)*0.0001; seqSpeed = ((1023 - analogRead(1)) >> 1)+1; seqLength = 31 >> map(analogRead(2), 0, 1023, 5, 0); //seqLength = (analogRead(2) >> 5); //this sellects all steps if(!digitalRead(7)){ store(); while(!digitalRead(7)){}; } if(!digitalRead(6)){ load(); while(!digitalRead(6)){}; } //select playback seqnuence if(!digitalRead(3)){ newSeqBank = 0; }else if(!digitalRead(4)){ newSeqBank = 1; }else if(!digitalRead(5)){ newSeqBank = 2; } //switch to new seq bank at begining of sequencer if(seqCounter == 0){ seqBank = newSeqBank; } //switch to manual play if(seqSpeed > 500){ seqMode = true; }else{ seqMode = false; } if(!seqMode){ standAlone(); } triggerPulse(); } if(ta){ ta = false; setVol(); } } void setVol(){ if(seqArrayAnalog[seqBank][seqCounter] == 2){ reset = true; tvol = 128; }else if(seqArrayAnalog[seqBank][seqCounter] == 1){ reset = true; tvol = 64; }else{ //no tvol, zodat de decay niet gecanselt wordt. } } inline static int cup(int a, int b){ a++; if(a >= b){ a = 0; } return a; } inline void midiNotesI0(){ //midi notes patch OCR2A = sampleRate; //slide if(S1volume){ oscC = cup(oscC, S1volume); //(was 16) delay for slide/legato if(!oscC){ if(tp < frequency){ tp++; }else if(tp > frequency){ tp--; } } }else{ //no slide tp = frequency; } oscA = cup(oscA, (tp >> 1)); if(TSelD == 0){ out = constrain((oscA<<1), 0, tvol); //forced fade out }else if(TSelD == 1){ out = constrain((oscA<<5), 0, tvol); //forced fade out cliped }else if(TSelD == 2){ if(!oscA){ FF = !FF; } if(FF){ out = constrain(60, 0, tvol); //forced fade out square }else{ out = 0; } } analogWrite(9, out); } inline void midiNotes(){ static byte activeCount = 0; S1volume = (analogRead(2) >> 2); setDecay(); //vibrato on/off if(!digitalRead(6)){ TSelA = !TSelA; while(!digitalRead(6)){} } //arpegio on/off if(!digitalRead(7)){ TSelB = !TSelB; while(!digitalRead(7)){} } //select sound if(!digitalRead(3)){ TSelD = 0; }else if(!digitalRead(4)){ TSelD = 1; }else if(!digitalRead(5)){ TSelD = 2; } //arpegio up or down if(!digitalRead(8)){ arpMode = !arpMode; while(!digitalRead(8)){} } if(!TSelA){ vibrato(); } if(!TSelB){ //midi note player and arpegiator.. if(millis() - timeArp > (((1023 - analogRead(1)) >> 1)+10)){ timeArp = millis(); for(byte i=0; i<37; i++){ if(arpMode){ activeCount++; activeCount %= 37; }else{ if(activeCount){ activeCount--; }else{ activeCount = 36; } } //if active note is found use it and break. if(arrA[activeCount] > 0){ frequency = arrA[activeCount]; break; } } } } } void midiHandler(byte channel, byte note, boolean volume){ if(channel == mainchannel){ if((note > 35) && (note < 73)){ byte noteIn = note - 36; if(!volume){ arrA[noteIn+50] = 0; //turn not off in nate array noteEraseTimer = millis(); }else{ sampleRate = 255; vibdepth = 255; vibdepthCounter = 0; tvol = 80; checkIfActiveNote(scale[noteIn]); //set emediatly so there are no missing notes when arp is slow arrA[noteIn+50] = scale[noteIn]; //turn note on in note array arrA[noteIn] = scale[noteIn]; //turn note on in note playbck array } } } } void vibrato(){ static boolean vibbool = false; if(millis() - vibratoLong > 8){ //vibrato speed vibratoLong = millis(); vibdepthCounter = cup(vibdepthCounter, 16); //vibrato depth increase if(!vibdepthCounter){ vibdepth--; vibdepth = max(vibdepth, 245); } if(vibbool){ if(sampleRate < 255){ sampleRate++; }else{ vibbool = false; } }else{ if(sampleRate < vibdepth){ vibbool = true; } sampleRate--; } } } inline void setDecay(){ int AV = (analogRead(3) >> 4) + 1; byte empty = 0; for(byte i=0; i<37; i++){ if(arrA[i+50]){ empty++; } } if(empty < 1){ if(millis() - tmills > AV){ tmills = millis(); tvol-=2; tvol = max(tvol, 0); } } } //check for active notes and delay erase from array to make it possibel to play arps. void checkIfActiveNote(int input){ byte count = 0; //check for active notes for(byte i=0; i<37; i++){ if(!arrA[i+50]){ if(millis() - noteEraseTimer > 2){ //set threshold for arpegio activation arrA[i] = 0; } } if(arrA[i]){ count++; } } //if little active notes are found set freq emediatly if(count < 2 || TSelB){ frequency = input; } } void load(){ int address = 0; for(byte h=0; h<3; h++){ for(byte i=0; i<3; i++){ for(byte j=0; j<32; j++){ if(h == 0){ seqArray[i][j] = EEPROM.read(address); }else if(h == 1){ seqArrayB[i][j] = EEPROM.read(address); }else if(h == 2){ seqArrayAnalog[i][j] = EEPROM.read(address); } address++; } } } } void store(){ int address = 0; for(byte h=0; h<3; h++){ for(byte i=0; i<3; i++){ for(byte j=0; j<32; j++){ if(h == 0){ EEPROM.write(address, seqArray[i][j]); }else if(h == 1){ EEPROM.write(address, seqArrayB[i][j]); }else if(h == 2){ EEPROM.write(address, (byte)seqArrayAnalog[i][j]); } address++; } } } }