9 Etudes, Op. 3: Iteration, Rows and Sets

Interaction 9-1. Using loop to collect numbers mod 12.

cm> (loop for i from 60 to 72 collect (mod i 12))
(0 1 2 3 4 5 6 7 8 9 10 11 0)
cm> (loop for k from 0 downto -12 collect (mod k 12))
(0 11 10 9 8 7 6 5 4 3 2 1 0)
cm>

Example 9-1. Converting key numbers to pitch classes.

(define (keynum->pc k)
  (mod k 12))

(define (list->pcs knums)
  (loop for k in knums collect (keynum->pc k)))

Interaction 9-2. Pitch classes from measure 15 of Berg's Violinkonzert.

cm> (define albans-notes 
      '(55 58 62 66 69 72 76 80 83 85 87 89))

cm> (list->pcs albans-notes)
(7 10 2 6 9 0 4 8 11 1 3 5)
cm>

Example 9-2. Normalizing a list of pitch classes or key numbers.

(define (normalize-pcs knums)
  (loop with root = (first knums)
        for k in knums
        collect (keynum->pc (- k root))))

Interaction 9-3. Normalizing pitch classes.

cm> (define albans-notes 
      '(55 58 62 66 69 72 76 80 83 85 87 89))

cm> (normalize-pcs (list->pcs albans-notes))
(0 3 7 11 2 5 9 1 4 6 8 10)
cm>

Example 9-3. Twelve-Tone Functions.

(define (retrograde-row row)
  (reverse row))

(define (transpose-row row to)
  (loop for pc in row collect (keynum->pc (+ pc to))))

(define (invert-row row)
  (loop for pc in row collect (keynum->pc (- 12 pc))))

(define (retrograde-invert-row row)
  (retrograde-row (invert-row row)))

(define (row->matrix row)
  (loop for i in (invert-row row)
        collect (transpose-row row i)))

(define (print-matrix matrix)
  (loop for row in matrix
        do (print row)))

Interaction 9-4. Twelve-tone matrix operations.

cm> (define albans-row '(0 3 7 11 2 5 9 1 4 6 8 10))

cm> (retrograde-row albans-row)
(10 8 6 4 1 9 5 2 11 7 3 0)
cm> (transpose-row albans-row 3)
(3 6 10 2 5 8 0 4 7 9 11 1)
cm> (invert-row albans-row)
(0 9 5 1 10 7 3 11 8 6 4 2)
cm> (retrograde-invert-row albans-row)
(2 4 6 8 11 3 7 10 1 5 9 0)
cm> (print-matrix (row->matrix albans-row))
(0 3 7 11 2 5 9 1 4 6 8 10)
(9 0 4 8 11 2 6 10 1 3 5 7)
(5 8 0 4 7 10 2 6 9 11 1 3)
(1 4 8 0 3 6 10 2 5 7 9 11)
(10 1 5 9 0 3 7 11 2 4 6 8)
(7 10 2 6 9 0 4 8 11 1 3 5)
(3 6 10 2 5 8 0 4 7 9 11 1)
(11 2 6 10 1 4 8 0 3 5 7 9)
(8 11 3 7 10 1 5 9 0 2 4 6)
(6 9 1 5 8 11 3 7 10 0 2 4)
(4 7 11 3 6 9 1 5 8 10 0 2)
(2 5 9 1 4 7 11 3 6 8 10 0)
cm>

Example 9-4. Determining pitch class sets.

(define (reduce-pcs knums)
  ;; create a scratch pad list with 12 locations to
  ;; remember the pitch classes in knums. each element
  ;; in the pad is initially false.
  (let ((pad (make-list 12)))
    ;; remember each pitch class in knums by setting
    ;; its position in the scratch pad to true.
    (loop for k in knums
          for pc = (keynum->pc k)
          do (list-set! pad pc true))
    ;; iterate over the scratch pad and return
    ;; a list of the positions where pitch classes
    ;; were recorded
    (loop for i in pad
          for j from 0
          when i collect j)))

Interaction 9-5. Calling reduce-pcs on two octaves of G dom7.

cm> (define g-dom7 '(55 59 62 65 67 71 74 77))

cm> (reduce-pcs g-dom7)
(2 5 7 11)
cm>

Interaction 9-6. A list of all but the first element.

cm> (define test-set '(2 5 7 11))

cm> (rest test-set)
(5 7 11)
cm>

Interaction 9-7. A list of only the first element.

cm> (first test-set)
2
cm> (list (first test-set))
(2)
cm>

Interaction 9-8. Reordering the destructured lists.

cm> (append (rest test-set) (list (first test-set)))
(5 7 11 2)
cm>

Example 9-5. Permute pitch class set.

(define (permute-set set)
  (let ((front (list (first set)))
        (others (rest set)))
    (append others front)))

Interaction 9-9. Examples of set permutation.

cm> (permute-set test-set)
(5 7 11 2)
cm> (permute-set (permute-set test-set))
(7 11 2 5)
cm>

Example 9-6. Set permutation.

(define (set-weight set)
  ;; set must be normalized (zero based)
  (loop for s in set sum (expt 2 s)))

Interaction 9-10. Comparing inversion weights of a dom7.

cm> (set-weight '(0 4 7 10))
1169
cm> (set-weight '(0 3 6 8))
329
cm> (set-weight '(0 3 5 9))
553
cm> (set-weight '(0 2 6 9))
581
cm>

Example 9-7. Computing the normal order of a note set.

(define (normal-order notes)
  (let ((pclist (reduce-pcs notes)))
    (loop with memory and winner 
          repeat (length pclist)
          for normal = (normalize-pcs pclist)
          for weight = (set-weight normal)
          do
          (if (or (not winner)
                  (< weight memory))
            (begin (set! winner normal)
                   (set! memory weight)))
          (set! pclist (permute-set pclist))
          finally (return winner))))

Interaction 9-11. Computing normal orders.

cm> (normal-order g-dom7)
(0 3 6 8)
cm> (normal-order '(72 64 67))
(0 4 7)
cm> (normal-order '(65 64 75 70))
(0 1 2 7)
cm>

Chapter Source Code

The source code to all of the examples and interactions in this chapter can be found in the file sets.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.