// HSS2b // Gijs Gieskes, start project == januari 2008 // http://gieskes.nl //sequencers unsigned long prevMillis = 0; byte seqArray[2][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} }; byte seqArrayB[2][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} }; int seqArrayAnalog[2][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} }; //interupt vars volatile byte seqCounter = 0; volatile byte seqLength = 31; volatile boolean ledPin = HIGH; byte seqBank = 0; byte 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 //{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; byte ReadPINDb; boolean pin1state = HIGH; boolean pin8state = HIGH; void setup() { analogReference(INTERNAL); //speed up PWM on pin 9 and 10: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1235060559 TCCR1B = TCCR1B & 0b11111000 | 0x01; for(byte i=3; i<8; i++){ pinMode(i, INPUT); digitalWrite(i, HIGH); } pinMode(1, INPUT); digitalWrite(1, HIGH); pinMode(8, INPUT); digitalWrite(8, HIGH); //led pin pinMode(19, OUTPUT); digitalWrite(19, ledPin); if(digitalRead(8) == LOW){ seqMode = true; attachInterrupt(0, triggerNormal, RISING); } //Serial.begin(9600); } void loop(){ butReadTSelA(); //1-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//- //1-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//- //1-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//-//- //Synth 1 if(seqArray[seqBank][seqCounter] == 1){ VDFinalTB = 0; VDFoptelB = 0; VDFSpeedB = 0; VirtDelFunctionB(15); S1volume = 64; S1volumeT = 1; while(seqArray[seqBank][seqCounter] == 1){ VDFSpeed = (int) (32-(analogReadF(3)/32)); //vibrato speed VirtDelFunction(15); delV = delayF(); //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); delayMicroseconds(2049 - delV); } butReadTSelA(); } //Synth 2 }else if(seqArray[seqBank][seqCounter] == 2){ //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(seqArray[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); } 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(); } //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 = (analogRead(1)/6)+2; //playback speed select 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(); ledPin = !ledPin; digitalWrite(19, ledPin); //sequencer playback array selectors prevSeqCount = seqCounter; if(seqCounter > seqLength){ seqCounter = 0; }else{ seqCounter++; } } } void triggerNormal(){ //led pin on off. ledPin = !ledPin; digitalWrite(19, ledPin); //increase counter seqCounter++; if(seqCounter > seqLength){ seqCounter = 0; } } //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. } }