slippery chicken documentation - reeling trains

## "Reeling Trains" — Composing with Rhythm Chains

### + Associated files

- The source code for this composition
- The CMN score of this piece
- The LilyPond score of this piece
- The MIDI file of this piece
- An MP3 of the MIDI mockup of this piece using sample instruments

close

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)))

close

### + 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.

close

### + 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+))

close

### + 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.

close

### + 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)

close

### + 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))))

close

### + 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))

close

### + 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.

close

### + 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.

close

### + 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)))

close

### + 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)

close

### + 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)

close

### + 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)))

close