Boots-n-Cats: Every Techno Song Ever In Clojure

February 10, 2012

I’ve wanted to do a post about programming music for quite a while, but honestly there aren’t very many opportunities for an online financial advisor to do very much research into the breadth of music libraries (even for a sophisticated, yet simple one, like us). Regardless, I chose to disregard these realities when I discovered a neat little library called Overtone. Here’s the technical summary for the project:

Overtone is a musical programming library written in Clojure which uses the SuperCollider audio engine and synthesis server under the covers. We’re essentially marrying an awesome live-synthesis server with an insanely cool state-of-the-art lisp to create a glorious union that only the Gods can dream about.

Seriously, that’s the kind of bravado that’s going to propel us to rock stardom in no time (leather pants optional). But what shall we create? Well, it also happens that a friend of mine sent me this video, and I instantly thought, I can do that!

Now, let’s see how.

It’s really easy actually if you’re on a mac, but first, you’ll probably want to install Leiningen, the Clojure project tool. Follow the instructions on their page to get it set up. Then you can type:

$ lein new boots-and-cats
$ cd boots-and-cats

Then edit the project.clj file to contain:

(defproject boots-and-cats "1.0"
  :dependencies [[org.clojure/clojure "1.3.0"]
                 [overtone "0.6.0"]])

At this point, I’ll let you know that you should also just clone my repo at GitHub. It already contains the samples, but you can also just go there and download them directly.

git clone git://github.com/hitch17/boots-n-cats.git

Then you can use lein to grab all the dependencies and be you on your way. If you’re on linux, you’ll also want to follow these instructions for getting your audio set up.

$ lein deps # Note: this downloads the entire internet.

Now let’s get this thing started. You’ll also want to turn your speakers to be sufficiently loud. I can guarantee that all the co-workers/family/roommates in your vicinity don’t want to miss out on hearing the birth of a legend.

$ lein repl
REPL started; server listening on localhost port 48182
user=> (use 'overtone.live)
[... prints a bunch of stuff talking about your audio system ...]
          _____                 __
         / __  /_  _____  _____/ /_____  ____  ___
        / / / / | / / _ / ___/ __/ __ / __ / _ 
       / /_/ /| |/ /  __/ /  / /_/ /_/ / / / /  __/
       ____/ |___/___/_/   __/____/_/ /_/___/


                          Programmable Music. v0.6
[...]

You should get some sweet Ascii Art and then the fun begins. Load some samples and play them:

user=> (def boot (sample "boot.wav"))
#'user/boot
user=> (boot)
28
user=> (def cat (sample "cat.wav"))
#'user/cat
user=> (cat)
28

Let’s add a little reverb to the samples in one ear and get a little bit of a panning effect.

user=> (def boot-sample (load-sample "boot.wav"))
#'user/boot-sample
user=> (defsynth reverb-boot []
  (let [dry (play-buf 1 boot-sample)
        wet (free-verb dry 0.6)]
      (out 0 [wet dry])))
#<synth: reverb-boot>
user=> (reverb-boot)
28
user=> (def cat-sample (load-sample "cat.wav"))
#'user/cat-sample
user=> (defsynth reverb-cat []
  (let [dry (play-buf 1 cat-sample)
        wet (free-verb dry 0.6)]
    (out 0 [dry wet])))
#<synth: reverb-cat>
user=> (reverb-cat)

Pretty cool and shockingly easy. Let’s load our other samples.

user=> (def bees (sample "bees.wav"))
#'user/bees
user=> (def kneehigh (sample "kneehigh.wav"))
#'user/kneehigh

Let’s also set up a beat with our boots and cats samples using the metronome function which helps the library keep everything in time and create a player for our beat.

user=> (def metro (metronome 60))
#'user/metro
user=> (defn player [beat]
  (at (metro beat) (reverb-boot))
  (at (metro (+ 0.5 beat)) (reverb-cat))
  (apply-at (metro (inc beat)) #'player (inc beat) []))
#'user/player
user=> (player (metro))

And when you’re done, call (stop):

user=> (stop)

You can also record your masterpiece and when you’re finished call (recording-stop).

user=> (recording-start "awesome.wav")
:recording-started
[... play something awesome ...]
user=> (recording-stop)

With a little practice and decent timing (copy-and-paste skills help), you should be able to create a pretty decent techno song like this one: Bootz-and-Catz. Well, okay, maybe making something really awesome takes a little more work, but hopefully by now you have a good idea of where to get started.

Now go forth and unleash your inner Techno-Viking!