Introduction
The following article is about another library that I have written: libRtttl is a c++ library for manipulating the RTTTL audio format.
Skip to the download section for quick download.
See this post for a quick recall of the RTTTL format.
Edit: for a better understanding and examples of what libRTTTL can do, please see this post: How to convert arduino code to actual RTTTL melodies using libRtttl and AnyRtttl.
Purpose
RTTTL songs available on the internet are not optimized for the smallest size. Still they are readable by a human but they are far from optimized for the arduino embedded device. Most RTTTL song can be optimized (without quality loss) and have their size reduced by ~20%. Conversion to binary allows even better compression but it wont be human readable anymore.
The library also allows one to convert an RTTTL song to hardcoded function calls (tone()
and delay()
calls). This is really useful if your dynamic memory is almost completely full and you would like to move the load from dynamic memory to program storage space.
The UI (rtttlOptimizerGui) also features a basic RTTTL player. The quality of the playback is limited but it allows one to prove that a compression did not changed the song’s melody.
Library
Functionalities / Features
Possible use are:
- Optimize an existing RTTTL melodies.
- Convert RTTTL melodies to other format:
- MIDI.
- Arduino
tone()
anddelay()
function calls. - Binary format (10 bits per note) for maximum compression (minimum size).
- Binary format (16 bits per note) for quick note offset addressing and minimum code footprint.
- Convert arduino
tone()
anddelay()
function calls back to a valid RTTTL melody. - Allow relaxed RTTTL settings for easier conversions.
Note that RTTTL binary format requires an external arduino library for playback. The AnyRtttl library supports all common RTTTL format including the binary format generated by this library.
Requirements
The library has some compilation requirements and library dependencies which are:
libRtttl
- Only Visual Studio 2008 projects files are available. Files can be manually moved to other platforms or IDE as required. Supporting other compilers is not currently planned.
- Requires code from BitReader and AnyRtttl arduino libraries, libMidi and win32Arduino win32 library which are all already included in source code.
- The Google Test v1.6 library is required for running test cases.
rtttlOptimizerGui
- Requires the wxWidgets Cross-Platform GUI Library v2.8.12 for compiling.
- The UI design files must be edited with wxFormBuilder v3.0.57 (a RAD tool for wxWidgets GUI design). This tools is not required for compilation.
- NSIS: Nullsoft Scriptable Install System is required for generating the installation package.
- The & functionalities require the Windows platform for runtime.
- The code uses some compiler-dependent instructions for debugging the UI under Windows.
- All non-portable code is protected with
#ifdef _WIN32
to be cross-platform friendly.
Usage
All functionalities of the library are available through the UI.
Start the UI by launching rtttlOptimizerGui.exe.
Copy & paste the input data in the Command Input text area. Click on one of the available command buttons. The output result will be displayed in the Command Output area.
Optimize
Copy & paste a valid song in RTTTL format in the Command Input section.
Press the button to compress the RTTTL code to its shortest form.
During optimization, the library will convert the input RTTTL song to “raw” data and re-encode the result back to RTTTL using all possible combinations of default duration, default octave and BPM (Beats per minute).
From all combination possibilities, the library will select the shortest one. For example, the following RTTTL code from The Legend of Zelda :
1 2 3 4 5 6 7 8 9 |
Zelda1:d=4,o=5,b=125:a#,f.,8a#,16a#,16c6,16d6,16d#6,2f6, 8p,8f6,16f.6,16f#6,16g#.6,2a#.6,16a#.6,16g#6,16f#.6, 8g#.6,16f#.6,2f6,f6,8d#6,16d#6,16f6,2f#6,8f6,8d#6,8c#6, 16c#6,16d#6,2f6,8d#6,8c#6,8c6,16c6,16d6,2e6,g6,8f6,16f, 16f,8f,16f,16f,8f,16f,16f,8f,8f,a#,f.,8a#,16a#,16c6, 16d6,16d#6,2f6,8p,8f6,16f.6,16f#6,16g#.6,2a#.6,c#7,c7, 2a6,f6,2f#.6,a#6,a6,2f6,f6,2f#.6,a#6,a6,2f6,d6,2d#.6, f#6,f6,2c#6,a#,c6,16d6,2e6,g6,8f6,16f,16f,8f,16f,16f, 8f,16f,16f,8f,8f |
can be optimized to the following code:
1 2 3 4 5 6 |
Zelda1:d=8,o=6,b=250:2a#5,2f.5,4a#5,a#5,c,d,d#,1f,4p,4f,f.,2p, 1f#,g#.,1a#.,a#.,g#,f#.,4g#.,f#.,1f,2f,4d#,d#,2p,1f,1f#,4f,4d#, 4c#,c#,d#,1f,4d#,4c#,4c,c,d,1e,2p,2g,4f,f5,f5,4f5,f5,f5,4f5,f5,f5, 4f5,4f5,2a#5,2f.5,4a#5,a#5,c,d,d#,2p,2f,4p,4f,f.,f#,g#.,1a#., 2c#7,2c7,1a,2f,1f#.,2a#,2a,1f,2f,2p,2f#.,2a#,2a,1f,2d,1d#.,2f#, 2f,1c#,2a#5,2c,d,1e,2g,4f,f5,f5,4f5,2p,1f5,f5,4f5,f5,f5,4f5,4f5 |
which reduces the original code length by 89 bytes (from 446 bytes to 357 bytes), that is a 19.95% size reduction.
Play RTTTL
Copy & paste a valid song in RTTTL format in the Command Input section.
Press the button to play the melody.
Note that application will momentary freeze during the playback. The application will respond again once the melody is done playing.
RTTTL to MIDI
Copy & paste a valid song in RTTTL format in the Command Input section.
Press the button to convert the melody to the MIDI sound format and automatically play the melody.
Note that MIDI sound format offers much better playback capabilities and sound quality than beeping each tone. See my post about my MIDI library for more details: libMIDI – A C++ open-source library for generating single tone melodies in MIDI format.
tone() to RTTTL
Copy & paste a valid song in arduino code (tone()
and delay()
function calls) in the Command Input section.
Press the button to encode the melody into RTTTL.
For example, the following arduino code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
void playArkanoid(int pin) { tone(pin, 1568, 214); delay(215); delay(107); tone(pin, 1568, 160); delay(161); tone(pin, 1865, 856); delay(857); delay(53); tone(pin, 1760, 214); delay(215); tone(pin, 1568, 214); delay(215); tone(pin, 1397, 214); delay(215); tone(pin, 1760, 214); delay(215); tone(pin, 1568, 856); delay(857); noTone(pin); } |
is encoded into the following RTTTL code:
1 |
unknown:d=8,o=6,b=140:g,16p,16g.,2a#,32p,a,g,f,a,2g |
This feature is useful for moving data from program storage space to dynamic memory.
RTTTL to tone()
Copy & paste a valid song in RTTTL format in the Command Input section.
Press the button to decode the input song to “raw” data (note with frequency and duration) and generate the arduino code required to play the song.
This process is really useful if your dynamic memory is almost completely full and you would like to move the load from dynamic memory to program storage space.
For instance, the RTTTL code from Super Mario Bros. – 1-up sound :
1 |
mario1up:d=16,o=7,b=180:e.6,g.6,e.,c.,d.,g. |
generates the following arduino code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void playMario1up(int pin) { tone(pin, 1319, 124); delay(125); tone(pin, 1568, 124); delay(125); tone(pin, 2637, 124); delay(125); tone(pin, 2093, 124); delay(125); tone(pin, 2349, 124); delay(125); tone(pin, 3136, 124); delay(125); noTone(pin); } |
RTTTL to Binary (10 bits)
Copy & paste a valid song in RTTTL format in the Command Input section.
Press the button to decode the input RTTTL song and encode the same melody into a binary RTTTL format where each note is encoded into 10 bits. The bits definition is already documented in section RTTTL binary format definition of AnyRtttl library post.
The AnyRtttl library can be used to play the compressed RTTTL data.
For example, the RTTTL code for playing Tetris theme song:
1 2 3 |
tetris:d=4,o=5,b=160:e6,8b,8c6,8d6,16e6,16d6,8c6,8b,a,8a, 8c6,e6,8d6,8c6,b,8b,8c6,d6,e6,c6,a,2a,8p,d6,8f6,a6,8g6, 8f6,e6,8e6,8c6,e6,8d6,8c6,b,8b,8c6,d6,e6,c6,a,a |
is compressed to the following :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
//Notes: // 10 Bits RTTTL format requires AnyRtttl & BitReader libraries. // The code & updates for AnyRtttl & BitReader libraries can be found on http://end2endzone.com #include <anyrtttl.h> #include <binrtttl.h> #include <pitches.h> #include <bitreader.h> //#define ANY_RTTTL_INFO //#define ANY_RTTTL_DEBUG //RTTTL 10 bits binary format for the following: tetris:d=4,o=5,b=160:e6,8b,8c6,8d6,16e6,16d6,8c6,8b,a,8a,8c6,e6,8d6,8c6,b,8b,8c6,d6,e6,c6,a,2a,8p,d6,8f6,a6,8g6,8f6,e6,8e6,8c6,e6,8d6,8c6,b,8b,8c6,d6,e6,c6,a,a //Compatible with AnyRtttl library v2.0 const unsigned char tetris[] = {0x0A, 0x14, 0x12, 0xCE, 0x34, 0xE0, 0x82, 0x14, 0x32, 0x38, 0xE0, 0x4C, 0x2A, 0xAD, 0x34, 0xA0, 0x84, 0x0B, 0x0E, 0x28, 0xD3, 0x4C, 0x03, 0x2A, 0x28, 0xA1, 0x80, 0x2A, 0xA5, 0xB4, 0x93, 0x82, 0x1B, 0xAA, 0x38, 0xE2, 0x86, 0x12, 0x4E, 0x38, 0xA0, 0x84, 0x0B, 0x0E, 0x28, 0xD3, 0x4C, 0x03, 0x2A, 0x28, 0xA1, 0x80, 0x2A, 0xA9, 0x04}; const int tetris_length = 42; //BitReader support #ifndef USE_BITADDRESS_READ_WRITE BitReader bitreader; #else BitAddress bitreader; #endif //the following function reads numBits from the tetris buffer uint16_t readNextBits(uint8_t numBits) { uint16_t bits = 0; bitreader.read(numBits, &bits); return bits; } //Add the following in setup() //bitreader.setBuffer(tetris); //Call the following for playing tetris melody //anyrtttl::blocking::play10Bits(BUZZER_PIN, tetris_length, &readNextBits); |
which reduces the original code length by 104 bytes (from 159 bytes to 55 bytes), that is a 65% size reduction.
RTTTL to Binary (16 bits)
Copy & paste a valid song in RTTTL format in the Command Input section.
Press the button to decode the input RTTTL song and encode the same melody into a binary RTTTL format where each note is encoded into 16 bits. The bits definition is already documented in section RTTTL binary format definition of AnyRtttl library post.
The AnyRtttl library can be used to play the compressed RTTTL data.
For example, the same RTTTL code for playing Tetris theme song:
1 2 3 |
tetris:d=4,o=5,b=160:e6,8b,8c6,8d6,16e6,16d6,8c6,8b,a,8a, 8c6,e6,8d6,8c6,b,8b,8c6,d6,e6,c6,a,2a,8p,d6,8f6,a6,8g6, 8f6,e6,8e6,8c6,e6,8d6,8c6,b,8b,8c6,d6,e6,c6,a,a |
is compressed to the following :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//Notes: // 16 Bits RTTTL format requires AnyRtttl library. // The code & updates for AnyRtttl library can be found on http://end2endzone.com #include <anyrtttl.h> #include <binrtttl.h> #include <pitches.h> //#define ANY_RTTTL_INFO //#define ANY_RTTTL_DEBUG //RTTTL 16 bits binary format for the following: tetris:d=4,o=5,b=160:e6,8b,8c6,8d6,16e6,16d6,8c6,8b,a,8a,8c6,e6,8d6,8c6,b,8b,8c6,d6,e6,c6,a,2a,8p,d6,8f6,a6,8g6,8f6,e6,8e6,8c6,e6,8d6,8c6,b,8b,8c6,d6,e6,c6,a,a //Compatible with AnyRtttl library v2.0 const unsigned char tetris[] = {0x0A, 0x14, 0x12, 0x02, 0x33, 0x01, 0x03, 0x02, 0x0B, 0x02, 0x14, 0x02, 0x0C, 0x02, 0x03, 0x02, 0x33, 0x01, 0x2A, 0x01, 0x2B, 0x01, 0x03, 0x02, 0x12, 0x02, 0x0B, 0x02, 0x03, 0x02, 0x32, 0x01, 0x33, 0x01, 0x03, 0x02, 0x0A, 0x02, 0x12, 0x02, 0x02, 0x02, 0x2A, 0x01, 0x29, 0x01, 0x3B, 0x01, 0x0A, 0x02, 0x1B, 0x02, 0x2A, 0x02, 0x23, 0x02, 0x1B, 0x02, 0x12, 0x02, 0x13, 0x02, 0x03, 0x02, 0x12, 0x02, 0x0B, 0x02, 0x03, 0x02, 0x32, 0x01, 0x33, 0x01, 0x03, 0x02, 0x0A, 0x02, 0x12, 0x02, 0x02, 0x02, 0x2A, 0x01, 0x2A, 0x01}; const int tetris_length = 42; //Call the following for playing tetris melody //anyrtttl::blocking::play16Bits(BUZZER_PIN, tetris, tetris_length); |
which reduces the original code length by 73 bytes (from 159 bytes to 86 bytes), that is a 46% size reduction.
License
libRTTTL Library / rtttlOptimizer
Copyright (C) 2016 Antoine Beauchamp
The code & updates for the library can be found on http://end2endzone.com
AUTHOR/LICENSE:
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License (LGPL-3.0) for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
DISCLAIMER:
This software is furnished “as is”, without technical support, and with no warranty, express or implied, as to its usefulness for any purpose.
Download
You can download the libRTTTL library / rtttlOptimizer by clicking on the following links: