Twister bash script

So I don’t have to spin that dial over and over when kids play Twister. Randomly chooses color, limb, and right or left, pipes results to espeak. :)


#!/bin/bash - 
#===========================================================================
#          FILE: twister.sh
#         USAGE: ./twister.sh 
#   DESCRIPTION: spin the dial for twister
#  REQUIREMENTS: espeak 
#        AUTHOR: Jonathan Kulp ()
#       CREATED: 04/21/2013 01:37:00 PM CDT
#      REVISION:  ---
#===========================================================================

colorfile=/tmp/color.txt
limb=/tmp/limb.txt
direction=/tmp/rl.txt

shuf -n1 > $colorfile <<EOFcolors
  red
  green
  yellow
  blue
EOFcolors

shuf -n1 > $limb <<EOFlimbs
  hand
  foot
EOFlimbs

shuf -n1 > $direction <<EOFrl
  left
  right
EOFrl

command=$(echo "$(cat $direction) $(cat $limb) on $(cat $colorfile)")

echo $command | espeak #festival --tts

rm $colorfile $limb $direction

Posted in Uncategorized | Comments Off

Random 12-Tone Alarm

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.
Randomly generated 12-tone-Row
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:

  1. Define the 12 chromatic pitches using Lilypond’s pitch names
  2. Put the pitches in a random order using the shuf command
  3. Assign rhythmic values to certain pitches (this part is not random)
  4. Assemble a Lilypond source file using the random pitches
  5. Compile the Lilypond source file to generate MIDI output
  6. 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/^/2/' > $chordOne
  cat $random | sed -n '5,8p' \
  | sed -e :a -e '$!N;s/\n/ /;ta' -e 'P;D' \
  | 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/^/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


Posted in Tech | Tagged | Comments Off

Record Terrestrial Radio with bash script and cron job

This script makes use of the streamripper package to record an audio stream from a terrestrial radio station’s website. I wrote it to record the morning news on our local public radio station between 4 and 5 a.m. every day since I’m not up at that hour and there’s no podcast available. I got the streaming url from their website by clicking the “listen live” button. A side benefit of having it recorded is that I can listen at 1.5x speed like I do all of my podcasts–60 minutes of audio in 40 minutes! Strange at first but it’s hard to go back to normal speed once you get used to speedy podcast listening. I record the shows on a server that’s always on and then transfer the mp3 files to my laptop with an rsync script. I also record a couple of weekly radio shows on other stations using different scripts and crontab entries. Once you know the correct URL of the audio stream it’s easy to set up as many of these as you want.


#!/bin/bash - 

# get & format date for renaming file
today=$(date +%Y_%m_%d)

# tell it where to put file
streamdir=/home/$(whoami)/streamdir

# 88.7 FM KRVS (Lafayette, LA) streaming url
url=http://pubint.ic.llnwd.net/stream/pubint_krvs1

cd $streamdir

# find any old files by inverse grep of today's date
old=$(find . |grep -v $today)

# delete the old one(s)
rm $old > /dev/null 2>&1

# run the command. Records in one big file for 60 minutes (3600 
# seconds) with no console output and sticks the output in 
# specified directory

$(which streamripper) $url -a -A -l 3600 -s --quiet -d $streamdir/ 

# delete the .cue file, not sure what it's for anyway
rm $streamdir/*.cue > /dev/null 2>&1

# find files with default name still in 'em, rename w/show name 
file=$(ls |grep sr_program)
newname=$(echo "$file" |grep sr_program |sed -e 's/sr_program/morning_edition/')
mv $file $newname

I make it run at 4am Monday-Friday by setting a cron job:


0 4 * * 1-5 /path/to/script.sh

Posted in Uncategorized | Comments Off

Bash script to sync podcasts on iPod

After grabbing new podcasts with mashpodder, I use this little script to sync up my laptop’s podcast directory with my Rockbox-powered iPod 4th gen. The laptop podcast directory is authoritative. I delete files there after listening. The script then gets rid of the same files from the iPod.


#!/bin/bash

# see if my iPod is attached
ispod=$(df | grep IPOD &> /dev/null ; echo $?)

if [ "$ispod" == 0 ] ; then
    PODNAME=$(df | grep IPOD | awk '{ print $6 }')
  else
    echo "No media player is mounted." ; exit 0
fi 

echo "syncing with "$PODNAME""

# sync it up, deleting files on dest if not present on source
rsync -rtvL --delete --ignore-errors --size-only ~/Podcasts "$PODNAME"/ 

Posted in Tech | Tagged | Comments Off

Concatenate all html files from Moodle “online text” assignment into one big file

With more than 90 online text essays to grade for my music 300
online class, I got tired of clicking and maximizing and closing and
clicking etc. I chose the option to download all essays in a zip file,
and found that there were 91 *separate* HTML files. This was not much
better so I wrote a script to join them all into a single big page that
I can read all at once. It also does a word count and puts student’s names
at beginning and end of each with a horizontal rule between. Much easier.

Workflow: download the zip file, run the script on it, big page with all
essays opens shortly in new browser tab.


#!/bin/bash - 
#===========================================================================
#
#          FILE: join_essays.sh
# 
#         USAGE: ./join_essays.sh archive_of_moodle_essays.zip
# 
#   DESCRIPTION: 
# 
#       OPTIONS: ---
#  REQUIREMENTS: ---
#          BUGS: ---
#         NOTES: ---
#        AUTHOR: Jonathan Kulp (), 
#  ORGANIZATION: 
#       CREATED: 02/26/2013 08:55:53 PM CST
#      REVISION:  ---
#===========================================================================

zipfile=$(readlink -f "$1")
outdir=$(echo "$zipfile" | sed -e 's/\.zip//')
mkdir $outdir
cd $outdir

unzip $zipfile

files=`find . -type f -iname "*"|sed 's/ /+/g' | sort`

# replace spaces in filenames w/underscores
for spacyfile in $files
do
    oldname=`echo $spacyfile |sed 's/+/ /g'`
    newname=`echo $oldname|sed 's/ /_/g'`
    mv -v "$oldname" "$newname"
done

# put some header stuff
bigfile=$(pwd)/allinonefile.html
echo '<meta http-equiv=Content-Type content="text/html; charset=UTF-8">' > $bigfile
echo '<style TYPE="text/css"> body { max-width:40em; } </style>' >> $bigfile

# run it concatenating all in one file, separating w/ horizontal
# rules, showing filenames & word counts
essays=$(find . -type f -iname "*.html" | grep -v allinone)
for i in $essays

do 
    file=$(basename $i)
    filename=$(echo "$file")
    echo "BEGIN $filename" >> $bigfile
    cat $i >> $bigfile
    echo "END $filename" >> $bigfile
    echo "                     <br>" >> $bigfile
    # do a word count
    wordcount=$(cat $i | wc -w)
    echo "$wordcount words" >> $bigfile
    echo "<hr>" >> $bigfile
done

xdg-open $bigfile

Posted in Uncategorized | Comments Off

MYIP: script to display IP address on Linux

This is a little script I wrote to get rid of all the non-ip-address stuff from the output of the ip addr command on Linux. It tells you the current IP and which network interface is using it.


#!/bin/bash


wifiip=$(ip addr \
| grep inet | grep wlan0 \
| awk -F" " '{print $2}' \
| sed -e 's/\/.*$//')

checketh0=$(ip addr |grep eth0 |grep DOWN &> /dev/null ; echo $?)

if [ "$checketh0" == "0" ] ; then
    eth0ip="not connected"
  else
    eth0ip=$(ip addr \
    | grep inet | grep eth0 \
    | awk -F" " '{print $2}' \
    | sed -e 's/\/.*$//')
fi

checketh1=$(ip addr |grep eth1 |grep DOWN &> /dev/null ; echo $?)

if [ "$checketh1" == "0" ] ; then
    eth1ip="not connected"
  else
    eth1ip=$(ip addr \
    | grep inet | grep eth1 \
    | awk -F" " '{print $2}' \
    | sed -e 's/\/.*$//')
fi

# report findings, only returning devices with IPs
echo "wlan0: $wifiip" | grep [0-9]$
echo "eth0: $eth0ip" | grep [0-9]$
echo "eth1: $eth1ip" | grep [0-9]$

And here’s a sample of the output:


jon@hostname:~$ myip
wlan0: 192.168.1.199
jon@hostname:~$ 

Posted in Tech | Tagged , , , | Comments Off

Dark Angels now on Amazon and iTunes

The Lester/Carr Duo’s new album Dark Angels, which includes selections from my Five Poems of Emily Dickinson, is now available via mp3 download in the iTunes music store and on Amazon: http://amzn.com/B00B6A424S

Posted in Uncategorized | Comments Off

Dark Angels

I got my copy of the new recording Dark Angels by CN Lester and Toby Carr a couple of weeks ago, much sooner than I expected. It’s excellent.  They included three songs from my song cycle Five Poems of Emily Dickinson. CN’s voice is beautifully suited to the songs, and I love her flexible performance style, which shows excellent classical training but also experience in popular genres.  Toby Carr’s performance on the guitar is rock solid and always musical in some very demanding repertoire.  The whole thing is great.  If you are interested in purchasing a copy of the CD, visit CN’s website for information on how to do so.  I believe that for the moment at least there is no way to purchase the tracks as mp3 downloads. Thanks so much for recording my songs, guys!

Posted in Uncategorized | Comments Off

Lester / Carr to Record Dickinson Songs

I got an email today from guitarist Toby Carr telling me that he and mezzo-soprano CN Lester are planning to record three songs from my song cycle Five Poems of Emily Dickinson. Also on the recording will be music by Benjamin Britten and Peter Maxwell Davies, plus a newly-commissioned work by Philip Lawton. Good luck with the recording, guys, I can’t wait to hear it!

Posted in Uncategorized | Comments Off

Markdown to LaTeX conversion Script

Nowadays I do almost all of the documents for the courses I teach in Markdown format, but sometimes I would like to have printer-friendly versions of these documents. I have failed miserably at trying to create a printer-friendly style sheet that works with our Moodle theme, so I decided to try to use my markdown source files to generate pdf files.

Fletcher Penny’s excellent Multimarkdown package has an option for output in LaTeX format, but I have found that its output is not ready to be compiled. It lacks a preamble and a few other LaTeX indicators that tell the program where stuff is and what to do with it. Rather than have to add these lines in by hand every time, I have written a script that will take my Markdown files and convert them to LaTeX, adding in all of the necessary LaTeX commands and compiling to pdf. It also runs some substitution commands to handle special UTF8 characters, since LaTeX has different formatting for these. At the moment, I want all of my files to be in the same document class, but it would not be too hard to add command-line options for the script that would allow for alternate document classes.

I hope someone else finds the script useful too. To see with proper indentation and syntax highlighting click here.

#!/bin/bash - 
#=============================================================================
#
#          FILE: mkd2latex.sh 
# 
#         USAGE: ./mkd2latex somefile.mkd <fontsize>
# 
#   DESCRIPTION: Converts markdown files to LaTeX and performs
#   various cleanup tasks for foreign characters, etc.
# 
#       OPTIONS: ---
#  REQUIREMENTS: multimarkdown, latex
#          BUGS: ---
#         NOTES: ---
#        AUTHOR: Jonathan Kulp (),
#  ORGANIZATION: 
#       CREATED: 10/14/2012 06:52:09 AM CDT
#      REVISION:  ---
#=============================================================================

# get the environment sorted out first

infile=$(readlink -f $1)
stem=$(basename $infile | sed -e 's/\..*$//')
basedir=$(dirname "$infile")
outdir="$basedir/out"
nohtml="$outdir/$stem-nohtml.mkd"
tempfile="$outdir/$stem.tmp"
outfile="$basedir/$stem.tex"
createdon=$(date +%m\/%d\/%Y,\ %r)

#---------------------------------------------------------------------------
# make a place to put the garbage
#---------------------------------------------------------------------------

if [ -e "$outdir" ] ; then
    echo "Output directory already exists"
  else
    mkdir "$outdir"
fi

#---------------------------------------------------------------------------
#  check to see if fontsize is specified, if not default to 11
#---------------------------------------------------------------------------
if [ -z "$2" ] ; then
    size="11"
  else
    size="$2"
fi

#---------------------------------------------------------------------------
#  Default output of multimarkdown has no preamble, do that here.
#  Change options as desired.
#---------------------------------------------------------------------------

preamble(){
cat >> $tempfile << EOFpreamble
  \documentclass[$size pt,oneside,letterpaper]{article} 
  \usepackage{fullpage,amsmath,tabu,hyperref} 
  \begin{document}
  \thispagestyle{empty}
EOFpreamble
} # ----------  end of function preamble ----------

remove_tags (){
  sed -f - $infile > $nohtml << EOFnotags
  s/]*>/#/
  s/]*>/##/
  s/]*>/###/
  s/<\/h[1-3]>//
EOFnotags
} # ----------  end of function remove_tags  ----------

run_multimarkdown(){
  multimarkdown -t latex $nohtml >> $tempfile
} # ----------  end of function run_multimarkdown ----------

#---------------------------------------------------------------------------
#   Put the LaTeX \end{document} command, creation date, etc.
#---------------------------------------------------------------------------
postamble(){
cat >> $tempfile << EOFpostamble
  \hspace*{\fill} \\\\
  \begin{center} \begin{small}
  This printer-friendly document was generated with \LaTeX \  on $createdon.
  \end{small} \end{center}
  \end{document}
EOFpostamble
} # ----------  end of function postamble ----------

#---------------------------------------------------------------------------
#  Convert any international characters to LaTeX's format, also
#  change to unnumbered sections and parts, change chapters to sections.
#  Get rid of autorefs like "Back to top"
#  Note that to insert a single quote ' you have to surround the
#  sed command with double quotes instead of the usual single
#  quotes.
#---------------------------------------------------------------------------

fixes(){
  sed -f - $tempfile > $outfile << EOFsed
  /label/d
  /<\/style>/d
  s/chapter/section/
  s/part{/part\*{/
  s/tion{/tion\*{/
  s/ó/\\\'{o}/g
  s/ñ/\\\~{n}/g
  s/ò/\\\`{o}/g
  s/è/\\\`{e}/g
  s/à/\\\`{a}/g
  s/á/\\\'{a}/g
  s/í/\\\'{i}/g
  s/ú/\\\'{u}/g
  s/ö/\\\"{o}/g
  s/ä/\\\"{a}/g
  s/ü/\\\"{u}/g
  s/é/\\\'{e}/g
EOFsed
} # ----------  end of function fixes ----------


#---------------------------------------------------------------------------
#  Compile the cleaned-up LaTeX code & output as pdf
#---------------------------------------------------------------------------

compile (){
  pdflatex -halt-on-error -output-format pdf --output-directory $outdir $outfile
  cp $outdir/$stem.pdf $basedir/$stem.pdf
}	# ----------  end of function compile  ----------


#---------------------------------------------------------------------------
#  Open it up in a pdf viewer
#---------------------------------------------------------------------------
preview (){
  xdg-open $basedir/$stem.pdf &
}	# ----------  end of function preview  ----------

#cd $basedir
preamble
remove_tags
run_multimarkdown
postamble
fixes
compile
preview

rm -rf $outdir

exit 0
 
Posted in Tech | Tagged , , , , | Comments Off