This sequencer scans images, and plays the image as midi notes.
It uses LDRs to measure the gray-scale of specific point of a image, and triggers midi notes from a selected threshold. When the threshold is reached the velocity will be set by the darkness at that point. the darker point the higher the velocity will be.
The sequencer plays the notes as a arpeggiator, i chose for this playback method because i dont have a midi device that can play 24 keys at the same time.. There are 2 different arpeggio modes. One rearranges the playback sequence to the active notes velocitys. And the second mode changes the arpeggio playback speed to the amount of notes that are active. If this mode is not selected the playback speed is set by a potentiometer. These modes can also be combined.
The sequencer has 24 LDRs that are read into 3 ADC ports of the arduino, via 3 4051 ics.
The image that i used for the midi sequence in the demo movie below, is a modified version of Treatise by Cornelius Cardew. And the instrument used to play the melody is a micro modular.
I also made script in PHP that generates images that can be played back on the sequencer. The script can be found here. (It is a smaller version then the one i printed, but every time it reloads it will be different).
A smaller version of this image is shown below..
I also added a script, so the scanner can be used to scan images.. You can see a example in the picture and demo movie below.
The scripts to scan images can be found here.
//Image Scan Sequencer, by: Gijs Gieskes 2008 //Copyleft: This is a free work, you can copy, distribute, and modify it //under the terms of the Free Art License: //http://artlibre.org/licence/lal/en/ //MIDI byte setNoteOn = 0x90; byte setNoteOff= 0x80; byte pitch = 65; int velocity = 0; int arpegiator = 0; long prevMillis = 0; byte stateArrCounter = 0; byte arpCounter = 0; byte prevPitch = 0; boolean enableNoteOff = true; boolean rearangeYesNo = false; boolean arpegiatorYesNo = false; boolean read11 = HIGH; int noteOnRange = 0; //multiplex variables int multiArray[3][8] = { {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 stateArray[3][24]= { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; void setup() { DDRB = DDRB | B00000111; // 10, 9, 8 zijn outputs pinMode(11, INPUT); digitalWrite(11, HIGH); //baut reet: Serial.begin(31250); //Serial.begin(9600); } void loop() { //read multiplexor inputs readAnalogs(); switcher(); //bepaalt de hoeveelheid noten die gespeelt worden in de arpegio. stateArrCounter = 0; //modify/organize recieved data for(byte i=0; i<3; i++){ for(byte j=0; j<8; j++){ int avals = multiArray[i][j]; velocity = (noteOnRange - avals); //inverse velocity = map(velocity, 0, noteOnRange, 0, 127); //bazeer de velocity op de noteOnRange. velocity = constrain(velocity, 0, 127); //voor de zekerheid.. if(avals <= noteOnRange){ stateArray[0][stateArrCounter] = setNoteOn; stateArray[1][stateArrCounter] = pitch; stateArray[2][stateArrCounter] = velocity; stateArrCounter++; }else{ stateArray[0][stateArrCounter] = setNoteOff; } pitch++; } } //als er weinig noten zijn word de arpegiator speed hoger. if(arpegiatorYesNo == true){ arpegiator = (stateArrCounter*16)+10; } //re-organize and send data as arpegio if(millis() - prevMillis > arpegiator) { prevMillis = millis(); if(rearangeYesNo == true){ rearangeToVel(); //reanrange notes to velocity } arpCounter++; if(arpCounter >= stateArrCounter){arpCounter = 0;} byte arpOnOff = stateArray[0][arpCounter]; byte arpInPitch = stateArray[1][arpCounter]; byte arpInVel = stateArray[2][arpCounter]; if(arpInPitch != prevPitch){ sendMIDI(setNoteOn, arpInPitch, arpInVel); } if(arpCounter == 0 && arpOnOff == setNoteOff && enableNoteOff == true){ sendMIDI(setNoteOff, arpInPitch, 0); enableNoteOff = false; //set note off once } if(arpInPitch != prevPitch){ //turn off the last played note sendMIDI(setNoteOff, prevPitch, 0); enableNoteOff = true; //set note off once } prevPitch = arpInPitch; } //just some delay delay(8); } //http://itp.nyu.edu/physcomp/Labs/MIDIOutput void sendMIDI(char sb, char data1, char data2) { Serial.print(sb, BYTE); Serial.print(data1, BYTE); Serial.print(data2, BYTE); } //lees de multiplex LDRs in void readAnalogs(){ for(byte i=0; i<8; i++){ PORTB &= B11111000; PORTB |= i; //schijf naar poort 10,9,8 delayMicroseconds(3); //geef de multiplexor de teid om te schakelen.. multiArray[0][i] = analogRead(0); multiArray[1][i] = analogRead(1); multiArray[2][i] = analogRead(2); } } //http://www.arduino.cc/playground/Main/DigitalSmooth void rearangeToVel(){ boolean done = 0; // flag to know when were done sorting byte temp0 = 0; byte temp1 = 0; byte temp2 = 0; while(done != 1){ // simple swap sort, sorts numbers from lowest to highest done = 1; for (byte j = 0; j < (stateArrCounter - 1); j++){ if (stateArray[2][j] > stateArray[2][j + 1]){ // numbers are out of order - swap temp0 = stateArray[0][j + 1]; temp1 = stateArray[1][j + 1]; temp2 = stateArray[2][j + 1]; stateArray[0][j+1] = stateArray[0][j] ; stateArray[1][j+1] = stateArray[1][j] ; stateArray[2][j+1] = stateArray[2][j] ; stateArray[0][j] = temp0; stateArray[1][j] = temp1; stateArray[2][j] = temp2; done = 0; } } } } void switcher(){ read11 = digitalRead(11); int Aread4T = analogRead(4); int Aread5T = analogRead(5); if(read11 == LOW){ if(Aread4T < 512){ noteOnRange = Aread5T/2; pitch = 65; }else{ //switch to select different types of playback (rearange to vel and vel dendant speed). if(Aread5T < 255){ rearangeYesNo = true; arpegiatorYesNo = false; }else if(Aread5T < 512 && Aread5T >= 255){ rearangeYesNo = false; arpegiatorYesNo = true; }else if(Aread5T < 765 && Aread5T >= 512){ rearangeYesNo = false; arpegiatorYesNo = false; }else{ rearangeYesNo = true; arpegiatorYesNo = true; } pitch = 65; } }else{ pitch = (Aread5T/10)+1; arpegiator = ((1023 - Aread4T)/2)+1; } }























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































