Posted by karthik
The Instrument:
We adapted the concept of a Theremin, as we felt it's really cool to be able to generate music with just motion and no contact. We also wanted to add a gaming aspect to the instrument, in effect making one player copy the hand motions of the other. The metaphor was someone dancing to match an instructor, but producing music as they went along.
The instrument consists of two pads, each with two light sensors. The left hand controls the octave, while the right hand controls the notes. The sound is output using the piezo speakers.
Modes:
Freestyle:
Go wild and play away in this mode! Lift your left hand high to scale the notes to higher octaves, while your right hand beats out the notes.
Game:
Here, Player2 has to match player1 for music to play. Player1 will play a note using a hand gesture, and the instrument will stay silent until Player2 uses an identical gesture.
Video:
http://www.youtube.com/watch?v=HzhTy-r_vIE
Code:
/* note frequency period PW (timeHigh)
* c 261 Hz 3830 1915
* d 294 Hz 3400 1700
* e 329 Hz 3038 1519
* f 349 Hz 2864 1432
* g 392 Hz 2550 1275
* a 440 Hz 2272 1136
* b 493 Hz 2028 1014
* C 523 Hz 1912 956
*
* (cleft) 2005 D. Cuartielles for K3
*/
int photo1a = A0;
int photo1b = A1;
int photo2a = A4;
int photo2b = A5;
int speakerPin1 = 3;
int speakerPin2 = 5;
int aval1a;
int aval1b;
int aval2a;
int aval2b;
int val1a;
int val1b;
int val2a;
int val2b;
int aval1;
int mode = 0;
int aval2;
int octave;
int note;
String note1;
char input;
float timeHigh;
float tones1[] = {
16.35, 18.35, 20.60, 21.83, 24.5, 27.5, 30.87};
int tones2[] = {
1960, 1850, 1746, 1648, 1555, 1468, 1385, 1308};
int tones3[] = {
1648, 1555, 1468, 1385, 1308,1960, 1850, 1746};
int tone1store;
void setup() {
Serial.begin(9600);
pinMode(speakerPin1, OUTPUT);
pinMode(speakerPin2, OUTPUT);
//ambient max
aval1a = analogRead(photo1a); // read value from the sensor
aval1b = analogRead(photo1b); // read value from the sensor
aval2a = analogRead(photo2a); // read value from the sensor
aval2b = analogRead(photo2b); // read value from the sensor
aval1 = aval1a*10+aval1b;
aval2 = aval2a*10+aval2b;
}
String Notemaker(int octave, int note)
// takes octave and note to return a string that minim reads Eg: C4, E3
{
String note1;
switch(note)
{
case 0: note1 = "C";
break;
case 1: note1 = "D";
break;
case 2: note1 = "E";
break;
case 3: note1 = "F";
break;
case 4: note1 = "G";
break;
case 5: note1 = "A";
break;
case 6: note1 = "B";
break;
}
note1 = note1+octave;
return note1;
}
void loop() {
if(Serial.available()>0){
input = Serial.read();
if((input == 'g')||(input == 'G')) {
mode = 1;
}
else if((input == 'f')||(input == 'F')) {
mode = 2;
}
}
if(mode == 1) {
digitalWrite(speakerPin1, LOW);
digitalWrite(speakerPin2, LOW);
val1a = abs(aval1a - analogRead(photo1a)); // read value from the sensor
val1b = abs(aval1b - analogRead(photo1b)); // read value from the sensor
int toneBase1 = val1a*10 + val1b;
int tone1 = map(toneBase1,0,aval1,0,7);
for( int i=0; i<50; i++ ) { // play it for 50 cycles
digitalWrite(speakerPin1, HIGH);
delayMicroseconds(tones2[tone1]);
digitalWrite(speakerPin1, LOW);
delayMicroseconds(tones2[tone1]);
}
int exit = 0;
while(exit==0) {
val2a = abs(aval2a - analogRead(photo2a)); // read value from the sensor
val2b = abs(aval2b - analogRead(photo2b)); // read value from the sensor
int toneBase2 = val2a*10 + val2b;
int tone2 = map(toneBase2,0,aval2,0,7);
if(abs(tone1-tone2)<1) {
for( int i=0; i<50; i++ ) { // play it for 50 cycles
digitalWrite(speakerPin2, HIGH);
delayMicroseconds(tones3[tone2]);
digitalWrite(speakerPin2, LOW);
delayMicroseconds(tones3[tone2]);
}
exit=1;
}
}
}
if(mode == 2) // freestyle
{
digitalWrite(speakerPin1, LOW);
digitalWrite(speakerPin2, LOW);
val1a = abs(aval1a - analogRead(photo1a)); // read value from the sensor
val1b = abs(aval1b - analogRead(photo1b)); // read value from the sensor
// calculate octave
if(val1a >= 200)
val1a = 200;
val1a = 200 - val1a;
octave = map(val1a,0,200,3,5);
// calculate note
if(val1b >= 200)
val1b = 200;
val1b = 200 - val1b;
note = map(val1b,0,200,0,6);
note1 = Notemaker(octave,note);
// play the note
float note2 = tones1[note];
Serial.print("note = ");
Serial.println(note2);
for(int i = 1;i<octave;i++)
note2 = note2*2;
timeHigh = 1000000.0/(2.0 * note2);
Serial.print("note2 ");
Serial.println(note2);
Serial.print("timeHigh ");
Serial.println(timeHigh);
Serial.print("octave ");
Serial.println(octave);
for( int i=0; i<8; i++ ) { // play it for 50 cycles
digitalWrite(speakerPin1, HIGH);
delayMicroseconds(timeHigh);
digitalWrite(speakerPin1, LOW);
delayMicroseconds(timeHigh);
}
// delayMicroseconds(100);
digitalWrite(speakerPin1,LOW);
//Serial.println(5);
val2a = abs(aval2a - analogRead(photo2a)); // read value from the sensor
val2b = abs(aval2b - analogRead(photo2b)); // read value from the sensor
// calculate octave
if(val2a >= 200)
val2a = 200;
val2a = 200 - val2a;
octave = map(val2a,0,200,3,5);
// calculate note
if(val2b >= 200)
val2b = 200;
val2b = 200 - val2b;
note = map(val1b,0,200,0,6);
note1 = Notemaker(octave,note);
// play the note
note2 = tones1[note];
Serial.print("note = ");
Serial.println(note2);
for(int i = 1;i<octave;i++)
note2 = note2*2;
timeHigh = 1000000.0/(2.0 * note2);
Serial.print("note2 ");
Serial.println(note2);
Serial.print("timeHigh ");
Serial.println(timeHigh);
Serial.print("octave ");
Serial.println(octave);
for( int i=0; i<8; i++ ) { // play it for 50 cycles
digitalWrite(speakerPin2, HIGH);
delayMicroseconds(timeHigh);
digitalWrite(speakerPin2, LOW);
delayMicroseconds(timeHigh);
}
// delayMicroseconds(100);
digitalWrite(speakerPin2,LOW);
}
}