14 Etudes, Op. 5: Steve Reich's Piano Phase

Example 14-1. Helper functions and Piano 1.

(define phasing-trope
  (keynum '(e4 fs b cs5 d fs4 e cs5 b4 fs d5 cs5)))

(define phasing-pulse 1/24)

(define phasing-tempo 72)

(define (bpm->seconds bpm)
  (/ 60.0 bpm))

(define (rhythm->seconds rhy tempo)
  (* rhy 4.0 (bpm->seconds tempo)))

(define (piano1 trope amp chan)
  (let* ((tlen (length trope))
         (cycs tlen)
         (rate (rhythm->seconds phasing-pulse
                                phasing-tempo)))
    (process repeat (* tlen cycs)
             for i from 0
             for x = (mod i tlen)
             for k = (list-ref trope x)
             output (new midi :time (now)
                         :keynum k
                         :duration (* rate 1.5)
                         :amplitude amp
                         :channel chan)
             wait rate)))

Interaction 14-1. Listening to 12 repetitions of phasing-trope.

cm> (events (piano1 phasing-trope .5 0) "reich.mid")
"reich-1.mid"
cm>

Example 14-2. The phasing-tempo-curve definition.

(define (phasing-tempo-curve tlen stay move)
  (let* ((p (* tlen move))
         (n (+ 1 (* tlen move)))
         (l1 (loop repeat (* tlen stay)
                   collect 1))
         (l2 (loop repeat (+ 1 (* tlen move))
                   collect (/ p n))))
    (append l1 l2)))

Interaction 14-2. Creating a tempo curve list.

cm> (phasing-tempo-curve 3 1 1)
(1 1 1 0.75 0.75 0.75 0.75)
cm>

Example 14-3. The piano2 process.

(define (piano2 trope stay move amp chan)
  (let* ((tlen (length trope))
         (cycs tlen) 
         (coda (* stay tlen))  ; ends with unison segment
         (curve (phasing-tempo-curve tlen stay move))
         (clen (length curve))
         (rate (rhythm->seconds phasing-pulse phasing-tempo)))
    (process repeat (+ (* clen cycs) coda)
             for i from 0
             for k = (list-ref trope (mod i tlen))
             for c = (list-ref curve (mod i clen))
             output (new midi :time (now)
                         :keynum k
                         :duration (* rate 1.5)
                         :amplitude amp
                         :channel chan)
             wait (* rate c))))

Interaction 14-3. Listening to repeats of the phase pattern.

cm> (events (piano2 phasing-trope 1 1 .5 0) "reich.mid")
"reich-2.mid"
cm>

Example 14-4. The final version of piano1 and the pphase function.

(define (piano1 trope stay move amp chan)
  (let* ((tlen (length trope))
         (cycl tlen)
         (reps (* tlen (+ stay move) cycl))
         (coda (* stay tlen))
         (rate (rhythm->seconds phasing-pulse phasing-tempo)))
    (process repeat (+ reps coda)
             for i from 0
             for x = (mod i tlen)
             for k = (list-ref trope x)
             output (new midi :time (now)
                         :keynum k
                         :duration (* rate 1.5)
                         :amplitude amp
                         :channel chan)
             wait rate)))

(define (pphase trope stay move amp)
  (list (piano1 trope stay move amp 0)
        (piano2 trope stay move amp 1)))

Interaction 14-4. Listening to pphase.

cm> (events (pphase phasing-trope 1 1 .5) "reich.mid")
"reich-3.mid"
cm> (events (pphase phasing-trope 1 8 .5) "reich.mid")
"reich-4.mid"
cm>

Chapter Source Code

The source code to all of the examples and interactions in this chapter can be found in the file reich.cm located in the same directory as the HTML file for this chapter. The source file can be edited in a text editor or evaluated inside the Common Music application.