Bridging Science and Art with Ruby
29 Dec 2012Introduction
Having a love for music and technology at the same time can be a dangerous business. You can really fool yourself into thinking that you can boil art down into algebraic or procedural recipes that you can just turn the handle on. The frustration sets in when it’s just not that black-and-white. In this post, I’ve put some Ruby code together that takes in an array of musical intervals and attempts to give that array of intervals a name.
In music, this is better known as a chord or arpeggio.
Assumptions
As above, I want an array of intervals in so this is going to take shape in the form of an integer array. These integers will be the individual distances (in semi-tones) from the root which will start at 0. For reference, here’s a chart that I used during development.
First Octave | Second Octave | Interval Names |
---|---|---|
0 | 12 | Root/Unison |
1 | 13 | Minor Second/Flat Nine |
2 | 14 | Major Second/Nine |
3 | 15 | Minor Third |
4 | 16 | Major Third |
5 | 17 | Perfect Fourth/Eleventh |
6 | 18 | Tritone/Sharp Eleven |
7 | 19 | Perfect Fifth |
8 | 20 | Minor Sixth/Flat Thirteen |
9 | 21 | Major Sixth/Thirteenth |
10 | 22 | Minor Seventh |
11 | 23 | Major Seventh |
</div><div>
Intervals that are emphasised, didn’t really factor into the overall solution as they add nothing to the chord’s quality or extension. Well, this may not be entirely true, some jazz-heads have probably already got their cross-hairs locked onto me, ready to flame away.
Gathering facts
First of all, we need the array of intervals into our class. We’ll always assume that there is a root and if there isn’t one, we’ll pop one into the array for good measure.
We’re now managing an array of intervals. What we need to do is ask questions of that array so we can gather information about our chord. The following methods ask the important questions in the first octave.
With just this base information we can find a lot out about the chord, but it’s not nearly enough. We need to be sure. The best part about putting these basic building blocks in place is that our methods are going to read a little more human from now on. Here are some more fact finders.
Finally we have a couple more tests that we need to conduct on the array in the upper octave, otherwise none of the jazz-guys are going to get their chords! These again will form syntactic sugar for the main feature, to_s
.
Piecing it together
It’s good that we know so much about our chord. It means that we can ask questions and make decisions based on the outcomes of these questions. Upon reflection, I did have another idea on assembling those fact-finding methods into a more flexible but highly-unhuman set of methods that when you asked about a particular interval, you’d get back either :flat
, :natural
or :sharp
. Perhaps I’ll try it in another revision; I digress. All the facts are in front of us, let’s construct a string from these facts. Now here’s where the awkward bridge between science and art starts to burn a little, then a lot. Questions must not only be asked of the array, but they have to be asked in the right order otherwise you’ll get a different result.</div><div>
</div><div>That’s naming for you though. It doesn’t read pretty, but here it is.
Woosh. That was a lot of if-treeing. There has to be a better way of doing this, but by my calculations using this code I’ve covered the following use-cases off:
- Major
- Minor
- Diminished
- Diminished Seventh
- Augmented
- Seventh
- Minor Seventh
- Major Seventh
- Suspended Second
- Suspended Fourth
- Seventh Flat 5
- Seventh Sharp 5
- Major Seventh Flat 5
- Major Seventh Sharp 5
- Minor Seventh Flat 5
- Minor Seventh Sharp 5
- Ninth
- Eleventh
- Thirteenth
There’s a few chords there, but there are just so many more and this code may work for them. Those other cases just haven’t made it into my unit tests yet.
Plans
I really want to make this part of a bigger application that I’m writing at the moment. I was motivated to write a unit like this because I didn’t want chord definitions just sitting in a database, I wanted the application to do the think work. Possibilities from here also reach into inversions and slash chords. It would be easy to permute the list of intervals and enumerate all of the inversion scenarios.
Anyway, until next time!