Saturday, August 24, 2013

Algorithmic composition: generating tonal canons with Python and music21

1x spiced up chord progression (intermediate step in canon generation)

 

  What?

According to wikipedia:
Algorithmic composition is the technique of using algorithms to create music.

Some algorithms that have no immediate musical relevance are used by composers as creative inspiration for their music. Algorithms such as fractals, L-systems, statistical models, and even arbitrary data (e.g. census figures, GIS coordinates, or magnetic field measurements) have been used as source materials.
And:
In music, a canon is a contrapuntal compositional technique that employs a melody with one or more imitations of the melody played after a given duration (e.g., quarter rest, one measure, etc.).

How?

Last year I wrote a series of articles on an easy method for writing some types of canons:
In at least one of those articles I claimed that the methods described there should be easy to use as basis for automation. Here I automate the method for writing a simple canon as explained in the first of these articles.

Code?

The code discussed below is available under GPLv3 license on github: https://github.com/shimpe/canon-generator. Similar to the gcc compiler, the music you generate with this program is yours. The GPLv3 license only applies to the code itself.

It depends on free software only: python 2.7, music21 and MuseScore.

Explanation? 

This program generates canons from a given chord progression in a fixed key (no modulations for now, sorry!).

It does NOT generate atonal or experimental music, that is, if you're willing to accept the limitations of the program. It can occasionally generate "grave" errors against common practice rules (e.g. parallel fifths/octaves) -> see further explanation.

It closely follows the method as explained in the  Tutorial on my technique for writing a Canon article referenced above. If you want to understand in detail how it all works, please read that article first, and then come back here. If you just want to experiment with the different program settings, continue :)


One thing is worth explaining in more detail: the article mentions in one of the first steps of the recipe that the composer can start from a chord progression, and "spice it up" to get a choral.  So: how to we get a computer to spice up a chord progression, without building in thousands of composition rules?

I introduced some note transformations that:
  • introduce small steps between notes so as to generate something that could be interpreted as a melody
  • do not fundamentally alter the harmonic function in the musical context
To accomplish this I replace with a sequence of notes without altering the total duration of the fragment, e.g.
  • original note (half note) -> original note (quarter note), neighbouring note (8th note), original note (8th note)
Other transformations  look at the current note and the next note, and interpolate a note in between (again, without changing total duration)
  • original note (half note), next note -> original note (quarter note), note between original note and next note (quarter note), next note
A property of generating melodies by spicing up lists of notes using this method is that after spicing up a list of notes, you can spice the spiced up list again to get an even spicier list (more complex melody, both in pitch and in rhythm).

Finally a warning for the sensitive ears: for a composer to write a choral that obeys all the rules of the "common practice" takes years of study and lots of practice. Given the extreme simplicity of the program, the computer doesn't have any of this knowledge and it will happily generate errors against the common practice rules (e.g. parallel fifths and octaves). Not always, but sometimes, as dicated by randomness. Note that this is an area in which the program could be improved, by checking for errors while spicing up and skipping proposed spicings that introduce errors against the common practice rules.

Yet, despite the extreme simplicity of the method, the results can be surprisingly complex and in some cases sound interesting.

How can I use it?

In its current form, the program is not really easy to install and use, at least if you have no computer experience:
  • You need to install the free python programming language from http://www.python.org/download/releases. I recommend using version 2.7. Version 3 and later of python won't work! 
  • You also need to install the free music21toolkit for computer-aided musicology. Follow the instructions on their website. Music21 provides for vast amounts of music knowledge which would take a long time to write ourselves. I'm using only a fraction of its possibilities in the canon generator.
  • Then you need something to visualize and audition the MusicXml that is generated by the program. For our purposes, the free MuseScore program works perfectly.
  • Finally you need to get the free canon-gen.py program from the github repository https://github.com/shimpe/canon-generator.
The main function defined near the bottom of the canon-gen.py file contains some parameters you can edit to experiment with the generator:
  • chords = "C F Am Dm G C"
    #You can insert a new chord progression here. 
  • scale = music21.scale.MajorScale("C")
    #You can define a new scale in which the notes of the chords should be interpreted here 
  • voices = 5
    #Define the number of voices in your canon here 
  • quarterLength = 2
    #Define the length of the notes used to realize the chord progression
    #(don't choose them too short, since the automatic spicing-up will make them shorter) 
  • spice_depth = 1
    # Define how many times a stream (recursively) should be spiced up
    # e.g. setting 2 will first spice up the chords, then again spice up the already spiced chords.
    # scores very quickly become rhytmically very complex for settings > 2
  • stacking = 1
    # the code can generate multiple versions of the spiced up chord progression, and use those
    # versions to create extra voices
    # e.g. setting stacking = 2 will turn a 3-voice canon into a 3*2 = 6-voice canon 
  • voice_transpositions = { VOICE1 : +12, VOICE2 : 0, VOICE3 : -12, VOICE4: -24, VOICE5: 0 }
    # allow extra octave jumps between voices

What does it sound like?

This is a simple example generated with the program with settings
  • chords = "C F Am Dm G C"
  • scale = music21.scale.MajorScale("C")
  • voices = 5
  • quarterLength = 2 
  • spice_depth = 1
  • stacking = 1 
  • voice_transpositions = { VOICE1 : 0, VOICE2 : 0, VOICE3 : -12, VOICE4: -24, VOICE5: 0 }  

Ideas for future improvements

I see many possible improvements, most of which are low-hanging fruits. Feel free to jump in and improve the code :D
  • fix a known bug related to octaviations in keys other than C
  • support modulations, i.e. keep musical key per measure/beat instead of over the complete chord progression
  • extend the code to cover the things explained in the later articles: crab and table canons
  • see if the method/code can be extended to generate canons at the third, fifth, ...
  • smarter spicing up of chord progressions to avoid parallel fifths/octaves (e.g. rejecting a proposed spice if it introduces an error in the overall stream); or use Dmitry Tymoczko's voice leading spaces to ensure better voice leading by construction.
  • protect the end chord from getting spiced up
  • implement more note transformations, e.g. appogiatura
  • experiment with more rhythms
  • how can we better spice up the chord progressions without messing up too much of the original harmonies?
  • ... 

No comments:

Post a Comment