WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

end2endzone/AnyRtttl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AnyRtttl logo

License: MIT Github Releases Visitors

Button Install Button Changelog

AnyRtttl

AnyRtttl is a feature rich arduino library for playing RTTTL melodies. The library offers much more interesting features than relying on the widely available void play_rtttl(char *p) function. The library supports all best RTTTL features.

Library features:

  • Really small increase in memory & code footprint compared to the usual blocking algorithm.
  • Blocking & Non-Blocking modes available.
  • Support custom tone(), noTone(), delay() and millis() functions.
  • Compatible with external Tone libraries.
  • Supports RTTTL melodies stored in RAM or Program Memory (PROGMEM).
  • Compatible with any custom or arbitrary RTTTL format that can be decoded as legacy RTTTL.
  • Supports highly compressed RTTTL binary format. See Play16Bits or Play10Bits examples.
  • Support for playing 2 melodies simultaneously (using 2 speakers on two different pins). See ESP32DualPlayRtttl example.

Status

Build:

Service Build Tests
Windows Server 2019 Build on Windows Tests on Windows
Ubuntu 22.04 Build on Linux Tests on Linux

Purpose

After publishing NonBlockingRtttl arduino library, I started using the library in more complex projects which was requiring other libraries. I quickly ran into the hell of library dependencies and library conflicts. I realized that I needed more features that could help me prototype faster.

Other libraries available which allows you to "play" a melody in RTTTL format suffer the same issue: they are based on blocking APIs or the RTTTL data is not optimized for space.

AnyRtttl is different since it packs multiple RTTTL related features in a single library. It supports blocking & non-blocking API which makes it suitable to be used by more advanced algorithm. For instance, when using the non-blocking API, the melody can be stopped when a button is pressed. The library is also compatible with external Tone libraries and it supports highly compressed RTTTL binary formats.

Non-Blocking

Most of the code that can "play" a melody on internet are build the same way: sequential calls to tone() and delay() functions using hardcoded values. This type of implementation might be good for robots but not for realtime application or projects that needs to monitor pins while the song is playing.

With AnyRtttl non-blocking mode, your program can read/write IOs pins while playing and react on changes. Implementing a "stop" or "next song" push button is easy!

External Tone or Timer #0 libraries

The AnyRtttl library is also flexible by allowing you to use the build-in arduino tone() and noTone() functions or an implementation from any external library which makes it compatible with any Tone library in the market.

The library also supports custom delay() and millis() functions. If a project requires modification to the microcontroller's build-in Timer #0, the millis() function may be impacted and behave incorrectly. To maximize compatibility, one can supply a custom function which behaves like the original to prevent altering playback.

Binary RTTTL / Compatibility with custom RTTTL formats

AnyRtttl can be configured for playing your custom format. AnyRtttl can use a custom function for decoding such a custom format. This allows the library to be compatible with any custom RTTTL formats that can be decoded as legacy RTTTL.

For example, AnyRtttl library can be adapted to play RTTTL data which is stored as binary data instead of text. This is actually a custom implementation of the RTTTL format. Using this format, one can achieve storing an highly compressed RTTTL melody which saves memory.

The Play10Bits and Play16Bits are examples for showing AnyRtttl's capability to adapt to custom formats.

See BinaryRTTTL.md for a definition of this custom RTTTL format.

Usage

The following instructions show how to use the library.

Define ANY_RTTTL_INFO to enable the debugging of the library state on the serial port.

Use ANY_RTTTL_VERSION to get the current version of the library.

Note, the specified macros must be defined before including anyrtttl.h in your sketches.

Non-blocking mode

  anyrtttl::nonblocking::begin(BUZZER_PIN, mario);

Call anyrtttl::nonblocking::begin() to setup AnyRtttl library in non-blocking mode.

Then call anyrtttl::nonblocking::play() to update the library's state and play notes as required.

Use anyrtttl::done() or anyrtttl::nonblocking::isPlaying() to know if the library is done playing the given song.

Anytime, one can call anyrtttl::nonblocking::stop() to stop playing the current song.

The following code shows how to use the library in non-blocking mode:

#include <anyrtttl.h>
#include <binrtttl.h>
#include <pitches.h>

//project's constants
#define BUZZER_PIN 8
const char * tetris = "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";
const char * arkanoid = "Arkanoid:d=4,o=5,b=140:8g6,16p,16g.6,2a#6,32p,8a6,8g6,8f6,8a6,2g6";
const char * mario = "mario:d=4,o=5,b=100:16e6,16e6,32p,8e6,16c6,8e6,8g6,8p,8g,8p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,16p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16c7,16p,16c7,16c7,p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16d#6,8p,16d6,8p,16c6";
byte songIndex = 0; //which song to play when the previous one finishes

void setup() {
  pinMode(BUZZER_PIN, OUTPUT);

  Serial.begin(115200);
  Serial.println();
}

void loop() {
  // If we are not playing something 
  if ( !anyrtttl::nonblocking::isPlaying() )
  {
    // Play a song based on songIndex.
    if (songIndex == 0)
      anyrtttl::nonblocking::begin(BUZZER_PIN, tetris);
    else if (songIndex == 1)
      anyrtttl::nonblocking::begin(BUZZER_PIN, arkanoid);
    else if (songIndex == 2)
      anyrtttl::nonblocking::begin(BUZZER_PIN, mario);

    //Set songIndex ready for next song
    songIndex++;
  }
  else
  {
    anyrtttl::nonblocking::play();
  }
}

Playing RTTTL data stored in flash (program) memory

AnyRtttl also supports RTTTL melodies stored in flash or Program Memory (PROGMEM).

The anyrtttl::nonblocking::begin() function supports Program Memory macros such as FPSTR() or F().

The following code shows how to use the library with RTTTL data stored in flash (program) memory instead of SRAM:

#include <anyrtttl.h>
#include <binrtttl.h>
#include <pitches.h>

//project's constants
#define BUZZER_PIN 8
const char tetris[] PROGMEM = "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";
const char arkanoid[] PROGMEM = "Arkanoid:d=4,o=5,b=140:8g6,16p,16g.6,2a#6,32p,8a6,8g6,8f6,8a6,2g6";
const char mario[] PROGMEM = "mario:d=4,o=5,b=100:16e6,16e6,32p,8e6,16c6,8e6,8g6,8p,8g,8p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,16p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16c7,16p,16c7,16c7,p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16d#6,8p,16d6,8p,16c6";
// James Bond theme defined in inline code below (also stored in flash memory) 
byte songIndex = 0; //which song to play when the previous one finishes

void setup() {
  pinMode(BUZZER_PIN, OUTPUT);

  Serial.begin(115200);
  Serial.println();
}

void loop() {
  // If we are not playing something 
  if ( !anyrtttl::nonblocking::isPlaying() )
  {
    // Play a song based on songIndex.
    if (songIndex == 0)
      anyrtttl::nonblocking::beginProgMem(BUZZER_PIN, tetris);
    else if (songIndex == 1)
      anyrtttl::nonblocking::begin_P(BUZZER_PIN, arkanoid);
    else if (songIndex == 2)
      anyrtttl::nonblocking::begin(BUZZER_PIN, FPSTR(mario));
    else if (songIndex == 3)
      anyrtttl::nonblocking::begin(BUZZER_PIN, F("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"));

    //Set songIndex ready for next song
    songIndex++;
  }
  else
  {
    anyrtttl::nonblocking::play();
  }
}

Advanced Usage

Custom Tone function (a.k.a. RTTTL 2 code)

This example shows how custom functions can be used by the AnyRtttl library to convert an RTTTL melody to arduino code.

First define replacement functions like the following:

void serialTone(byte pin, uint16_t frequency, uint32_t duration) {
  Serial.print("tone(");
  Serial.print(pin);
  Serial.print(",");
  Serial.print(frequency);
  Serial.print(",");
  Serial.print(duration);
  Serial.println(");");
}

void serialNoTone(byte pin) {
  Serial.print("noTone(");
  Serial.print(pin);
  Serial.println(");");
}

void serialDelay(uint32_t duration) {
  Serial.print("delay(");
  Serial.print(duration);
  Serial.println(");");
}

Each new functions prints the function call & arguments to the serial port.

In the setup() function, setup the AnyRtttl library to use the new functions:

//Use custom functions
anyrtttl::setToneFunction(&serialTone);
anyrtttl::setNoToneFunction(&serialNoTone);
anyrtttl::setDelayFunction(&serialDelay);

Use the anyrtttl::blocking::play() API for "playing" an RTTTL melody and monitor the output of the serial port to see the actual arduino code generated by the library.

The following code shows how to use the library with custom functions:

#include <anyrtttl.h>
#include <binrtttl.h>
#include <pitches.h>

//project's constants
#define BUZZER_PIN 8
const char * tetris = "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";

//*******************************************************************************************************************
//  The following replacement functions prints the function call & parameters to the serial port.
//*******************************************************************************************************************
void serialTone(byte pin, uint16_t frequency, uint32_t duration) {
  Serial.print("tone(");
  Serial.print(pin);
  Serial.print(",");
  Serial.print(frequency);
  Serial.print(",");
  Serial.print(duration);
  Serial.println(");");
}

void serialNoTone(byte pin) {
  Serial.print("noTone(");
  Serial.print(pin);
  Serial.println(");");
}

void serialDelay(uint32_t duration) {
  Serial.print("delay(");
  Serial.print(duration);
  Serial.println(");");
}

void setup() {
  pinMode(BUZZER_PIN, OUTPUT);

  Serial.begin(115200);
  Serial.println();

  //Use custom functions
  anyrtttl::setToneFunction(&serialTone);
  anyrtttl::setNoToneFunction(&serialNoTone);
  anyrtttl::setDelayFunction(&serialDelay);
}

void loop() {
  anyrtttl::blocking::play(BUZZER_PIN, tetris);

  while(true)
  {
  }
}

Examples

More AnyRtttl examples are also available:

RTTTL

Format specification

This library implements the original Nokia Phone specification (backup copy here).

This format is specified as the following:
<name>:<control-section>:<tone-commands>,<tone-commands>...

Control Section:

The control section is optional. It defines the following parameters for the melody:

  • d=<value> : Default duration of a note if unspecified.
  • o=<value> : Default octave of a note if unspecified.
  • b=<value> : Beats per minutes of a quarter note

Tone commands:

Tones can be represented in the following format:

<duration><note><octave><.> where :

  • duration is the duration divider of full note duration, eg. 4 represents a quarter note.
  • note is the note name (one of p,c,c#,d,d#,e,f,f#,g,g#,a,a#,b). The note p is a special note that represents a pause, a silent note in the melody.
  • scale is the scale of the melody: from 4 to 7.
  • . is a dotted note which increases the duration.

The duration, octave and dot are optional.

Example: Simpsons:d=4,o=5,b=160:32p,c.6,e6,f#6,8a6,g.6,e6,c6,8a,8f#,8f#,8f#,2g.

Other specifications:

RTTTL ressources

Online RTTTL players:

Other:

Melody databases:

Building

Please refer to file INSTALL.md for details on how installing/building the application.

Platforms

AnyRtttl has been tested with the following platform:

  • Linux x86/x64
  • Windows x86/x64

Versioning

We use Semantic Versioning 2.0.0 for versioning. For the versions available, see the tags on this repository.

Authors

See also the list of contributors who participated in this project.

License

This project is licensed under the MIT License - see the LICENSE file for details

About

A feature rich arduino library for playing rtttl melodies

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •