//Gijs Gieskes 2010 //Modified version of part of Synth Car V2 (wavtable radar synth) //This one has a button that can be used to set the wave form playback frequency. //A midi keyboard can be used to pitch the wavtable to notes, and there is a arpegiator. //http://gieskes.nl/instruments/?file=wavetable-radar //for use with: GP2Y0A21YK0F. //midi library: //http://timothytwillman.com/itp_blog/?page_id=240 #include "Midi.h" byte wave[256]; byte frame = 0; unsigned long time = 0; byte recTime = 10; int frequency = 50; byte position = 0; volatile byte volume = 0; //mode type byte mode = 2; //analog values int AV4 = 100; int AV5 = 100; byte scale[33] = { 239, 226, 213, 201, 190, 179, 169, 160, 150, 142, 134, 126, 119, 112, 106, 100, 94, 89, 84, 79, 75, 71, 67, 63, 59, 56, 53, 50, 47, 44, 42, 39, 37 }; //if wtl == 255 //5: c=29 //4: b=31 a#=33 a=35 g#=37 g=39 f#=42 f=44 e=47 d#=50 d=53 c#=56 c=59 //3: b=63 a#=67 a=71 g#=75 g=79 f#=84 f=89 e=94 d#=100 d=106 c#=112 c=119 //2: b=126 a#=134 a=142 g#=150 g=160 f#=169 f=179 e=190 d#=201 d=213 c#=226 c=239 byte wtl = 255; //midi boolean midiActive = false; boolean prevState = false; int midiNotes[3] = {0,0,0}; byte incomingByte = 0; byte note = 0; boolean noteDown = LOW; int state = 0; byte mainchannel = 1; //midi seq byte activeNotes[25]; byte activeCount = 1; unsigned long timeArp = 0; byte platBackMode = 1; boolean hold = true; class MyMidi : public Midi { public: // Need this to compile; it just hands things off to the Midi class. MyMidi(HardwareSerial &s) : Midi(s) {} void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity) { mode = 2; midiActive = true; midiHandler(channel, note, true); } void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity) { midiHandler(channel, note, false); } }; MyMidi midi(Serial); void setup() { pinMode(2, INPUT); digitalWrite(2, HIGH); pinMode(4, OUTPUT); pinMode(9, OUTPUT); cli(); TCCR1B = TCCR1B & B11111000 | B00000001; TCCR2A = TCCR2A & B11111000 | B00000010; TCCR2B = TCCR2B & B11111000 | B00000010; TIMSK2 = TIMSK2 & B11111000 | B00000010; OCR2A = frequency; sei(); midi.begin(0); } //From TIMSK2 ISR(TIMER2_COMPA_vect) { frame++; if(frame > wtl){frame = 0;} OCR2A = frequency; analogWrite(9, (wave[frame] >> volume)); } void loop() { midi.poll(); //midi note player and arpegiator.. if(millis() - timeArp > (((1023-AV4) >> 1)+10)){ timeArp = millis(); if(midiActive){ if(platBackMode == 0){ //check for active notes. for(byte i=0; i<25; i++){ activeCount++; activeCount %= 25; //if active note is found use it and break. if(activeNotes[activeCount] > 37){ frequency = activeNotes[activeCount]; break; } } }else if(platBackMode == 1){ //check for active notes. for(byte i=0; i<25; i++){ if(activeCount){ activeCount--; }else{ activeCount = 24; } //if active note is found use it and break. if(activeNotes[activeCount] > 37){ frequency = activeNotes[activeCount]; break; } } }else if(platBackMode == 2){ //check for active notes. for(byte i=0; i<25; i++){ activeCount++; activeCount %= 25; //if active note is found use it and break. if(activeNotes[activeCount] > 37 && random(2)){ frequency = activeNotes[activeCount]; break; } } } } } static byte frameCounter = 0; //Set interval for recording wave form. if(millis() - time > recTime){ time = millis(); frameCounter++; frameCounter %= wtl; AV4 = 1023 - analogRead(4); AV5 = analogRead(5); if(!digitalRead(2)){ if(prevState){ prevState = false; if(!midiActive){ mode++;//AV4 >> 7; mode %= 4; }else{ hold++; hold %= 2; } } }else{ prevState = true; } if(mode == 0){ volume = 0; //playback frequency frequency = (AV4 >> 4)+61; //record to array, use max to cutoff sensor noise.. wave[frameCounter] = map(constrain(AV5, 68, 630), 68, 630, 0, 255); }else if(mode == 1){ //sensor records wave form volume = 0; //playback frequency frequency = ((1023-AV4) >> 4) + 123; //record to array, use max to cutoff sensor noise.. wave[frameCounter] = map(constrain(AV5, 68, 630), 68, 630, 0, 255); }else if(mode == 2){ //sensor records wave form volume = 0; //if midi available use midi note.. if(!midiActive){ byte selNote = map((AV4 >> 3), 0, 127, 5, 24); frequency = scale[selNote]; sendMidi(selNote+36); } if((midiActive && hold) || (!midiActive)){ //record to array, use max to cutoff sensor noise.. wave[frameCounter] = map(constrain(AV5, 68, 630), 68, 630, 0, 255);//max(map(AV5, 0, 700, 0, 255), 20); } }else if(mode == 3){ //sensor sets playback frequency in notes //pot sets playback frequency frequency = scale[map(constrain(AV5, 68, 630), 68, 630, 25, 0)]; sendMidi(map(constrain(AV5, 68, 630), 68, 630, 25, 0) + 36); if(AV5 < 77){ //put -- inside min/max, helps to prevent crash... also not higher then 5. volume = min(volume++, 8); }else{ volume = max(volume--, 0); } //use AV4 to fill wave with "random" or wtr values. if(AV4 > 512){ wave[frameCounter] = random(255); }else{ wave[frameCounter] = map(constrain(AV5, 68, 630), 68, 630, 0, 255); } } //blink light at start of wave form if(frameCounter){ digitalWrite(4, LOW); }else{ digitalWrite(4, HIGH); } } } void midiHandler(byte channel, byte note, boolean onOff){ if(channel == mainchannel){ if((note > 34) && (note < 61)){ byte noteIn = note - 36; //some keyboards don't send note off.. if(!onOff){ //scale over array, and reset note value. activeNotes[noteIn] = 0; midi.sendNoteOff(mainchannel, note, 0); }else{ //set emediatly so there are no missing notes when arp is slow checkIfActiveNote(scale[noteIn]); //scale over array, and set note value. activeNotes[noteIn] = scale[noteIn]; midi.sendNoteOn(mainchannel, note, 127); } }else if(note >= 61){ if(note == 61){ wtl = 255; recTime = 10; }else if(note == 62){ wtl = 127; recTime = 20; }else if(note == 63){ wtl = 63; recTime = 40; }else if(note == 64){ wtl = 32; //should be 31? but 32 sounds better recTime = 80; }else if(note == 65){ platBackMode = 0; //arp up }else if(note == 66){ platBackMode = 1; //arp down }else if(note == 67){ platBackMode = 2; //random arp } } } } void checkIfActiveNote(int input){ byte count = 0; //check for active notes for(byte i=0; i<25; i++){ if(activeNotes[i]){ count++; } } //if little active notes are found set freq emediatly if(count < 2){ frequency = input; } } void sendMidi(int noteIn){ static int noteHolder; if(noteIn != noteHolder){ midi.sendNoteOff(mainchannel, noteHolder, 0); noteHolder = noteIn; midi.sendNoteOn(mainchannel, noteIn, 127); } }