Lately I have been using my Raspberry Pi as an internet radio, streaming my favorite terrestrial radio stations through my bedside clock radio. Since I am using my clock radio for speakers, I thought it might be fun to program the Raspberry Pi with a custom wake-up alarm. It would be easy to tell it to play an audio file of my choice, or even a randomly selected audio file, but then the music-theory nerd in me got the idea to make it generate a random 12-tone row and play that as my alarm.

The Raspberry Pi is running as a headless computer, with no graphical environment, so it had to be done with command-line tools. Enter a bash script (of course) that calls Lilypond to generate a MIDI file and Timidity to play the file. Both of these programs are available in the Rasbian repositories.
In short, here is how the script works:
- Define the 12 chromatic pitches using Lilypond’s pitch names
- Put the pitches in a random order using the
shuf command
- Assign rhythmic values to certain pitches (this part is not random)
- Assemble a Lilypond source file using the random pitches
- Compile the Lilypond source file to generate MIDI output
- Play the MIDI file using timidity
After I achieved basic functionality, I decided to up the ante a bit and create three chords based on tetrachords from the row. This was a bit tricky, but I got some help from the famous sed one-liners page.
Next I thought wouldn’t it be cool to use this script to generate a “12-tone row of the day” and post an image of it in a static HTML page. I had recently done something like this with my “is it Friday yet?” bash script, which uses a random Cowsay image to tell you whether it is Friday yet or not. It was pretty easy to add another function to the bash script to assemble a static HTML page, and I modified the Lilypond command so that it generated a “preview” image of the tone row instead of a full-page PDF. I put the script on one of my web servers and set a Cron job to run at 1 AM each day to generate and post a new row. You can see the modified “web” version of the script on the 12-Tone Tune of the Day webpage, and of course see an example of the notation output and its corresponding MIDI file. Here is the script that generates and plays the MIDI file for use as an alarm.
#!/bin/bash -
#===========================================================================
#
# FILE: serial.sh
#
# USAGE: ./serial.sh
#
# DESCRIPTION: generates tonerow randomly, compiles on Lilypond
# and plays resulting MIDI file. Suitable for gentle
# alarm in morning on my raspberry pi radio
# OPTIONS: ---
# REQUIREMENTS: lilypond, timidity, shuf
# BUGS: ---
# NOTES: ---
# AUTHOR: Jonathan Kulp (),
# CREATED: 03/20/2013 07:35:41 AM CDT
#===========================================================================
pitches=/tmp/pitches.ily
random=/tmp/random.ily
lilyfile=/tmp/tonerow.ly
midifile=/tmp/tonerow.midi
stem=$(readlink -f $lilyfile | sed -e 's/\..*$//')
withrhythms=/tmp/withrhythms.ily
chordOne=/tmp/chord1.ily
chordTwo=/tmp/chord2.ily
chordThree=/tmp/chord3.ily
prime=/tmp/prime.txt
getpitches (){
# first make a list of all 12 chromatic pitches
# using lilypond's naming conventions
# one per line b/c it's easier to shuffle, add rhythms, etc
cat > $pitches << EOFallpitches
c'
cis'
d'
dis'
e'
f'
fis'
g'
gis'
a'
bes'
b'
EOFallpitches
# now run them through the shuf command to put them in random order
shuf $pitches > $random
} # ------------ end of getpitches ---------------
add_rhythms(){
# todo: randomize the rhythms
sed -f - $random > $withrhythms << EOFrhythms
1s/$/4/
3s/$/4../
4s/$/16/
5s/$/4/
6s/$/4./
7s/$/8/
8s/$/4/
9s/$/8/
10s/$/8/
11s/$/8/
12s/$/8/
EOFrhythms
} # ------------ end of add_rhythms ---------------
chords(){
# stack up the notes of the row in 3 chords of
# 4 notes each
cat $random | sed -n '1,4p' \
| sed -e :a -e '$!N;s/\n/ /;ta' -e 'P;D' \
| sed -e 's/^/' | sed -e 's/$/>2/' > $chordOne
cat $random | sed -n '5,8p' \
| sed -e :a -e '$!N;s/\n/ /;ta' -e 'P;D' \
| sed -e 's/^/' | sed -e 's/$/>4/' > $chordTwo
cat $random | sed -n '9,12p' \
| sed -e :a -e '$!N;s/\n/ /;ta' -e 'P;D' \
| sed -e 's/^/' | sed -e 's/$/>2./' > $chordThree
} # ------------ end of chords ---------------
make_lily_file (){
# determine lilypond version for later inclusion
version=$(lilypond --version | grep LilyPond | cut -d " " -f3)
# make it cat the random list of pitches
lilypitches=$(cat $withrhythms $chordOne $chordTwo $chordThree)
# assemble the lilypond source file, sticking the
# pitches in at the right place
cat > $lilyfile << EOFscore
\\score {
{
\\version "$version"
\\time 3/4
#(set-accidental-style 'dodecaphonic)
#(set-global-staff-size 24)
\\set Staff.midiInstrument = "violin"
\\partial 4
$lilypitches
\\bar "|."
}
\\layout {} \\midi {\\tempo 4 = 120}
}
EOFscore
#cat $lilyfile
} # ------------ end of chords ---------------
runlily(){
# compile the score redirecting all console output to /dev/null
lilycmd="lilypond -dno-point-and-click -ddelete-intermediate-files -dpreview"
$lilycmd $lilyfile &> /dev/null
} # ------------ end of runlily ---------------
html(){
web="$stem".html
image="$stem".preview.png
midi="$stem".midi
cat > $web << EOFhtml
<meta http-equiv=Content-Type content="text/html; charset=UTF-8">
<title>12-Tone Tune of the Day</title>
<h2>Random 12-Tone Tune of the Day</h2>
<p>
<img src="tonerow.preview.png" alt="randomly generated 12-tone
row"
title="randomly-generated 12-tone row">
</p>
<a href="tonerow.midi">Midi file</a>
<p>
Generated with bash fu and <a href="http://lilypond.org"
target="_blank">Lilypond</a>
</p>
EOFhtml
} # ------------ end of html ---------------
# RUN ALL FUNCTIONS HERE
cd /tmp
getpitches
chords
add_rhythms
make_lily_file
runlily
# sleep for half a second to make sure Lilypond has time to compile
sleep .5
html
xdg-open $web
timidity $midifile &> /dev/null
#clean stuff up
rm /tmp/*.ily /tmp/*.eps