"Reeling Trains" — Composing with Rhythm Chains
+ Associated files
This demo composition and tutorial focuses on slippery
          chicken's rhythm chains feature. It also implements two
          user-defined functions and the process-events-by-time
          method to distribute dynamics and articulation throughout the
          instruments over the course of the piece, and it makes use of
          the map-over-bars, consolidate-notes,
          and auto-slur methods for further automatic adjustment
          of the piece created before outputting the result.
More on the rthm-chain class can be found on
          the rhythm chains page of the user
          manual. 
+ The Code
;; A function to place dynamics on random notes in the score
(defun place-dyns (event)
  (when (equalp (start-time event) 0.0)
    (random-rep 10 t))
  (unless (is-rest event)
    (when (> (random-rep 100) 67)
      (setf (marks event) 
            (list (nth (random-rep 8) '(ppp pp p mp mf f ff fff)))))))
;; A function to place articulations (accent or staccato) on random notes in
;; the score
(defun place-arts (event)
  (when (equalp (start-time event) 0.0)
    (random-rep 10 t))
  (unless (is-rest event)
    (when (> (random-rep 100) 67)
      (setf (marks event) 
            (list (nth (random-rep 5) '(a s)))))))
;; Disabling the chord function on the string instruments (no double-stops) 
(loop for i in '(violin viola cello)
     do
     (set-slot 'chords
               nil
               i
               +slippery-chicken-standard-instrument-palette+))
;; Changing the chord function for the piano instruments
(loop for i in '(piano piano-lh)
   do
     (set-slot 'chord-function
               'chord-fun1
               i
               +slippery-chicken-standard-instrument-palette+))
(let* ((num-seqs 137) ; The number of sequences in the rthm-chain to be made
       ;; Defining the rthm-chain object
       (rch
        (make-rthm-chain
         'test-rch 
         num-seqs
         '((((e) e) ; the 1-beat fragments: 4 in total
            (- s (s) (s) s -)
            ({ 3 (te) - te te - })
            ((e.) s))
           (({ 3 (te) te (te) }) ; what we transition to
            ({ 3 - te (te) te - })
            ({ 3 (te) - te te - })
            ({ 3 (te) (te) te }))
           (((q)) ; the second transition
            (- s e s -)
            ({ 3 te (tq) })
            (s (e.)))
           ((- e e -) ; the third transition
            (- s s s - (s))
            ((32) 32 (e.))
            ((q))))
         '((((q q) ; the 2/4 bars: 4 total
             ((q) q)
             ((q) q)
             ((q) (s) e.))
            (({ 3 te te +te te +te te }) ; what we transition to
             (q - s e. -)
             (q (s) e.)
             (q (s) - s e -))
            ((q - +e e -) ; the second transition
             ((e) e +e e)
             (q - s (e) s -)
             ((s) e. +s e.)))
           ((((e.) s (e) e (s) e.) ; the 3/4 bars: 4 total
             (- e e - (e) e (q))
             (- e. s - - +e e - (q))
             (q (e.) s (q)))
            (({ 3 (te) (te) te +te te +te } (q)) ; what we transition to
             (- e. s - (q) (s) - s e -)
             ({ 3 te te +te } (q) q)
             ({ 3 - te +te te - } (e) e { 3 (te) (te) te }))
            ((q +q +q) ; the second transition
             (q +q (q))
             (- e e - +q (q))
             (s (e.) (q) (q)))))
         ;; The proportion of rests or sounding notes in each passage
         :activity-curve '(0 5 20 7 30 8 50 3 70 5 80 8 100 10)
         ;; The durations to be used for the inserted rests
         :rests '(s e s q)
         ;; The durations to be used for the inserted rhythms
         :sticking-rthms '(e h e. w s e h s)
         ;; The activity-curve for the sticking rhythms
         :sticking-curve '(0 2 20 3 30 5 50 8 80 10 100 2)
         ;; The number of times each sticking rhythm is repeated
         :sticking-repeats '(3 5 3 5 8)
         ;; The number of consecutive sequences that have the same 
         ;; harmonic set
         :harmonic-rthm-curve '(0 1 10 2 30 3 40 1 50 2 80 4 90 5 100 1) 
         ;; The min and max beat duration of bars generated; beat taken from
         ;; the given time signature.
         :split-data '(4 7)
         ;; The IDs for the original two players
         :players '(fl cl))))
  ;; Adding new voices based on the content of the original two, these with
  ;; offsets however to avoid completely identical voices.
  (add-voice rch '(1 fl) 'ob 1)
  (add-voice rch '(1 cl) 'bn 1)
  (add-voice rch '(1 fl) 'pnr 2)
  (add-voice rch '(1 cl) 'pnl 2)
  (add-voice rch '(1 fl) 'vn 3)
  (add-voice rch '(1 fl) 'va 4)
  (add-voice rch '(1 cl) 'vc 3)
  (add-voice rch '(1 cl) 'vb 4)
  ;; Creating automatically generated pitch-seq palettes for the rthm-seqs made 
  (create-psps (palette rch))
  ;; A series of variables for the make-slippery-chicken function, starting
  ;; with the definition of the set-palette
  (let* ((sp '((1 ((c3 cs3 d3 e3 fs3 g3 c4 cs4 e4 c5 gs5 cs6 d6
                       ds6))) 
               (2 ((b2 c3 fs3 gs3 ds4 e4 d5 ds5 cs6)))
               (3 ((af2 f3 fs3 d4 e4 fs4 a4 d5 e5 c6 af6)))
               (4 ((b2 c3 df3 f3 af3 c4 e4 d5 c6)))
               (5 ((bf2 g3 e4 ef5 d6)))
               (6 ((f3 ef4 a4 d5 e5 df6)))
               (7 ((a2 b2 af3 f4 ef5 e5 c6)))
               (8 ((e4 a4 c5 g5 af5 e6)))
               (9 ((e4 df5 bf5)))
               (10 ((b1 a2 g3 e4 df5 a5)))
               (11 ((ef3 bf3 e4 b4 d5 f5 c6 ef6)))
               (12 ((f3 df4 e4 b4 e5 f5 c6 g6)))
               (13 ((e4 b4 df5)))
               (14 ((d4 ef4 bf4)))
               (15 ((df4 bf4 a5 fs6)))
               (16 ((d4 ef4 f4 g4)))
               (17 ((g1 bf1 fs2 af2 f3 fs3 e4)))
               (18 ((ef1 df2 b2 a3 e4 f4 fs4 d5 a5 bf5)))
               (19 ((e4 f4 g4 b4 c5 g5 af5 e6 f6)))
               (20 ((bf3 b3 e4 f4 bf4)))
               (21 ((e3 f3 df4 d4 ds4 f4 df5 d5 b5)))
               (22 ((d3 g3 a3 e4 af4 ef5 df5)))
               (23 ((g4 af4 df5 d5 af5 df6 d6)))
               (24 ((af3 e4 a4 e5 bf5)))
               (25 ((df2 a2 e3 ef4 d5 af5)))
               (26 ((b2 ef3 df4 e4 c5 g5 ef6)))
               (27 ((d1 a1 ef2 c3 a3 f4)))
               (28 ((df3 g3 c4 df4 d4 e4)))
               (29 ((c3 b3 e4 df5 b5)))
               (30 ((ds1 ef2 b2 c3 g3 af3 d4 e4 b4 fs5 d6)))
               (31 ((d1 ef2 a2 ef3 bf3 e4 d5 bf5 g6)))))
         ;; Creating the set-palette using the procession algorithm
         (sm (procession (num-rthm-seqs rch) (length sp)))
         ;; Determining the high and low pitches for each instrument for each
         ;; harmonic set. Every time the same set occurs, the same instruments
         ;; will have the same limits.
         (sls '((fl ((1 gs5 c7) (2 d5 c7) (3 e5 c7) (4 d5 c7) (5 ef5 c7) 
                     (6 e5 c7) (7 ef5 c7) (8 g5 c7) (9 df5 c7) (10 df5 c7) 
                     (11 d5 c7) (12 e5 c7) (13 df5 c7) (14 bf4 c7) (15 a5 c7) 
                     (16 g4 c7) (17 e4 c7) (18 d5 c7) (19 g5 c7) (20 bf4 c7) 
                     (21 df5 c7) (22 ef5 c7) (23 af5 c7) (24 e5 c7)
                     (25 d5 c7) (26 g5 c7) (27 f4 c7) (28 e4 c7) (29 df5 c7) 
                     (30 fs5 c7) (31 d5 c7)))
                (ob ((1 g4 a5) (2 g4 a5) (3 g4 a5) (4 g4 a5) (5 g4 a5) 
                     (6 g4 a5) (7 g4 a5) (8 g4 a5) (9 g4 a5) (10 g4 a5) 
                     (11 g4 a5) (12 g4 a5) (13 g4 a5) (14 g4 a5) (15 g4 a5) 
                     (16 g4 a5) (17 e4 a5) (18 g4 a5) (19 g4 a5) (20 g4 a5) 
                     (21 g4 a5) (22 g4 a5) (23 g4 a5) (24 g4 a5) (25 g4 a5)
                     (26 g4 a5) (27 f4 a5) (28 e4 a5) (29 g4 a5) (30 g4 a5) 
                     (31 g4 a5)))
                (cl ((1 b4 c6) (2 b4 c6) (3 b4 c6) (4 b4 c6) (5 b4 c6) 
                     (6 b4 c6) (7 b4 c6) (8 b4 c6) (9 b4 c6) (10 b4 c6) 
                     (11 b4 c6) (12 b4 c6) (13 b4 c6) (14 bf4 c6) (15 b4 c6) 
                     (16 g4 c6) (17 e4 c6) (18 b4 c6) (19 b4 c6) (20 bf4 c6) 
                     (21 b4 c6) (22 b4 c6) (23 b4 c6) (24 b4 c6) (25 b4 c6)
                     (26 b4 c6) (27 f4 c6) (28 e4 c6) (29 b4 c6) (30 b4 c6) 
                     (31 b4 c6)))
                (bn ((1 a2 d4) (2 a2 d4) (3 a2 d4) (4 a2 d4) (5 a2 d4) 
                     (6 a2 d4) (7 a2 d4) (8 a2 e4) (9 a2 e4) (10 a2 d4) 
                     (11 a2 d4) (12 a2 d4) (13 a2 e4) (14 a2 d4) (15 a2 d4) 
                     (16 a2 d4) (17 a2 d4) (18 a2 d4) (19 a2 e4) (20 a2 d4) 
                     (21 a2 d4) (22 a2 d4) (23 a2 g4) (24 a2 d4) (25 a2 d4)
                     (26 a2 d4) (27 a2 d4) (28 a2 d4) (29 a2 d4) (30 a2 d4) 
                     (31 a2 d4)))
                (vb ((1 c4 f6) (2 c4 f6) (3 c4 f6) (4 c4 f6) (5 c4 f6) 
                     (6 c4 f6) (7 c4 f6) (8 c4 f6) (9 c4 f6) (10 c4 f6) 
                     (11 c4 f6) (12 c4 f6) (13 c4 f6) (14 c4 f6) (15 c4 f6) 
                     (16 c4 f6) (17 c4 f6) (18 c4 f6) (19 c4 f6) (20 c4 f6) 
                     (21 c4 f6) (22 c4 f6) (23 c4 f6) (24 c4 f6) (25 c4 f6) 
                     (26 c4 f6) (27 c4 f6) (28 c4 f6) (29 c4 f6) (30 c4 f6) 
                     (31 c4 f6)))
                (pnr ((1 c4 c8) (2 c4 c8) (3 c4 c8) (4 c4 c8) (5 c4 c8) 
                      (6 c4 c8) (7 c4 c8) (8 g5 c8) (9 df5 c8) (10 c4 c8) 
                      (11 c4 c8) (12 c4 c8) (13 b4 c8) (14 ef4 c8) (15 a5 c8)
                      (16 f4 c8) (17 f3 c8) (18 c4 c8) (19 c5 c8) 
                      (20 e4 c8) (21 df5 c8) (22 c4 c8) (23 af5 c8) (24 a4 c8) 
                      (25 c4 c8) (26 c4 c8) (27 a3 c8) (28 c4 c8) (29 c4 c8) 
                      (30 c4 c8) (31 c4 c8)))
                (pnl ((1 a0 b3) (2 a0 b3) (3 a0 b3) (4 a0 b3) (5 a0 b3) 
                      (6 a0 b3) (7 a0 b3) (8 a0 c5) (9 a0 e4) (10 a0 b3) 
                      (11 a0 b3) (12 a0 b3) (13 a0 e4) (14 a0 d4) 
                      (15 a0 bf4) (16 a0 ef4) (17 a0 af2) (18 a0 b3) 
                      (19 a0 b4) (20 a0 b3) (21 a0 ds4) (22 a0 b3) (23 a0 d5)
                      (24 a0 e4) (25 a0 b3) (26 a0 b3) (27 a0 c3) (28 a0 b3) 
                      (29 a0 b3) (30 a0 b3) (31 a0 b3))) 
                (vn ((1 a4 c7) (2 a4 c7) (3 a4 c7) (4 a4 c7) (5 a4 c7) 
                     (6 a4 c7) (7 a4 c7) (8 a4 c7) (9 a4 c7) (10 a4 c7) 
                     (11 a4 c7) (12 a4 c7) (13 a4 c7) (14 a4 c7) (15 a4 c7) 
                     (16 f4 c7) (17 e4 c7) (18 a4 c7) (19 a4 c7) (20 f4 c7) 
                     (21 a4 c7) (22 a4 c7) (23 a4 c7) (24 a4 c7) (25 a4 c7) 
                     (26 a4 c7) (27 a3 c7) (28 d4 c7) (29 a4 c7) (30 a4 c7) 
                     (31 a4 c7)))
                (va ((1 g3 gs4) (2 g3 gs4) (3 g3 gs4) (4 g3 gs4) (5 g3 gs4) 
                     (6 g3 gs4) (7 g3 gs4) (8 g3 gs4) (9 g3 gs4) 
                     (10 g3 gs4) (11 g3 gs4) (12 g3 gs4) (13 g3 gs4)
                     (14 g3 gs4) (15 g3 gs4) (16 g3 gs4) (17 g3 gs4) 
                     (18 g3 gs4) (19 g3 gs4) (20 g3 gs4) (21 g3 gs4) 
                     (22 g3 gs4) (23 g3 gs4) (24 g3 gs4) (25 g3 gs4) 
                     (26 g3 gs4) (27 g3 gs4) (28 g3 gs4) (29 g3 gs4) 
                     (30 g3 gs4) (31 g3 gs4))) 
                (vc ((1 c2 fs3) (2 c2 fs3) (3 c2 fs3) (4 c2 fs3) (5 c2 fs3) 
                     (6 c2 fs3) (7 c2 fs3) (8 c2 e4) (9 c2 e4) 
                     (10 c2 fs3) (11 c2 fs3) (12 c2 fs3) (13 c2 e4)
                     (14 c2 d4) (15 c2 df4) (16 c2 d4) (17 c2 fs3) 
                     (18 c2 fs3) (19 c2 e4) (20 c2 b3) (21 c2 fs3) 
                     (22 c2 fs3) (23 c2 g4) (24 c2 af3) (25 c2 fs3) 
                     (26 c2 fs3) (27 c2 fs3) (28 c2 fs3) (29 c2 fs3) 
                     (30 c2 fs3) (31 c2 fs3)))))
         ;; Creating a list for just the low set-limits, with consecutive
         ;; integers as x-values so there are equal number of breakpoint pairs
         ;; as sets in the set-palette
         (sll (loop for p in sls
                 collect
                   (list (first p)
                         (loop for s in sm
                            for i from 1
                            collect i
                            collect (second (nth (1- s) (second p)))))))
         ;; Creating a list for just the high set-limits, with consecutive
         ;; integers as x-values so there are equal number of breakpoint pairs
         ;; as sets in the set-palette
         (slh (loop for p in sls
                 collect
                   (list (first p)
                         (loop for s in sm
                            for i from 1
                            collect i
                            collect (third (nth (1- s) (second p)))))))
         ;; Creating the sc object
         (reeling-trains
          (make-slippery-chicken
           '+reeling-trains+
           :title "reeling trains"
           :ensemble '(((fl (flute :midi-channel 1))
                        (ob (oboe :midi-channel 2))
                        (cl (b-flat-clarinet :midi-channel 3))
                        (bn (bassoon :midi-channel 4))
                        (vb (vibraphone :midi-channel 5))
                        (pnr (piano :midi-channel 6))
                        (pnl (piano-lh :midi-channel 7))
                        (vn (violin :midi-channel 8))
                        (va (viola :midi-channel 9))
                        (vc (cello :midi-channel 11))))
           :staff-groupings '(4 1 2 3)
           :set-palette sp
           :set-map `((1 ,sm))
           :set-limits-low sll 
           :set-limits-high slh
           :tempo-map '((1 (q 72)))
           ;; The rs palette and map can be taken directly from the rthm-chain
           ;; object. 
           :rthm-seq-palette (palette rch)
           :rthm-seq-map rch)))
    ;; add random dynamics
    (process-events-by-time reeling-trains #'place-dyns)
    ;; add random articulations
    (process-events-by-time reeling-trains #'place-arts)
    ;; remove repeated dynamics
    (remove-extraneous-dynamics reeling-trains)
    ;; remove specific marks
    (loop for pm in '((1 1 (cl bn vb pnr pnl vc) s) (2 1 vc ppp) 
                      (2 2 (vn vc) s) (2 3 vc ff) (3 1 va p) (3 2 (ob va) s) 
                      (3 2 vc fff) (5 3 ob f) (5 2 vn mf) (6 3 bn p) (8 4 ob s) 
                      (9 1 fl s) (12 1 vn s) (17 1 ob ff) (17 2 fl ppp)
                      (19 3 vc mf) (20 2 cl s) (26 2 vn s) (26 2 va p) 
                      (27 1 bn p) (27 2 va s) (28 3 ob ff) (35 1 vn s)
                      (38 2 bn fff) (42 2 vc f) (44 1 bn s) (47 2 ob mp)
                      (47 3 bn ppp) (51 1 pnr s) (53 1 (fl vb) s) 
                      (53 2 (vb vc) s) (53 2 pnl mf) (54 2 vn s) (58 1 vc pp) 
                      (61 1 bn s) (61 4 (ob pnr va) (mf fff ppp)) (62 1 ob s) 
                      (62 2 va s) (63 2 va s) (65 1 pnr s) (66 1 ob pp)
                      (66 3 ob s) (66 3 fl s) (70 2 fl mf) (72 1 va p) 
                      (73 2 vn s) (74 2 vn fff) (75 3 cl pp) (76 2 ob s)
                      (77 2 ob s) (85 1 bn s) (85 3 vb ff) (85 4 bn s)
                      (85 5 cl p) (85 5 bn a) (85 5 vc a) 
                      (86 3 (bn vc) (pp fff)) (86 4 vc s) (86 5 vb f) 
                      (87 2 ob s) (90 2 vb mf) (90 3 bn ff) (96 2 ob pp) 
                      (97 1 fl pp) (98 4 vn mf) (100 1 ob mf) (101 1 fl p)
                      (101 1 vn s) (101 2 vn p) (102 1 vn s) (103 1 ob s)
                      (103 1 vc mf) (105 1 vn s) (105 1 vb mp) (106 2 va fff)
                      (106 2 vc s) (106 3 vb s) (106 3 vn f) (106 5 vb ff)
                      (106 5 pnl ff) (106 5 vc p) (110 2 vn s) (110 3 va s)
                      (110 3 vn mp) (110 2 va ppp) (111 2 ob fff) 
                      (114 2 vn fff) (114 2 ob mp) (114 3 pnr ppp) 
                      (116 3 vb mp) (118 2 pnr s) (118 2 vn mf) (120 2 va s)
                      (120 2 cl pp) (120 3 pnr mp) (125 3 fl f) (125 3 va p)
                      (125 3 va mp) (131 2 vn mf) (132 1 fl mp) (134 1 va ppp)
                      (137 1 vn s) (137 2 fl fff) (138 2 pnr p) (139 1 va mp)
                      (139 3 vn p) (142 2 vn s) (143 1 vn f) (144 1 pnr ff)
                      (151 3 ob f) (153 1 bn s) (156 1 pnl s) (156 2 bn fff)
                      (156 3 vb pp) (156 3 pnl fff) (156 3 va f) (156 5 vc a)
                      (156 6 vb mf) (158 3 pnr ff) (163 2 fl p) (163 2 vn mp)
                      (163 3 ob fff) (166 1 (fl va) (p mf)) (166 2 ob p) 
                      (167 1 cl f) (169 3 ob mp) (170 2 vn mf) (172 3 pnr s)
                      (172 3 vn pp) (173 1 pnr s) (173 1 vb ff) (173 3 vn mp)
                      (175 4 pnr mf) (175 4 vn ff) (175 4 va p) (176 2 cl s)
                      (178 2 pnr pp) (178 2 va ff))
       do 
         (rm-marks-from-notes reeling-trains 
                              (first pm) 
                              (second pm) 
                              (third pm)
                              (fourth pm)))
    ;; add diminuendo marks
    (loop for pdcr in '((pnr 2 2 4 1) (pnl 2 4 4 1) (vn 2 2 2 3) (bn 5 1 5 2)
                        (bn 14 1 14 2) (fl 17 1 18 1) (ob 26 1 27 2) 
                        (fl 26 2 27 2) (ob 54 1 54 3) (vn 81 1 81 2) 
                        (ob 103 1 103 2) (bn 102 2 103 2) (vb 102 2 103 2) 
                        (va 107 1 107 2) (va 118 1 118 3) (va 169 1 169 3) 
                        (vn 172 2 172 4) (va 176 1 176 2)) 
       do
         (add-mark-to-note reeling-trains
                           (second pdcr)
                           (third pdcr)
                           (first pdcr)
                           'dim-beg)
         (add-mark-to-note reeling-trains
                           (fourth pdcr)
                           (fifth pdcr)
                           (first pdcr)
                           'dim-end))
    ;; add crescendo marks
    (loop for pdcr in '((va 2 2 4 3) (va 10 1 10 3) (cl 14 1 14 2) 
                        (va 17 2 18 1) (va 26 1 27 1) (fl 35 1 35 3) 
                        (ob 48 1 48 3) (vb 53 1 53 3) (pnl 54 1 54 2) 
                        (pnr 57 1 57 3) (fl 65 2 66 2) (bn 67 1 67 2) 
                        (va 66 3 67 1) (fl 77 3 78 1) (va 83 1 83 2) 
                        (fl 93 1 94 1) (va 93 2 94 1) (va 98 3 98 5) 
                        (pnr 106 1 106 3) (ob 110 1 110 3) (fl 142 2 143 2) 
                        (cl 145 1 145 3) (cl 164 1 164 2) (vb 170 1 170 2)
                        (vn 175 3 175 5) (vc 176 1 176 2))
       do
         (add-mark-to-note reeling-trains
                           (second pdcr)
                           (third pdcr)
                           (first pdcr)
                           'cresc-beg)
         (add-mark-to-note reeling-trains
                           (fourth pdcr)
                           (fifth pdcr)
                           (first pdcr)
                           'cresc-end))
    ;; consolidate sounding durations
    (map-over-bars reeling-trains 1 nil nil #'consolidate-notes)
    ;; make the first dynamic forte
    (loop for p in '(fl ob cl bn vb pnr pnl vn va vc)
       do
         (add-mark-to-note reeling-trains 1 1 p 'f))
    ;; auto-slur
    (auto-slur reeling-trains '(fl ob cl bn vb pnr pnl vn va vc) 
               :over-accents nil
               :rm-staccatos nil)
    ;; output
    (midi-play reeling-trains :midi-file "/tmp/reeling-trains.mid")
    (cmn-display reeling-trains 
                 :file "/tmp/reeling-trains.eps"
                 :size 14
                 :auto-clefs nil
                 :in-c t)
    (write-lp-data-for-all reeling-trains
                           :auto-clefs nil
                           :in-c t)))
        
      + Functions to auto-insert dynamics and articulation
The musical material for this piece is generated automatically by
          the algorithms associated with the rthm-chain class. The
          ultimate sequences of the given rhythm fragments will be influenced
          by the procession function as well as by values passed
          to the rthm-chain object's slots for controlling
          activity levels and the automatic insertion of rests and notes. For
          this reason, the final outcome will be rather difficult to predict,
          and the smallest changes to any of those parameters may result in
          very different content.
Correspondingly, this demo composition uses a post-generation data
          editing method called process-events-by-time in
          conjunction with two user-defined functions to automatically place
          dynamics and articulation into the score after the notes,
          rests, and rhythms have all be generated.
process-events-by-time
The process-events-by-time method will be covered in
          more detail below, but its basic function is described here briefly
          as a background to the first two functions defined in the code for
          the piece. 
The method essentially takes two arguments: The
          slippery-chicken object to process, and a
          function that modifies individual events. It then passes through the
          events of the generated piece in absolute chronological order,
          regardless of the player, and applies the specified function to every
          event in chronological sequence.
place-dyns and place-arts
The two user-defined functions
        here, place-dyns and place-arts, are
        essentially the same except for the marks they apply. They use
        fixed-seed random processes to select articulation and dynamic marks.
        They each first test to see if the current event object is
        at the beginning of the piece by checking to see if its
        start-time slot is 0.0. If it is, they call
        the random-rep function once with the optional argument
        T to reset the random state of the current Lisp
        environment. This ensures that the exact same pseudo-random series of
        marks are chosen for the same notes each time the piece is generated
        within that Lisp.
The functions then test to see whether the
          current event object is a rest or not. If not, they
          choose a random number between 0 and 99, and if that number is
          greater than 67 (i.e. roughly a third of the time), they replace
          the marks slot of that event object with a
          random mark from a specified list of marks. In the first function,
          these marks are all dynamics, and in the second they are articulation
          (either an accent or a staccato). 
Both functions use 
          slippery chicken's random-rep function again to
          choose the mark, by pseudo-randomly selecting the position within the
          list for the mark to be added. The articulation function includes an
          additional degree of sparsity in its placement of marks, in that it
          chooses a random number between 0 and 4 for the index position,
          although there are only two marks in the given list.
;; A function to place dynamics on random notes in the score
(defun place-dyns (event)
  (when (equalp (start-time event) 0.0)
    (random-rep 10 t))
  (unless (is-rest event)
    (when (> (random-rep 100) 67)
      (setf (marks event) 
            (list (nth (random-rep 8) '(ppp pp p mp mf f ff fff)))))))
;; A function to place articulations (accent or staccato) on random notes in
;; the score
(defun place-arts (event)
  (when (equalp (start-time event) 0.0)
    (random-rep 10 t))
  (unless (is-rest event)
    (when (> (random-rep 100) 67)
      (setf (marks event) 
            (list (nth (random-rep 5) '(a s)))))))
        These two functions are defined first, outside of the scope of the rest of the code, as they are called within the primary block of code that follows.
+ Adjusting the chord functions
The next two loops in the the code for this piece adjust the chord
          functions for the instrument objects which the piece is
          to use.
Turning off double-stop capability in the strings
By default, the violin, viola,
          and cello instruments of
          the +slippery-chicken-standard-instrument-palette+ are
          set to be chord-capable. This allows double-stops to be incorporated
          into pieces where chords are indicated. For this piece, the strings
          are to play single notes only, so the first loop changes
          the chords slot of the
          corresponding instrument objects
          to NIL. 
;; Disabling the chord function on the string instruments (no double-stops) 
(loop for i in '(violin viola cello)
     do
     (set-slot 'chords
               nil
               i
               +slippery-chicken-standard-instrument-palette+))
        
        Changing the default chord function for the piano parts
The default chord function for the piano
          and piano-lh instruments of
          the +slippery-chicken-standard-instrument-palette+
          attempts to create four-note chords from consecutive pitches in the
          current set. Since the pitch sets used in this piece contain
          consecutive pitches that are minor and major seconds apart, this
          default function would potentially create four-note clusters in the
          resulting piano parts.
To avoid the creation of such clusters, this piece sets
          the chord-function slots of the
          corresponding piano and piano-lh
          instruments to chord-fun1, which attempts to create only
          three-note chords from every second pitch in the set.
;; Changing the chord function for the piano instruments
(loop for i in '(piano piano-lh)
   do
     (set-slot 'chord-function
               'chord-fun1
               i
               +slippery-chicken-standard-instrument-palette+))
        
      + Defining the rhythm fragments
The next section in the code for this piece consists of the
          definition of the 1-beat, 2-beat, and 3-beat rhythmic fragments that
          are to serve as the source material for the resulting
          composition. Each of these lists will be used implicitly in
          conjunction with the procession algorithm to generate
          the chains of rhythms for the piece (see the rhythm chains page for more
          detail).
Each group also includes at least two transition sublists as well. This will result in a fibonacci-based transition from the initial fragments to the final fragments in each group over the course of the piece (again, see the rhythm chains page).
(let* ((num-seqs 137) ; The number of sequences in the rthm-chain to be made
       ;; Defining the rthm-chain object
       (rch
        (make-rthm-chain
         'test-rch 
         num-seqs
         '((((e) e) ; the 1-beat fragments: 4 in total
            (- s (s) (s) s -)
            ({ 3 (te) - te te - })
            ((e.) s))
           (({ 3 (te) te (te) }) ; what we transition to
            ({ 3 - te (te) te - })
            ({ 3 (te) - te te - })
            ({ 3 (te) (te) te }))
           (((q)) ; the second transition
            (- s e s -)
            ({ 3 te (tq) })
            (s (e.)))
           ((- e e -) ; the third transition
            (- s s s - (s))
            ((32) 32 (e.))
            ((q))))
         '((((q q) ; the 2/4 bars: 4 total
             ((q) q)
             ((q) q)
             ((q) (s) e.))
            (({ 3 te te +te te +te te }) ; what we transition to
             (q - s e. -)
             (q (s) e.)
             (q (s) - s e -))
            ((q - +e e -) ; the second transition
             ((e) e +e e)
             (q - s (e) s -)
             ((s) e. +s e.)))
           ((((e.) s (e) e (s) e.) ; the 3/4 bars: 4 total
             (- e e - (e) e (q))
             (- e. s - - +e e - (q))
             (q (e.) s (q)))
            (({ 3 (te) (te) te +te te +te } (q)) ; what we transition to
             (- e. s - (q) (s) - s e -)
             ({ 3 te te +te } (q) q)
             ({ 3 - te +te te - } (e) e { 3 (te) (te) te }))
            ((q +q +q) ; the second transition
             (q +q (q))
             (- e e - +q (q))
             (s (e.) (q) (q)))))
        num-seqs
The second argument to the make-rthm-chain function
          called above is passed the variable num-seqs, which is
          defined as 137 in the first line of
          this let* enclosure. This simple variable allows for
          the quick-and-easy modification of the length of the piece generated
          through the modification of just one number.
+ Setting activity and auto-insertion of rests and rhythms
The rthm-chain class has numerous slots whose values
          influence the final sequences of the musical material generated. Most
          of these are also made conveniently accessible through keyword
          arguments to the make-rthm-chain function. A number of
          these will be looked at here briefly. For a complete list, see the
          source code documentation
          for rthm-chain. More
          information on curves (envelopes) can be found on
          the envelopes page.
activity-curve
The activity-curve slot takes a list of breakpoint
          pairs to define how active the instruments are over the course of the
          piece. As with other slippery chicken curves, the x-values
          of the activity-curve can span any arbitrary
          (increasing) range, which will then be scaled to the duration of the
          entire piece.
The y-values for this curve must be between 1 and
          10, and these values indicate the amount of overall
          activity at that given point in the piece. A value of 10
          indicates that all beats generated for the rthm-chain
          object will consist of sounding notes, while a value of
          1 indicates that only 1 in 10 beats will have sounding
          notes, with the remainder being rests. This algorithm is
          deterministic, not stochastic, so the results will be the same each
          time the piece is re-generated.
The activity curve for the rthm-chain object in this
          piece varies between 3 and 10 over the
          course of the piece:
         ;; The proportion of rests to sounding notes in each passage
         :activity-curve '(0 5 20 7 30 8 50 3 70 5 80 8 100 10)
        rests
The rests slot of the rthm-chain object
          takes a list of rhythms from which the durations will be selected
          when applying the automatic rest-insertion algorithm. This list
          defaults to (e q q. w), but has been specified as
          follows for this piece, so as to result in shorter rests being
          inserted than is default:
         ;; The durations to be used for the inserted rests
         :rests '(s e s q)
        The order in which specific durations are chosen for insertion is
          based on the rest-cycle slot. More on
          the rest-cycle and other rest-related slots can be found
          in
          the rthm-chain
          source code documentation.
sticking-rthms
In addition to automatically inserting rests,
          the rthm-chain class also automatically inserts
          so-called sticking-rhythms. These are notes of specified
          durations that are inserted at various points throughout the piece
          (always after rests), according to predefined curves, and
          repeated in a broken-record manner. The default sticking rhythms are
          (e e e. q e s), but these have been changed to the
          following for this piece, so as to incur a greater number of
          sustained durations over the course of the composition:
         ;; The durations to be used for the inserted rhythms
         :sticking-rthms '(e h e. w s e h s)
        sticking-curve
Similar to the activity-curve, the
          sticking-curve slot acts as an activity envelope to
          control the degree of repetition when inserting sticking
          rhythms. 
         ;; The activity-curve for the sticking rhythms
         :sticking-curve '(0 2 20 3 30 5 50 8 80 10 100 2)
        sticking-repeats
The sticking-repeats slot takes a list of integers that
          indicate the number of repetitions applied in sticking segments. When
          the values of this list have been exhausted, the method cycles to the
          beginning and continues drawing from the head of the list again.
         ;; The number of times each sticking rhythm is repeated
         :sticking-repeats '(3 5 3 5 8)
        harmonic-rthm-curve
The general speed of harmonic motion in the resulting piece can be
          influenced by defining a harmonic-rthm-curve. This curve
          determines how many slower (2-beat and 3-beat) rhythm fragments are
          combined into one rthm-seq (each rthm-seq
          in a slippery-chicken object takes only one set of
          pitches).  
         ;; The number of consecutive sequences that have the same
         ;; harmonic set
         :harmonic-rthm-curve '(0 1 10 2 30 3 40 1 50 2 80 4 90 5 100 1)
        split-data
The split-data slot allows the user to set target
          values for the minimum and maximum number of beats in the bars
          generated for the resulting piece. These values are targets only; the
          method may create bars of different lengths if the data generated
          cannot be otherwise split. The values given here will apply to a
          different beat basis depending on the time signature of each bar,
          rather than on a consistent beat basis. The default value is
          (2 5), but has been changed for this piece to avoid
          very short bars:
         ;; The min and max beat duration of bars generated; beat taken from
         ;; the given time signature.
         :split-data '(4 7)
        
      + Setting up the players and adding voices
The last slot of the rthm-chain object that is
          explicitly set for this piece is the players
          slot. The rthm-chain class initially generates music
          data with only two voices, and these two voices must be assigned
          player IDs that correspond to the players in
          the ensemble slot of the
          associated slippery-chicken object.
         ;; The IDs for the original two players
         :players '(fl cl))))
        add-voice
The add-voice method allows the user to automatically
          expand the content of the rthm-chain object generated to
          include further voices. Each new voice is based on sequences drawn
          from one of the original two voices in the
          initial rthm-chain object, and must be assigned a player
          ID. An additional integer can be passed to the method to indicate a
          specific offset of the sequences chosen. More on this method can be
          found on the rhythm chains manual
          page. 
;; Adding new voices based on the content of the original two, these with ;; offsets however to avoid completely identical voices. (add-voice rch '(1 fl) 'ob 1) (add-voice rch '(1 cl) 'bn 1) (add-voice rch '(1 fl) 'pnr 2) (add-voice rch '(1 cl) 'pnl 2) (add-voice rch '(1 fl) 'vn 3) (add-voice rch '(1 fl) 'va 4) (add-voice rch '(1 cl) 'vc 3) (add-voice rch '(1 cl) 'vb 4)
The IDs specified in the above slot and method correspond to
          the ensemble slot of the
          subsequent slippery-chicken object, as can be seen
          here:
           :ensemble '(((fl (flute :midi-channel 1))
                        (ob (oboe :midi-channel 2))
                        (cl (b-flat-clarinet :midi-channel 3))
                        (bn (bassoon :midi-channel 4))
                        (vb (vibraphone :midi-channel 5))
                        (pnr (piano :midi-channel 6))
                        (pnl (piano-lh :midi-channel 7))
                        (vn (violin :midi-channel 8))
                        (va (viola :midi-channel 9))
                        (vc (cello :midi-channel 11))))
        
      + Automatic pitch-seq-palettes
The rthm-chain object contains an automatically
          generated palette of rthm-seq objects and
          a rthm-seq-map. The rthm-seq objects must
          have curves assigned to them for their melodic contours
          (pitch-seqs), and these can be automatically generated
          for all rthm-seqs in a rthm-chain using
          the create-psps method, which takes
          a rthm-seq-palette object as its only required
          argument. The rthm-seq-palette for a
          given rthm-chain object can be accessed using
          the palette accessor keyword.
;; Creating automatically generated pitch-seq palettes for the rthm-seqs made (create-psps (palette rch))
+ The set-palette and the set-map
The set-palette and the set-map for this
          piece are defined as variables prior to the call
          to make-slippery-chicken. 
set-palette
The set-palette consists of 31 pitch collections with
          consecutive numerical IDs from 1
          to 31. 
  (let* ((sp '((1 ((c3 cs3 d3 e3 fs3 g3 c4 cs4 e4 c5 gs5 cs6 d6
                       ds6))) 
               (2 ((b2 c3 fs3 gs3 ds4 e4 d5 ds5 cs6)))
               (3 ((af2 f3 fs3 d4 e4 fs4 a4 d5 e5 c6 af6)))
               (4 ((b2 c3 df3 f3 af3 c4 e4 d5 c6)))
               (5 ((bf2 g3 e4 ef5 d6)))
               (6 ((f3 ef4 a4 d5 e5 df6)))
               (7 ((a2 b2 af3 f4 ef5 e5 c6)))
               (8 ((e4 a4 c5 g5 af5 e6)))
               (9 ((e4 df5 bf5)))
               (10 ((b1 a2 g3 e4 df5 a5)))
               (11 ((ef3 bf3 e4 b4 d5 f5 c6 ef6)))
               (12 ((f3 df4 e4 b4 e5 f5 c6 g6)))
               (13 ((e4 b4 df5)))
               (14 ((d4 ef4 bf4)))
               (15 ((df4 bf4 a5 fs6)))
               (16 ((d4 ef4 f4 g4)))
               (17 ((g1 bf1 fs2 af2 f3 fs3 e4)))
               (18 ((ef1 df2 b2 a3 e4 f4 fs4 d5 a5 bf5)))
               (19 ((e4 f4 g4 b4 c5 g5 af5 e6 f6)))
               (20 ((bf3 b3 e4 f4 bf4)))
               (21 ((e3 f3 df4 d4 ds4 f4 df5 d5 b5)))
               (22 ((d3 g3 a3 e4 af4 ef5 df5)))
               (23 ((g4 af4 df5 d5 af5 df6 d6)))
               (24 ((af3 e4 a4 e5 bf5)))
               (25 ((df2 a2 e3 ef4 d5 af5)))
               (26 ((b2 ef3 df4 e4 c5 g5 ef6)))
               (27 ((d1 a1 ef2 c3 a3 f4)))
               (28 ((df3 g3 c4 df4 d4 e4)))
               (29 ((c3 b3 e4 df5 b5)))
               (30 ((ds1 ef2 b2 c3 g3 af3 d4 e4 b4 fs5 d6)))
               (31 ((d1 ef2 a2 ef3 bf3 e4 d5 bf5 g6)))))
        set-map
The set-map is automatically generated using
          the rthm-chain class's procession
          function. It accesses the num-rthm-seqs slot of the
          given rthm-chain object to obtain the number of items
          that need to be in that map (one for each rthm-seq), and
          uses the length of the variable sp
          (the set-palette defined above) as its second argument,
          thereby determining that it is to create its output from a list of
          elements consisting of integers 1
          to 31.
         ;; Creating the set-palette using the procession algorithm
         (sm (procession (num-rthm-seqs rch) (length sp)))
        These two variables will be passed directly to
          the :set-palette and :set-map keyword
          arguments of the make-slippery-chicken function. 
+ Set-limits for each instrument and each set
The next three variables determine the set-limits-high
          and set-limits-low envelopes for each player in the
          piece. Usually these limits would be specified explicitly with an
        envelope but here we use another mechanism for expressing this data
          which seems more appropriate to the piece in hand. Essentially we use
          the set-map to create the envelope, ensuring that when
          a specific set occurs then the upper and lower pitches for each
          player are drawn from our hand-typed data.
The sls variable consists of a list of the player IDs
          paired with lists of 3-item sublists, each of those consisting of an
          integer and two note-name symbols. The integers refer to pitch sets
          in the set-palette, and the two pitches represent the
          lowest and highest pitches to be played by the given player whenever
          that set occurs in the piece. There is one sublist for each set for
          each player.
         ;; Determining the high and low pitches for each instrument for each
         ;; harmonic set. Every time the same set occurs, the same instruments
         ;; will have the same limits.
         (sls '((fl ((1 gs5 c7) (2 d5 c7) (3 e5 c7) (4 d5 c7) (5 ef5 c7) 
                     (6 e5 c7) (7 ef5 c7) (8 g5 c7) (9 df5 c7) (10 df5 c7) 
                     (11 d5 c7) (12 e5 c7) (13 df5 c7) (14 bf4 c7) (15 a5 c7) 
                     (16 g4 c7) (17 e4 c7) (18 d5 c7) (19 g5 c7) (20 bf4 c7) 
                     (21 df5 c7) (22 ef5 c7) (23 af5 c7) (24 e5 c7)
                     (25 d5 c7) (26 g5 c7) (27 f4 c7) (28 e4 c7) (29 df5 c7) 
                     (30 fs5 c7) (31 d5 c7)))
                (ob ((1 g4 a5) (2 g4 a5) (3 g4 a5) (4 g4 a5) (5 g4 a5) 
                     (6 g4 a5) (7 g4 a5) (8 g4 a5) (9 g4 a5) (10 g4 a5) 
                     (11 g4 a5) (12 g4 a5) (13 g4 a5) (14 g4 a5) (15 g4 a5) 
                     (16 g4 a5) (17 e4 a5) (18 g4 a5) (19 g4 a5) (20 g4 a5) 
                     (21 g4 a5) (22 g4 a5) (23 g4 a5) (24 g4 a5) (25 g4 a5)
                     (26 g4 a5) (27 f4 a5) (28 e4 a5) (29 g4 a5) (30 g4 a5) 
                     (31 g4 a5)))
                (cl ((1 b4 c6) (2 b4 c6) (3 b4 c6) (4 b4 c6) (5 b4 c6) 
                     (6 b4 c6) (7 b4 c6) (8 b4 c6) (9 b4 c6) (10 b4 c6) 
                     (11 b4 c6) (12 b4 c6) (13 b4 c6) (14 bf4 c6) (15 b4 c6) 
                     (16 g4 c6) (17 e4 c6) (18 b4 c6) (19 b4 c6) (20 bf4 c6) 
                     (21 b4 c6) (22 b4 c6) (23 b4 c6) (24 b4 c6) (25 b4 c6)
                     (26 b4 c6) (27 f4 c6) (28 e4 c6) (29 b4 c6) (30 b4 c6) 
                     (31 b4 c6)))
                (bn ((1 a2 d4) (2 a2 d4) (3 a2 d4) (4 a2 d4) (5 a2 d4) 
                     (6 a2 d4) (7 a2 d4) (8 a2 e4) (9 a2 e4) (10 a2 d4) 
                     (11 a2 d4) (12 a2 d4) (13 a2 e4) (14 a2 d4) (15 a2 d4) 
                     (16 a2 d4) (17 a2 d4) (18 a2 d4) (19 a2 e4) (20 a2 d4) 
                     (21 a2 d4) (22 a2 d4) (23 a2 g4) (24 a2 d4) (25 a2 d4)
                     (26 a2 d4) (27 a2 d4) (28 a2 d4) (29 a2 d4) (30 a2 d4) 
                     (31 a2 d4)))
                (vb ((1 c4 f6) (2 c4 f6) (3 c4 f6) (4 c4 f6) (5 c4 f6) 
                     (6 c4 f6) (7 c4 f6) (8 c4 f6) (9 c4 f6) (10 c4 f6) 
                     (11 c4 f6) (12 c4 f6) (13 c4 f6) (14 c4 f6) (15 c4 f6) 
                     (16 c4 f6) (17 c4 f6) (18 c4 f6) (19 c4 f6) (20 c4 f6) 
                     (21 c4 f6) (22 c4 f6) (23 c4 f6) (24 c4 f6) (25 c4 f6) 
                     (26 c4 f6) (27 c4 f6) (28 c4 f6) (29 c4 f6) (30 c4 f6) 
                     (31 c4 f6)))
                (pnr ((1 c4 c8) (2 c4 c8) (3 c4 c8) (4 c4 c8) (5 c4 c8) 
                      (6 c4 c8) (7 c4 c8) (8 g5 c8) (9 df5 c8) (10 c4 c8) 
                      (11 c4 c8) (12 c4 c8) (13 b4 c8) (14 ef4 c8) (15 a5 c8)
                      (16 f4 c8) (17 f3 c8) (18 c4 c8) (19 c5 c8) 
                      (20 e4 c8) (21 df5 c8) (22 c4 c8) (23 af5 c8) (24 a4 c8) 
                      (25 c4 c8) (26 c4 c8) (27 a3 c8) (28 c4 c8) (29 c4 c8) 
                      (30 c4 c8) (31 c4 c8)))
                (pnl ((1 a0 b3) (2 a0 b3) (3 a0 b3) (4 a0 b3) (5 a0 b3) 
                      (6 a0 b3) (7 a0 b3) (8 a0 c5) (9 a0 e4) (10 a0 b3) 
                      (11 a0 b3) (12 a0 b3) (13 a0 e4) (14 a0 d4) 
                      (15 a0 bf4) (16 a0 ef4) (17 a0 af2) (18 a0 b3) 
                      (19 a0 b4) (20 a0 b3) (21 a0 ds4) (22 a0 b3) (23 a0 d5)
                      (24 a0 e4) (25 a0 b3) (26 a0 b3) (27 a0 c3) (28 a0 b3) 
                      (29 a0 b3) (30 a0 b3) (31 a0 b3))) 
                (vn ((1 a4 c7) (2 a4 c7) (3 a4 c7) (4 a4 c7) (5 a4 c7) 
                     (6 a4 c7) (7 a4 c7) (8 a4 c7) (9 a4 c7) (10 a4 c7) 
                     (11 a4 c7) (12 a4 c7) (13 a4 c7) (14 a4 c7) (15 a4 c7) 
                     (16 f4 c7) (17 e4 c7) (18 a4 c7) (19 a4 c7) (20 f4 c7) 
                     (21 a4 c7) (22 a4 c7) (23 a4 c7) (24 a4 c7) (25 a4 c7) 
                     (26 a4 c7) (27 a3 c7) (28 d4 c7) (29 a4 c7) (30 a4 c7) 
                     (31 a4 c7)))
                (va ((1 g3 gs4) (2 g3 gs4) (3 g3 gs4) (4 g3 gs4) (5 g3 gs4) 
                     (6 g3 gs4) (7 g3 gs4) (8 g3 gs4) (9 g3 gs4) 
                     (10 g3 gs4) (11 g3 gs4) (12 g3 gs4) (13 g3 gs4)
                     (14 g3 gs4) (15 g3 gs4) (16 g3 gs4) (17 g3 gs4) 
                     (18 g3 gs4) (19 g3 gs4) (20 g3 gs4) (21 g3 gs4) 
                     (22 g3 gs4) (23 g3 gs4) (24 g3 gs4) (25 g3 gs4) 
                     (26 g3 gs4) (27 g3 gs4) (28 g3 gs4) (29 g3 gs4) 
                     (30 g3 gs4) (31 g3 gs4))) 
                (vc ((1 c2 fs3) (2 c2 fs3) (3 c2 fs3) (4 c2 fs3) (5 c2 fs3) 
                     (6 c2 fs3) (7 c2 fs3) (8 c2 e4) (9 c2 e4) 
                     (10 c2 fs3) (11 c2 fs3) (12 c2 fs3) (13 c2 e4)
                     (14 c2 d4) (15 c2 df4) (16 c2 d4) (17 c2 fs3) 
                     (18 c2 fs3) (19 c2 e4) (20 c2 b3) (21 c2 fs3) 
                     (22 c2 fs3) (23 c2 g4) (24 c2 af3) (25 c2 fs3) 
                     (26 c2 fs3) (27 c2 fs3) (28 c2 fs3) (29 c2 fs3) 
                     (30 c2 fs3) (31 c2 fs3)))))
        Separating low from high
The two individual set-limits-low
          and set-limits-high lists are then collected using
          loops:
         ;; Creating a list for just the low set-limits, with consecutive
         ;; integers as x-values so there are equal number of breakpoint pairs
         ;; as sets in the set-palette
         (sll (loop for p in sls
                 collect
                   (list (first p)
                         (loop for s in sm
                            for i from 1
                            collect i
                            collect (second (nth (1- s) (second p)))))))
         ;; Creating a list for just the high set-limits, with consecutive
         ;; integers as x-values so there are equal number of breakpoint pairs
         ;; as sets in the set-palette
         (slh (loop for p in sls
                 collect
                   (list (first p)
                         (loop for s in sm
                            for i from 1
                            collect i
                            collect (third (nth (1- s) (second p)))))))
        These will be passed directly to the corresponding keyword
          arguments within the make-slippery-chicken
          function.
+ The call to make-slippery-chicken
With all of these variables declared, the call to
          the make-slippery-chicken function remains quite
          sleek. Only the global variable, title, ensemble, staff groups, and
          tempo must be specified explicitly; the remaining keyword arguments
          can be passed the variables declared above. 
         ;; Creating the sc object
         (reeling-trains
          (make-slippery-chicken
           '+reeling-trains+
           :title "reeling trains"
           :ensemble '(((fl (flute :midi-channel 1))
                        (ob (oboe :midi-channel 2))
                        (cl (b-flat-clarinet :midi-channel 3))
                        (bn (bassoon :midi-channel 4))
                        (vb (vibraphone :midi-channel 5))
                        (pnr (piano :midi-channel 6))
                        (pnl (piano-lh :midi-channel 7))
                        (vn (violin :midi-channel 8))
                        (va (viola :midi-channel 9))
                        (vc (cello :midi-channel 11))))
           :staff-groupings '(4 1 2 3)
           :set-palette sp
           :set-map `((1 ,sm))
           :set-limits-low sll 
           :set-limits-high slh
           :tempo-map '((1 (q 72)))
           ;; The rs palette and map can be taken directly from the rthm-chain
           ;; object. 
           :rthm-seq-palette (palette rch)
           :rthm-seq-map rch)))
        
      + Post-generation placement and editing of marks
With the pitch and rhythm data now generated and stored in
          a slippery-chicken object, the next few post-generating
          editing entries are used to apply and manipulate marks in the
          piece. 
process-events-by-time
As mentioned above, the process-events-by-time method
          is used here to randomly place dynamics and articulations into the
          score. The method takes as its two required arguments the name of
          the slippery-chicken object to be processed, and the
          name of the function to apply to each event in that object. It is
          called here once with the place-dyns function, and once
          with the place-arts function, both defined above. 
    ;; add random dynamics
    (process-events-by-time reeling-trains #'place-dyns)
    ;; add random articulations
    (process-events-by-time reeling-trains #'place-arts)
        remove-extraneous-dynamics
One possible side-effect of placing marks randomly is that the score
          may then contain two or more identical dynamics in sequence in the
          same part. The remove-extraneous-dynamics method
          resolves this by deleting all consecutive repetitions of a given
          dynamic in the same part.
    ;; remove repeated dynamics
    (remove-extraneous-dynamics reeling-trains)
        rm-marks-from-notes
If the user is not completely satisfied with some of the randomly
          placed marks, the rm-marks-from-notes method can be used
          to remove specific marks from specific notes, as is done here.
Since the two user-defined functions for random marks placement use
          the random-rep function and reset the random state each
          time, the marks placed, though random, will be identical each time
          the piece is generated in the same Lisp environment. This allows the
          user to create a list of bar numbers, note numbers, players, and
          marks for specific dynamics and articulations to be removed from the
          score. In this piece, this list is then passed to
          the rm-marks-from-notes method, using
          the first, second, third,
          and fourth functions to retrieve the values for its
          arguments from that list. 
    ;; remove specific marks
    (loop for pm in '((1 1 (cl bn vb pnr pnl vc) s) (2 1 vc ppp) 
                      (2 2 (vn vc) s) (2 3 vc ff) (3 1 va p) (3 2 (ob va) s) 
                      (3 2 vc fff) (5 3 ob f) (5 2 vn mf) (6 3 bn p) (8 4 ob s) 
                      (9 1 fl s) (12 1 vn s) (17 1 ob ff) (17 2 fl ppp)
                      (19 3 vc mf) (20 2 cl s) (26 2 vn s) (26 2 va p) 
                      (27 1 bn p) (27 2 va s) (28 3 ob ff) (35 1 vn s)
                      (38 2 bn fff) (42 2 vc f) (44 1 bn s) (47 2 ob mp)
                      (47 3 bn ppp) (51 1 pnr s) (53 1 (fl vb) s) 
                      (53 2 (vb vc) s) (53 2 pnl mf) (54 2 vn s) (58 1 vc pp) 
                      (61 1 bn s) (61 4 (ob pnr va) (mf fff ppp)) (62 1 ob s) 
                      (62 2 va s) (63 2 va s) (65 1 pnr s) (66 1 ob pp)
                      (66 3 ob s) (66 3 fl s) (70 2 fl mf) (72 1 va p) 
                      (73 2 vn s) (74 2 vn fff) (75 3 cl pp) (76 2 ob s)
                      (77 2 ob s) (85 1 bn s) (85 3 vb ff) (85 4 bn s)
                      (85 5 cl p) (85 5 bn a) (85 5 vc a) 
                      (86 3 (bn vc) (pp fff)) (86 4 vc s) (86 5 vb f) 
                      (87 2 ob s) (90 2 vb mf) (90 3 bn ff) (96 2 ob pp) 
                      (97 1 fl pp) (98 4 vn mf) (100 1 ob mf) (101 1 fl p)
                      (101 1 vn s) (101 2 vn p) (102 1 vn s) (103 1 ob s)
                      (103 1 vc mf) (105 1 vn s) (105 1 vb mp) (106 2 va fff)
                      (106 2 vc s) (106 3 vb s) (106 3 vn f) (106 5 vb ff)
                      (106 5 pnl ff) (106 5 vc p) (110 2 vn s) (110 3 va s)
                      (110 3 vn mp) (110 2 va ppp) (111 2 ob fff) 
                      (114 2 vn fff) (114 2 ob mp) (114 3 pnr ppp) 
                      (116 3 vb mp) (118 2 pnr s) (118 2 vn mf) (120 2 va s)
                      (120 2 cl pp) (120 3 pnr mp) (125 3 fl f) (125 3 va p)
                      (125 3 va mp) (131 2 vn mf) (132 1 fl mp) (134 1 va ppp)
                      (137 1 vn s) (137 2 fl fff) (138 2 pnr p) (139 1 va mp)
                      (139 3 vn p) (142 2 vn s) (143 1 vn f) (144 1 pnr ff)
                      (151 3 ob f) (153 1 bn s) (156 1 pnl s) (156 2 bn fff)
                      (156 3 vb pp) (156 3 pnl fff) (156 3 va f) (156 5 vc a)
                      (156 6 vb mf) (158 3 pnr ff) (163 2 fl p) (163 2 vn mp)
                      (163 3 ob fff) (166 1 (fl va) (p mf)) (166 2 ob p) 
                      (167 1 cl f) (169 3 ob mp) (170 2 vn mf) (172 3 pnr s)
                      (172 3 vn pp) (173 1 pnr s) (173 1 vb ff) (173 3 vn mp)
                      (175 4 pnr mf) (175 4 vn ff) (175 4 va p) (176 2 cl s)
                      (178 2 pnr pp) (178 2 va ff))
       do 
         (rm-marks-from-notes reeling-trains 
                              (first pm) 
                              (second pm) 
                              (third pm)
                              (fourth pm)))
        Adding diminuendos and crescendos
Two more loops are used in a similar manner to add diminuendo and
          crescendo marks to the score. The lists created specify the player
          ID, the bar and note numbers where the mark is to begin, and the bar
          and note numbers where the mark is to end. These are then passed to
          the add-mark-to-note method in conjunction with
          the dim-beg/cresc-beg
          and dim-end/cresc-end marks to insert
          those marks into the score.
    ;; add diminuendo marks
    (loop for pdcr in '((pnr 2 2 4 1) (pnl 2 4 4 1) (vn 2 2 2 3) (bn 5 1 5 2)
                        (bn 14 1 14 2) (fl 17 1 18 1) (ob 26 1 27 2) 
                        (fl 26 2 27 2) (ob 54 1 54 3) (vn 81 1 81 2) 
                        (ob 103 1 103 2) (bn 102 2 103 2) (vb 102 2 103 2) 
                        (va 107 1 107 2) (va 118 1 118 3) (va 169 1 169 3) 
                        (vn 172 2 172 4) (va 176 1 176 2)) 
       do
         (add-mark-to-note reeling-trains
                           (second pdcr)
                           (third pdcr)
                           (first pdcr)
                           'dim-beg)
         (add-mark-to-note reeling-trains
                           (fourth pdcr)
                           (fifth pdcr)
                           (first pdcr)
                           'dim-end))
    ;; add crescendo marks
    (loop for pdcr in '((va 2 2 4 3) (va 10 1 10 3) (cl 14 1 14 2) 
                        (va 17 2 18 1) (va 26 1 27 1) (fl 35 1 35 3) 
                        (ob 48 1 48 3) (vb 53 1 53 3) (pnl 54 1 54 2) 
                        (pnr 57 1 57 3) (fl 65 2 66 2) (bn 67 1 67 2) 
                        (va 66 3 67 1) (fl 77 3 78 1) (va 83 1 83 2) 
                        (fl 93 1 94 1) (va 93 2 94 1) (va 98 3 98 5) 
                        (pnr 106 1 106 3) (ob 110 1 110 3) (fl 142 2 143 2) 
                        (cl 145 1 145 3) (cl 164 1 164 2) (vb 170 1 170 2)
                        (vn 175 3 175 5) (vc 176 1 176 2))
       do
         (add-mark-to-note reeling-trains
                           (second pdcr)
                           (third pdcr)
                           (first pdcr)
                           'cresc-beg)
         (add-mark-to-note reeling-trains
                           (fourth pdcr)
                           (fifth pdcr)
                           (first pdcr)
                           'cresc-end))
        One starting dynamic for all parts
A final dynamic is added to the first note of all players' parts to produce an initial dynamic for all players in the piece:
    ;; make the first dynamic forte
    (loop for p in '(fl ob cl bn vb pnr pnl vn va vc)
       do
         (add-mark-to-note reeling-trains 1 1 p 'f))
        auto-slur
The last kind of mark to be added here is
          the slur. The auto-slur method automatically
          places slur marks into the parts of the specified players. By default
          it slurs all notes between two rests, slurring over accents and first
          removing all staccatos from the specified part.
Since accents and staccatos have been already placed in this piece,
          the optional keyword arguments over-accents
          and rm-staccatos for this method are both set
          to NIL. This will result in slurs that always end prior
          to an accent, and in staccato markings being left in the
          score. Unwanted staccato markings were removed in the above steps,
          however, thus leaving the score as desired.
    ;; auto-slur
    (auto-slur reeling-trains '(fl ob cl bn vb pnr pnl vn va vc) 
               :over-accents nil
               :rm-staccatos nil)
                                          
        
      + Consolidating durations
The last post-generation editing method to be called here prior to
          the output methods is map-over-bars. This method can be
          used in conjunction with a second method or function to apply that
          second function to every bar in a specified range of a specified
          player's part. 
The method takes as its arguments the slippery-chicken
          object to be processed, two integers indicating the first and last
          bars to process within that object, and the ID of the player whose
          part is to be changed. If the end bar and player arguments are set
          to NIL, all bars from the start bar to the end of the
          piece in all players' parts will be processed. 
The use of map-over-bars in this piece applies
          the consolidate-notes method to every bar of the piece
          in all players' parts. It is important that this be called prior to
          the auto-slur method, as
          the consolidate-notes method may remove a number of
          event objects during the consolidation process. 
    ;; consolidate sounding durations
    (map-over-bars reeling-trains 1 nil nil #'consolidate-notes)
        
      + Output
With the music generated, the marks placed, and the durations
          consolidated, the final step is to generate the MIDI and score
          output for the composition. This is done in the same manner as
          described in the other tutorials, with the addition of the
          specification of the font-size for the CMN output, and the
          indication that both the CMN and LilyPond scores are to be in C. For
          the scope of this piece, as well, the auto-clefs
          function has been disabled, as the set-limits- values
          have been specified such that clef changes are not necessary.
    ;; output
    (midi-play reeling-trains :midi-file "/tmp/reeling-trains.mid")
    (cmn-display reeling-trains 
                 :file "/tmp/reeling-trains.eps"
                 :size 14
                 :auto-clefs nil
                 :in-c t)
    (write-lp-data-for-all reeling-trains
                           :auto-clefs nil
                           :in-c t)))