Generating Melody to Fit Harmony

Written by on May 10, 2016 in LISP, Music, Programming with 0 Comments

There are two common approaches to composing music. One involves synthesizing a suitable chord progression first and then layering melody over it. The other is to start with melody and then harmonize it by applying chords. Of course, you can mix both approaches – use one technique for a portion of the song and then another for other portions. Remember, this is art, and hence nothing is cast in stone.

I have two objectives in this post:

1) Describe a simple technique for deriving melody based on the chord progression. We will use both Chord Tones and Non Cord Tones (but in the same scale – diatonic).

2) Play the generated music through Ableton Live using its rich instrument collection.

In many cases, we might want the melody to be at a higher octave than the chord progression, so this octave shift is passed as an argument to our algorithm. We also assume that the chords are in a specific scale, and hence diatonic.

Here are the steps:

1) Given a chord progression, for each bar: find the pitches of the chord, remove duplicates and sort the pitches in ascending order.

2) Since the melody must be from the same scale (but shifted by some octave), expand the scale to determine its pitches and derive a sequence of pitches {-1, 0, +1} octaves apart.

3) Taking the pitches obtained in (1), determine a sub-sequence from (2) that covers both chord and non-chord tones.

4) Take as many consecutive elements as possible from (3) based on the melodic rhythm for that bar.

5) Apply a pitch-shaper function randomly on the sequence obtained in (4)

Let us take a simple example and work through the steps. Suppose the first bar has the chord c3e3g3 (i.e., Tonic in c3 major scale). We will assume that we need the melody in 4th octave, not 3rd, but in the same scale.

1) We get (c4 e4 g4) from the first chord

2) The allowed pitches for this scale after extended transpositions will be:

(c3 d3 e3…c4 d4 e4 f4 g4 a4 b4 c5 d5 e5 …)

3) We get (c4 d4 e4 f4 g4) as the largest sub-sequence in (2)

4) If our melodic rhythm for this bar is ‘(q -e e q q), we need 4 pitches, so we select a random subset of (3), say, (d4 e4 f4 g4)

5) Applying a random pitch shaper function, we might get the sequence (d4 e4 g4 f4) as the final melody for this bar

We repeat the above steps for all the bars.

As you can see, the core logic is straightforward. The code I have uploaded has many functions (distributed over 3 source files), including some utility functions from my own library, so that you will be able to test the entire implementation without other dependencies.

Melody Over Harmony

Melody Over Harmony

Let us now come to the second part of this post: How to connect Opusmodus to Ableton Live? By the way, the only reason I wanted to connect to Live was the rich set of instruments available in Live compared to the GM. In an earlier article, I showed how to connect OM to Reaktor, so connecting to Live itself is simple.

I have included the screenshot of Live instrument setup, so that you can see what instruments I have used in different tracks. Make sure you configure the input Bus correctly for each of the tracks.

Ableton Live 9 Setup

Ableton Live 9 Setup

I also recorded the playing (by arming the tracks) and exported the song as a WAV file. You can download it and listen to the generated song. One advantage of using an external environment such as Ableton Live is that when you playback, you can add other effects to soup up the song. In my case, that was not the intention, so I let go at the basic step.

Here is the source code (zipped).

If you want to use the GM set in stead of Live, remove the ports from the def-score and include the conventional parameters instead.

I would love to hear about your own techniques, if you have tried any, for layering melody on top of harmony.

Tags: , ,


If you enjoyed this article, subscribe now to receive more just like it.

Subscribe via RSS Feed

Leave a Reply

Your email address will not be published. Required fields are marked *