Music on Arduino 2 Picaxe collection

Music on Arduino 2
Picaxe collection

How to write a really simple program

On the Web most of Arduino melody and music players are based on relativly ineffective example, such as Jeremy Blum's book "Exploring Arduino. Tools and Techniques for Engineerig Wizardry", chapter 5. blum_ch5.zip In this examle two arrays of type int are defined. notes[] array contains notes' frequancies (Hz) and times[] array contains notes' durations (milliseconds). And the notes are determined using #define directives from the file pitches.h. This is supposed to make writing a program easier. (the programmer writes the names of the notes, not the frequencies). The length of the melody is set by variable i - the programmer must (in his mind) count the number of notes. For short tunes such program looks good. But what happens if someone wants to write a longer melody?

It is clear that each note with this approach takes 4 bytes. Let's suppose the melody has 200 notes length, that means 800 bytes. It is easy to reduce times[] array memory size - we have to simply write char instead of int and then we need to divide array values by 125 (the shortest note duration in milliseconds). notes[] array memory size is more complex to reduce but we can substitute notes frequancies by note numbers with the help of #define. In this example notes are encoded by numbers 0 - 14 (0 - pause и 2 octaves of note without #), and frequancies are encoded by numbers 1 - 4. Also using the PROGMEM keyword it is possible to ensure that arrays are not copied to RAM.

"He's A Pirate" / "Pirates of the Caribbean"

ROM RAM
original 3322 bytes 844 bytes
optimized 1612 bytes 9 bytes

Download melody_pirate.zip

This way, only by slightly editing the program source text, I reduced the resulting program code more than twice. But you can reduce the code of the melodies even stronger encoding melody with only 1 byte per note. On the cite www.picaxe.com I found examples of such encoded ringtones.

The last two archives on this page contain codes written in PICAXE BASIC, but these codes can be easily translated into any language. One byte of code corresponds to one note formatted as:

BitsVariable
3-0note - note (0-11) or pause (12)
5-4ioctave - octave (0-2)
7-6ilen - duration (1/8,1/4,1/2,1)

Such coding has disadvantages. 1/16 notes and notes with a dot are missing. Besides such code is hard to use when manually typing notes comparing with Quick Basic PLAY format. Encoding in PICAXE format (from Nokia RTTTL ringtones) requires a special wizard program. But for this format - "one note - one byte" is very easy to write a decoder:

#include "notes.h"
//Octave frequancy table for 12 notes (including with # notes)
const PROGMEM unsigned int freqtab[]={200,211,224,238,252,267,283,300,318,337,358,379};
//Length of 1/8 note in milliseconds
//Possible values: from 125 (fast) to 250 (slow)
#define SPEED 125
//Place your beeper pin number here
const int buzzer = 8;

const unsigned char coct[]={1,2,0,1}; //note octaves
const unsigned char clen[]={2,1,8,4}; //note durations: 1/4, 1/8, 1, 1/2
unsigned int freq,durat;

//This function plays note. See zip file for source
void toneWithDelay (uint8_t _pin, unsigned int frequency, unsigned long duration)
{
...
}

void decod(unsigned char d)
{unsigned char note,ioctave,ilen;
 note=d & 15;ioctave=(d >> 4) & 3;ilen=(d >> 6) & 3;
 durat=SPEED*(unsigned int)(clen[ilen]);
 if (note != 12) freq=pgm_read_word(freqtab+note)  << coct[ioctave];else freq=0;
}

void play(const unsigned char *melody)
{unsigned char d;unsigned int i;
 for (i=0;d=pgm_read_byte(melody+i), d != 255;i++) {decod(d);toneWithDelay(buzzer,freq,durat);} 
}

void setup()
{
 pinMode(buzzer,OUTPUT);play(notes);
}

void loop()
{}

In order not to be confused with a large number of tiny ringtone files, I packed the melody data into programs ringtv.exe and ringxmas.exe. These programs are written on Visual Basic 6. Simply select a melody and press button - melody code will be written to notes.h file. The source code of these programs in Visual Basic 6 is also contained in the archive.

Fixed 5 August 2019 RTTTL converter with examples of ringtones is added to archive.

Download PICAXE music sketch for Arduino and ringtones