// Arduino HSS2a // Gijs Gieskes, start project januari 2008 // script: hss2 v10.2 // http://gieskes.nl //analog Read bool boolean anaRTF = false; //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} }; byte seqCounter = 0; byte seqBank = 0; byte seqSpeed = 100; byte seqLength = 31; byte seqRand = 0; byte midiClockCounter = 0; boolean seqMode = false; boolean seqStart = true; //analog in pins byte inputPinA[] = {4,1,2,3}; 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 pin7state = HIGH; boolean ledPin = HIGH; void setup() { analogReference(INTERNAL); DDRB = B111111; DDRD = DDRD & B10000011; //65432 zijn nu inputs for(byte i=1; i<8; i++){ pinMode(i, INPUT); digitalWrite(i, HIGH); } //led pinMode(14, OUTPUT); //led pin pinMode(19, OUTPUT); digitalWrite(19, ledPin); //Serial.begin(31250); //midiInCheck(); } 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> 2; ReadPINDa = ~ReadPINDa; ReadPINDb = (ReadPINDa >> 3) & 3; ReadPINDa = ReadPINDa & 7; if(seqMode){ midiClockIn(); }else{ standAlone(); } //pin states pin7state = digitalRead(7); pin1state = digitalRead(1); if(pin1state == HIGH){ if(pin7state == HIGH){ //record pins 2,3,4 if(ReadPINDa != 0){ seqArray[seqBank][seqCounter] = ReadPINDa; seqArrayAnalog[seqBank][seqCounter] = analogRead(1); //analog pot 1 animation anaRTF = true; } //record pins 5,6 if(ReadPINDb != 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: seqLength = analogRead(1) >> 5; //shift to make 32 anaRTF = true; break; case 4: seqRand = 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; } } //Serial.print(ReadPINDa, BIN); //Serial.print(" - "); //Serial.println(ReadPINDb, BIN); 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; } void randPlay(){ switch(seqRand){ case 0: break; case 1: seqArray[seqBank][seqCounter] = random(1, 8); break; case 2: seqArray[seqBank][seqCounter] = random(1, 8); seqArrayAnalog[seqBank][seqCounter] = random(1024); break; case 3: seqArray[seqBank][seqCounter] = random(1, 8); seqArrayB[seqBank][seqCounter] = random(1, 4); seqArrayAnalog[seqBank][seqCounter] = 0; break; } } byte prevSeqCount = 0; int analogTstorage[] = {10,10}; int analogReadF(byte input){ if(input == 1 && seqArrayAnalog[seqBank][seqCounter] != 0){ if(seqArrayAnalog[seqBank][seqCounter] < analogTstorage[seqBank]){ analogTstorage[seqBank] -= 16; }else if(seqArrayAnalog[seqBank][seqCounter] > analogTstorage[seqBank]){ analogTstorage[seqBank] += 16; } analogTstorage[seqBank] = constrain(analogTstorage[seqBank], 0, 1023); return analogTstorage[seqBank]; }else{ return analogRead(inputPinA[input]); } } void midiInCheck(){ //activate midi or not.. delay(100); if(Serial.available() > 0){ seqMode = true; }else{ seqMode = false; } } 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++; } //random shit randPlay(); } } void midiClockIn(){ if(Serial.available() > 0){ if(Serial.read() == 248){ midiClockCounter++; if(midiClockCounter > 5){ ledPin = !ledPin; digitalWrite(19, ledPin); midiClockCounter = 0; seqCounter++; if(seqCounter > seqLength){seqCounter = 0;} //random shit randPlay(); } Serial.flush(); //test.. } } } //sample rate / pitch int delayF(){ return (int) ((analogReadF(1)*2)+1); //sample rate } //output to audio void aWrite(byte i){ amArrCappture(i); PORTB = PORTB & B000000; PORTB = PORTB | i; } //output to audio void aWrite2(byte i){ PORTB = PORTB & B000000; PORTB = PORTB | 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. } }