Nikolai Rimsky-Korsakov’s interlude gets a 21st Century literal makeover.
The idea for this project was conceived when I was shown a working model of Benoît Mandelbrot’s ‘Lévy flight’ for the first time. Whilst watching the random walker move using ‘Cauchy flight’ (where the distribution of step sizes is a Cauchy distribution which is a probability distribution that has a probability density function) I immediately thought it would be perfect for utilising in generative audio-visual sketch, as not only would the behaviour of the flight (a higher probability of small steps intermittently interrupted by a less frequent big steps) transpose wonderfully to rhythm and/or pitch in music, but the name of the algorithm is perfect too, affording a charming reference.
Nikolai Rinksy-Korsakov’s ‘Flight of the bumblebee’ (an orchestral interlude from his opera ‘The Tale of Tsar Saltan’ composed in 1899-1900) is a well known, frequently referenced, and parodied piece of music. The original piece accompanies a scene in which the Tsar’s son is transformed into a bumblebee so he can fly away, and is compositionally characterised by frantic semiquavers that are played nearly entirely uninterrupted. After watching the Lévy flight there were already two parallels between the original interlude and the algorithm: the frequent short step sizes, and the representation of the flight of a bumblebee; Korsakov’s being metaphorical whilst the Lévy flight being a literal model of how (possibly) bumblebee fly in search of food.
I also decided early on in the project that I would represent the piece visually in real-time both as an animated score akin to the to the traditional western music score, and in the form of a two dimensional Lévy flight.
How It Works
To begin the user selects both a tonic and a scale from the row of boxes under the title of the screen (in either order). Once the key has been selected the sketch automatically creates the correct key signature (the right number of sharps and flats placed correctly on the stave) for the start of the score. As soon as both inputs are recognised a Cauchy distribution Lévy flight starts generating midi notes straightaway (the code for the levy algorithm was graciously given to me by my lecturer Tim Blackwell). These values are rounded and constrained to a set range (from a lower octave of a C to a higher octave of a C) to get a pitch value. They are then passed into a sorting loop that calculates the pitch (minus an offset that represents the current key with 0 being C, 11 being B) divided by 12 (total notes in an octave) and checked against a constant array class for the specific scale (these constants are provided in the Soundcipher library that must be additionally added in processing). If the sorting loop finds the pitch to be outside the scale, it will iterate, counting up, until it finds a pitch that fits the scale.
Once it has a note it checks the quality of that specific note (whether it should be a C# or Db relative to the user’s specified scale) and places it accordingly on the score. Whilst the pitch value from the Lévy flight is scaled the step length of flight is also being checked, and depending on its size, triggers a correspondingly sized rhythmic duration. The rhythm value is combined with the pitch value and is used to place the note on the score. By simply using the rhythm value as the horizontal position, adding the next rhythm value to the previous, it effectively creates a ‘playhead’ (like a tape in reverse) that moves in time with the music being generated. Additionally the pitch values are mapped relative to pixel increases/decreases and provide the vertical position placement.
When the playhead reaches within a predefined threshold of the edge of the page a row variable used for vertical position is increased and the playheadautomatically starts lower down the page on a new row. It continues in this fashion until in reaches a row count that would put it off the page, upon reaching this limit the score is stopped.
I chose to keep roughly the same tempo as the original, selecting 140 beats per minute as the original is in ‘Vivace’, which implies a tempo between 132- 160. Additionally, as the original piece is in 2/4 I decided I would keep this time signature and implemented a short line of code that would check if total current durations were over the corresponding number of beats. If the total was over, it draws a bar line. Although this method is not entirely correct (the total beat value rarely adds up to an even beat) the desired aesthetical quality is present. The same can also be said for the alignment of the stems. As per standard notation, if the note is equal to, or under the B on the stave the stem should point up. If it is over this note the stem should point down. However although this condition is defined in my code, the reason why it doesn’t always display the correct stem is quite complex. This is because rather than constraining the pitch value to an upper limit (say constraining a high G to a the highest note, a C in the case of my code for the score) by using the scale checker I was essentially able to construct a wrap around stave, like a Möbius strip. The resulting consequence is that some notes are identified as lower note, actually get placed above and vice versa.
Rather than drawing each individual score element (note, stem, tail, stave, sharps etc) I thought it would be much more prudent to utilise a font that was constructed from forms typical found on a score. Using the ‘Sonata’ font that I downloaded (it is external to both Mac and Windows machines) I created a new font in processing and used the text function to draw the individual score elements. This was advantageous as I would not have to spend so much time trying to draw the correct forms, however it did mean I would have to compromise control (for instance, attempting to tie the correct note tails together couldn’t be done without great difficulty).
Problems Encountered And Known Issues
The biggest problem encountered frequently when working with this project is due to the midi setup only working exclusive of a loop function, as it will constantly try to read back the file every frame. The solution to this is to use a call back function to trigger a redraw every time the score gets updated. The main downside of this particular setup is the play function of the score must be setup to play from the start; otherwise there is no draw/loop function at all!
The second known issue is the occasionally extra note animated on the score. Typically this happens after a semibreve or breve, when a demisemiquaver gets drawn even though the longer note is still sounding out. After trying lots of different possible solutions, such as stalling the drawing of the note either by an offset in time or by delaying the drawing by an incoming pitch, I was still unable to find a solution. Consequently I think this may be due to the shortness of the demisemiquaver note, registering a trigger between each redraw call.
Despite these issues I am very pleased with the overall result achieved as the project looks exactly as hoped and the musical outcome has a totally unexpected delightful charm to it. Unlike Korsakov’s frantic regular semiquavers the resulting music from my works sounds much more characteristic of a real bumblebee; haphazardly direct, playfully meandering with intent.