Without veering too deeply into extended vocal technique, there are three
components for each note we can vary to create a more musically interesting piece
from our first draft:
dynamic
pitch
phoneme sound/quality
Dynamics
Dynamic is perhaps the simplest parameter here. In my head, the more frequent a part’s
pulse is, the more it should blend, dynamically, with the whole piece. This means that
for parts with the lowest sound event frequencies, their sounding notes will sound
more as interruptions, while the rest of the parts will provide more of a background constancy.
This is easy enough, in theory, to generate an algorithm for. For each measure, we can
take a look at the fraction of sounding note events / total events map that inversely
to a list of possible dynamics (i.e. smaller fraction = louder sound)
To calculate the density of a measure:
Looking through a sampling of the generated densities, it’s possible to generate
a density -> dynamic mapping.
I set the breakpoints in the cond above based on a very
unscientific analysis of the fractions present in an attempt to skew the
resulting dynamics towards the quiet side. Let’s see how that worked out.
We start off with a lot of forte and louder on the first page, and by the last page we’re mostly in the pianissimo range.
Which is potentially fine, depending on what you want the dynamic envelope of the piece to be. Personally, I’d rather it start
off on the quieter side, and build intensity, perhaps with a bit of a denouement through the last pages. But it’s unlikely
that a single algorithm is going to get me that. Fortunately, there’s an easier way.
Rather than a single density -> dynamic mapping, we can create as many as we want, and
pick which one to use based on the current measure. Something like
and of course this can be tailored to personal aesthetics for the piece. For the next
draft, I’m working with this envelope map:
Clearly the first page will be entirely pianississimo, so I won’t bother printing
that out. Let’s take a look at the last page:
That looks like something we can work with! There may be additional tweaking we can do,
but to my mind we have the framework to make those tweaks, and that means it’s time
to move on to pitch.
Pitch
For pitch, I want the pulse to maintain a single pitch throughout the piece, to anchor
the pulse-iness of it. Let’s say that pitch is C. Then every other part begins on C as well,
and gradually the pitch collection expands by the end of the piece. The question then becomes
how to handle that expansion.
A quarter tone chromatic scale has 24 distinct pitches, so it would be possible to generate
a tone row from those pitches to determine the order of the pitch set expansion.
With the pulse remaining on C throughout, and one line for each of those pitches
(meaning two lines on C for a very slight sense of anchoring), that leaves
one line left to account for.
There are two options here that I like for a first pass:
a third part stays (or returns) to C
the part with the lowest event frequency (z unless z is the pulse, in which case it would be q) plays
the prime form of the quarter tone chromatic row we’ve generated.
Before we get too far down the rabbit hole, let’s generate that pitch row. I decided to use a row built off the
harmonic overtone series, with the pitches in order of their first appearance in the series. Or at least approximate first appearance; since
most equal tempered pitches don’t ever appear in the overtone series I did some creative rounding to keep things/me sane.
One evening of looking up the first 64 overtones on the internet later, I came up with a working row, based on A
Transposed to begin on C, and using LilyPond accidentals (qs = quarter sharp, tqf = three quarters flat, etc.),
we get
Taking choice 2 from above, with the z line performing that tone row’s prime form,
we’re left with the 24 other rows to gradually spread to encomass the row.
Here’s the description of the algorithm for how I want to fill out that expansion
While building up list, we also want to create a list of conversion steps. The code
for this looks like this:
Running PitchGenerator.V2.calculate_conversion_steps() returns a list of pitch conversion tuples:
Once we have our list of pitch shifts, we can build up a pitch-per-measure list for each part. To determine the
order of parts that shift pitches, I’m going based on letter frequency order (etaoin…jxqz)
To seed the measures, we create a list of tuples in the form {letter, [ordered pitches for measures]} and iterate through it.
Explanation:
Actual code:
One last piece, and that is the least frequent row, which is iterating through the pitch
row we have. In English, this is a simple exercise:
In real code, in part because of the way notes and measures are represented in data,
it is rather less simple:
With all these pieces, we can generate a new version of the score, including
our rhythmic, dynamic, and pitch modifications. Let’s see what we’ve got.
Unsurprisingly, the first page looks the same, since the dynamic level is
universally pianississimo and the pitches don’t start changing until measure 4
About halfway through, we see that both the dynamic and pitch ranges have expanded.
In measure 31 (last measure on the page), we can see the line for V (fifth from the bottom)
change from c to d
And here at the end, we see the full pitch spread, as well as the Z part iterating through the full pitch set.
This is coming together pretty nicely! There’s one more piece, and that’s deciding on how the voices are going
to articulate their phonemes. For example:
for consonants, only the stopped phoneme, or should I add a vowel sound
if I add vowels, are they the same throughout, or do they change? and, if so, how?
do the voices hold their notes, or are they all performed as short pulses
I’ll be honest: I’m not really sure of the answers to these questions yet, but if you come
back for the next post, I’ll do my best!
Thanks for reading! If you liked this post, and want to know when the next one
is coming out, follow me on Twitter (link below)!