3.2. Steve Reich: Piano Phase

(in-package :cm)
(ql:quickload "cm-utils")

;;; STEVE REICH - PIANO PHASE

;;; Töne

(defparameter *pattern* '(60 62 67 69 70 62 60 69 67 62 70 69))

;;; Partitur für den Rhythmusstream der beiden Pianos: Jedes Element
;;; der Partitur entspricht einer Phrase. Eine Phrase wird durch eine
;;; Liste mit zwei Zahlen definiert. Die erste Zahl gibt die Anzahl
;;; der Wiederholungen eines Patterns an, die zweite Zahl gibt den
;;; offset an, um den das Pattern nach der Anzahl der Wiederholungen
;;; verschoben sein soll. Mit anderen Worten sind die Rhythmen so
;;; berechnet, dass nach der Anzahl der Wiederholungen im
;;; Originaltempo die Notenverschiebung erreicht wird, die die zweite
;;; Zahl angibt.

(defparameter *score-pno1* '((12 0)))
(defparameter *score-pno2* '((12 0) (12 1)))

(defparameter *playing* t)

;;;; Verschachtelte Patterns:

(defun mache-rhythmus-phrasen-stream (eventstream patternlaenge dauer-einer-ganzen)
  (new thunk :of
       (lambda ()
         (let ((ne (next eventstream)))
           (destructuring-bind (anzahl-perioden verschiebung) ne
             (next (new cycle
                     :of (* (/ (* anzahl-perioden patternlaenge)
                               (+ verschiebung (* anzahl-perioden patternlaenge)))
                            (* 1/16 dauer-einer-ganzen))
                     :for (+ verschiebung (* anzahl-perioden patternlaenge)))
                   t))))))

#|

(loop
   with rstr = (mache-rhythmus-phrasen-stream (new cycle :of '((4 0) (4 1))) 3 1)
   for count below 2
   collect (next rstr t))

;;; -> ((1/16 1/16 1/16 1/16 1/16 1/16 1/16 1/16 1/16 1/16 1/16 1/16)
;;;     (3/52 3/52 3/52 3/52 3/52 3/52 3/52 3/52 3/52 3/52 3/52 3/52 3/52))

|#

(defun play-pno (score pat tempo channel)
  (let* ((dauer-einer-ganzen (/ 60 (apply #'* tempo)))
         (events (new cycle :of score))
         (pattern (new cycle :of pat))
         (patternlaenge (length pat))
         (rhythmen (mache-rhythmus-phrasen-stream
                    events patternlaenge dauer-einer-ganzen)))
    (process
      while *playing*
      for rhythmus = (next rhythmen)
      for keynum = (next pattern)
      output (new midi :keynum keynum :duration rhythmus :channel channel)
      wait rhythmus)))

;;; Aufruf für piano phase:

(let ((tempo '(1/4 120)))
  (setf *playing* t)
  (sprout (play-pno *score-pno1* *pattern* tempo 0))
  (sprout (play-pno *score-pno2* *pattern* tempo 1)))

;;; stoppen:

(setf *playing* nil)

;;; --------------------------------------------------

#|

;;; in einer Funktion zusammengefasst:

(defun play-pno (score pat tempo channel)
  (let* ((time-per-whole (/ 60 (apply #'* tempo)))
         (events (new cycle :of score))
         (pattern (new cycle :of pat))
         (period (length pat))
         (rhythms (new thunk :of (lambda ()
                                   (let ((ne (next events)))
                                     (destructuring-bind (num-periods offset) ne
                                       (next (new cycle :of (* (/ (* num-periods period)
                                                                  (+ offset (* num-periods period)))
                                                               (* 1/16 time-per-whole))
                                                  :for (+ offset (* num-periods period)))
                                             t)))))))
    (process
      while *playing*
      for rhythm = (next rhythms)
      output (new midi :keynum (next pattern) :duration rhythm :channel channel)
      wait rhythm)))

;;; Aufruf für piano phase:

(let ((tempo '(1/4 120)))
  (setf *playing* t)
  (sprout (play-pno *score-pno1* *pattern* tempo 0))
  (sprout (play-pno *score-pno2* *pattern* tempo 1)))

;;; stoppen:

(setf *playing* nil)

| #

results matching ""

    No results matching ""