Home

Awesome

The ArduboyTones Library

The ArduboyTones library is maintained in a git repository hosted on GitHub at:

https://github.com/MLXXXp/ArduboyTones

ArduboyTones is a library for playing tones and tone sequences, intended to be used with the Arduino based Arduboy miniature game system (but could be used with other Arduino boards).

Description

ArduboyTones is a small, efficient library which generates tones and tone sequences on a speaker attached to digital output pins. It is intended to be used by games and other sketches written for the Arduboy, so the pins (and timer) used are hard coded for the Arduboy, and thus aren't specified in any functions.

Like the Arduino built in tone() function, the tones are simple square waves generated by toggling a pin digitally high and low with a 50% duty cycle. Also like Arduino tone(), once started, interrupts are used so that the sound plays in the background while the real code continues to run.

ArduboyTones has equivalents to Arduino tone() and noTone() and additionally:

Note that even with all these features, ArduboyTones will use significantly less code space than using Arduino tone() functions.

Converting MIDI files

A separate command line utility program, midi2tones, is available. It will convert standard MIDI files to ArduboyTones format when the -o2 option is specified.

Installation

The library can be installed using the Arduino IDE library manager:

For more library installation information see

Installing Additional Arduino Libraries - Using the Library Manager

Using the library

Setting up

Include the library using

#include <ArduboyTones.h>

You must then create an ArduboyTones object which specifies the callback function used for muting. The function is a required parameter. It must return a boolean (or bool) value which will be true if sound should be played, or false if all sounds should be muted. In this document the ArduboyTones object will be named sound. The audio.enabled() function of the Arduboy library will be used for the mute callback. The Arduboy object will be named arduboy.

So, to set things up we can use:

#include <Arduboy2.h>
#include <ArduboyTones.h>

Arduboy2 arduboy;
ArduboyTones sound(arduboy.audio.enabled);

Specifying tones

Each tone is specified by a frequency and duration pair, the same as with Arduino tone(). Like tone(), the frequency is specified in hertz (Hz, cycles per second). The duration is in milliseconds (actually very slightly shorter; see below).

There are some small differences between the Arduino tone() and the ArduboyTones frequency and duration parameters.

Frequency

Duration

Defines for musical notes

ArduboyTones includes file ArduboyTonesPitches.h which will automatically be included by ArduboyTones.h. ArduboyTonesPitches.h provides frequency values for musical notes based on A4 = 440 Hz.

The format is:

NOTE_<letter><optional S for sharp><octave number><optional H for high volume>

NOTE_REST is defined as 0 and can be used for a musical rest.

There are no flats. You have to use the sharp note equivalent.

Notes are define over the range of C0 (16 Hz) to B9 (15804 Hz)

Examples: NOTE_C3 NOTE_GS4 NOTE_B5H NOTE_DS6H

Functions

All functions are members of class ArduboyTones, so you must remember to reference each function with the object name. Example: sound.tone(1000, 500);


Play a tone forever or until interrupted:

void tone(frequency)

Play a single tone for the duration. Duration can be 0 (forever):

void tone(frequency, duration)

Play two tones in sequence:

void tone(freq1, dur1, freq2, dur2)

Play three tones in sequence:

void tone(freq1, dur1, freq2, dur2, freq3, dur3)


Play a tone sequence from frequency/duration pairs in an array in program memory:

void tones(arrayInProgram)

The array must end with a single value of either TONES_END, to end the sequence, or TONES_REPEAT to continuously repeat from beginning to end.

Example:

const uint16_t song1[] PROGMEM = {
  220,1000, 0,250, 440,500, 880,2000,
  TONES_END };

sound.tones(song1);

The same as tones() above except the frequency/duration pairs are in an array in RAM instead of in program memory:

void tonesInRAM(arrayInRAM)

Generally, the only reason to use tonesInRAM() instead of tones() would be if dynamically altering the contents of the array is required.

Example:

uint16_t song2[] = {
  NOTE_A3,1000, NOTE_REST,250, NOTE_A4,500, NOTE_A5,2000,
  TONES_REPEAT };

sound.tonesInRAM(song2);

Stop playing the tone or sequence:

void noTone()

If called when nothing is playing, it will do nothing.


Set the volume to always be normal, always high, or tone controlled:

void volumeMode(mode)

The following values for mode should be used:


Check if a tone or tone sequence is playing:

boolean playing()

Returns true if playing (even if sound is muted).


Notes and Hints

Example sketch

The ArduboyTones library contains an example sketch ArduboyTonesTest in the examples folder. It was primarily written to test the library but the code can be examined and uploaded for examples of using all the functions. It uses the Arduboy2 library, which must be installed to compile the sketch. ArduboyTonesTest can be loaded into the Arduino IDE using the menus:

File > Examples > ArduboyTones > ArduboyTonesTest

Frequencies and durations work the same everywhere

You can use rests and infinite durations in tone() functions the same as in sequence arrays. Most of the time this wouldn't be useful, however...

Something to consider for all of the above points, though:

Using a two or three tone array in program memory with tones() is likely more efficient than using a two or three tone tone() function. The two and three tone tone() functions were only added to make things easier and quick for sketches where code size isn't an issue.

Why durations aren't exactly in milliseconds

Ideally, to match Arduino tone(), durations should be given in 1000ths of a second (milliseconds). However, ArduboyTones treats durations as being in 1024ths of a second. Here's why:

To calculate internal timing values for a duration given in milliseconds, a divide by 500 on an unsigned long (32 bit) number is required, which is what Arduino tone() does. On an 8 bit processor without any native divide instructions, this is slow and takes a fair amount of code. On the other hand, a divide by 512 is easily and quickly accomplished by simply shifting the value right 9 bits. This is what ArduboyTones does, at the expense of durations being about 2.34% shorter than the same value would be with Arduino tone().

In most circumstances, the slightly shorter durations will likely be unnoticeable. If a duration needs to be precise, the required value can be calculated by multiplying the desired duration, in milliseconds, by 1.024.

Use with the Arduboy Development Kit (DevKit) version

ArduboyTones will work with the Arduboy DevKit. The DevKit is limited to controlling only one pin for the speaker, so all tones will sound at normal volume. The high volume setting in tones will be ignored, and calls to volumeMode() will have no effect.