Making music with our computer

Our little Launchpad computer has three timers that can control three output pins. That means we can tell each of the timers to turn its pin high or low (on or off)  at three different frequencies. If we select frequencies in the audible range (16 times per second up to 25,000 times per second), and attach a speaker to the pin, we can make tones we can hear.

The timers will be simply turning the pin on and off, so the sounds will be the same as those used in early video games, sounding something like a harmonica or a bagpipe.

Because we have three timers, we can play three notes at once. That's not a lot, compared to what a piano player can do (he has ten fingers and a sustain pedal), but it is enough for many basic chords.

There is a lot of free music available on the Internet in the form of MIDI files. You can search for "free MIDI songs" and find almost anything.

I have written a program that can convert MIDI songs into source code for the three timers in the Launchpad. If the song is playing more than three notes at once, the program does a fair job of selecting which notes are important to keep, and which ones can be shortened or eliminated.

The Launchpad has enough memory for most of the songs you will find. If the song is particularly complex or long, the program will convert the entire song, but it will comment out the past parts so the program will still run, even though it cuts the song short.

The program you copy and paste into Energia to compile for the Launchpad is actually fairly simple. It starts with a list of the frequencies for each note. Then there is a list of all the notes to be played. The code that does the playing of the notes is short enough to show here:

const unsigned long int microseconds_per_tick = 4222UL;

enum { SILENCE=128 };

unsigned char last_timer1 = SILENCE;
unsigned char last_timer2 = SILENCE;
unsigned char last_timer3 = SILENCE;

void
setup( void )
{
  pinMode( PUSH2, INPUT_PULLUP );
  for( unsigned int which_event = 0; which_event < sizeof events / sizeof *events; which_event++ )
  {
    if( digitalRead( PUSH2 ) == LOW )
    {
      tone( P2_2, 0, 0 );
      tone( P2_3, 0, 0 );
      tone( P2_4, 0, 0 );
      break;
    }

    event e = events[ which_event ];

    if( e.timer1 != last_timer1 )
      tone( P2_2, notes[ e.timer1 ], -1 );

    if( e.timer1 != last_timer2 )
      tone( P2_3, notes[ e.timer2 ], -1 );

    if( e.timer3 != last_timer3 )
      tone( P2_4, notes[ e.timer3 ], -1 );

    last_timer1 = e.timer1;
    last_timer2 = e.timer2;
    last_timer3 = e.timer3;

    long int slp = microseconds_per_tick * e.sleep_for;
    delay( slp / 1000 );
    delayMicroseconds( slp % 1000 );
  }
}

void
loop( void )
{
    delay( 10000 );
}

Everything is done in the setup() function. This lets us start the song by pushing the RESET button on the Launchpad. When the song ends, the Launchpad goes to sleep until the RESET button is pushed again.

The first thing we do in the setup() function is make the other button on the Launchpad be an input, so we can use it to stop the music. Then we loop through all of the events in the list. An event is a change to one, two, or all three of the notes we can play. If any note in the song needs to change, there is an event telling us what to change.

Inside the loop we check to see if the STOP button has been pushed. If it has, we stop all the timers and break out of the loop.

Otherwise, we examine the next event, checking to see which note(s) have changed. If a note has changed, we call the tone() function to tell the timer which pin to use, and which note to play. Then we remember which notes are playing (so we can check for a change). Finally, we sleep for as long as we need to until the next event is to be processed.

 

To hear the music, we need to connect a speaker to the output pins (our program uses pins P2.2, P2.3, and P2.4). Speakers have two wires. One speaker wire will be attached to the ground pin (GND), which is always at zero volts. The other wire from the speaker goes to one of the three output pins.

If we only have one speaker, we can connect all three output pins together, and attach the speaker wire to all three at once. But if we have three speakers, we can space them out, so the listener can hear the notes coming from different places, as if played by different instruments in an orchestra. Many MIDI songs sound like the melody is coming from pin P2.2, and the bass from P2.3, and percussion from P2.4.

 

Some songs transcribed by the MIDI to Launchpad program:

Yankee Doodle

The Entertainer

Amazing Grace

Hey Jude

Let It Be

Beat It

Billie Jean (nice, but almost unrecognizable)

Bohemian Rhapsody

Fur Elise