Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: SuperMbedBall Tono
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 }
Generated on Tue Jul 12 2022 18:38:04 by
1.7.2