Michael Dushkoff / Music Featured

Dependents:   SuperMbedBall Tono

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Music.cpp Source File

Music.cpp

00001 /* * * * * * * * * * * * * * * * * * * * * * * * * * *
00002  * This is a simple music library for the mbed.      *
00003  *                                                   *
00004  * Created by: Michael Dushkoff (mad1841@rit.edu)    *
00005  * * * * * * * * * * * * * * * * * * * * * * * * * * */
00006 
00007 #include "mbed.h"
00008 #include "Music.h"
00009 #include "Notes.h"
00010 
00011 /*
00012  * This is the minimal constructor that creates a music object
00013  * with 0 initial output frequency on a specified pin
00014  *
00015  * M0 - The pin to output on
00016  */
00017 music::music(PinName M0) : _M0(M0){
00018     _flipper.attach(this,&music::flip,0);
00019 }
00020 
00021 /*
00022  * This constructs a music object which has an initial frequency
00023  * equal to a given one
00024  *
00025  * M0 - The pin to output on
00026  * freq - The initial frequency
00027  */
00028 music::music(PinName M0, double freq) : _M0(M0), _freq(freq) {
00029     _flipper.attach(this,&music::flip,1/(2*_freq));
00030 }
00031 
00032 /*
00033  * This changes the current output frequency to a given one
00034  *
00035  * freq - The given frequency
00036  */
00037 void music::freq(double freq){
00038     _freq=freq;
00039     _flipper.detach();
00040     _flipper.attach(this,&music::flip,1/(2*_freq));
00041 }
00042 
00043 /*
00044  * This is an internal flipper that allows for a fixed
00045  * frequency oscillation.
00046  */
00047 void music::flip(){
00048     _M0 = !_M0;
00049 }
00050 
00051 /*
00052  * This initializes a given m_song to a given size
00053  *
00054  * *m - The given m_song
00055  * num - The given size
00056  */
00057 void music::init_song(m_song *m, int num){
00058     m->len = 0;
00059     m->note = new music_note[((int)(num/5))];
00060 }
00061 
00062 /*
00063  * This deallocates an m_song by deallocating the notes
00064  * that it contains and setting the length to 0
00065  *
00066  * *m - The given m_song
00067  */
00068 void music::dal_song(m_song *m){
00069     m->len = 0;
00070     delete [] m->note;
00071 //    free(m->note);
00072 }
00073 
00074 /*
00075  * This parses a given character array into an m_song
00076  *  Format:
00077  *    <note_letter><[sharp]><octave>:<length>; . . .;
00078  *  Example (Super Mario Bros.):
00079  *    E3:8; E3:8; R:8; E3:8; R:8; C3:8; E3:4; G3:4; R:4; G2:4; R:4;
00080  *
00081  *  Sharp notes are represented with the # symbol as shown below:
00082  *    C#:4;
00083  *
00084  * song - The song character array
00085  * num - The number of characters in the array 
00086  */
00087 m_song music::parse(char* song, int num){
00088     //Create a new song and initialize it
00089     m_song out;
00090     init_song(&out,num);
00091     
00092     char curnote = ' ';   // Note
00093     int octave = 0;       // Octave
00094     int dur[] = {0,0};     // Duration
00095     int flag = 0;         // Complete flag
00096     int sharp = 0;        // Sharp flag
00097     int inl = 1;          // Index of dur[]
00098     
00099     for (int i=0; i<num; i++){
00100         switch(song[i]){
00101             case 'A':
00102                 //A Note
00103                 curnote = 'A';
00104             break;
00105             case 'B':
00106                 //B Note
00107                 curnote = 'B';
00108             break;
00109             case 'C':
00110                 //C Note
00111                 curnote = 'C';
00112             break;
00113             case 'D':
00114                 //D Note
00115                 curnote = 'D';
00116             break;
00117             case 'E':
00118                 //E Note
00119                 curnote = 'E';
00120             break;
00121             case 'F':
00122                 //F Note
00123                 curnote = 'F';
00124             break;
00125             case 'G':
00126                 //G Note
00127                 curnote = 'G';
00128             break;
00129             case 'R':
00130                 //Rest
00131                 curnote = 'R';
00132             break;
00133             case '#':
00134                 //Sharp set
00135                 sharp = 1;
00136             break;
00137             case '0':
00138                 if (flag == 0){
00139                     //Octave set
00140                     octave = 0;
00141                 }
00142                 else {
00143                     //Duration set
00144                     if (inl == 0){
00145                         //Shift
00146                         dur[0] = dur[1];
00147                         
00148                         //Set
00149                         dur[1] = 0;
00150                     }
00151                     else{
00152                         //Set
00153                         dur[1] = 0;
00154                         inl=0;
00155                     }
00156                 }
00157             break;
00158             case '1':
00159                 if (flag == 0){
00160                     //Octave set
00161                     octave = 1;
00162                 }
00163                 else {
00164                     //Duration set
00165                     if (inl == 0){
00166                         //Shift
00167                         dur[0] = dur[1];
00168                         
00169                         //Set
00170                         dur[1] = 1;
00171                     }
00172                     else{
00173                         //Set
00174                         dur[1] = 1;
00175                         inl=0;
00176                     }
00177                 }
00178             break;
00179             case '2':
00180                 if (flag == 0){
00181                     //Octave set
00182                     octave = 2;
00183                 }
00184                 else {
00185                     //Duration set
00186                     if (inl == 0){
00187                         //Shift
00188                         dur[0] = dur[1];
00189                         
00190                         //Set
00191                         dur[1] = 2;
00192                     }
00193                     else{
00194                         //Set
00195                         dur[1] = 2;
00196                         inl=0;
00197                     }
00198                 }
00199             break;
00200             case '3':
00201                 if (flag == 0){
00202                     //Octave set
00203                     octave = 3;
00204                 }
00205                 else {
00206                     //Duration set
00207                     if (inl == 0){
00208                         //Shift
00209                         dur[0] = dur[1];
00210                         
00211                         //Set
00212                         dur[1] = 3;
00213                     }
00214                     else{
00215                         //Set
00216                         dur[1] = 3;
00217                         inl=0;
00218                     }
00219                 }
00220             break;
00221             case '4':
00222                 if (flag == 0){
00223                     //Octave set
00224                     octave = 4;
00225                 }
00226                 else {
00227                     //Duration set
00228                     if (inl == 0){
00229                         //Shift
00230                         dur[0] = dur[1];
00231                         
00232                         //Set
00233                         dur[1] = 4;
00234                     }
00235                     else{
00236                         //Set
00237                         dur[1] = 4;
00238                         inl=0;
00239                     }
00240                 }
00241             break;
00242             case '5':
00243                 if (flag == 0){
00244                     //Octave set
00245                     octave = 5;
00246                 }
00247                 else {
00248                     //Duration set
00249                     if (inl == 0){
00250                         //Shift
00251                         dur[0] = dur[1];
00252                         
00253                         //Set
00254                         dur[1] = 5;
00255                     }
00256                     else{
00257                         //Set
00258                         dur[1] = 5;
00259                         inl=0;
00260                     }
00261                 }
00262             break;
00263             case '6':
00264                 if (flag == 0){
00265                     //Octave set
00266                     octave = 6;
00267                 }
00268                 else {
00269                     //Duration set
00270                     if (inl == 0){
00271                         //Shift
00272                         dur[0] = dur[1];
00273                         
00274                         //Set
00275                         dur[1] = 6;
00276                     }
00277                     else{
00278                         //Set
00279                         dur[1] = 6;
00280                         inl=0;
00281                     }
00282                 }
00283             break;
00284             case '7':
00285                 if (flag == 0){
00286                     //Octave set
00287                     octave = 7;
00288                 }
00289                 else {
00290                     //Duration set
00291                     if (inl == 0){
00292                         //Shift
00293                         dur[0] = dur[1];
00294                         
00295                         //Set
00296                         dur[1] = 7;
00297                     }
00298                     else{
00299                         //Set
00300                         dur[1] = 7;
00301                         inl=0;
00302                     }
00303                 }
00304             break;
00305             case '8':
00306                 if (flag == 0){
00307                     //Octave set
00308                     octave = 8;
00309                 }
00310                 else {
00311                     //Duration set
00312                     if (inl == 0){
00313                         //Shift
00314                         dur[0] = dur[1];
00315                         
00316                         //Set
00317                         dur[1] = 8;
00318                     }
00319                     else{
00320                         //Set
00321                         dur[1] = 8;
00322                         inl=0;
00323                     }
00324                 }
00325             break;
00326             case '9':
00327                 if (flag == 1){
00328                     //Duration set
00329                     if (inl == 0){
00330                         //Shift
00331                         dur[0] = dur[1];
00332                         
00333                         //Set
00334                         dur[1] = 9;
00335                     }
00336                     else{
00337                         //Set
00338                         dur[1] = 9;
00339                         inl=0;
00340                     }
00341                 }
00342             break;
00343             case ':':
00344                 flag = 1;
00345             break;
00346             case ';':
00347                 if (flag == 1){
00348                     //Calculate duration
00349                     int t1 = (dur[0])*10;
00350                     int t2 = dur[1];
00351                     int tst = t1+t2;
00352                     
00353                     if (tst>0 && tst<=64 && curnote != ' '){
00354                         notes n;
00355                         
00356                         //DEAD CODE: Will work when realloc is fixed
00357                         //Create a temporary checker
00358                         //music_note* tmpn; //= new music_note[out.len+1];
00359                         
00360                         //Reallocate space for note
00361                         //tmpn = (music_note*) realloc(out.note, (out.len+1)*sizeof(music_note));
00362 //                        if (tmpn == NULL){
00363 //                            //Failed to allocate
00364 //                            free(out.note);
00365 //                            exit(1);
00366 //                        }
00367 //                        out.note = tmpn;
00368                         
00369                         //Set frequency using lookup function
00370                         out.note[out.len].freq = n.get_freq(curnote, sharp, octave);
00371                         
00372                         //Set duration
00373                         out.note[out.len].duration = tst;
00374                         
00375                         //Increment current song size
00376                         out.len=out.len+1;
00377                     }
00378                     
00379                     //Reset values
00380                     flag = 0;
00381                     sharp = 0;
00382                     dur[0] = 0;
00383                     dur[1] = 0;
00384                     curnote = ' ';
00385                     octave = 0;
00386                     inl = 1;
00387                 }
00388                 else{
00389                     //Default to quarter note:
00390                 }
00391             break;
00392         }
00393     }
00394     return out;
00395 }
00396 
00397 /*
00398  * This plays a given song string at a given tempo
00399  *
00400  * song - The song character array
00401  * tempo - The specified beats per minute
00402  * num - The number of characters in the array
00403  */
00404 void music::play(char* song, double tempo, int num){
00405     double dl;
00406     m_song msng = parse(song, num);
00407     
00408     /* Play m_song */
00409     for (int i=0; i<msng.len; i++){
00410         // Output the frequency:
00411         freq(msng.note[i].freq);
00412         
00413         // Calculate delay:
00414         dl = (60*4)/(tempo*(msng.note[i].duration));
00415         
00416         // Wait for the note to be complete
00417         wait(dl);
00418     }
00419     
00420     //Stop playing
00421     freq(0);
00422     
00423     //Deallocate song:
00424     dal_song(&msng);
00425 }