//Youtube mixer interface/sequencer, Gijs Gieskes 2010 //It is optimized for use with: http://gieskes.nl/browserjockey/youtube-mixer/ //midi library: //http://timothytwillman.com/itp_blog/?page_id=240 #include "Midi.h" unsigned long seqTimer = 0; byte pos = 0; unsigned long timeout = 0; //trigger vars boolean externalTrigger = false; boolean triggerActive = false; boolean inLoop = false; byte ledPins[5] = {12, 11, 8, 9, 10}; char sequence[3][128]; byte channel = 1; Midi midi(Serial); void setup() { //erase array for(byte i=0; i<128; i++){ sequence[0][i] = -1; sequence[1][i] = -1; sequence[2][i] = -1; } //keyboard contacts pinMode(13, INPUT); digitalWrite(13, HIGH); pinMode(14, INPUT); digitalWrite(14, HIGH); //mode pinMode(7, INPUT); digitalWrite(7, HIGH); //display pinMode(8, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(11, OUTPUT); pinMode(12, OUTPUT); pinMode(2, INPUT); digitalWrite(2, HIGH); attachInterrupt(0, triggerNormal, CHANGE); midi.begin(0); } void loop() { inLoop = true; if(digitalRead(7)){ sequencer(); }else{ selectVideo(); setVolume(); playSelect(); startStop(); delay(10); } } void rec(){ static byte pr0 = 0; static byte pr1 = 0; static byte pr2 = 0; byte r0 = map(analogRead(2), 0, 1023, 15, 0); byte r1 = map(analogRead(5), 0, 1023, 9, 0); byte r2 = map(analogRead(3), 0, 1023, 5, 0); //play select record(0, r0+36); //select video record(1, r1+24); //set volume record(2, r2+60); if(r0 != pr0){ pr0 = r0; setDisplay(r0); timeout = millis(); } if(r1 != pr1){ pr1 = r1; setDisplay(r1); timeout = millis(); } if(r2 != pr2){ pr2 = r2; setDisplay(r2); timeout = millis(); } } //recor to array void record(byte type, byte inp){ if(!digitalRead(14)){ sequence[type][pos] = inp; } if(!digitalRead(13)){ sequence[type][pos] = -1; } } inline void sequencer(){ if(triggerME(40)){ static char prev1 = -1; static char prev2 = -1; static byte prevlength = 255; byte length = map(analogRead(4), 0, 1023, 127, 0); if(length != prevlength){ prevlength = length; timeout = millis(); setDisplay(length); } pos++; if(pos > length){ pos = 0; } rec(); if(millis() - timeout > 1000){ setDisplay(pos >> 2); } if(sequence[0][pos] >= 0){ sendMIDImem(sequence[0][pos]); } //volume if(sequence[2][pos] >= 0 && sequence[2][pos] != prev2){ prev1 = -1; prev2 = sequence[2][pos]; sendMIDImem(sequence[2][pos]); } //video select if(sequence[1][pos] >= 0 && sequence[1][pos] != prev1){ prev1 = sequence[1][pos]; sendMIDImem(sequence[1][pos]); } } } inline void startStop(){ static boolean s = 0; if(!digitalRead(13)){ s = 0; sendMIDI(68); //stop while(!digitalRead(13)); } if(!digitalRead(14)){ if(s){ sendMIDI(67); //pause }else{ sendMIDI(66); //play } s = !s; while(!digitalRead(14)); } } inline void playSelect(){ static byte selVideo = 0; static byte preVideo = 0; selVideo = map(analogRead(2), 0, 1023, 15, 0); if(preVideo != selVideo){ preVideo = selVideo; sendMIDImem(selVideo+36); setDisplay(preVideo); } } //select a video inline void selectVideo(){ static byte selVideo = 0; static byte preVideo = 0; selVideo = map(analogRead(5), 0, 1023, 9, 0); if(preVideo != selVideo){ preVideo = selVideo; sendMIDImem(selVideo+24); setDisplay(preVideo); } } //set volume of selected video inline void setVolume(){ static byte setVol = 0; static byte preVol = 0; setVol = map(analogRead(3), 0, 1023, 5, 0); if(preVol != setVol){ preVol = setVol; sendMIDImem(preVol+60); setDisplay(preVol); } } void setDisplay(byte input){ for(byte i=0; i<5; i++){ if(bitRead(input, i)){ digitalWrite(ledPins[i], HIGH); }else{ digitalWrite(ledPins[i], LOW); } } } void sendMIDImem(byte newNote) { static byte lastNote = 0; if(newNote != lastNote){ lastNote = newNote; midi.sendNoteOn(channel, newNote, 127); } } void sendMIDI(byte newNote) { midi.sendNoteOn(channel, newNote, 127); } //if trigger use trigger, otherwise use millis.. boolean triggerME(int mil){ boolean retVal = false; if(!externalTrigger){ if(millis() - seqTimer > mil){ seqTimer = millis(); retVal = true; }else{ retVal = false; } }else if(triggerActive){ //reset trigger status, for trigger below triggerActive = false; retVal = true; } return retVal; } void triggerNormal(){ if(inLoop){ //set external trigger to true if there is a trigger signal.. externalTrigger = true; //set trigger to active, see above triggerActive = true; } }