This project was our version of a theremin. It was created by using a Leap Motion controller to read in the number of fingers over the sensor. This data was sent to the k64f for translation into musical notes and then sent to a speaker. Features include playing hard coded songs such as Ode to Joy, recording and playing your own music with a SD card, and changing octaves at any time.
Dependencies: SDFileSystem mbed
main.cpp
00001 //libraries 00002 #include "mbed.h" 00003 #include "SDFileSystem.h" // SD File System functions 00004 00005 PwmOut tone(PTC2); //create a PWM pin 00006 Serial pc(USBTX,USBRX); //create a COM port 00007 SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd"); //MOSI, MISO, clk, CS 00008 //switches 00009 DigitalIn sw2(SW2); //playback recording 00010 DigitalIn sw4(PTD1); //play a song 00011 DigitalIn sw5(PTD3); //start/end recording 00012 DigitalIn sw6(PTD2); //play a song 00013 //LEDs 00014 DigitalOut led1(LED_RED); 00015 DigitalOut led2(LED_GREEN); 00016 DigitalOut led3(LED_BLUE); 00017 DigitalOut recordLight(PTA2); 00018 //interrupts 00019 InterruptIn Interrupt1(SW3); //change the octave 00020 //defines 00021 #define MAXRECORDLENGTH 100 00022 #define ODE2JOYLENGTH 62 00023 #define JINGLELENGTH 51 00024 00025 //vars 00026 int tonelevel = 4; //Default octave 4 00027 int mode = 0; //mode=0 play //mode=1 record 00028 int recordLength = 0; //keep track of the actual length vs. the max length 00029 float record[MAXRECORDLENGTH]; //array for storing recorded tone 00030 00031 //determine which song is playing 00032 bool jingleSet = false; 00033 bool odeSet = false; 00034 00035 //####################################################################################################### 00036 float octave[7][12]={ 00037 {55.0,62.0,33.0,37.0,41.0,44.0,49.0,58.0,35.0,39.0,46.0,52.0}, //1 00038 {110.0,123.0,65.0,73.0,82.0,87.0,98.0,117.0,69.0,78.0,93.0,104.0}, //2 00039 {220.0,247.0,131.0,147.0,165.0,175.0,196.0,233.0,139.0,156.0,185.0,208.0}, //3 00040 {440.0,494.0,262.0,294.0,330.0,349.0,392.0,466.0,277.0,311.0,370.0,415.0}, //4 00041 {880.0,988.0,523.0,587.0,659.0,698.0,784.0,932.0,554.0,622.0,740.0,831.0}, //5 00042 {1760.0,1976.0,1047.0,1175.0,1319.0,1397.0,1568.0,1865.0,1109.0,1245.0,1480.0,1661.0}, //6 00043 {3520.0,3951.0,2093.0,2349.0,2637.0,2794.0,3136.0,3729.0,2217.0,2489.0,2960.0,3322.0} //7 00044 }; 00045 //####################################################################################################### 00046 float starwars[]={octave[2][2],octave[2][6],octave[2][5],octave[2][4],octave[2][3],octave[3][2], 00047 octave[2][2],octave[2][6],octave[2][5],octave[2][4],octave[2][3],octave[3][2], 00048 octave[2][6],octave[2][5],octave[2][4],octave[2][5],octave[2][3] 00049 }; 00050 //####################################################################################################### 00051 float ode2joy[]= {octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][5],octave[tonelevel][6],octave[tonelevel][6],octave[tonelevel][5],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][2],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][3], 00052 octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][5],octave[tonelevel][6],octave[tonelevel][6],octave[tonelevel][5],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][2],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][2],octave[tonelevel][2], 00053 octave[tonelevel][3],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][5],octave[tonelevel][4],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][5],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][2], 00054 octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][5],octave[tonelevel][6],octave[tonelevel][6],octave[tonelevel][5],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][2],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][2],octave[tonelevel][2]}; 00055 //####################################################################################################### 00056 float jingle[]={octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][6],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][4], 00057 octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4], 00058 octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][6], 00059 octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][6],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][4], 00060 octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4], 00061 octave[tonelevel][6],octave[tonelevel][6],octave[tonelevel][5],octave[tonelevel][3],octave[tonelevel][2]}; 00062 //####################################################################################################### 00063 int ode2joyNotes[] = {4,4,5,6,6,5,4,3,2,2,3,4,4,3,3,4,4,5,6,6,5,4,3,2,2,3,4,3,2,2,3,3,4,2,3,4,5,4,2,3,4,5,4,3,2,3,2,4,4,5,6,6,5,4,3,2,2,3,4,3,2,2}; 00064 //####################################################################################################### 00065 int jingleNotes[] = {4,4,4,4,4,4,4,6,2,3,4,5,5,5,5,5,4,4,4,4,4,3,3,4,3,6,4,4,4,4,4,4,4,6,2,3,4,5,5,5,5,5,4,4,4,4,6,6,5,3,2}; 00066 //####################################################################################################### 00067 int tempo[]={600,400,400,400,500,600,400,400,400,500,600,400,400,400,400,400,1000}; 00068 //####################################################################################################### 00069 int tempo2[]={400,400,400,400,400,400,400,400,400,400,400,400,600,200,650, 00070 400,400,400,400,400,400,400,400,400,400,400,400,600,200,650, 00071 400,400,400,400,400,200,200,400,400,400,200,200,400,400,400,400,650, 00072 400,400,400,400,400,400,400,400,400,400,400,400,600,200,1000}; 00073 //####################################################################################################### 00074 int tempo3[]={400,400,500,350,350,500,350,350,350,350,700, 00075 400,400,400,350,350,350,400,150,600, 00076 400,400,400,400,450,600, 00077 400,400,500,350,350,500,350,350,350,350,700, 00078 400,400,400,350,350,350,400,150,600, 00079 400,400,400,400,600}; 00080 //####################################################################################################### 00081 00082 //function prototypes 00083 void changeOctave(void); 00084 bool writeSD(void); 00085 bool readSD(void); 00086 bool removeFile(void); 00087 00088 int main() 00089 { 00090 //INITIALIZATIONS 00091 tone = 0; //volume (duty cycle) 00092 int recordCounter = 0; //used to count up to max number of notes 00093 00094 led1 = 1; //turn all LEDs off 00095 led2 = 1; 00096 led3 = 1; 00097 recordLight = 0; 00098 00099 pc.baud(9600); //set baud 00100 00101 Interrupt1.fall(&changeOctave); //detect interrupt on falling edge and call ISR 00102 00103 //BEGIN LOOP 00104 while (true) 00105 { 00106 //CHECK SW4 -- determine if we should play this song 00107 if(sw4 == 1) 00108 { 00109 led3 = !led3; 00110 odeSet = true; 00111 for(int i=0;i<ODE2JOYLENGTH;i++) 00112 { 00113 tone=0.5; 00114 tone.period(1/ode2joy[i]); 00115 wait_ms(tempo2[i]); 00116 } 00117 odeSet = false; 00118 tone=0; 00119 }//end sw4 00120 00121 //CHECK SW6 -- determine if we should play this song 00122 if(sw6 == 1) 00123 { 00124 led2 = !led2; 00125 jingleSet = true; 00126 for(int i=0;i<JINGLELENGTH;i++) 00127 { 00128 tone=0.5; 00129 tone.period(1/jingle[i]); 00130 wait_ms(tempo2[i]); 00131 } 00132 jingleSet = false; 00133 tone=0; 00134 }//end sw6 00135 00136 //mode 0 just recieves a character from the COM port, looks up the corresponding node 00137 //and plays it over the speaker at a 50% duty cycle (loudest volume available) 00138 if(mode==0 && pc.readable()) 00139 { 00140 switch(pc.getc()) //Note selection 00141 { 00142 case 'a': 00143 tone=0.5; 00144 tone.period(1/octave[tonelevel][0]); 00145 break; 00146 case 'b': 00147 tone=0.5; 00148 tone.period(1/octave[tonelevel][1]); 00149 break; 00150 case 'c': 00151 tone=0.5; 00152 tone.period(1/octave[tonelevel][2]); 00153 break; 00154 case 'd': 00155 tone=0.5; 00156 tone.period(1/octave[tonelevel][3]); 00157 break; 00158 case 'e': 00159 tone=0.5; 00160 tone.period(1/octave[tonelevel][4]); 00161 break; 00162 case 'f': 00163 tone=0.5; 00164 tone.period(1/octave[tonelevel][5]); 00165 break; 00166 case 'g': 00167 tone=0.5; 00168 tone.period(1/octave[tonelevel][6]); 00169 break; 00170 case 'h': 00171 tone=0.5; 00172 tone.period(1/octave[tonelevel][7]); 00173 break; 00174 case 'i': 00175 tone=0.5; 00176 tone.period(1/octave[tonelevel][8]); 00177 break; 00178 case 'j': 00179 tone=0.5; 00180 tone.period(1/octave[tonelevel][9]); 00181 break; 00182 case 'k': 00183 tone=0.5; 00184 tone.period(1/octave[tonelevel][10]); 00185 break; 00186 case 'l': 00187 tone=0.5; 00188 tone.period(1/octave[tonelevel][11]); 00189 break; 00190 case 'm': 00191 tone=0.5; 00192 tone.period(1/octave[tonelevel][11]); 00193 break; 00194 default: //in the default case mute the sound 00195 tone=0; 00196 }//end switch 00197 00198 }//end if mode 0 00199 00200 00201 //CHECK SW5 -- Go to recording mode 00202 if(sw5 == 1) 00203 { 00204 while(sw5 == 1); 00205 mode = 1; 00206 led1 = !led1; 00207 //reset length when we record a new song 00208 recordLength = 0; 00209 //delete the current recording before storing a new one 00210 removeFile(); 00211 } 00212 00213 00214 //record notes and set mode back to 0 00215 if(mode==1) 00216 { 00217 tone=0.5; 00218 //play a tone to let user know they can record 00219 tone.period(1/octave[3][6]); 00220 wait_ms(500); 00221 tone.period(1/octave[5][6]); 00222 wait_ms(500); 00223 tone.period(1/octave[3][6]); 00224 wait_ms(500); 00225 tone.period(1/octave[5][6]); 00226 wait_ms(500); 00227 tone=0; 00228 00229 //read until we have reached max record length 00230 while(recordCounter < MAXRECORDLENGTH ) 00231 { 00232 switch(pc.getc()) //Note selection 00233 { 00234 case 'a': 00235 record[recordCounter]=octave[tonelevel][0]; 00236 tone=0.5; 00237 tone.period(1/octave[tonelevel][0]); 00238 00239 break; 00240 case 'b': 00241 record[recordCounter]=octave[tonelevel][1]; 00242 tone=0.5; 00243 tone.period(1/octave[tonelevel][1]); 00244 00245 break; 00246 case 'c': 00247 record[recordCounter]=octave[tonelevel][2]; 00248 tone=0.5; 00249 tone.period(1/octave[tonelevel][2]); 00250 00251 break; 00252 case 'd': 00253 record[recordCounter]=octave[tonelevel][3]; 00254 tone=0.5; 00255 tone.period(1/octave[tonelevel][3]); 00256 break; 00257 case 'e': 00258 record[recordCounter]=octave[tonelevel][4]; 00259 tone=0.5; 00260 tone.period(1/octave[tonelevel][4]); 00261 00262 break; 00263 case 'f': 00264 record[recordCounter]=octave[tonelevel][5]; 00265 tone=0.5; 00266 tone.period(1/octave[tonelevel][5]); 00267 00268 break; 00269 case 'g': 00270 record[recordCounter]=octave[tonelevel][6]; 00271 tone=0.5; 00272 tone.period(1/octave[tonelevel][6]); 00273 00274 break; 00275 case 'h': 00276 record[recordCounter]=octave[tonelevel][7]; 00277 tone=0.5; 00278 tone.period(1/octave[tonelevel][7]); 00279 00280 break; 00281 case 'i': 00282 record[recordCounter]=octave[tonelevel][8]; 00283 tone=0.5; 00284 tone.period(1/octave[tonelevel][8]); 00285 00286 break; 00287 case 'j': 00288 record[recordCounter]=octave[tonelevel][9]; 00289 tone=0.5; 00290 tone.period(1/octave[tonelevel][9]); 00291 00292 break; 00293 case 'k': 00294 record[recordCounter]=octave[tonelevel][10]; 00295 tone=0.5; 00296 tone.period(1/octave[tonelevel][10]); 00297 tone=0; 00298 break; 00299 case 'l': 00300 record[recordCounter]=octave[tonelevel][11]; 00301 tone=0.5; 00302 tone.period(1/octave[tonelevel][11]); 00303 00304 break; 00305 case 'm': 00306 record[recordCounter]=octave[tonelevel][11]; 00307 tone=0.5; 00308 tone.period(1/octave[tonelevel][11]); 00309 00310 break; 00311 default: //use a dummy note that will never get played in the default case 00312 record[recordCounter]=octave[6][6]; 00313 tone=0; 00314 }//end switch 00315 00316 recordCounter++; 00317 recordLight = !recordLight; 00318 00319 //CHECK SW5 -- start or end recording 00320 if(sw5 == 1) 00321 { 00322 while(sw5 == 1); 00323 mode=1; 00324 led1 = !led1; 00325 recordLength = recordCounter; 00326 break; 00327 } 00328 00329 }//end while 00330 recordCounter = 0; 00331 mode = 0; 00332 recordLight = 0; 00333 00334 //play a tone to let user know they are done 00335 tone=0.5; 00336 tone.period(1/octave[3][6]); 00337 wait_ms(500); 00338 tone.period(1/octave[5][6]); 00339 wait_ms(500); 00340 tone.period(1/octave[3][6]); 00341 wait_ms(500); 00342 tone.period(1/octave[5][6]); 00343 wait_ms(500); 00344 tone=0; 00345 //write to the SD card after recording 00346 writeSD(); 00347 00348 }//end if 00349 00350 //play recored notes 00351 if(mode==0 && sw2==0) 00352 { 00353 if(readSD() == true) 00354 { 00355 tone = 0.5; 00356 for(int i=0;i<recordLength;i++) 00357 { 00358 if(record[i]==octave[6][6]) 00359 tone=0; 00360 else 00361 tone=0.5; 00362 00363 tone.period(1/record[i]); 00364 //play the recording back a little faster than it was recorded 00365 wait_ms(450); 00366 } 00367 led1 = !led1; 00368 tone=0; 00369 } 00370 }//end play 00371 led1 = !led1; 00372 wait_ms(100); 00373 00374 }//end main while loop 00375 00376 }//main closes 00377 00378 //used to change the current octave even in the middle of playing a preset song but 00379 //has no effect during playback of recorded music 00380 void changeOctave() 00381 { 00382 tonelevel+=1; 00383 if(tonelevel > 6) 00384 tonelevel = 2; 00385 led2 = !led2; 00386 00387 //account for change in octave level 00388 if(odeSet == true) 00389 { 00390 for(int i=0; i<ODE2JOYLENGTH; i++) 00391 { 00392 ode2joy[i] = octave[tonelevel][ode2joyNotes[i]]; 00393 } 00394 } 00395 else if(jingleSet == true) 00396 { 00397 for(int i=0; i<JINGLELENGTH; i++) 00398 { 00399 jingle[i]= octave[tonelevel][jingleNotes[i]]; 00400 } 00401 } 00402 }//end change octave 00403 00404 //Write to the SD card 00405 bool writeSD() 00406 { 00407 FILE *fp = fopen("/sd/sdfile.txt", "w"); // open file for writing 00408 00409 if (fp==NULL) 00410 { 00411 pc.printf("Could not open file to write\n"); 00412 return false; 00413 } 00414 else 00415 { 00416 pc.printf("SC card opened\r\n"); 00417 //wait_ms(1000); 00418 } 00419 00420 if(fprintf(fp, "%d", recordLength)) //first store the size of the array 00421 pc.printf("Write of length of sucessful and it is %d\r\n\n", recordLength); 00422 00423 //wait_ms(1000); 00424 fprintf(fp, " "); //delimit the values 00425 00426 for(int i=0; i<recordLength; i++) //copy all values over 00427 { 00428 if(fprintf(fp, "%f", record[i])) 00429 { 00430 fprintf(fp," "); //delimit the values 00431 pc.printf("Number of tones stored is : %d\r\n\n", i+1); 00432 pc.printf("The tone is %f \r\n", record[i]); 00433 } 00434 } 00435 //wait_ms(1000); 00436 fclose(fp); 00437 00438 return true; 00439 }//end write 00440 00441 //read from a SD card 00442 bool readSD() 00443 { 00444 FILE *fp = fopen("/sd/sdfile.txt", "r"); // open file for writing 00445 00446 if (fp==NULL) 00447 { 00448 pc.printf("Could not open file to write\n"); 00449 return false; 00450 } 00451 else 00452 { 00453 pc.printf("SC card opened\r\n"); 00454 //wait_ms(1000); 00455 } 00456 00457 00458 00459 if(fscanf(fp, "%d", &recordLength)) //first read the size of the array 00460 { 00461 pc.printf("Write of length of sucessful and its value is %d\r\n\n", recordLength); 00462 //wait_ms(1000); 00463 } 00464 else 00465 return false; 00466 00467 for(int i=0; i<recordLength; i++) //copy all values over 00468 { 00469 if(fscanf(fp, "%f", &record[i])) 00470 pc.printf("Tone stored is %f\r\n\n", record[i]); 00471 else 00472 return false; 00473 } 00474 //wait_ms(1000); 00475 fclose(fp); 00476 return true; 00477 }//end read 00478 00479 //remove the file from the SD card before we create a new one 00480 bool removeFile() 00481 { 00482 //create a string 00483 char filename[] = "/sd/sdfile.txt"; 00484 00485 int ret = remove(filename); 00486 00487 if(ret == 0) 00488 { 00489 pc.printf("File deleted successfully"); 00490 return false; 00491 } 00492 else 00493 { 00494 pc.printf("Error: unable to delete the file"); 00495 } 00496 return true; 00497 }
Generated on Sat Jul 30 2022 21:52:03 by 1.7.2