# "Second Law": \newline Intra-phrasal Looping

## Using algorithms to generate slot data

- Use of functions, loops, methods to generate data for `make-slippery-chicken`.
- Two options:
    - Place algorithms directly in sc argument positions.
    - Assign the generating code to variables and set arguments to variable
      names.
- Both used in this tutorial.
    - Algorithms to generate rthm-seq-palette, rthm-seq-map, and set-map.

----

## Setting up the environment

- Same procedure as first tutorial

        (in-package :sc)
        (in-scale :chromatic)

----

## Setting up the scope

### Setting the variables

- Three variables here.
    1. `sl-rsp-orig`: original rthm-seq-palette for use with `chop`.
    2. `sl-rsp-chopped`: chopped rthm-seq-palette.
    3. `num-seqs-list`: list of numbers: number of rthm-seqs and
        sets for both maps; used for structure of piece.
- Declared using `let*`.
    - In same scope as call to `make-slippery-chicken`.
    - Another option would be to declare global variables.

----

#### First variable: The original rthm-seq-palette

    (sl-rsp-orig 
     (make-rsp
      'sl-rsp
      '((1 
         ((((4 4) - (e.) s - - \+32 32 32 32 (e) - 
            - 32 32 (s) 32 32 32 (32) - - (s) s s (s) - )
           (- (e..) 32 - +q q (q))
           (h. (q)))
          :pitch-seq-palette ((1 2 1 2 3 2 3 3 1 2 5 5 7 6)
                              (2 1 2 1 2 3 2 2 4 3 2 2 1 2)
                              (5 3 4 5 4 5 4 5 2 3 6 6 8 7))
          :marks (a 1 s 1 slur 3 5 a 6 slur 6 7 slur 8 10 a 11 
                    s 11 12 a 13))))))

----

##### Multiple curves in the same pitch-seq-palette

- Produces multiple pitch curves for same rhythmic material.
- Depending upon rthm-seq-map: 
    - may be played by different players at the same time
    - or by same player at different times 
    - or both.
- Consecutive pitch-seqs are applied in sequence
    - moving down through the players.

----

###### Example of multiple curves in same pitch-seq-palette

    (make-slippery-chicken
     '+multi-ps+
     :ensemble '(((fl (flute :midi-channel 1))
                  (ob (oboe :midi-channel 2))
                  (cl (b-flat-clarinet :midi-channel 3))))
     :set-palette '((1 ((c4 d4 e4 f4 g4 a4 b4 c5))))
     :set-map '((1 (1)))
     :rthm-seq-palette '((1 ((((4 4) - e e e e - - e e e e -))
                             :pitch-seq-palette ((8 7 8 7 8 7 8 7)
                                                 (5 4 3 4 5 4 3 4)
                                                 (1 2 1 2 1 2 1 2)))))
     :rthm-seq-map '((1 ((fl (1))
                         (ob (1))
                         (cl (1))))))

----

###### Output of above code

![Multiple pitch-seqs in one pitch-seq-palette](../doc/manual/resources/resultsOfMultiplePitchSeqs.png)

----

#### Second variable: Creating the chopped rthm-seq-palette

- Chopping unit of `'e` results in three chop points for a quarter note.

        (sl-rsp-chopped (chop sl-rsp-orig '((1 2) (1 1) (2 2)) 'e))

----

#### Third variable: Setting the sequence (measure) structure

- Number of sequences in consecutive sections of set-map and rthm-seq-map.
- Since each rthm-seq is one bar, this will also be the measure structure.

        (num-seqs-list '(53 61 97 79 89 73))

----

### Adjusting instrument attributes for the scope of the piece

- `set-slot` method changes value of any slot of any object of type
  recursive-assoc-list, e.g. instrument-palette  
- Arguments:
    - slot name
    - new value
    - reference ID
    - object
- e.g. `(set-slot 'largest-fast-leap 10 'oboe +slippery-chicken-standard-instrument-palette+)`

- Used here in a loop to change `largest-fast-leaps` slot of instrument
  objects.

<!-- end list -->

- `largest-fast-leaps`: largest interval (semitones) playable at a fast
  tempo.
- "Fast" set for whole piece by sc class's `fast-leap-threshold` slot.

----

#### The routine
- Limits interval between consecutive 32nd-notes to mostly fourths and
  fifths.
- IDs are instrument names in the instrument-palette, not player IDs.

        (loop for i in 
             '((flute 13)
               (oboe 7)
               (b-flat-clarinet 9)
               (bassoon 7)
               (french-horn 5)
               (b-flat-trumpet 7)
               (tenor-trombone 5)
               (double-bass 5))
          do (set-slot 'largest-fast-leap 
                       (second i)
                       (first i)
                       +slippery-chicken-standard-instrument-palette+))

----

## The call to make-slippery-chicken

### First few arguments same procedure as in Core Usage

- object ID
- title
- instrument-palette
- ensemble
- set-limits-high
- staff-groupings
- tempo-map

----

\small

    (make-slippery-chicken
     '+second-law+
     :title "Second Law"
     :instrument-palette +slippery-chicken-standard-instrument-palette+
     :ensemble '(((fl (flute :midi-channel 1))
                  (ob (oboe :midi-channel 2))
                  (cl (b-flat-clarinet :midi-channel 3))
                  (bn (bassoon :midi-channel 4))
                  (hn (french-horn :midi-channel 5))
                  (tp (b-flat-trumpet :midi-channel 6))
                  (tb (tenor-trombone :midi-channel 7))
                  (vno (violin :midi-channel 8))
                  (vnt (violin :midi-channel 9))
                  (va (viola :midi-channel 12))
                  (vc (cello :midi-channel 13))
                  (cb (double-bass :midi-channel 14))))
     :set-limits-high '((cl (0 c6 100 c6))
                        (vc (0 a4 100 a4))
                        (cb (0 f3 100 f3)))
     :staff-groupings '(4 3 5)
     :tempo-map '((1 (q 69))))

\normalsize

----

### Well-considered set palettes

- Pitches seldom more than a third apart allow for smoother lines.

<!-- end list -->

    :set-palette '((1 ((c3 g3 cs4 e4 fs4 a4 bf4 c5 d5 f5 gf5 af5 ef6)))
                   (2 ((c3 fs3 cs4 e4 g4 a4 b4 c5 df5 f5 g5 af5 ef6)))
                   (3 ((d3 f3 cs4 e4 fs4 a4 b4 c5 d5 e5 fs5 af5 ef6)))
                   (4 ((d3 e3 cs4 ef4 fs4 a4 b4 c5 d5 e5 fs5 af5 d6)))
                   (5 ((d3 e3 g3 a3 c4 ef4 f4 af4 bf4 cs5 fs5 b5 df6)))
                   (6 ((c3 d3 gf3 af3 b3 e4 a4 df5 ef5 g5 bf5 df6)))
                   (7 ((b2 e3 fs3 as3 ef4 g4 a4 d5 f5 af5 c6 df6)))
                   (8 ((af2 b2 ef3 fs3 as3 cs4 e4 g4 a4 d5 f5 bf5 c6 e6 af6)))
                   (9 ((af2 b2 ef3 fs3 bf3 d4 f4 a4 cs5 e5 g5 c6 f5 af6)))
                   (10 ((af2 c3 ef3 fs3 bf4 d4 f4 a4 cs5 e5 g5 b5 fs6))))
 
----

## An application of fibonacci-transitions

### Generating the set-map algorithmically
- Refers back to `num-seqs-list` variable.
- Creates transitions between each item in the sublists: `(second section)`.
- Pairs results with a section number: `(first section)`. 
- Collects pairs in a list.

----

#### The routine

    (num-seqs-list '(53 61 97 79 89 73))

    :set-map (loop for section in 
                  '((1 (1 2 3)) 
                    (2 (2 3 4 1))
                    (3 (1 3 5 6 7))
                    (4 (8 9))
                    (5 (5 6 7 9 3))
                    (6 (9 10)))
                collect
                  (list (first section)
                        (fibonacci-transitions 
                         (nth (1- (first section)) num-seqs-list)
                         (second section)))) 

----

#### Replaces

##### This:

\small

    (list
     (list 1 (fibonacci-transitions 53 '(1 2 3)))
     (list 2 (fibonacci-transitions 61 '(2 3 4 1)))
     (list 3 (fibonacci-transitions 97 '(1 3 5 6 7)))
     (list 4 (fibonacci-transitions 79 '(8 9)))
     (list 5 (fibonacci-transitions 89 '(5 6 7 9 3)))
     (list 6 (fibonacci-transitions 73 '(9 10))))

\normalsize

----

##### or this:

\footnotesize

    ((1
      (1 1 1 1 1 1 2 1 1 1 1 2 1 1 2 1 2 2 2 1 2 1 2 2 2 2 2 2 2 3 2 2 3 2 3 3
       3 2 3 2 3 3 3 2 3 3 3 3 3 3 3 3 3))
     (2
      (2 2 2 2 2 3 2 2 2 2 3 2 2 3 2 3 2 3 2 3 3 3 3 3 4 3 4 3 4 3 4 3 4 3 4 4
       4 4 4 1 4 1 4 1 4 1 4 1 4 1 1 1 4 1 1 1 1 1 1 1 1))
     (3
      (1 1 1 1 1 1 1 3 1 1 1 1 3 1 1 3 1 3 1 3 1 3 1 3 1 3 3 3 3 3 3 3 5 3 3 5
       3 5 3 5 3 5 3 5 3 5 5 5 5 5 5 5 6 5 5 6 5 6 5 6 6 5 6 5 6 6 6 6 6 6 6 7
       6 6 7 6 7 6 7 7 6 7 6 7 7 7 6 7 7 7 7 7 7 7 7 7 7))
     (4
      (8 8 8 8 8 8 8 8 8 8 8 8 8 8 9 8 8 8 8 8 8 8 9 8 8 8 8 9 8 8 9 8 8 9 8 9
       8 9 8 9 9 8 9 8 9 9 8 9 9 8 9 9 9 9 9 8 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
       9 9 9 9 9 9 9))
     (5
      (5 5 5 5 5 5 6 5 5 5 5 6 5 5 6 5 6 6 6 5 6 5 6 6 6 6 6 6 6 7 6 6 7 6 7 7
       7 6 7 6 7 7 7 7 7 7 7 9 7 7 9 7 9 9 9 7 9 7 9 9 9 9 9 9 9 3 9 9 3 9 3 3
       3 9 3 9 3 3 3 9 3 3 3 3 3 3 3 3 3))
     (6
      (9 9 9 9 9 9 9 9 9 9 9 9 9 10 9 9 9 9 9 9 9 10 9 9 9 9 10 9 9 10 9 9 10
       9 10 9 10 10 9 10 9 10 9 10 10 9 10 10 10 10 10 9 10 10 10 10 10 10 10
       10 10 10 10 10 10 10 10 10 10 10 10 10 10)))

\normalsize

----

## An application of the chop method

- Applying `chop` to the original rthm-seq-palette produces 36 fragments.
- Calling `print-simple` with the variable of the chopped object returns:

\small

    (print-simple sl-rsp-chopped) 

    => rthm-seq 1
       (1 4): rest E., note S, 
       rthm-seq 2
       (1 8): rest 8, 
       rthm-seq 3
       (1 8): rest S, note S, 
       rthm-seq 4
       (1 4): rest 32, note 32, note 32, note 32, rest E, 
       rthm-seq 5
       (1 8): rest 32, note 32, note 32, note 32, 
       rthm-seq 6
       (1 8): rest 8, 
       rthm-seq 7
       (1 4): note 32, note 32, rest S, note 32, note 32, note 32, rest 32, 
       rthm-seq 8
       (1 8): note 32, note 32, rest S, 
       rthm-seq 9
       [...]

\normalsize

----

### Putting the chopped material into the sc object

- The variable assigned to the results of the `chop` method can be passed
  directly to the `:rthm-seq-palette` argument of `make-slippery-chicken`.

        :rthm-seq-palette sl-rsp-chopped

----

## Intra-phrasal looping

### Algorithmically generating the rthm-seq-map

\footnotesize

     :rthm-seq-map (loop for section in
                        '((((1 3) fl ob ))
                          (((3 4) fl ob cl))
                          (((5 6 7 8) fl ob cl)
                           ((11 12 13 14) bn tb vc cb))
                          (((9 10 11) hn tp))
                          (((15 16 25 26) fl ob vno vnt)
                           ((9 10 13 14) cl hn va)
                           ((3 1 16 3) tp tb)
                           ((12 13 10 11) bn vc cb))
                          (((1 3 4) fl ob cl bn hn tp tb vno vnt va vc cb)))
                      for section-num from 1
                      collect 
                        (list section-num
                              (loop for ins-group in section 
                                 appending
                                   (loop with fts =
                                        (loop for ch in (first ins-group) 
                                           collect
                                             (list 1 ch))
                                      for ins in (rest ins-group) 
                                      collect
                                        (list ins
                                              (fibonacci-transitions
                                               (nth (1- section-num)
                                                    num-seqs-list) 
                                               fts))))))

\normalsize

----

### The rthm-seq-map and orchestration

- Only the players listed in each section will play in that section.
- Players can be assigned same list of rthm-seq IDs for rhythmic coupling.
- This allows the same "motive" to be played by several instruments.

        :rthm-seq-map '((1 ((fl (1 1 2 1 1))
                            (ob (1 1 2 1 1))))
                        (2 ((fl (2 3 2 1 1))
                            (vn (2 3 2 1 1))
                            (hn (4 4 5 5 5))
                            (vc (6 7 8 7 8))))
                        (3 ((fl (9 10 10 9 10))
                            (ob (9 10 10 9 10))
                            (vn (9 10 10 9 10))
                            (hn (11 12 12 11 12))
                            (vc (13 14 13 14 14)))))

----

#### First part of rthm-seq-map loop determines orchestration

- List of six sublists: six sections.
- Each sublist contains lists that are each one instrument group.
- Each instrument group list contains list of rthm-seq IDs... 
    - Refer to chopped rthm-seq-palette.
    - Will be used for a call to fibonacci-transitions below.
- ... paired with a series of player IDs to determine orchestration.

\small

     '((((1 3) fl ob))
       (((3 4) fl ob cl))
       (((5 6 7 8) fl ob cl)
        ((11 12 13 14) bn tb vc cb))
       (((9 10 11) hn tp))
       (((15 16 25 26) fl ob vno vnt)
        ((9 10 13 14) cl hn va)
        ((3 1 16 3) tp tb)
        ((12 13 10 11) bn vc cb))
       (((1 3 4) fl ob cl bn hn tp tb vno vnt va vc cb)))

----

### Assembling the rthm-seq-map from the chop fragments

- Only one rthm-seq defined in original rthm-seq-palette.
- This rthm-seq was given ID `1`.
- Thus: Fragments in chopped rthm-seq-palette accessed by `(1 1)`, `(1 2)` etc.
        
        (loop with fts =
             (loop for ch in (first ins-group) 
                collect
                  (list 1 ch))

----

### Applying fibonacci-transitions to rthm-seq IDs

- Call to fibonacci-transitions for each player ID in instrument group.
    - Referring again to `num-seqs-list`.
- Called using rthm-seq IDs from each instrument group (`fts`).
- Results collected in lists.

        collect
          (list ins
                (fibonacci-transitions
                 (nth (1- section-num) num-seqs-list) 
                 fts))))))

- These lists are paired with section numbers.

        for section-num from 1
        collect 
          (list section-num

----

#### Replaces this:

    ((1
       ((fl (fibonacci-transitions 53 '((1 1) (1 3))))
        (ob (fibonacci-transitions 53 '((1 1) (1 3)))))
      (2
       ((fl (fibonacci-transitions 61 '((1 3) (1 4))))
        (ob (fibonacci-transitions 61 '((1 3) (1 4))))
        (cl (fibonacci-transitions 61 '((1 3) (1 4))))))
        etc.

----

#### or this:

\footnotesize

    ((1
      ((FL
        ((1 1) (1 1) (1 1) (1 1) (1 1) (1 1) (1 1) (1 1) (1 1) (1 3) (1 1)
         (1 1) (1 1) (1 1) (1 3) (1 1) (1 1) (1 3) (1 1) (1 1) (1 3) (1 1)
         (1 3) (1 1) (1 3) (1 1) (1 3) (1 3) (1 1) (1 3) (1 3) (1 1) (1 3)
         (1 3) (1 3) (1 3) (1 3) (1 1) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3)
         (1 3) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3)))
       (OB
        ((1 1) (1 1) (1 1) (1 1) (1 1) (1 1) (1 1) (1 1) (1 1) (1 3) (1 1)
         (1 1) (1 1) (1 1) (1 3) (1 1) (1 1) (1 3) (1 1) (1 1) (1 3) (1 1)
         (1 3) (1 1) (1 3) (1 1) (1 3) (1 3) (1 1) (1 3) (1 3) (1 1) (1 3)
         (1 3) (1 3) (1 3) (1 3) (1 1) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3)
         (1 3) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3)))))
     (2
      ((FL
        ((1 3) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3)
         (1 4) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3) (1 3) (1 4) (1 3) (1 3)
         (1 3) (1 3) (1 4) (1 3) (1 3) (1 4) (1 3) (1 4) (1 4) (1 4) (1 3)
         (1 4) (1 3) (1 4) (1 4) (1 3) (1 4) (1 4) (1 4) (1 4) (1 4) (1 3)
         (1 4) (1 4) (1 4) (1 4) (1 4) (1 4) (1 4) (1 4) (1 4) (1 4) (1 4)
         (1 4) (1 4) (1 4) (1 4) (1 4) (1 4)))

     etc.

\normalsize

----

### Equal lengths

- *Reminder*: All simultaneously played rthm-seqs  must be of same length.
- For example: 5th section of this piece transitions from
    - `(1 15)` to `(1 16)` to `(1 25)` to `(1 26)` in the `fl`, `ob`, `vno` and `vnt`,
      *against*:
    - `(1 3)` to `(1 1)` to `(1 16)` to `(1 3)` in the `tp` and `tb`.
- Works because: 
    - `(1 15)` and `(1 3)` both 1/8 bars
    - `(1 16)` and `(1 1)` both 1/4 bars etc.


---- 

## Re-barring generated material

- As described when discussing `chop` method:
- Changes bar numbers and rthm-seq IDs, which affects post-generation
  editing.

        (re-bar +second-law+
                :min-time-sig '(4 4) 
                :auto-beam 'q)

----

## Output

- Generated in the same manner described in Core Usage. 
- Additional argument for `cmn-display` --- `:size`.

        ;;; midi
        (midi-play +second-law+ :midi-file "/tmp/second-law.mid")

        ;; CMN output
        (cmn-display +second-law+ :file "/tmp/second-law.eps" :size 12)
 
        ;; LP output
        (write-lp-data-for-all +second-law+ :base-path "/tmp/")
 
----

## Post-generation editing

- slippery-chicken has predefined algorithms for automatic tidying.
- `respell-notes`: attempts to choose best enharmonic spelling of pitches.
- Called automatically within `cmn-display` and `write-lp-data-for-all`.
- To disable set `:respell-notes nil` in call to `cmn-display` or
`write-lp-data-for-all`.
- Can tweak generated data manually using post-generation editing methods.
    - Such as changing enharmonic spellings.
- This has not been done here.
- Will be covered in a later tutorial.
