The piece begins with an evolving sequence of rhythmic patterns in each hand. It uses the function COMBINATION2, which here lists all the possible combinations of a 1 and 0 (the binary pair) spread over a list of five ‘bits’:
=> ((0 0 0 0 0) (1 0 0 0 0) (0 1 0 0 0) (1 1 0 0 0) (0 0 1 0 0) . . .))
With the function RND-ORDER the variable series can be re-ordered:
(rnd-order series :seed 312 :list t)) => ((1 0 0 0 0) (0 0 0 1 0) (0 0 0 0 1) (0 0 1 0 1) (0 1 1 1 1) . . .))
These binary lists now provide the rhythmic template for right and left hands. With the BINARY-MAP function the rhythmic value (e), or (1/8) notes, can be mapped onto both binary templates creating patterns of note lengths and rests.
Next the collection of pitches is processed and extended by PITCH-EXPANSION-SERIES to make variations. This function uses a list of interval values to make changes to each five-pitch list:
(setf p-rows (pitch-expansion-series (length series) '(1 -1 2 -2 3 4 5) '(2 1) pitches))
This is quite a complex function that has at its heart randomisation. This is how it works in a simplified example from the OM Documentation. As you can see, the function runs four times, selecting 2 to 3 items to transpose according to a given series of intervals:
(pitch-expansion-series 4 '(1 -1 2 2) '(2 3) '(c4 g4 g4 db5 ab5)) => (c4 g4 g4 db5 ab5) (d4 g4 = eb5 ab5) ; step original 2 0 0 2 0 ; count 2 (db4 g4 a4 eb5 ab5) (db4 a4 b4 eb5 bb5)) ; step -1 0 2 0 0 0 2 2 0 2 ; count 2 3
But we need to know how many lists of pitches to expand to, to work out the first parameter slot in the function. In the midst of the expression you'll find:
(length series) => 32
This is another good example of using the LISP primitive LENGTH to find out the length of a list. By using this we actually don't have to know the length of series and can make a global change (perhaps to the list length) if necessary.
The function PITCH-EXPANSION-SERIES is the first of several functions that contain a string of parameter slots and keywords. They seem at first a little forbidding, but you'll soon learn how they work by looking at the document entry for the function.
(setf p-rows-t (sort-asc (pitch-transpose -12 p-rows)))
In the material for the left hand we're using the same expanded pitch list but it's been reorganised by SORT-ASC (a function that sorts each list in ascending order). It is also mapped to a different binary rhythm.
=> ((c4 cs4 fs4 g4 c5) (c4 cs4 fs4 c5 =) (as3 cs4 fs4 c5 b4) . . .))
Finally, notice how GEN-LOOP is used to generate a dynamic structure for each of the lists, and again that LENGTH function is used to count the length of series.
(setf series (combination2 5 '(1 0))) (setf reordered-series (rnd-order series :seed 312 :list t)) (setf rhythm (binary-map reordered-series '(e))) (setf rhy-b (binary-map series '(e))) (setf pitches '(c4 cs4 fs4 g4 c5)) (setf p-rows (pitch-expansion-series (length series) '(1 -1 2 -2 3 4 5) '(2 1) pitches)) (setf p-rows-t (sort-asc (pitch-transpose -12 p-rows))) (setf dyn-1 (gen-eval (length series) '(rnd-pick (mclist '(p mp mf f ff))) :seed 23)) (setq rh-1 (make-omn :length rhythm :pitch p-rows :velocity dyn-1)) (setq lh-1 (make-omn :length rhy-b :pitch p-rows-t :velocity dyn-1)) (def-score lesson-19 (:key-signature 'chromatic :time-signature '((5) 8) :tempo '(q 140) :flexible-clef t :layout (piano-layout 'piano-rh 'piano-lh)) (piano-rh :omn rh-1 :channel 1 :sound 'gm :program 'acoustic-grand-piano) (piano-lh :omn lh-1) )
Go back to Reference page.