Introduction: Arduino Christmas Tunes

The Arduino can produce very decent music as demonstrated before here. The code of a previous polyphonic FM-synthesizer was adapted to play pre-programmed tunes, thanks to the hint of another instructable user.

Watch the video to hear the sound quality, a world apart from the usual beeps! The code has 12 Christmas songs which are played in random order with an instrument chosen randomly out of 10 settings, that roughly correspond to piano, harp, xylophone, guitar, 3 bells, flute, trumpet and baritone. It uses Nokia’s RTTTL (Ring Tone Text Transfer Language) to describe a song in a text string. It is limited to simple tunes, but there are thousands of songs readily available online, and you can easily replace the Christmas tunes by pop, rock, classic, or theme songs. This project is just a minimal demo, the code can be adapted in a straightforward way for other projects that require playing a particular song in high quality at a given time or in reaction to a button or a sensor. Try it out, you only need an Arduino Uno, a speaker, a capacitor and some cables to connect them!

Step 1: Building Instructions

All that is needed is an Arduino Uno (or Nano), a speaker and a capacitor (to block the DC current). I used an 8Ohm speaker but higher impedance would work even better.

A 100muF electrolytic capacitor is put with its ‘+’ side in pin9. The speaker is connected between ground and the negative pin of the capacitor. I used 2 crocodile leads and a breadboard jumper, as shown in the picture. Upload the sketch with the Arduino IDE and it starts playing music, that’s all! You can now disconnect it from the computer and it will work anywhere, the songs are stored on the Arduino itself.

Step 2: ​Technical Considerations and Future Ideas

For detail on how the sound is generated, or what the 8 parameters of the instrument definitions mean, have a look at earlier instructables (here and here) that use the same core.

RTTTL is by nature monophonic: the notes are indicated sequentially. However, the polyphony in the code is still being used since some instruments (bells in particular) keep playing for a long time, even when the next note has started. The MIDI format is much richer, but much more complex and beyond my skills and interests.

How many songs can be stored? The compiler states:

"Sketch uses 8876 bytes (27%) of program storage space. <br>Maximum is 32256 bytes. Global variables use 729 bytes (35%) of dynamic memory,<br>leaving 1319 bytes for local variables. Maximum is 2048 bytes."

So there is 24kB of free memory, so the flash can easily store 100 songs. The extra 100 pointers will take up another 200(?) bytes in RAM, that should not be an issue either.

It is possible to adapt the code to play music based on more complicated decisions. The main "loop()" is dead simple:

void loop() {
  //select random instrument and song
  byte ins=random(ninstr);
byte isong=random(nsong);
playsong (ins,songs[isong]);

All the action happens inside the "void playsong(byte ins, char* song)" routine. Note that once the song starts playing, you loose control, so it can't react to anything else, even interrupts have been disabled. To make a program that is reactive while playing songs is slightly more involved: it could be done with polling inside the "playsong" routine, or interrupts need to be selectively enabled: the main problem with interrupts is the one that counts the milliseconds, it gives audible glitches. But a pin-change interrupt should be harmless.

Ideas: in combination with a real-time clock, it could play a song at certain times of the day. Or it could be part of an installation where a celebration song is being played when a puzzle has been solved. Or as part of a game where a tune needs to be recognised. Or as a doorbell, or in a halloween costume, etc. etc.

It would be nice if this could fit in an ATTINY85 microprocessor: it is much smaller and allows to switch itself completely off. It could run off a coin cell for months with occasional use. That way it could be built into anything, even a small Christmas-tree decoration or a toy. The code would probably need to be simplified since the ATTINY85 has less memory, no 16-bit timer and no hardware multiplication.