diff --git a/README.md b/README.md index 7f9c91c..6680147 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Improved Arduino library version of the RTTTL.pde example code written by Brett - Random play of melodies from array. - Supports inverted tone pin logic i.e. tone pin is HIGH at playing a pause. - Accepts even invalid specified RTTTL files found in the wild. - - Supports RTX format. + - Supports RTX format - 2 additional parameters: 1. l= 2.s=). - Tone style (relation of tone output to note length) and loop count can be set for a melody. Youtube video of the RandomMelody example in action @@ -45,6 +45,11 @@ More RTTTL songs can be found under http://www.picaxe.com/RTTTL-Ringtones-for-Tu # Revision History +### Version 1.2.1 + - Natural is the new default style. + - New RTTTLMelodiesSmall sample array with less entries. + - Parameter now order independent. + - Modified oneMelody example. ### Version 1.2.0 No Serial.print statements in this library anymore, to avoid problems with different Serial implementations. - Function playRandomRtttlBlocking() + startPlayRandomRtttlFromArrayPGM() do not print name now. If needed, use new functions playRandomRtttlSampleBlockingAndPrintName() + startPlayRandomRtttlFromArrayPGMAndPrintName(). diff --git a/examples/OneMelody/OneMelody.ino b/examples/OneMelody/OneMelody.ino index 9b025ea..dc42bba 100644 --- a/examples/OneMelody/OneMelody.ino +++ b/examples/OneMelody/OneMelody.ino @@ -33,29 +33,37 @@ const int TONE_PIN = 11; +char StarWarsInRam[] = + "StarWars:d=32,o=5,b=45,l=2,s=N:p,f#,f#,f#,8b.,8f#.6,e6,d#6,c#6,8b.6,16f#.6,e6,d#6,c#6,8b.6,16f#.6,e6,d#6,e6,8c#6"; + void setup() { Serial.begin(115200); - while (!Serial); //delay for Leonardo + while (!Serial) + ; //delay for Leonardo // Just to know which program is running on my Arduino Serial.println(F("START " __FILE__ "\r\nVersion " VERSION_EXAMPLE " from " __DATE__)); /* * Play one melody */ - playRtttlBlockingPGM(TONE_PIN, Bond); + playRtttlBlocking(TONE_PIN, StarWarsInRam); delay(5000); } void loop() { /* - * And another one, but use non blocking functions + * And all the others, but use non blocking functions */ - startPlayRtttlPGM(TONE_PIN, TakeOnMe); - while (updatePlayRtttl()) { - /* - * your own code here... - */ - delay(1); + for (uint8_t i = 1; i < ARRAY_SIZE_MELODIES; ++i) { + const char* tSongPtr = (char*) pgm_read_word(&RTTTLMelodies[i]); + startPlayRtttlPGM(TONE_PIN, tSongPtr); + while (updatePlayRtttl()) { + /* + * your own code here... + */ + delay(1); + } + delay(2000); } delay(20000); } diff --git a/library.properties b/library.properties index 94b4015..03f70e5 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=PlayRtttl -version=1.2.0 +version=1.2.1 author=Armin Joachimsmeyer maintainer=Armin Joachimsmeyer sentence=Plays RTTTL / RTX melodies/ringtones from FLASH or RAM.
diff --git a/src/PlayRtttl.cpp b/src/PlayRtttl.cpp index 06fcfbe..4ff7f6f 100644 --- a/src/PlayRtttl.cpp +++ b/src/PlayRtttl.cpp @@ -34,7 +34,7 @@ #include "PlayRtttl.h" //uncomment next line to see debug output, which shows the note played, on serial. -//#define DEBUG +#define DEBUG struct playRtttlState sPlayRtttlState; @@ -47,7 +47,7 @@ NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_ #define OCTAVE_OFFSET 0 #define isdigit(n) (n >= '0' && n <= '9') -uint8_t sDefaultStyleDivisorValue = 0; +uint8_t sDefaultStyleDivisorValue = RTTTL_STYLE_DEFAULT; // Natural /* * Blocking versions @@ -83,125 +83,124 @@ void startPlayRtttlPGM(uint8_t aTonePin, const char * aRTTTLArrayPtrPGM, void (* #endif char tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); while (tPGMChar != ':') { + /* + * Read title + */ #ifdef DEBUG Serial.print(tPGMChar); #endif aRTTTLArrayPtrPGM++; tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); } - aRTTTLArrayPtrPGM++; - tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); - - /* - * Read song info with format: d=N(N),o=N,b=NNN: - */ - - /* - * get default duration - */ - tNumber = DEFAULT_DURATION; - if (tPGMChar == 'd') { - aRTTTLArrayPtrPGM++; - aRTTTLArrayPtrPGM++; // skip "d=" - tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); - tNumber = 0; - while (isdigit(tPGMChar)) { - tNumber = (tNumber * 10) + (tPGMChar - '0'); - aRTTTLArrayPtrPGM++; - tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); - } - if (tNumber == 0) { - tNumber = DEFAULT_DURATION; - } - aRTTTLArrayPtrPGM++; // skip comma - tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); - } - sPlayRtttlState.DefaultDuration = tNumber; - /* - * get default octave - */ - tNumber = DEFAULT_OCTAVE; - if (tPGMChar == 'o') { - aRTTTLArrayPtrPGM++; - aRTTTLArrayPtrPGM++; // skip "o=" - tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); - aRTTTLArrayPtrPGM++; - tNumber = tPGMChar - '0'; - if (tNumber < 3 && tNumber > 7) { - tNumber = DEFAULT_OCTAVE; - } - - aRTTTLArrayPtrPGM++; // skip comma - tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); - } - sPlayRtttlState.DefaultOctave = tNumber; + sPlayRtttlState.DefaultDuration = DEFAULT_DURATION; + sPlayRtttlState.DefaultOctave = DEFAULT_OCTAVE; + sPlayRtttlState.TimeForWholeNoteMillis = (60 * 1000L / DEFAULT_BPM) * 4; + sPlayRtttlState.NumberOfLoops = 1; + sPlayRtttlState.StyleDivisorValue = sDefaultStyleDivisorValue; -#ifdef SUPPORT_EXTENSIONS - // get Style - tNumber = sDefaultStyleDivisorValue; #ifdef SUPPORT_RTX_FORMAT #ifdef DEBUG char tStyleChar = RTX_STYLE_DEFAULT; #else char tStyleChar; #endif - if (tPGMChar == 's') { - aRTTTLArrayPtrPGM++; - aRTTTLArrayPtrPGM++; // skip "s=" - tStyleChar = pgm_read_byte(aRTTTLArrayPtrPGM); - tNumber = convertStyleCharacterToDivisorValue(tStyleChar); - aRTTTLArrayPtrPGM++; - aRTTTLArrayPtrPGM++; // skip comma - tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); - } #endif - sPlayRtttlState.StyleDivisorValue = tNumber; + int tBPM; - // get loops - tNumber = 1; -#ifdef SUPPORT_RTX_FORMAT - if (tPGMChar == 'l') { + do { + /* + * Get character after separator (comma or colon) + */ aRTTTLArrayPtrPGM++; - aRTTTLArrayPtrPGM++; // skip "l=" tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); - tNumber = 0; - while (isdigit(tPGMChar)) { - tNumber = (tNumber * 10) + (tPGMChar - '0'); + /* + * Read song info with format: d=N(N),o=N,b=NNN: + */ + if (tPGMChar == 'd') { + /* + * get default duration + */ aRTTTLArrayPtrPGM++; + aRTTTLArrayPtrPGM++; // skip "d=" tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); - } - if (tNumber == 15) { tNumber = 0; - } + while (isdigit(tPGMChar)) { + tNumber = (tNumber * 10) + (tPGMChar - '0'); + aRTTTLArrayPtrPGM++; + tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); + } + if (tNumber == 0) { + tNumber = DEFAULT_DURATION; + } + sPlayRtttlState.DefaultDuration = tNumber; + } else if (tPGMChar == 'o') { + /* + * get default octave + */ + aRTTTLArrayPtrPGM++; + aRTTTLArrayPtrPGM++; // skip "o=" + tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); + tNumber = tPGMChar - '0'; + if (tNumber < 3 && tNumber > 7) { + tNumber = DEFAULT_OCTAVE; + } + sPlayRtttlState.DefaultOctave = tNumber; + //get comma or colon + aRTTTLArrayPtrPGM++; + tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); + } else - aRTTTLArrayPtrPGM++; // skip comma - tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); - } -#endif - sPlayRtttlState.NumberOfLoops = tNumber; +#ifdef SUPPORT_RTX_FORMAT + if (tPGMChar == 's') { + // get Style + aRTTTLArrayPtrPGM++; + aRTTTLArrayPtrPGM++; // skip "s=" + tStyleChar = pgm_read_byte(aRTTTLArrayPtrPGM); + tNumber = convertStyleCharacterToDivisorValue(tStyleChar); + sPlayRtttlState.StyleDivisorValue = tNumber; + //get comma or colon + aRTTTLArrayPtrPGM++; + tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); + } else if (tPGMChar == 'l') { + // get loops + aRTTTLArrayPtrPGM++; + aRTTTLArrayPtrPGM++; // skip "l=" + tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); + tNumber = 0; + while (isdigit(tPGMChar)) { + tNumber = (tNumber * 10) + (tPGMChar - '0'); + aRTTTLArrayPtrPGM++; + tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); + } + if (tNumber == 15) { + tNumber = 0; + } + sPlayRtttlState.NumberOfLoops = tNumber; + } else #endif - // get BPM - tNumber = DEFAULT_BPM; - if (tPGMChar == 'b') { - aRTTTLArrayPtrPGM++; - aRTTTLArrayPtrPGM++; // skip "b=" - tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); - tNumber = 0; - while (isdigit(tPGMChar)) { - tNumber = (tNumber * 10) + (tPGMChar - '0'); + // get BPM + if (tPGMChar == 'b') { aRTTTLArrayPtrPGM++; + aRTTTLArrayPtrPGM++; // skip "b=" tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); + tBPM = 0; + while (isdigit(tPGMChar)) { + tBPM = (tBPM * 10) + (tPGMChar - '0'); + aRTTTLArrayPtrPGM++; + tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); + } + if (tBPM == 0) { + tBPM = DEFAULT_BPM; + } + // BPM usually expresses the number of quarter notes per minute + sPlayRtttlState.TimeForWholeNoteMillis = (60 * 1000L / tBPM) * 4; } - if (tNumber == 0) { - tNumber = DEFAULT_BPM; - } - aRTTTLArrayPtrPGM++; // skip colon - tPGMChar = pgm_read_byte(aRTTTLArrayPtrPGM); - } - // BPM usually expresses the number of quarter notes per minute - sPlayRtttlState.TimeForWholeNoteMillis = (60 * 1000L / tNumber) * 4; + + } while (tPGMChar != ':'); + + aRTTTLArrayPtrPGM++; // skip colon #ifdef DEBUG Serial.print(" DefaultDuration="); @@ -209,7 +208,7 @@ void startPlayRtttlPGM(uint8_t aTonePin, const char * aRTTTLArrayPtrPGM, void (* Serial.print(" DefaultOctave="); Serial.print(sPlayRtttlState.DefaultOctave); Serial.print(" BPM="); - Serial.print(tNumber); + Serial.print(tBPM); #ifdef SUPPORT_RTX_FORMAT Serial.print(" Style="); Serial.print(tStyleChar); @@ -253,98 +252,111 @@ void startPlayRtttl(uint8_t aTonePin, char * aRTTTLArrayPtr, void (*aOnComplete) Serial.print("Title="); #endif while (*aRTTTLArrayPtr != ':') { + /* + * Read title + */ #ifdef DEBUG Serial.print(*aRTTTLArrayPtr); #endif aRTTTLArrayPtr++; } - aRTTTLArrayPtr++; - /* - * Read song info with format: d=N,o=N,b=NNN: - */ + sPlayRtttlState.DefaultDuration = DEFAULT_DURATION; + sPlayRtttlState.DefaultOctave = DEFAULT_OCTAVE; + sPlayRtttlState.TimeForWholeNoteMillis = (60 * 1000L / DEFAULT_BPM) * 4; + sPlayRtttlState.NumberOfLoops = 1; + sPlayRtttlState.StyleDivisorValue = sDefaultStyleDivisorValue; - /* - * get default duration - */ - tNumber = DEFAULT_DURATION; - if (*aRTTTLArrayPtr == 'd') { - aRTTTLArrayPtr++; - aRTTTLArrayPtr++; // skip "d=" - tNumber = 0; - while (isdigit(*aRTTTLArrayPtr)) { - tNumber = (tNumber * 10) + (*aRTTTLArrayPtr++ - '0'); - } - if (tNumber == 0) { - tNumber = DEFAULT_DURATION; - } - aRTTTLArrayPtr++; // skip comma - } - sPlayRtttlState.DefaultDuration = tNumber; +#ifdef SUPPORT_RTX_FORMAT +#ifdef DEBUG + char tStyleChar = RTX_STYLE_DEFAULT; +#else + char tStyleChar; +#endif +#endif + int tBPM; - /* - * get default octave - */ - tNumber = DEFAULT_OCTAVE; - if (*aRTTTLArrayPtr == 'o') { + do { + /* + * Get character after separator (comma or colon) + */ aRTTTLArrayPtr++; - aRTTTLArrayPtr++; // skip "o=" - tNumber = *aRTTTLArrayPtr++ - '0'; - if (tNumber < 3 && tNumber > 7) { - tNumber = DEFAULT_OCTAVE; - } - aRTTTLArrayPtr++; // skip comma - } - sPlayRtttlState.DefaultOctave = tNumber; -#ifdef SUPPORT_EXTENSIONS - // get Style - tNumber = sDefaultStyleDivisorValue; -#ifdef SUPPORT_RTX_FORMAT - if (*aRTTTLArrayPtr == 's') { - aRTTTLArrayPtr++; - aRTTTLArrayPtr++; // skip "s=" - tNumber = convertStyleCharacterToDivisorValue(*aRTTTLArrayPtr++); + /* + * Read song info with format: d=N(N),o=N,b=NNN: + */ + if (*aRTTTLArrayPtr == 'd') { + /* + * get default duration + */ + aRTTTLArrayPtr++; + aRTTTLArrayPtr++; // skip "d=" + tNumber = 0; + while (isdigit(*aRTTTLArrayPtr)) { + tNumber = (tNumber * 10) + (*aRTTTLArrayPtr++ - '0'); + } + if (tNumber == 0) { + tNumber = DEFAULT_DURATION; + } + sPlayRtttlState.DefaultDuration = tNumber; + } - aRTTTLArrayPtr++; // skip comma - } -#endif - sPlayRtttlState.StyleDivisorValue = tNumber; + /* + * get default octave + */ + if (*aRTTTLArrayPtr == 'o') { + aRTTTLArrayPtr++; + aRTTTLArrayPtr++; // skip "o=" + tNumber = *aRTTTLArrayPtr++ - '0'; + if (tNumber < 3 && tNumber > 7) { + tNumber = DEFAULT_OCTAVE; + } + sPlayRtttlState.DefaultOctave = tNumber; + } - // get loops - tNumber = 1; #ifdef SUPPORT_RTX_FORMAT - if (*aRTTTLArrayPtr == 'l') { - aRTTTLArrayPtr++; - aRTTTLArrayPtr++; // skip "l=" - while (isdigit(*aRTTTLArrayPtr)) { - tNumber = (tNumber * 10) + (*aRTTTLArrayPtr++ - '0'); + if (*aRTTTLArrayPtr == 's') { + // get Style + aRTTTLArrayPtr++; + aRTTTLArrayPtr++; // skip "s=" + tStyleChar = *aRTTTLArrayPtr++; + tNumber = convertStyleCharacterToDivisorValue(tStyleChar); + sPlayRtttlState.StyleDivisorValue = tNumber; } - if (tNumber == 15) { + + // get loops + if (*aRTTTLArrayPtr == 'l') { tNumber = 0; + aRTTTLArrayPtr++; + aRTTTLArrayPtr++; // skip "l=" + while (isdigit(*aRTTTLArrayPtr)) { + tNumber = (tNumber * 10) + (*aRTTTLArrayPtr++ - '0'); + } + if (tNumber == 15) { + tNumber = 0; + } + sPlayRtttlState.NumberOfLoops = tNumber; } - aRTTTLArrayPtr++; // skip comma - } -#endif - sPlayRtttlState.NumberOfLoops = tNumber; #endif - // get BPM - tNumber = DEFAULT_BPM; - if (*aRTTTLArrayPtr == 'b') { - aRTTTLArrayPtr++; - aRTTTLArrayPtr++; // skip "b=" - tNumber = 0; - while (isdigit(*aRTTTLArrayPtr)) { - tNumber = (tNumber * 10) + (*aRTTTLArrayPtr++ - '0'); - } - if (tNumber == 0) { - tNumber = DEFAULT_BPM; + if (*aRTTTLArrayPtr == 'b') { + // get BPM + aRTTTLArrayPtr++; + aRTTTLArrayPtr++; // skip "b=" + tBPM = 0; + while (isdigit(*aRTTTLArrayPtr)) { + tBPM = (tBPM * 10) + (*aRTTTLArrayPtr++ - '0'); + } + if (tBPM == 0) { + tBPM = DEFAULT_BPM; + } + // BPM usually expresses the number of quarter notes per minute + sPlayRtttlState.TimeForWholeNoteMillis = (60 * 1000L / tBPM) * 4; } - aRTTTLArrayPtr++; // skip colon - } - // BPM usually expresses the number of quarter notes per minute - sPlayRtttlState.TimeForWholeNoteMillis = (60 * 1000L / tNumber) * 4; + + } while (*aRTTTLArrayPtr != ':'); + + aRTTTLArrayPtr++; // skip colon #ifdef DEBUG Serial.print(" DefaultDuration="); @@ -352,11 +364,16 @@ void startPlayRtttl(uint8_t aTonePin, char * aRTTTLArrayPtr, void (*aOnComplete) Serial.print(" DefaultOctave="); Serial.print(sPlayRtttlState.DefaultOctave); Serial.print(" BPM="); - Serial.print(tNumber); + Serial.print(tBPM); #ifdef SUPPORT_RTX_FORMAT - Serial.print(" Style=1/"); - Serial.print(sPlayRtttlState.StyleDivisorValue); - Serial.print(" pause between notes, Loops="); + Serial.print(" Style="); + Serial.print(tStyleChar); + if (sPlayRtttlState.StyleDivisorValue != 0) { + Serial.print(" -> 1/"); + Serial.print(sPlayRtttlState.StyleDivisorValue); + Serial.print(" pause between notes,"); + } + Serial.print(" Loops="); Serial.print(sPlayRtttlState.NumberOfLoops); #endif Serial.println(); @@ -577,7 +594,9 @@ bool updatePlayRtttl(void) { if (isSharp) { Serial.print('#'); } - Serial.print(tOctave, 10); + if (tNote) { + Serial.print(tOctave, 10); + } Serial.print(", "); Serial.print(tDurationNumber, 10); diff --git a/src/PlayRtttl.h b/src/PlayRtttl.h index 0e5f345..e6de971 100644 --- a/src/PlayRtttl.h +++ b/src/PlayRtttl.h @@ -36,8 +36,13 @@ #include #include "pitches.h" -#define VERSION_PLAY_RTTTL 1.2.0 +#define VERSION_PLAY_RTTTL 1.2.1 /* + * Version 1.2.1 + * - Natural is the new default style. + * - New RTTTLMelodiesSmall sample array with less entries. + * - Parameter now order independent. + * - Modified oneMelody example. * Version 1.2.0 * No Serial.print statements in this library anymore, to avoid problems with different Serial implementations. * - Function playRandomRtttlBlocking() + startPlayRandomRtttlFromArrayPGM() do not print name now. If needed, use new functions playRandomRtttlSampleBlockingAndPrintName() + startPlayRandomRtttlFromArrayPGMAndPrintName(). @@ -61,12 +66,13 @@ #define RTX_STYLE_CONTINUOUS 'C' // Tone length = note length #define RTX_STYLE_NATURAL 'N' // Tone length = note length - 1/16 #define RTX_STYLE_STACCATO 'S' // Tone length = note length - 1/2 +#define RTX_STYLE_DEFAULT RTX_STYLE_NATURAL #define RTTTL_STYLE_CONTINUOUS 0 // Tone length = note length #define RTTTL_STYLE_NATURAL 16 // Tone length = note length - 1/16 #define RTTTL_STYLE_STACCATO 2 // Tone length = note length - 1/2 #define RTTTL_STYLE_4 4 // Tone length = note length - 1/4 #define RTTTL_STYLE_8 8 // Tone length = note length - 1/8 -#define RTX_STYLE_DEFAULT RTX_STYLE_CONTINUOUS +#define RTTTL_STYLE_DEFAULT RTTTL_STYLE_NATURAL void setTonePinIsInverted(bool aTonePinIsInverted); @@ -120,11 +126,12 @@ struct playRtttlState { uint8_t DefaultOctave; long TimeForWholeNoteMillis; #ifdef SUPPORT_EXTENSIONS - const char * LastTonePointer; // used for loops + uint8_t NumberOfLoops; // 0 means forever, 1 means we are in the last loop // The divisor for the formula: Tone length = note length - note length * (1 / divisor) // If 0 then Tone length = note length; uint8_t StyleDivisorValue; - uint8_t NumberOfLoops; // 0 means forever, 1 means we are in the last loop + const char * LastTonePointer; // used for loops + #endif }; @@ -138,10 +145,13 @@ struct playRtttlState { /* * Disclaimer: These ringtone melodies are for personal enjoyment only. All copyright belongs to its respective author. */ +// Use rtx format to save space static const char StarWars[] PROGMEM - = "StarWars:d=4,o=5,b=45:32p,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#.6,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#6"; += "StarWars:d=32,o=5,b=45,l=2:p,f#,f#,f#,8b.,8f#.6,e6,d#6,c#6,8b.6,16f#.6,e6,d#6,c#6,8b.6,16f#.6,e6,d#6,e6,8c#6"; static const char MahnaMahna[] PROGMEM - = "MahnaMahna:d=16,o=6,b=125:c#,c.,b5,8a#.5,8f.,4g#,a#,g.,4d#,8p,c#,c.,b5,8a#.5,8f.,g#.,8a#.,4g,8p,c#,c.,b5,8a#.5,8f.,4g#,f,g.,8d#.,f,g.,8d#.,f,8g,8d#.,f,8g,d#,8c,a#5,8d#.,8d#.,4d#,8d#."; + = "MahnaMahna:d=16,o=6,b=125:c#,c.,b5,8a#.5,8f.,4g#,a#,g.,4d#,8p,c#,c.,b5,8a#.5,8f.,g#.,8a#.,4g,8p,c#,c.,b5,8a#.5,8f.,4g#,f,g.,8d#.,f,g.,8d#.,f,8g,8d#.,f,8g,d#,8c,a#5,8d#.,8d#.,16d#.,16d#.,8d#."; +static const char LeisureSuit[] PROGMEM + = "LeisureSuit:d=16,o=6,b=56:f.5,f#.5,g.5,g#5,32a#5,f5,g#.5,a#.5,32f5,g#5,32a#5,g#5,8c#.,a#5,32c#,a5,a#.5,c#.,32a5,a#5,32c#,d#,8e,c#.,f.,f.,f.,f.,f,32e,d#,8d,a#.5,e,32f,e,32f,c#,d#.,c#"; static const char MissionImp[] PROGMEM = "MissionImp:d=16,o=6,b=95:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f,32p,a#5,g5,2e,d#,8d"; static const char Entertainer[] PROGMEM @@ -149,7 +159,7 @@ static const char Entertainer[] PROGMEM static const char Muppets[] PROGMEM = "Muppets:d=4,o=5,b=250:c6,c6,a,b,8a,b,g,p,c6,c6,a,8b,8a,8p,g.,p,e,e,g,f,8e,f,8c6,8c,8d,e,8e,8e,8p,8e,g,2p,c6,c6,a,b,8a,b,g,p,c6,c6,a,8b,a,g.,p,e,e,g,f,8e,f,8c6,8c,8d,e,8e,d,8d,c"; static const char Flinstones[] PROGMEM - = "Flinstones:d=4,o=5,b=40:32p,16f6,16a#,16a#6,32g6,16f6,16a#.,16f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c6,d6,16f6,16a#.,16a#6,32g6,16f6,16a#.,32f6,32f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c6,a#,16a6,16d.6,16a#6,32a6,32a6,32g6,32f#6,32a6,8g6,16g6,16c.6,32a6,32a6,32g6,32g6,32f6,32e6,32g6,8f6,16f6,16a#.,16a#6,32g6,16f6,16a#.,16f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c.6,32d6,32d#6,32f6,16a#,16c.6,32d6,32d#6,32f6,16a#6,16c7,8a#.6"; + = "Flinstones:d=32,o=5,b=40:p,16f6,16a#,16a#6,g6,16f6,16a#.,16f6,d#6,d6,d6,d#6,f6,16a#,16c6,4d6,16f6,16a#.,16a#6,g6,16f6,16a#.,f6,f6,d#6,d6,d6,d#6,f6,16a#,16c6,4a#,16a6,16d.6,16a#6,a6,a6,g6,f#6,a6,8g6,16g6,16c.6,a6,a6,g6,g6,f6,e6,g6,8f6,16f6,16a#.,16a#6,g6,16f6,16a#.,16f6,d#6,d6,d6,d#6,f6,16a#,16c.6,d6,d#6,f6,16a#,16c.6,d6,d#6,f6,16a#6,16c7,8a#.6"; static const char YMCA[] PROGMEM ="YMCA:d=4,o=5,b=160:8c#6,8a#,2p,8a#,8g#,8f#,8g#,8a#,c#6,8a#,c#6,8d#6,8a#,2p,8a#,8g#,8f#,8g#,8a#,c#6,8a#,c#6,8d#6,8b,2p,8b,8a#,8g#,8a#,8b,d#6,8f#6,d#6,f.6,d#.6,c#.6,b.,a#,g#"; static const char Simpsons[] PROGMEM @@ -157,17 +167,17 @@ static const char Simpsons[] PROGMEM static const char Indiana[] PROGMEM = "Indiana:d=4,o=5,b=250:e,8p,8f,8g,8p,1c6,8p.,d,8p,8e,1f,p.,g,8p,8a,8b,8p,1f6,p,a,8p,8b,2c6,2d6,2e6,e,8p,8f,8g,8p,1c6,p,d6,8p,8e6,1f.6,g,8p,8g,e.6,8p,d6,8p,8g,e.6,8p,d6,8p,8g,f.6,8p,e6,8p,8d6,2c6"; static const char TakeOnMe[] PROGMEM - = "TakeOnMe:d=4,o=4,b=160:8f#5,8f#5,8f#5,8d5,8p,8b,8p,8e5,8p,8e5,8p,8e5,8g#5,8g#5,8a5,8b5,8a5,8a5,8a5,8e5,8p,8d5,8p,8f#5,8p,8f#5,8p,8f#5,8e5,8e5,8f#5,8e5,8f#5,8f#5,8f#5,8d5,8p,8b,8p,8e5,8p,8e5,8p,8e5,8g#5,8g#5,8a5,8b5,8a5,8a5,8a5,8e5,8p,8d5,8p,8f#5,8p,8f#5,8p,8f#5,8e5,8e5"; + = "TakeOnMe:d=8,o=4,b=160:f#5,f#5,f#5,d5,p,b,p,e5,p,e5,p,e5,g#5,g#5,a5,b5,a5,a5,a5,e5,p,d5,p,f#5,p,f#5,p,f#5,e5,e5,f#5,e5,f#5,f#5,f#5,d5,p,b,p,e5,p,e5,p,e5,g#5,g#5,a5,b5,a5,a5,a5,e5,p,d5,p,f#5,p,f#5,p,f#5,e5,e5"; static const char Looney[] PROGMEM = "Looney:d=4,o=5,b=140:32p,c6,8f6,8e6,8d6,8c6,a.,8c6,8f6,8e6,8d6,8d#6,e.6,8e6,8e6,8c6,8d6,8c6,8e6,8c6,8d6,8a,8c6,8g,8a#,8a,8f"; static const char _20thCenFox[] PROGMEM = "20thCenFox:d=16,o=5,b=140:b,8p,b,b,2b,p,c6,32p,b,32p,c6,32p,b,32p,c6,32p,b,8p,b,b,b,32p,b,32p,b,32p,b,32p,b,32p,b,32p,b,32p,g#,32p,a,32p,b,8p,b,b,2b,4p,8e,8g#,8b,1c#6,8f#,8a,8c#6,1e6,8a,8c#6,8e6,1e6,8b,8g#,8a,2b"; static const char Bond[] PROGMEM - = "Bond:d=4,o=5,b=80:32p,16c#6,32d#6,32d#6,16d#6,8d#6,16c#6,16c#6,16c#6,16c#6,32e6,32e6,16e6,8e6,16d#6,16d#6,16d#6,16c#6,32d#6,32d#6,16d#6,8d#6,16c#6,16c#6,16c#6,16c#6,32e6,32e6,16e6,8e6,16d#6,16d6,16c#6,16c#7,c.7,16g#6,16f#6,g#.6"; + = "Bond:d=16,o=5,b=80:p,c#6,32d#6,32d#6,d#6,8d#6,c#6,c#6,c#6,c#6,32e6,32e6,e6,8e6,d#6,d#6,d#6,c#6,32d#6,32d#6,d#6,8d#6,c#6,c#6,c#6,c#6,32e6,32e6,e6,8e6,d#6,d6,c#6,c#7,4c.7,g#6,f#6,4g#.6"; static const char GoodBad[] PROGMEM = "GoodBad:d=4,o=5,b=56:32p,32a#,32d#6,32a#,32d#6,8a#.,16f#.,16g#.,d#,32a#,32d#6,32a#,32d#6,8a#.,16f#.,16g#.,c#6,32a#,32d#6,32a#,32d#6,8a#.,16f#.,32f.,32d#.,c#,32a#,32d#6,32a#,32d#6,8a#.,16g#.,d#"; static const char PinkPanther[] PROGMEM -= "PinkPanther:d=4,o=5,b=160:8d#,8e,2p,8f#,8g,2p,8d#,8e,16p,8f#,8g,16p,8c6,8b,16p,8d#,8e,16p,8b,2a#,2p,16a,16g,16e,16d,2e"; += "PinkPanther:d=16,o=5,b=160:8d#,8e,2p,8f#,8g,2p,8d#,8e,p,8f#,8g,p,8c6,8b,p,8d#,8e,p,8b,2a#,2p,a,g,e,d,2e"; static const char A_Team[] PROGMEM = "A-Team:d=8,o=5,b=125:4d#6,a#,2d#6,16p,g#,4a#,4d#.,p,16g,16a#,d#6,a#,f6,2d#6,16p,c#.6,16c6,16a#,g#.,2a#"; static const char Jeopardy[] PROGMEM @@ -176,8 +186,6 @@ static const char Gadget[] PROGMEM = "Gadget:d=16,o=5,b=50:32d#,32f,32f#,32g#,a#,f#,a,f,g#,f#,32d#,32f,32f#,32g#,a#,d#6,4d6,32d#,32f,32f#,32g#,a#,f#,a,f,g#,f#,8d#"; static const char Smurfs[] PROGMEM = "Smurfs:d=32,o=5,b=200:4c#6,16p,4f#6,p,16c#6,p,8d#6,p,8b,p,4g#,16p,4c#6,p,16a#,p,8f#,p,8a#,p,4g#,4p,g#,p,a#,p,b,p,c6,p,4c#6,16p,4f#6,p,16c#6,p,8d#6,p,8b,p,4g#,16p,4c#6,p,16a#,p,8b,p,8f,p,4f#"; -static const char LeisureSuit[] PROGMEM - = "LeisureSuit:d=16,o=6,b=56:f.5,f#.5,g.5,g#5,32a#5,f5,g#.5,a#.5,32f5,g#5,32a#5,g#5,8c#.,a#5,32c#,a5,a#.5,c#.,32a5,a#5,32c#,d#,8e,c#.,f.,f.,f.,f.,f,32e,d#,8d,a#.5,e,32f,e,32f,c#,d#.,c#"; static const char Toccata[] PROGMEM ="Toccata:d=4,o=5,b=160:16a4,16g4,1a4,16g4,16f4,16d4,16e4,2c#4,16p,d.4,2p,16a4,16g4,1a4,8e.4,8f.4,8c#.4,2d4"; /* @@ -185,10 +193,14 @@ static const char Toccata[] PROGMEM */ #pragma GCC diagnostic ignored "-Wunused-variable" static const char * const RTTTLMelodies[] PROGMEM = { StarWars, MahnaMahna, LeisureSuit, MissionImp, Flinstones, YMCA, Simpsons, - Indiana, TakeOnMe, Entertainer, Muppets, Looney, _20thCenFox, Bond, StarWars, GoodBad, PinkPanther, A_Team, Jeopardy, - Gadget, Smurfs, Toccata }; + Indiana, TakeOnMe, Entertainer, Muppets, Looney, _20thCenFox, Bond, GoodBad, PinkPanther, A_Team, Jeopardy, Gadget, Smurfs, + Toccata }; #define ARRAY_SIZE_MELODIES (sizeof(RTTTLMelodies)/sizeof(const char *)) +static const char * const RTTTLMelodiesSmall[] PROGMEM = { StarWars, MahnaMahna, LeisureSuit, MissionImp, Indiana, TakeOnMe, + Muppets, _20thCenFox, Bond, GoodBad, PinkPanther }; +#define ARRAY_SIZE_MELODIES_SMALL (sizeof(RTTTLMelodiesSmall)/sizeof(const char *)) + static const char JingleBell[] PROGMEM = "JingleBell:d=8,o=5,b=112:a,a,4a,a,a,4a,a,c6,f.,16g,2a,a#,a#,a#.,16a#,a#,a,a.,16a,a,g,g,a,4g,4c6,16p,a,a,4a,a,a,4a,a,c6,f.,16g,2a,a#,a#,a#.,16a#,a#,a,a.,16a,c6,c6,a#,g,2f"; static const char Rudolph[] PROGMEM