One of the great things about the Clojure libraries is, that they are highly orthogonal. It’s easy to build systems for experimenting by using different, great libraries.
In this post I am going to demonstrate how I used Overtone, Quil and core.logic to explore tonal melodies. I have no formal musical education - I used to play the keyboard, but that was back when 2 Unlimited’s No Limits was considered cool. I started in the evening and posted this blog post the next day, even sparing time for a trip to IKEA. I’m very impressed by how fast it was to build.
Before I start, I would just like to state that I am in no way a musician or composer, and I have little grasp of the musical concepts. Any errors in use of terminology is fully my fault, and I am very sorry if they confuse more than explain.
If you want to play along, the full code can be found here at github.
Writing about something musical can be a bit difficult without some example. In this video, I demonstrate what I came up with. I will go through selections of the code below.
I must confess I’ve never played with Overtone before. I like to blame the fact that I don’t feel very musical, even though Sam Aaron repeatedly state that that is not the point. Reading through the tutorial, I found the definition of a triangle-wave, and instructions for how to play notes.
I figured out how to set up a metronome, and created an atom for holding my melody. The atom is our “sketch board”, which makes it extremely easy to play around. To test a new melody, simply reset the atom.
That’s all the pieces we need from Overtone.
My girlfriend helped me out with the musical theory (which I knew nothing about before starting), but she thought reading keyword sequences like [:D#4 :G#4 :D5 :F4 :B4 :F#4 :A#4 :D#4])
was difficult. I created a stave in Quil that uses the melody atom. I’m not going in to details as to how it works - I’ve been told that the stave is drawn an octave above what is actually playing. Also, everything is shown as sharps with a #
. Doing flats with require some more insight into sheet music.
I’m not going into details with the drawing routines themselves. They are pretty basic.
Now, to examine what makes a tonal melody, we are first going to define the concept of semitones. A semitone is two notes adjacent on a piano, which can be defined in core.logic like this.
Tones are defined as two semitone, so :C3
and :D3
are a tone. We ca create a core.logic function for that. We also need tones and a half.
The next concept is scales. Scales are adjacent notes that have a pattern of semitone, tone and tone-and-a-half between them (I once again apologise for my poor grasp of music). Here are some frequently used scales in our model.
To check if a sequence of notes are a scale, we define a function for checking this. We only operate with scales of length eight in this demonstration. The function takes a scale and defines a core.logic function that takes a sequence of notes and dictate they conform to the scale.
We can now generate scale using core.logic and play them in Overtone
Now, a tonal melody can be generated by using our scales and some other rules. In the example below, I dictate that a melody must
The example asks core.logic to generate 512 melodies that conform to these demands and plays a random one of those. If you run the code several times, you can probably find a melody you find pleasing. They are printed to standard out by Overtone every time they are played, so you can save them for later. And please play around with the different scales, cadences etc.. It’s great fun!
I didn’t know any of these rules before playing around with them, but they make for very pleasing melodies!
I think Clojure really showed what a powerful platform it is. In under 200 lines of code, I was able to implement a program that composes and plays music using logic programming.
The main thing that annoys me about my experiments is, that I need a scaleo
generator function. It would be mush nicer to define scaleo
as taking a melody and a scale. That would also allow me to feed a melody into core.logic, and having it telling me which scale the melody was using. I was not able to do so, as my attempts to define scaleo
ended up in something that I couldn’t figure out why didn’t work.
Feedback in the comments and pull requests on the project are more than welcome!
Mathfarmer has suggested an alternative, binary representation of scales. The representation makes it possible to derive the scale and base-note used for a melody, as long as it follows our rules. I’ve implemented it in a different namespace, so it is now possible to perform the following query
See this file for a complete example.
Also, Jack Rusher has a different approach for generating music in Clojure, using Markov models. You can find more information here on github.