Sound Generator Library
Fork of Sound_Generator by
Embed:
(wiki syntax)
Show/hide line numbers
piano4int.cpp
00001 /****************************************************************************** 00002 * DISCLAIMER 00003 * This software is supplied by Renesas Electronics Corporation and is only 00004 * intended for use with Renesas products. No other uses are authorized. This 00005 * software is owned by Renesas Electronics Corporation and is protected under 00006 * all applicable laws, including copyright laws. 00007 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING 00008 * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT 00009 * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 00010 * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. 00011 * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS 00012 * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE 00013 * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR 00014 * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE 00015 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 00016 * Renesas reserves the right, without notice, to make changes to this software 00017 * and to discontinue the availability of this software. By using this software, 00018 * you agree to the additional terms and conditions found by accessing the 00019 * following link: 00020 * http://www.renesas.com/disclaimer 00021 * Copyright (C) 2012 - 2015 Renesas Electronics Corporation. All 00022 * rights reserved. 00023 ******************************************************************************/ 00024 00025 /****************************************************************************** 00026 Includes <System Includes> , "Project Includes" 00027 ******************************************************************************/ 00028 #include <stdio.h> 00029 #include <ctype.h> 00030 #include <stdint.h> 00031 extern "C" { 00032 #include "iodefine.h" 00033 #include "dev_drv.h" 00034 #include "devdrv_sdg.h" 00035 } 00036 #include "mbed.h" 00037 #include "PinNames.h" 00038 00039 #include "piano4int.h" 00040 00041 /****************************************************************************** 00042 Macro definitions 00043 ******************************************************************************/ 00044 #define ASSERT( eval ) \ 00045 if (!(eval)) { \ 00046 printf( \ 00047 "%s: failed! at %d in %s\n", \ 00048 #eval, \ 00049 __LINE__, \ 00050 __FILE__); \ 00051 } 00052 00053 /* message to caller */ 00054 #define UNIT_MSG (32) 00055 00056 00057 /****************************************************************************** 00058 Typedef definitions 00059 ******************************************************************************/ 00060 /* a sound generator unit */ 00061 typedef struct { 00062 uint16_t speed; /* count of a tempo */ 00063 uint8_t loudness; /* current loudness */ 00064 uint16_t count; /* remain of time */ 00065 NOTE note; /* a next note */ 00066 const int8_t *score; /* a next score */ 00067 const int8_t *top; /* top of a score */ 00068 uint8_t channel; /* channel number */ 00069 #ifdef UNIT_MSG 00070 char msg[UNIT_MSG]; /* message */ 00071 #endif 00072 } UNIT; 00073 00074 00075 /****************************************************************************** 00076 Imported global variables and functions (from other files) 00077 ******************************************************************************/ 00078 00079 00080 /****************************************************************************** 00081 Exported global variables and functions (to be accessed by other files) 00082 ******************************************************************************/ 00083 00084 00085 /****************************************************************************** 00086 Private global variables and functions 00087 ******************************************************************************/ 00088 /* interrupt routine */ 00089 static void play_score(void); 00090 00091 00092 /* all work area for piano */ 00093 struct { 00094 UNIT unit[SDG_CH_TOTAL]; 00095 uint16_t fin; 00096 Ticker metronome; /* base tempo */ 00097 PIANO4INT_CB callback; 00098 } pianoT; 00099 00100 00101 /* init params for sound generator */ 00102 static const struct { 00103 uint16_t channel; 00104 R_SDG_CLOCK clock; 00105 } unitHW[SDG_CH_TOTAL] = { 00106 { DEVDRV_CH_0, R_SDG_CLOCK_4 }, 00107 { DEVDRV_CH_1, R_SDG_CLOCK_4 }, 00108 { DEVDRV_CH_2, R_SDG_CLOCK_4 }, 00109 { DEVDRV_CH_3, R_SDG_CLOCK_4 }, 00110 }; 00111 00112 00113 /* dummy entry of score (no sounds)*/ 00114 static const int8_t noscore[] = ""; 00115 00116 /* parameters of a rest */ 00117 static const NOTE rest4 = { 00118 0, /* tone */ 00119 0, /* sfs */ 00120 0, /* loud */ 00121 0, /* attenuation */ 00122 }; 00123 00124 00125 /* table of notes */ 00126 static const struct { 00127 uint8_t tone; 00128 uint8_t sfs; 00129 } note_timing[MAXOCTAVE][MAXNOTE] = { 00130 { /* octave 0 */ 00131 { 0, 0 }, /* -A */ 00132 { 0, 0 }, /* -A# */ 00133 { 0, 0 }, /* -B */ 00134 { 124, 255 }, /* -C */ 00135 { 117, 255 }, /* -C# */ 00136 { 111, 255 }, /* -D */ 00137 { 105, 255 }, /* -D# */ 00138 { 99, 255 }, /* -E */ 00139 { 93, 255 }, /* -F */ 00140 { 88, 255 }, /* -F# */ 00141 { 83, 255 }, /* -G */ 00142 { 78, 255 }, /* -G# */ 00143 { 0, 0 }, /* -R */ 00144 }, 00145 { /* octave 1 */ 00146 { 86, 220 }, /* A */ 00147 { 81, 220 }, /* A# */ 00148 { 76, 220 }, /* B */ 00149 { 72, 220 }, /* C */ 00150 { 68, 220 }, /* C# */ 00151 { 64, 220 }, /* D */ 00152 { 60, 220 }, /* D# */ 00153 { 57, 220 }, /* E */ 00154 { 54, 220 }, /* F */ 00155 { 51, 220 }, /* F# */ 00156 { 48, 220 }, /* G */ 00157 { 45, 220 }, /* G# */ 00158 { 0, 0 }, /* R */ 00159 }, 00160 { /* octave 2 */ 00161 { 49, 190 }, /* +A */ 00162 { 47, 190 }, /* +A# */ 00163 { 44, 190 }, /* +B */ 00164 { 41, 190 }, /* +C */ 00165 { 39, 190 }, /* +C# */ 00166 { 37, 190 }, /* +D */ 00167 { 35, 190 }, /* +D# */ 00168 { 33, 190 }, /* +E */ 00169 { 31, 190 }, /* +F */ 00170 { 29, 190 }, /* +F# */ 00171 { 27, 190 }, /* +G */ 00172 { 26, 190 }, /* +G# */ 00173 { 0, 0 }, /* +R */ 00174 }, 00175 { /* octave 3 */ 00176 { 31, 150 }, /* *A */ 00177 { 29, 150 }, /* *A# */ 00178 { 28, 150 }, /* *B */ 00179 { 26, 150 }, /* *C */ 00180 { 25, 150 }, /* *C# */ 00181 { 23, 150 }, /* *D */ 00182 { 22, 150 }, /* *D# */ 00183 { 21, 150 }, /* *E */ 00184 { 19, 150 }, /* *F */ 00185 { 18, 150 }, /* *F# */ 00186 { 17, 150 }, /* *G */ 00187 { 16, 150 }, /* *G# */ 00188 { 0, 0 }, /* *R */ 00189 }, 00190 }; 00191 00192 00193 /* name table of notes */ 00194 #ifdef UNIT_MSG 00195 static const char *note_name[MAXNOTE] = { 00196 "A", 00197 "A#", 00198 "B", 00199 "C", 00200 "C#", 00201 "D", 00202 "D#", 00203 "E", 00204 "F", 00205 "F#", 00206 "G", 00207 "G#", 00208 "R", 00209 }; 00210 #endif /*UNIT_MSG*/ 00211 00212 00213 /****************************************************************************** 00214 * Function Name: piano4int_start 00215 * Description : Play the score thru sound generator. 00216 * : This function receives the sound language, 00217 * : and plays specified sound language. 00218 * Arguments : const int8_t *scores : score 00219 * : PIANO4INT_CB callback : callback function 00220 * Return Value : none 00221 ******************************************************************************/ 00222 void piano4int_start(const int8_t *scores[SDG_CH_TOTAL], PIANO4INT_CB callback) 00223 { 00224 const int8_t *score; /* pointer to score */ 00225 uint16_t speed; /* sound speed */ 00226 int32_t ch; /* channel no */ 00227 int32_t ret; /* function result */ 00228 00229 /* prepare for playing the score */ 00230 for (ch = 0; ch < SDG_CH_TOTAL; ch++) { 00231 if (scores[ch] == NULL) { 00232 /* score is not specified */ 00233 pianoT.unit[ch].score = noscore; 00234 pianoT.unit[ch].top = noscore; 00235 } else { 00236 /* prepare for playing a score */ 00237 score = scores[ch]; 00238 00239 /* get the speed */ 00240 speed = 0; 00241 while (isdigit(*score)) { 00242 speed = (speed * 10) + ((*score++) - '0'); 00243 } 00244 if (0 == speed) { 00245 /* can not play the score */ 00246 printf("speed[%d]:%d, can not play, there is no speed information.\n", (int)ch, speed); 00247 return; 00248 } else { 00249 printf("speed[%d]:%d\n", (int)ch, speed); 00250 /* calculate a base speed for ticker */ 00251 pianoT.unit[ch].speed = BASESPEED / speed; 00252 00253 /* default loudness (unsupported to change) */ 00254 pianoT.unit[ch].loudness = DEFLOUDNESS; 00255 00256 /* set top of a score */ 00257 pianoT.unit[ch].top = score; 00258 pianoT.unit[ch].score = score; 00259 00260 /* play no sounds */ 00261 pianoT.unit[ch].count = 0; 00262 00263 /* rest4 */ 00264 pianoT.unit[ch].note = rest4; 00265 00266 /* channel number */ 00267 pianoT.unit[ch].channel = unitHW[ch].channel; 00268 00269 #ifdef UNIT_MSG 00270 /* message */ 00271 pianoT.unit[ch].msg[0] = '\0'; 00272 #endif 00273 00274 /* Initialize Sound Generator */ 00275 ret = R_SDG_Open(unitHW[ch].channel, unitHW[ch].clock); 00276 ASSERT(0 == ret); 00277 } 00278 } 00279 } 00280 00281 /* set callback function */ 00282 pianoT.callback = callback; 00283 00284 /* clear flags to finish playing */ 00285 pianoT.fin = 0; 00286 00287 /* start the metronome (unit: 1ms) */ 00288 pianoT.metronome.attach_us(&play_score, 1000.0); 00289 } 00290 00291 /****************************************************************************** 00292 * Function Name: piano4int_stop 00293 * Description : Stop the sounds through sound generator. 00294 * Arguments : bool force : flag to stop forcedly (now, ignored) 00295 * Return Value : none 00296 ******************************************************************************/ 00297 void piano4int_stop(bool force) 00298 { 00299 int32_t ch; 00300 int32_t ret; 00301 00302 /* wait until sounds stop */ 00303 do { 00304 /* wait 10.0 sec */ 00305 wait_us(10.0 * 1000.0); 00306 #ifdef UNIT_MSG 00307 for (ch = 0; ch < SDG_CH_TOTAL; ch++) { 00308 if ('\0' != pianoT.unit[ch].msg[0]) { 00309 printf(&pianoT.unit[ch].msg[0]); 00310 pianoT.unit[ch].msg[0] = '\0'; 00311 } 00312 } 00313 #endif /*UNIT_MSG*/ 00314 } while (pianoT.fin != ((1 << SDG_CH_TOTAL) - 1)); 00315 /* all scores finished */ 00316 00317 /* stops the metronome */ 00318 pianoT.metronome.detach(); 00319 00320 /* stop all sound generators */ 00321 for (ch = 0; ch < SDG_CH_TOTAL; ch++) { 00322 if (pianoT.unit[ch].top != noscore) { 00323 /* stop sound generator */ 00324 ret = R_SDG_Close(unitHW[ch].channel); 00325 ASSERT(0 == ret); 00326 } 00327 } 00328 } 00329 00330 /****************************************************************************** 00331 * Function Name: piano4int_status 00332 * Description : Get the flag to finish playing the score 00333 * Arguments : none 00334 * Return Value : The flag 00335 * Note : Output the comment if the macro "UNIT_MSG" is defined 00336 ******************************************************************************/ 00337 bool piano4int_status(void) 00338 { 00339 #ifdef UNIT_MSG 00340 int32_t ch; 00341 00342 /* output the comments from interrupts */ 00343 for (ch = 0; ch < SDG_CH_TOTAL; ch++) { 00344 if ('\0' != pianoT.unit[ch].msg[0]) { 00345 printf(&pianoT.unit[ch].msg[0]); 00346 pianoT.unit[ch].msg[0] = '\0'; 00347 } 00348 } 00349 #endif 00350 00351 return (pianoT.fin != ((1 << SDG_CH_TOTAL) - 1)); 00352 } 00353 00354 00355 /****************************************************************************** 00356 * Function Name: play_score 00357 * Description : Play the score on interrupt 00358 * Arguments : none 00359 * Return Value : none 00360 ******************************************************************************/ 00361 void play_score(void) 00362 { 00363 UNIT *unit; 00364 const int8_t *score; 00365 uint16_t octave; 00366 uint16_t key; 00367 uint16_t pitch; 00368 uint16_t dot; 00369 uint16_t tie; 00370 uint8_t loud; 00371 uint16_t duration; 00372 uint16_t value; 00373 uint16_t ch; 00374 bool err; 00375 00376 for (ch = 0; ch < SDG_CH_TOTAL; ch++) { 00377 /* Check finish flag */ 00378 if (0 != (pianoT.fin & (1 << ch))) { 00379 continue; /* finish */ 00380 } 00381 00382 if (0 == pianoT.unit[ch].count) { 00383 unit = &pianoT.unit[ch]; 00384 score = unit->score; 00385 00386 if ('\0' == *score) { 00387 /* set finish flag */ 00388 pianoT.fin |= (1 << ch); 00389 continue; 00390 } 00391 00392 /* Initialize parameters */ 00393 octave = 0; 00394 key = 0; 00395 pitch = 0; 00396 dot = 0; 00397 tie = 0; 00398 err = false; 00399 00400 /* skip some spaces */ 00401 while (' ' == *score) { 00402 score++; 00403 } 00404 00405 /* octave */ 00406 switch (*score) { 00407 case OCTAVE0_CHAR: { octave = OCTAVE_LEVEL_0; score++; break; } 00408 case OCTAVE1_CHAR: { octave = OCTAVE_LEVEL_1; score++; break; } 00409 case OCTAVE2_CHAR: { octave = OCTAVE_LEVEL_2; score++; break; } 00410 case OCTAVE3_CHAR: { octave = OCTAVE_LEVEL_3; score++; break; } 00411 default: { octave = OCTAVE_LEVEL_1; break; } 00412 } 00413 00414 /* key */ 00415 switch (toupper(*score)) { 00416 case NOTE_DO_CHAR: { key = KEY_C; score++; break; } 00417 case NOTE_RE_CHAR: { key = KEY_D; score++; break; } 00418 case NOTE_MI_CHAR: { key = KEY_E; score++; break; } 00419 case NOTE_FA_CHAR: { key = KEY_F; score++; break; } 00420 case NOTE_SO_CHAR: { key = KEY_G; score++; break; } 00421 case NOTE_RA_CHAR: { key = KEY_A; score++; break; } 00422 case NOTE_SI_CHAR: { key = KEY_B; score++; break; } 00423 case NOTE_REST_CHAR:{ key = KEY_R; score++; break; } 00424 default: 00425 err = true; 00426 } 00427 00428 if (((KEY_A == key) && (OCTAVE_LEVEL_0 == octave)) || 00429 ((KEY_B == key) && (OCTAVE_LEVEL_0 == octave))) { 00430 err = true; 00431 } 00432 00433 /* sharp */ 00434 if (NOTE_SHARP == (*score)) { 00435 if (KEY_R == key) { 00436 err = true; 00437 } else { 00438 key++; 00439 score++; 00440 } 00441 } 00442 00443 /* pitch */ 00444 if (isdigit(*score)) { 00445 pitch = ((*score++) - '0'); 00446 if (isdigit(*score)) { 00447 pitch = (pitch * 10) + ((*score++) - '0'); 00448 } 00449 } else { 00450 err = true; 00451 } 00452 00453 /* dotted */ 00454 if (NOTE_DOT == (*score)) { 00455 dot = DOTTED_NOTE; 00456 score++; 00457 } else { 00458 dot = NOT_DOTTED_NONE; 00459 } 00460 00461 /* tie */ 00462 if (NOTE_TIE == (*score)) { 00463 tie = TIED_NOTE; 00464 score++; 00465 } else { 00466 tie = NOT_TIED_NONE; 00467 } 00468 00469 /* set score */ 00470 unit->score = score; 00471 00472 #ifdef UNIT_MSG 00473 snprintf(&unit->msg[0], UNIT_MSG - 1, "%d)%d%s%d -> %d/%d/%d\n", 00474 unit->channel, 00475 octave, 00476 note_name[key], 00477 pitch, 00478 note_timing[octave][key].tone, 00479 note_timing[octave][key].sfs, 00480 unit->speed / pitch); 00481 #endif /* UNIT_MSG */ 00482 00483 if (!err) { 00484 /* set the sound volume */ 00485 loud = (0 == note_timing[octave][key].sfs) ? (0): (unit->loudness); 00486 /* set */ 00487 duration = unit->speed / pitch; 00488 if (dot) { 00489 duration += (duration >> 1); 00490 } 00491 00492 /* set next note or rest */ 00493 unit->note.tone = note_timing[octave][key].tone; 00494 unit->note.sfs = note_timing[octave][key].sfs; 00495 unit->note.loud = loud; 00496 unit->note.attenuation = tie; 00497 00498 R_SDG_Tone(pianoT.unit[ch].channel, &pianoT.unit[ch].note); 00499 pianoT.unit[ch].count = duration; 00500 } else { 00501 pianoT.fin |= (1 << ch); 00502 } 00503 00504 /* marker */ 00505 if (NOTE_MARKER == (*score)) { 00506 score++; 00507 value = 0; 00508 if (isdigit(*score)) { 00509 value = ((*score++) - '0'); 00510 if (isdigit(*score)) { 00511 value = (value * 10) + ((*score++) - '0'); 00512 } 00513 } 00514 unit->score = score; 00515 00516 if (NULL != pianoT.callback) { 00517 pianoT.callback(pianoT.unit[ch].channel, value); 00518 } 00519 } 00520 } else { 00521 pianoT.unit[ch].count--; 00522 } 00523 } 00524 } 00525 00526 /* End of File */
Generated on Fri Jul 15 2022 04:21:34 by
1.7.2
