Using Haskell to Write Music

Using Music to Learn Haskell


Happy Day Dance and Coursing as Accompaniments
[info]programmusic
What to do with these pieces? All the repetition, the dirt-simple harmonic progressions of most of these pieces--to the extent it adds up, it sums to a sort of minimalist minimalism--tight and bland. The pieces can be a nice mask for conversation or other distractions, although at a cost in mental energy that's still greater than actual silence.

That background role also suggests accompaniment. This post highlights two uses of the pieces as starting point. The first is by a good friend and expert audio engineer. He began with "Happy Day Dance" and used it as the starter track for a sonic collage, inspired by "As Falls Wichita, So Falls Wichita Falls" by Pat Metheny and Lyle Mays.

http://dl.dropbox.com/u/8704898/Happy%20Day%20Dance/FlightOverdue.m4a

His summary:

"The little girl yelling in that "concrete jungle" patch gave me the idea that maybe she's in the city on the way to the airport to take a trip. So she travels to the rain forest, jungle, beach, but then flying back some bad things happen to the airplane, they ditch at sea, and she needs to be rescued. (Oh and let's not forget the alien like spaceship noises - maybe the little grey guys are lending a hand helping the rescue helicopter and ship find her!) .. Or maybe I watch too many (sci fi) movies!"

In a similar vein, I tried my hand at a bare-bones music video, using "Coursing" as a starting point:

http://www.vimeo.com/18351203

The pulse of the music and the echoes back and forth when you listen with headphones seemed to fit the dense, regular patterns on the bark of trees. To match the slow motion in the music, I tried different simple movements across the bark, then stitched together clips at roughly the same time intervals as the shifts in the music harmony.

Accompaniment seems like a good fit for these pattern pieces. Generating parts from the Haskell has been fun, but the regularity of the voices and the unending continuity of the texture makes them not so well-suited to live performance. Going forward, my plan is to tailor the process so the parts will be easier to perform.

Monad Mechanics
[info]programmusic
There's lots going on in Haskell's "do" notation for monads. Reading carefully again through the tutorial at "Mike's World-O-Programming" I recently had a bit of trouble that I managed to dig myself out of with a mechanical application of a process, "de-sugar and reduce" that I want to present here. The process is a little painstaking. But it helped me discover some things I'd never really thought through before.

To see what this looks like in action, I need a monad with bit of very simple "do" notation, cribbed from the tutorial at "Mike's":

data ArithmeticError =
DivideByZero
| NotDivisible
deriving Show

-- Roll "My" Either and Monad instance to avoid ghci errors.
data MyEither e a = MyLeft e | MyRight a deriving Show

instance Monad (MyEither e) where
return x = MyRight x
(MyLeft x) >>= f = MyLeft x
(MyRight x) >>= f = f x

safe_divide :: Int -> Int -> MyEither ArithmeticError Int
safe_divide _ 0 = MyLeft DivideByZero
safe_divide i j | i `mod` j /= 0 = MyLeft NotDivisible
safe_divide i j = MyRight (i `div` j)

g :: Int -> Int -> Int -> MyEither ArithmeticError Int
g i j k =
do q1 <- i `safe_divide` k
q2 <- j `safe_divide` k
return (q1 + q2)

To prove to myself I understand the "do" block I want to de-sugar it and reduce it. Cribbing again from "Mike's" discussion of "do" syntax (as well as countless other examples in countless other monad tutorials and Haskell texts, I'm sure), the "do" block above turns into

(i `safe_divide` k) >>= (\q1 ->
((j `safe_divide` k) >>= (\q2 ->
(return (q1 + q1)))))

Roll it onto one line to get a sense of the way those parenthese pile up:

(i `safe_divide` k) >>= (\q1 -> ((j `safe_divide` k) >>= (\q2 -> (return (q1 + q2)))))

To double check the parenthese are right, put some values in i, j, and k, and evaluate it in a ghci prompt (load the excerpt above from a file):

*Main> 2 `safe_divide` 1 >>= (\q1 -> (4 `safe_divide` 1 >>= (\q2 -> (return (q1 + q2)))))
MyRight 6

So far so good. Next, rearrange ">>=" in function call form, and double-check with ghci:

(>>=) (i `safe_divide` k) (\q1 -> ((>>=) (j `safe_divide` k) (\q2 -> (return (q1 + q1)))))

*Main> (>>=) (2 `safe_divide` 1) (\q1 -> ((>>=) (4 `safe_divide` 1) (\q2 -> (return (q1 + q2)))))
MyRight 6

Next, I find it to be very revealing to outline the scope the evaluation contexts:

(>>=) (i `safe_divide` k) (\q1 -> ((>>=) (j `safe_divide` k) (\q2 -> (return (q1 + q1)))))
------------------- ----------------------------------------------------------------
>>= m a (a -> m b)

------------------ ----------------------------
>>= m a (a -> m b)

Here's visual proof of the impact of the fact that operators in the de-sugared "do" syntax associate to the right. Note how the scope of the second argument to the first ">>=" extends over the rest of the entire expression. I think this is one part of the impedence mismatch that "do" notation presents to programmers with imperative backgrounds. Those clauses in the "do" block may *look* like statements. They may even contain a "return" keyword. But when you de-sugar the notation and watch the extent of your parentheses, then you see they're all wrapped up inside one giant nested expression. The "do" sugar hits programmers from the land of imperative languages squarely between the eyes, the way it dresses up a giant nested expression in the clothing of a series of statements. There's no doubt it's a lot cleaner to read than a cascade of hanging lambdas. But it's still a giant expression, not a series of disconnected statements.

The other thing that grabs my attention when I do this is the discontinuity between bindings and functions. My mental model working with lambdas up to this point is that you specify an argument list and then you *use* the argument values. Why else did you elaborate them? But a quick look at the de-sugared notation above shows those bindings are really just to capture the value from the ">>=" left hand side, and they don't necessarily have anything to do with the lambda that immediately follows. In this case, lambda argument "q1" doesn't bind to anything in the next level ">>=" left hand side at all, although it could. The de-sugared "do" syntax shows the technique of "parking" those bindings for the next deeper level of expression evaluation, that's all.

Next, start reducing the de-sugared/functionalized version of the "do" block. Starting at the outermost layer, the first application of ">>=" has two arguments, the monad value (or the expression that reduces to a monad value) to the left and the function to the right. Note how, with the nesting of sub-expressions, each application of ">>=" scopes over all the remaining lines in the "do" block. The "do" notation may look like an orderly series of statements, but it ain't. Each time you apply ">>=" there's a choice: evaluate the expression to the right zero, once, or more than once.

Even the first, baby-step monad examples show the power latent in the scoping extents in the de-sugared notation. Both Maybe and Either apply a zero or once strategy, possibly just to dump the entire right hand ">>=" argument, without ever evaluating any of it. For another example, consider the list monad--another baby-step model. In this case, the ">>=" goes the other way, iterating in a kind of cross-product machine gun. Here's a trivial example:

h :: Int -> Int -> [Int]
h i j =
do l1 <- if (i > 0) then [0..i] else []
l2 <- if (j > 0) then [0..j] else []
return (l1 + l2)

De-sugared:

(if (i > 0) then [0..i] else []) >>= (\l1 -> (if (j > 0) then [0..j] else [] >>= (\l2 -> return (l1 + l2))))

Functionalized:

(>>=) (if (i > 0) then [0..i] else []) (\l1 -> (>>=) (if (j > 0) then [0..j] else []) (\l2 -> return (l1 + l2)))

Scope outlined:

(>>=) (if (i > 0) then [0..i] else []) (\l1 -> (>>=) (if (j > 0) then [0..j] else []) (\l2 -> return (l1 + l2)))
-------------------------------- -------------------------------------------------------------------------
>>= mv a (a -> mv b)
-------------------------------- --------------------------
>>= mv a a -> mv b

Reduced outer and inner scopes (for list, >>= means concat (map f mx)

concat (map (\l1 -> (>>=) (if (j > 0) then [0..j] else []) (\l2 -> return (l1 + l2))) (if (i > 0) then [0..i] else []))
------------------------------- --------------------------
mx f

concat (map (\l1 -> (concat (map (\l2 -> return (l1 + l2)) (if (j > 0) then [0..j] else [])))) (if (i > 0) then [0..i] else []))

Now you can see how the enumeration at the outer scope drives a second enumeration in the inner scope, with enumeration inputs getting carried along by bindings until they're referenced by the innermost "return" expression. What's getting "returned" (or monadized) is single item list with the sum of the two iterator values, with the encompassing "concat" calls stripping the inner list structure at each level of nested scope.

To summarize: mechanically transforming "do" syntax can help make behavior less opaque. Everything's an expression, appearances of "do" blocks to the contrary. Each successive expression in a "do" block scopes all subsequent expressions. Control flow varies monad by monad. Each line in a "do" block has implicit control over all the subsequent lines. When you can't quite grok the behavior, grab your ghci prompt, de-sugar, functionalize, scope, and start reducing.

Bittersweet Symphony
[info]programmusic
 Bittersweet Symphony

The pain of departure, the sweet sadness watching someone close move away to a new, exciting destination. These feelings found expression for me in this piece, Bittersweet Symphony:

http://dl.dropbox.com/u/8704898/Bittersweet/Bittersweet%20Symphony.m4a

It's a 35 minute long, two-part piece for two choirs, one with fast voices, one with sustained voices. This rendition is scored for clarinet and viola choirs, respectively, with English horn and Bassoon to add color to the violas. A marimba adds a bit of articulation to the clarinets in the second half. There's a brief sound-effect as a bridge between the first and second sections. The JamPack orchestra voices are quite nice, but the unvaried dynamic of the sustained pitches can't help but give a bit of the effect of a cheap electric organ, at least to my ear. A performance with real players would be much less monotonous. It would also require three or more players on a part, including the parts for the fast choir. Swells up and down during the sustained notes would keep the choir from being so omnipresent in the texture. I picked violas, English horn, bassoon, and marimba for the sound of the JamPack voices. It'd be fun to hear the piece with more varied instrumentation in both choirs.

The generative engine for this piece is successive transposition of pitches from the source pattern, just like for the other pieces--except for Train Trance, which blends patterns without transposition. What's different is the span of the transpositions. The other pieces span in over-and-back sequences, sometimes pitch-by-pitch (Coursing), sometimes with overlapping series of pitches (Happy Day Dance, Alleluia). For Bittersweet, the transpositions accumulate, leading to new pitch centers, although still within the same scale. The register shifts--gradually--and as it lands in different places, different modes latent in the diatonic scale emerge.

I split the pitches from this engine into two choirs. The fast one catches each note.  The slow one extracts sustained notes from the patterns following a rhythmic template. The template for the first half is short. The unit duration matches the total duration for the core pattern, so the two choirs move in a sort of harmonic lock-step. The sustained voices drop out from time to time, so the effect doesn't get too monotonous. The rhythmic template for the second half is much longer, with the unit extending well beyond the total duration for the core pattern in the second half. With the dissimilar rhythmic units and the very long total template duration, the two choirs in the second half have more independence.  The sustained choir captures repeated freeze-frame snapshots to hold the notes of the fast voices like a strobe light.

There's a change in affect between the two halves: the descending steps of the first half, with their echoes and pulsing repetitions have a weeping, rain-dripping effect, which contrasts with the skipping dance rhythms of the second half. In both cases, the effect is the sum of many factors: the number of pitches in the pattern, the count of voices (here five), the imitative distance in the canon. The process of writing the piece was, at least to start, a sightly directed random walk through these dimensions, perturbing a range or effect in one while holding the others steady. It's not hard to imagine many different pieces arising from different walks.

It's very similar of the process explorations that yield ambient music, although the examples I tend to think of were assembled from physical processes like tape loops or synthesizer patches.  Does it make a difference to do it in software? As an undergraduate in music school, I was privileged to attend a session led by none other than John Cage himself, during which we opened the windows and listened to the sounds of the streets outside. It was far beyond my capabilities then--or now--to assemble music out of that. But I've always liked the challenge it presented.

As a brass player in many classical orchestra performances, I found myself relishing my seat in the middle of the orchestra. One of my favorite memories is a performance of Mahler's fifth symphony.  The fourth movement is one of the crowning glories of Romantic music. I got to sit in the middle of the orchestra reveling in the beauty of that movement, never playing a note myself, but somehow still a part of the experience, an active participant in the unique moment.

Today, putting these algorithms to the task of spinning out note patterns, it can be a thrill to find a music emerging, from somewhere, I'm not sure exactly where. For me, listening to such a highly articulated and regular texture, I find my ear picking out this fragment, then that phrase, hearing something new, and the experience resonates with that challenge from years ago, my experiences as a performer, and from listening repeatedly to minimalist pieces by the pioneer composers. The software certainly makes possible patterns like these that can engage active listening, and maybe that's part of the appeal. Or maybe it's just if you're stuck listening to something so regular you become an active listener as a defense against boredom. There's a different balance for everybody!

Creating Parts for Coursing
[info]programmusic
What do parts for "Coursing" look like? Here are some samples:
  

  

For complete parts (PDF), download from these links:

Creating these parts was an adventure during which I learned a lot and benefited from the help of a couple friends. I was surprised at the effort required to produce parts that are easy to read. And I was delighted to find a sophisticated, well-documented, free music engraving software package, LilyPond (http://lilypond.org).

Starting off, I thought, why should this be so hard? My Haskell code generates Midi files with very regular rhythms. Even GarageBand can show me a score for an individual part. It may be a bit awkward.  But it's accurate. Downloading the free trial version of the Sibelius program, I generated a sample with annotations to show pitch changes in just a few minutes:



Feeling fairly confident the path to generating parts was mainly going to be painful for the significant cost of the software, I sent a sample to a friend who's a successful composer--with commissions for orchestra pieces even--and who knows lots about putting ideas into music so it can be performed.  He responded that the piece seemed like it could be performed, but if I took more care to organize the barring and rhythm, then the parts would be easier for the performers to read.

That's when things began to get interesting. Listening to the piece with all the voices pounding away together, I hear a mix of tuple and triple bars.  But trying to settle in on a regular downbeat is a challenge--and part of the appeal to the piece. The mix of two's and three's generates competing rhythms.  The pattern repeats in nine-note cycles, but the pitches subdivide 4 + 2 + 3.  The voices follow each other at a distance of two pitches.  With four voices and a cycle of nine notes, that gives a 2 + 2 + 2 + 3 cross rhythm that shifts as you ear picks out the pitches that change from pattern to pattern as rhythmic anchors.

To figure out how to organize the parts, I listened more closely and thought more carefully about the organization of the piece.  I arrived at the notation gradually. First, by isolating the first voice and slowing down the tempo in GarageBand it seemed the compound time signature of 4/16 + 5/16 best captured the organization of the pattern. The low notes serve as the organizing rhythmic anchor, at least in the initial repetitions of the pattern. That meant starting the piece from an upbeat, something that captures the fluidity of the rhythm, putting the meter as perceived by the performers at odds with what the audience experiences.

This ambiguity shows up sometimes when you first see a live performance of a supposedly familiar piece and the way the conductor starts the piece catches you completely by surprise. The rhythmic organization of the notation turns out to be quite different from what you'd imagined from just listening. And it's not just somebody you'd expect, like Stravinsky. It can happen with Brahms symphonies as well. It probably helps to be a performer, when you'd better be watching the conductor closely at least at the start of the piece! There's a tension between what the rhythm you hear and the rhythm you watch that adds a fine sense of reinterpretation, a new degree of discernment that can make the live performance of a familiar work new again.

But with "Coursing", all the parts are the same! The only difference from one voice to another is the point in the pattern where that voice starts.  The first voice starts on the first note, the second on the third note, the third on the fifth note, the fourth on the seventh note. A rhythmic grouping that works for one voice makes equal sense for all the other voices. The only rule you have to break is the idea that the downbeat is the same for all the voices. That's how I wound up notating the different voices, with different downbeats, or "differential barring" as I think of it. Beats me how you'd conduct it.  But it also beats me why you'd need a conductor for a piece with only four parts, except maybe to help out during rehearsal.

Meanwhile, I've got some things going on, notationally. There's the compound time signature. There's repeat bars that come in between downbeat bars for the meter. But especially, there's a ton of measure-by-measure annotations and other adjustment I'm going to have to make if I start from a rendering that begins with the Midi input.  When you're a programmer, these are the kinds of things you dread. They're repetitive and error prone.

That's where my other friend came to my rescue, by mentioning LilyPond, free software that creates scores from ordinary text files. Given the algorithmic core from where these pieces originate, why not create a different back-end to produce LilyPond input instead of Midi?  And that's exactly what I did. You can see the new Haskell to output LilyPond in the Coursing.hs and LilyPondOps.hs source files:
One of the beauties of text file input is the ease with which you can tweak things. The algorithmic bits in the Haskell cover the 95% of the notation that's repetitive and regular. A half-dozen manual steps tweak the changes unique to each part. LilyPond gives you an enormous variety of customizations, and the documentation is thorough, accurate, and deep. It's been a real pleasure getting to know it.

The only problem I gave up trying to solve was to render a score where the different voices have different downbeats--which makes sense when you think the software is going its best to line things up, and I'm doing my best to present it with voices that are purposefully not lined up.  A degenerate configuration, you could say! It's amazing LilyPond was able to make sense of it at all.  It's also a little questionable what value a score provides in a piece like this, where you essentially get a wall of notes that don't vary much in either horizontal or vertical dimension! On the other hand, it can be nice to have something to follow along when listening to a performance.

My solution was to just leave off the bar lines entirely, and let even the repeats be implicit:


http://dl.dropbox.com/u/8704898/Coursing/CoursingScore1.pdf

This goes along with another choice: to reduce the notation to the core of the piece, and leave off specifics about instrumentation, tempo, count of repetitions, and dynamics to the performers. My rendering uses one configuration: a choir of GarageBand "Swirling Electric Piano", 120 beats per minute, eight repeats each for the introduction and twenty for the body, and two crescendos during the introduction. But those were, in large part, an accident of rendering the thing with GarageBand in the first place. For example, 120 beats per minute is just the default tempo for all GarageBand pieces! That's no reason for an ensemble of marimbas and vibes, say, to crank it out at that speed.

The dotted bars in the notation show the unit for repetition. The colored note heads show pitches that vary, measure-to-measure. It's a little embarrassing.  The notation reveals the simplicity of the piece in all its minimalist glory.  There's just not very much that really happens, once things get wound up. Yet somehow it's still something I find makes enjoyable listening! There seems to be lots to explore, in this realm of fairly simple, mechanical transformations of musical textures. It's lots of fun.

Alleluia Haskell
[info]programmusic
Here is the Haskell text for the piece "Alleluia".

http://dl.dropbox.com/u/8704898/Alleluia/Alleluia.hs

Looking at the simplicity of the piece makes the title seem even more pretentious!

Here's what the pitch swells look like:

bodyPitchesList :: [Pitches]
bodyPitchesList =
bodyPitches `genTransp` (fMaj,[1,-1]) -- 99
    `genTranspN` (fMaj,[1,1,-1,-1]) -- 117
    `genTranspN` (fMaj,[1,1,1,-1,-1,-1]) -- 135
    `genTranspN` (fMaj,[1,1,1,1,-1,-1,-1,-1]) -- 153
    `genTranspN` (fMaj,[1,1,1,1,1,-1,-1,-1,-1,-1]) -- 171
    `genTranspN` (fMaj,[1,1,1,1,-1,-1,-1,-1])
    `genTranspN` (fMaj,[1,1,1,-1,-1,-1])
    `genTranspN` (fMaj,[1,1,-1,-1])
    `genTranspN` (fMaj,[1,-1])
    `mult` 2
    `rot` (4,2)
    `con` 4

The second argument to the `genTransp` and `genTranspN` operator is a tuple with a scale and a list of diatonic transpositions in that scale, to be applied successively to repetitions of the "Pitch" pattern in the first argument.

Here are the volume swells:

bodyVelocitiesList :: [Velocities]
bodyVelocitiesList =
    ( [0.5 `swell` (198, 1.3)]
    ++ [0.6 `swell` (234, 1.4)]
    ++ [0.7 `swell` (270, 1.5)]
    ++ [0.8 `swell` (306, 1.6)]
    ++ [0.9 `swell` (342, 1.7)]
    ++ [0.8 `swell` (306, 1.6)]
    ++ [0.7 `swell` (270, 1.5)]
    ++ [0.7 `swell` (234, 1.4)]
    ++ [0.5 `swell` (198, 1.3)] )
    `rot` (4,0)
    `con` 4

There's a bit of hand-coding here to get the volume swells to span the double-repetition of each transposition, where the length of the transposition segment grows with the transpose steps. This makes it a bit harder to parametrize the code that generates this piece.

A better solution would be to encapsulate the whole transposition sequence in a method with arguments for the extent of the swell (five above), etc., and emitted the whole sequence. Then there'd also have to be a way to parse out the count of voices in each segment for the counters in the velocity swells.

Maybe the next time I think a swell like this would make a good transformation in a new piece I'll come back and pull this code into a library. That's one of the intriguing things about this sort of blend of composing and computing.  There are many opportunities for cross-pollination.

Alleluia
[info]programmusic
Here's a very simple, short piece with a happy, jubilant feeling:

http://dl.dropbox.com/u/8704898/Alleluia/Alleluia.m4a

One of the fun things about GarageBand is the ease with which you can automate behaviors like tempo, volume, and a bunch of others. I'm sure other studio packages let you do this in more sophisticated ways.  But the GarageBand master track automation has saved me a bunch of time coding up Midi controls for things like master volume and tempo. It's also been fun to play with per-voice controls like pan and reverb settings.

In this piece, the introduction starts with a slow speed-up to tempo and fade-in for volume at the same time as the pattern gradually fills, note-by-note.  Then there's a brief break before the pattern resumes at a slightly faster tempo at 1:10 from the start, but much quieter for the body of the piece.

The body is a series of swells up and down that ripple through the pattern.  As the piece progresses, the swells grow step by step, until they reach a high point of five steps up, then five steps back. Then the process reverses and the swells diminish, again step by step, until we're back at the starting point of one up, one down.

Swells overlap as they propagate. Longer swells see more pitches simultaneously in motion.  I like to imagine fans at a stadium doing the wave, with the wave of standing fans on successive laps becoming first broader and broader, then narrowing back to an initial, brief peak. The swells in pitch are matched by volume (a.k.a. "velocity" in Midi-speak), which increase and decrease in intensity along with the pitch swells.

After the last swell, the pattern "dries up" as rests knock out more and more pitches. There's a final accelerando off to the horizon just as the fade-out tapers the volume down at the very end.

One of my issues with creating pieces like this is knowing when to stop. There are so many degrees of freedom. I'm always tempted to try one more variation, a texture with one more or one fewer voice, a different imitative distance, a different arrangement of the notes in the pattern, or adding or removing a note, a different instrument or collection of instruments, etc. ad infinitum.

Eventually, you have to say enough. This piece feels a little on the plain side to me--a little below even my threshold for stimulation. But there were some surprises that popped out. One thing is the spotty distortion in some of the trailing voices as the swells pile up. By chance, a bunch of voices pound away at the same note, and a surprising, funky sort of telegraphic inner rhythm bops to the foreground.

One thing I have consistently found to be true is the endless repetition is alleviated by avoiding even multiples of the number of voices, the length of the pattern, and the imitative distance. Or at least, that way you don't wind up hearing subdivisions within the pattern, which has the effect of robbing the texture of complexity.

Making Train Trance
[info]programmusic
 The pitches for the three patterns in Train Trance vary little:

redPitches = [Pitch G 0, Pitch D 1, Pitch G 0, Pitch E 1, Pitch D 1, Pitch A 1, Pitch E 1, Pitch C 1, Pitch G 0, Pitch C 1]
bluePitches = [Pitch G (-1), Pitch D 2, Pitch G 0, Pitch E 2, Pitch D 2, Pitch A 2, Pitch E 1, Pitch C (-1), Pitch C 2, Pitch C 1]
greenPitches = [Pitch C (-1), Pitch C 1, Pitch C 3, Pitch C 2, Pitch C 1, Pitch C 0, Pitch C 1, Pitch C 3, Pitch C (-1), Pitch C 1]

You have to look closely at the first two patterns to see the only pitch class that changes is the second to last one in the list. Otherwise, the changes are all just octave transpositions up or down one or two octaves. One of the notes stays the same.

So the harmony is even more static the other two pieces. Yet when those octave transpositions kick in, there's a sense of motion, or development, even within that same collection of pitches. There are a lot of choices, a lot of ways those transpositions could have gone--all low, or all high, for example. I liked the way the relatively tight range of the first pattern blossoms out to the expanded range of the second.

The third pattern does change pitches, but just to replace them with uniform C's, spread across a slightly greater range. As the blend progresses, and successive notes fall away to the background octaves, I find I hear two and three note groups revealed in the foreground, notes that were always there, but just swallowed in the business of the texture.

As more and more notes fall away to just octave C's, there's a switch in my attention from the progression of pitches to a sort of telegraph rhythm, in a barren desert of just plain C's bouncing around up and down. That's low energy enough that the arrival of the first new E has a sunrise effect, the beginning of a new day--or a more interesting pattern anyway.

Here's the Haskell for the blends, which makes up the pitch sequence for the entire piece:

trainPitchesList :: [Pitches]
trainPitchesList =
    redPitches `blendFromBack` bluePitches
                        `blendNFromBack` greenPitches
                        `blendNFromBack` bluePitches
                        `blendNFromBack` redPitches
                        `blendNFromBack` greenPitches
                        `blendNFromBack` redPitches
                        `blendNFromBack` greenPitches
                        `blendNFromBack` bluePitches
                        `blendNFromBack` bluePitches
                        `mult` 4
                        `rot` (4,-2)
                        `con` 4

If you look at just the pairings, red -> blue, blue -> green, green -> blue, etc., you'll see they're mainly unique, with two repetitions: green -> blue and red -> green. Then there's a "null" pairing blue -> blue to let the piece settle down for the end. The six pairings covers the combinatorial product, counting for order. I didn't make a search of all the orders of the six pairings, though. It just happened to come out this way.

The blend operator here pulls new notes in from the back of the list on the right-hand side. This was pretty much just an accident of the way I happened to code the first implementation. In fact, in the process of writing other pieces I'd corrected the implementation to blend from the back, and I had to reverse engineer the original implementation to recreate this piece, creating the "blendFromBack and "blendNFromBack" operators.   Both implementations are in the ListOps.hs module.

Duration and velocity for this piece are uniform repetitions of the Haskore thirty-second note duration and the velocity at value 1.0. I did more in GarageBand. I used automation for individual voices to pan each independently in cross-rhythms between left and right channels. And I used the master track to automate volume fade in and fade out, as well as long-term swells.





Train Trance
[info]programmusic
Got time? Take 16 minutes or so and give this a listen:

http://dl.dropbox.com/u/8704898/Train%20Trance/Train%20Trance.m4a

This piece grew out of an experiment in blending closely related patterns.  There are just three. They shift back and forth for the duration of the piece. So most of the piece is spent in transition, gradually acquiring a new set of notes, gradually releasing the old set of notes.

Of course, that pretty much describes most of this music. But the idea of transition or travel rhymed with the feel of this piece, jiggering a bit of my memory from a cross country train trip I took once, on my way across country to a new college.

Part of what I remember about the train was just to watch out the window, especially when you see those telephone wires bouncing alongside you in a hypnotic pattern up, down, up, down, back, forth, back, forth. There's lots of time. The rhythm of the tracks and the rhythm of patterns like the telephone poles blipping by or the rooftops of houses rising and falling--they all worked to lull me into a happy sort of trance, anticipating my destination, reveling in the long, drawn-out nature of the process of just getting there.  For the first day or so, anyway. It can get pretty boring. This piece lasts about 16 minutes. It can feel pretty long, too.

Listen with headphones--ideally something that gives the bass a bit of power.  When I hear that low note first arrive, at around 30 seconds in, that's when the train image starts to take hold. You hear the low note as it bounces between the four voices, first panning left to right, then as back right to left as old notes drop behind and new notes appear.

That's the way the whole piece works. Creating, then listening to these pieces, I'm amazed at how adeptly the ear--or maybe the part of your brain that assembles patterns--grabs onto the difference between old and new. The starting texture is a weave of four voices all repeating the same ten notes, each two notes apart from the other. Maybe Milton Babbitt could hear that. I don't. To me, it's all a wash, with maybe a bit of sloshing back and forth, low to high, as the pattern repeats.

Then that first new note arrives, and it immediately becomes a focus, a solo standing above the background. Then the next new note arrives, and it becomes the new focus, while the note before gradually slides back to the accompaniment.  Sometimes the notes are far apart--the first three are like that, high, low, high--and you might hold onto two for a while. Or sometimes the new notes are close to each other, or the new note falls in step with one of the old notes, and you hear a little two or three note sequence pop out.

There are three patterns in the piece. With one exception, the second is the same as the first but with pitches transposed up or down by octave. The third pattern is a bare-bones reduction to just octave transpositions of the low note, as a sort of quiet point, before relaunching into one of the other two.  With ten notes in each pattern and the fast tempo, what you tend to hear is a 5/4 bar, repeated some multiple of four times each. The imitation between the four voices works to counter-balance that a bit, although the repetition of among the four voices often gets swallowed up in the business of the surrounding texture.

Finding a title can be hard. I must have listened to this twenty times or so before the picture of those telephone wires bouncing up and down came to mind.  And then the more I thought about it and worked it out in this post, the more sense it made. I know I spent much of my train trip in a sort of trance.  Looking back on that experience reminds me how rarely I experience the same expanse of horizon, the deliberate unfolding of bit of time, and how enjoyable it all was.

Now with the title I like, I listen again, and feel glad I took the time. I wish you luck taking time, yourself.

Happy Day Dance Haskell
[info]programmusic
You can find the Haskell source for "Happy Day Dance" here:

http://dl.dropbox.com/u/8704898/Happy%20Day%20Dance/HappyDayDance.hs

The fade-in section is a blend of two patterns:

introPitches = 
    [Rest,Rest,Pitch B 0,Pitch G 1,Rest,Pitch G 1,Pitch A 1,Rest,Rest,Rest,Rest,Rest,Pitch D 1,Rest,Rest,Pitch A 1,Rest]

bodyPitches = 
    [Pitch D 2,Pitch D 1,Pitch C 2,Pitch B 1,Pitch A 1,Pitch Fs 1,Pitch G 1,Pitch A 1,Pitch B 0,Pitch G 1,Pitch Fs 1,Pitch G 1,Pitch A 1,Pitch B 0,Pitch D 2,Pitch D 1,Pitch G 0]

introPitchesList = introPitches `blend` bodyPitches `mult` 4 `rot` (4,7) `con` 4

You can find the "blend" method in the ListOps.hs file here:

http://dl.dropbox.com/u/8704898/HaskellOps/ListOps.hs

It's pretty trivial:

-- blend source and target lists into a list of lists progressively swapping in
-- new items from the beginning of the target list to the end of the source
-- list until the target list entirely replaces the source list
-- > [1..3] `blend` [4..6] => [[1,2,3],[1,2,4],[1,4,5],[4,5,6]]
blend :: [a] -> [a] -> [[a]]
blend source target =
    [take (len - x) source ++ take x target | x <- [0..len]]
    where
        len = length target

The body of the piece is just the transposition up and down a couple steps, then down and back up a couple steps again.  The transposition method ripples the voices sequentially up and down, with each voice joining the pattern immediately.  With a series of four intervals, there are four adjoining pitches from the pattern "in motion" at a time, following each other through the transposition list. It makes me think of change ringing, if you're an Anglophile or just a fan of Dorothy Sayers. The "genTranspN" method takes a list of transpositions, and appends a new series, using the last element from the input series as the starting point for the new transposition.

bodyPitchesList = bodyPitches `genTransp` (gMaj,[1,1,-1,-1]) `genTranspN` (gMaj,[-1,-1,1,1]) `mult` 4 `rot` (4,7) `con` 4

The other thing new with this piece is manipulation of the velocity dimension in the three-tuple (pitch, duration, dynamic).  Here I first use the "swell" to generate one swell with velocity range 0.5 to 1.2, then spread that through the four other voices using the "swells" method, so you hear the different voices rising individually, above the others, in periods that each last four repetitions of the pattern.

bodyVelocitiesList :: [Velocities]
bodyVelocitiesList = 0.5 `swell` ((4 * 17), 1.2) `swells` (4, (4 * 17)) `mult` 12 `con` 4

The plucked strings and legato clarinets come from Apple's "Orchestra" Jam Pack. I was hoping for a better selection of slurred samples, but I guess that's probably hard to generate--or maybe there are just ways to adjust the attack and delay portions of the envelope on the legato samples to get the same effect. The contrast with the sharp attack from the pizzicato makes the clarinets sound pretty slurred, as it is.

Happy Day Dance
[info]programmusic
Here's another pattern piece. I call it "Happy Day Dance":

http://dl.dropbox.com/u/8704898/Happy%20Day%20Dance/Happy%20Day%20Dance.m4a

The skipping motion of the theme in the full texture--once you reach it--and the incessant perkiness of the pattern and it's major mode harmonies brings a sunny summer day to my mind's eye, chiming with the exuberance from the variations with rising and falling notes and the quick back-and-forth harmony that emerges.

This piece uses a mix of two instruments: plucked strings, legato clarinet. The result is a richer texture, with the pizzicato strings forming the foreground and the clarinets in back. There are still only four independent voices, like the "Coursing" piece earlier. And like in "Coursing," there's a back-and-forth motion in pitches within the texture, although here it's a lot faster. The piece also uses silence--at least a bit anyway! It's the basis for the fade-in and fade-out sections at the beginning and end of the piece. To start, the four voices play their patterns with most of the notes missing. Then, gradually the texture fills out, signaled by the final arrival of the root of the harmony in the low voice of the texture, at around 2:30 from the start.

The piece ends with the reverse process, starting at 8:30 from the beginning. Holes gradually appear in the texture as notes get knocked out, one-by-one, with a couple transpositions, especially throwing the fifth to the bottom of the texture as though the piece was passing you by, leaving you behind as it keeps singing somewhere off in the distance.

Two transposition sequences make up the body of the piece. The first rises two steps and falls back. The second--big creative leap here--falls two steps and rises back up again. To my ear, these have the feel of a very long spinning-out the two traditional fifth relationships in classical harmony: dominant and plagal (or sub-dominant). Listen closely! The switch between the two sections starts at 5:40. The lowest note in the pattern comes at the end, so you can hear the end of the first and second transposition sections by listening for motion in the lowest pitch, starting at 4:58 for the end of the first half and 7:49 for the end of the second half.

In addition, there are surges in volume that spread sequentially among the voices, to mirror the slower surges in pitch. It's easier to hear the plucked voices swell and recede. They respond to the change in the MIDI "velocity" control more than the legato clarinets, although you can hear the clarints speak up, too. The stereo separation of the four voices means the foreground voices swim around a bit, especially if you listen with headphones. All this swelling forth and receding back has something in it suggestive of the super-abundance of high summer.

So what's new here? Anything? Certainly the technique of building a texture sequentially is as old as the hills. Scrounging around in my library I find John Adam's "Lollapalooza", the first movement to "Century Rolls", and in a slower vein his "Tromba Lontana" from his "Two Fanfares". They start the same way, although less gradually. And I'm sure there are countless others. The thing that surprised me a bit in "Happy Day Dance" was how easy it is to capture a similar effect, programmatically. It's just another example of the "blend" algorithm that just merges two patterns, item-by-item, starting from a pattern with rests, leading to almost the same pattern, but with no rests.

This kind of repurposing has been part of the fun of playing with algorithms and music. Simple processes usually work best. Sometimes I come up with an elaborate design I labor to code up, only to find the effects are either so subtle as to be inaudible or so pervasive as to yield chaos. Other times--like this one--I take a very simple process and find a way to vary the input to get a new transition. That's fun! Also, in terms of the structure of the piece, the pace of layering is very gradual. Then again, everything about this kind of piece is gradual! To my ear, the length and regularity of the sections help the whole cohere better, as a "piece" you can listen to. I like it. Let me know if you do too, especially if you'd be interested in trying to perform it.

You are viewing [info]programmusic's journal