;; pc:make-chord
;; creates a list of "number" pitches between "lower" and "upper"
;; bounds from the given "pc". a division of the bounds
;; by the number of elements requested breaks down the selection into
;; equal ranges from which each pitch is selected.
;; make-chord attempts to select pitches of all degrees of the pc.
;; it is possible for elements of the returned chord to be -1 if no
;; possible pc is available for the given range.
;; non-deterministic (i.e. result can vary each time)
;;
;; arg1: lower bound (inclusive)
;; arg2: upper bound (exclusive)
;; arg3: number of pitches in chord
;; arg4: pitch class
;;
;; example: c7
;; (pc:make-chord 60 85 4 '(0 4 7 10)) => (60 70 76 79)
;;
(define pc:make-chord
(lambda (lower upper number pc)
(let ((chord '()))
(let loop ((l (round lower))
(u (round upper))
(n number)
(p pc))
(if (< n 1)
(map (lambda (x)
(real->integer x))
(cl:sort (cl:remove -1 chord) <)) ; lowest pitch to highest pitch remove -1s
(let* ((range (- u l))
(gap (round (/ range n)))
(pitch (pc:random l (+ l gap) p)))
(if (not pitch) ; if new pitch is #f, try from whole range
(set! chord (cons (pc:random lower upper p) chord))
(set! chord (cons pitch chord)))
(loop (+ l gap)
u
(- n 1)
(if (> (length p) 1)
(cl:remove (modulo (car chord) 12) p)
pc))))))))