This is a project I build long time ago and I wanted to post it again in the blog. I was previously published on No Label Available‘s page and on Cooking Hacks as well, as a hack receipt.

Zheremino it’s a Optical Midi Theremin. In this project I wanted to control synthesizers from a sensor with a Theremin-like method. That is, playing the instrument without touching it. Despite the Theremin, this project don’t play continous notes, without space between B3 and C4, for instance. I rather play with the natural keyboard transitions between notes. Due that, playing a scale sounds easy and you don’t have to worry too much about the pitch, if the synth is rigth tunned, of course.

The following two videos show how it works, connected to a Roland Juno-106.

The Arduino code I build for this project is this one:

#define Nmedidas 38 //Define how many measures must the sensor do.
#define notaBaja 59 //Define the lowest playable note
#define notaAlta 72 //Define the highest playable note

int value;
int avg;
int Navg;
int sum;
int i;
int nota;

void setup(){
Serial.begin(31250); //31250 MIDI baud rate
}
 void loop(){
// Sensor reading and averaging (avg) de Nmedidas
sum=0;
for (i=1; i<=Nmedidas; i++){
value=analogRead(0);
sum = sum + value;
}
avg =map( sum / Nmedidas,40,400,notaBaja,notaAlta);

//Case 1: There's no note change
//go to end doing nothing
if((avg==Navg)||((avg<notaBaja)&&(Navg<notaBaja)))
{ goto fin;}

//Case 2: There was a note but now there's not.
//must send "note off"
if((avg<=notaBaja)&&(Navg>=notaBaja)){  Navg=avg;
noteOn(0x80,nota,0);
delay(30);
goto fin;
}

//Case 3: There's a different note from the former one.
//Send "note Off" to the previous and play the actual.
if((avg>=notaBaja)&&(avg<=notaAlta)){
//avg=map(avg,40,400,80,64);
Navg=avg;
noteOn(0x80,nota,00);
nota=avg;
noteOn(0x90,nota,90);
delay(100);
}

/End label
fin:
 ;
}

// plays a MIDI note. Doesn't check to see that
// cmd is greater than 127, or that data values are less than 127:
void noteOn(char cmd, char data1, char data2) {
Serial.print(cmd,BYTE);
Serial.print(data1,BYTE);
Serial.print(data2,BYTE);
}
Anuncios