# Featured Algorithms: rthm-chains

## rthm-chains

- Algorithmic generation of 2-voice rthm-seq-palette and rthm-seq-map.
- Generated from user-specified rhythmic fragments:
    - Shorter 1-beat fragments.
    - Longer 2- or 3-beat fragments (counterpoint).
- User-defined control over activity levels via envelopes.
- Automatic insertion of specified rests based on algorithmic patterns.
- Automatic insertion of specified "sticking" rhythms based on patterns.

----

### `procession`

- Used internally to determine the resulting order of the fragments.
- Extrapolates a list of specified length from items of a specified starting
  list.
- Deterministic algorithm, i.e. no randomness.
- Starts with first 3 elements of initial list.
- Gradually adds successive elements from initial list until all elements added.
- Initial list must have at least 4 elements.
- Initial list can be substituted by an integer >= `4`
    - Resulting list consists of numbers between `1` and the integer specified.

<!-- end list -->

    (procession 73 '(a b c d e))

    => 
    (A B A B C A C A A D B C B D B C B C D A D A A E C D C E B D B D E C D C C
     E A B A E B D B D E A C A A E B D B E C D C D E A B A A E C D C E B D B)

----

#### `procession` keyword arguments

- `:peak`. (float `>0.0 <=1.0`). Portion in new list where last element added.
    - Approximate value only. 
    - Shorter initial lists reflect this less accurately.
    - Also dependent on `:orders` argument.
    - Default =` 0.7`.
- `:expt`. (float). Determines curve of interval for adding each element.
    - Higher number = steeper exponential curve. 
    - Default = `1.3`.
- `:orders`. Patterns by which elements are added. 
    - Cyclically applied.
    - Must contain all and only numbers `1`, `2`, and `3`.
    - 1,2,3 represent the three least used elements at each pass. 
    - Default = `'((1 2 1 2 3) (1 2 1 1 3) (1 2 1 3))`.

----

\vspace*{1cm}

#### Example using `procession` keyword arguments

\small 

    (procession 500 '(a b c d e f g h i j k l m n o p q r s t u v w x y z) 
                :peak 0.9 :expt 0.7 
                :orders '((1 3 2 2 3 1) (3 1 1 2 3 3) (1 2 1 3 2 2)))

    =>
    (A C B B C A E A A D E E B D B F D D C F E E F C G A A F G G B C B G C C D
     H F F H D H E E G H H G H G I H H A I B B I A J D D I J J F I F J I I C J
     E E J C K G G J K K I J I K J J A K B B K A L D D K L L F K F L K K C L H
     H L C M E E L M M G L G M L L A M I I M A N B B M N N D M D N M M F N H H
     N F O J J N O O K N K O N N L O M M O L P N N O P P C O C P O O E P O O P
     E P G G I P P A P A Q P P B Q D D Q B Q F F H Q Q I J I Q J J K R Q Q R K
     R L L Q R R M Q M R Q Q N S R R S N S O O R S S P R P S R R C S R R S C T
     E E S T T G S G T S S H T S S T H T A A Q T T B T B U T T D U T T U D U F
     F I U U K L K U L L M V U U V M V N N U V V O U O V U U P V U U V P W Q Q
     V W W R V R W V V S W V V W S W T T V W W C E C W E E G X W W X G X H H W
     X X I W I X W W J X U U X J Y V V X Y Y A X A Y X X B Y X X Y B Y D D X Y
     Y F X F Y X X K Z Y Y Z K Z M M Y Z Z N Y N Z Y Y O Z P P Z O Z Q Q R Z Z
     S T S Z T T W Z Y Y Z W Z C C G Z Z H I H J I I L U R R U L Z A A V Z Z B
     D B E D D F J G G J F N K K M N N O P)

\normalsize

- E.g. [piano procession mini]

----

### `make-rthm-chain`

- Produces a rthm-seq-palette and a rthm-seq-map.
    - Map: a rthm-chain object is a rthm-seq-map 
        - i.e. it's a subclass of a rthm-seq-map. 
    - Palette accessed by `(palette rthm-chain-object)`.
- Uses `procession` to generate sequences.
    - Must therefore have at least 4 of each 1-beat and 2-/3-beat rhythms.
    - Rhythms must not overlap beats.
- 17 optional keyword arguments to control, e.g.
    - Activity (rests v. notes).
    - Automatic rest insertion.
    - Automatic "sticking rhythms" insertion.
 
----

#### Simple `rthm-chain` example

- Specifying number of beats to generate.
- Specifying source rhythm fragments.
- Specifying player IDs.
- Specifying map ID.
- Using `create-psps` to automatically generate pitch curves.
- Accessing `num-rthm-seqs` slot of rthm-chain object to get length.
    - Using `ml` = "make list".

----

#### Example code

- *See example code minis*

----

#### Using `fibonacci-transitions` instead of `procession`

- Transitions from first to second group of rhythms in each fragment list.
- Set `:1-beat-fibonacci` and/or `:slow-fibonacci` to `T`.
- *For example see corresponding mini example code*.

----

### Combining with post-generation editing methods

#### `consolidate-notes`

- Consolidate tied notes into one longer duration.
    - One bar only.
- Does not split long durations evenly at beats.
- Complex algorithm; not fool-proof.
- Automatically called by some methods.
    - Usually with option to disable by setting `:consolidate-notes` to `nil`.

    `(consolidate-notes (get-bar +sc-object+ 2 'vn))`

----

#### `consolidate-rests` and `consolidate-rests-max`

- Consolidate consecutive rests into one longer duration.
    - One bar only.
- Does not split long durations evenly at beats.
- Complex algorithm; not fool-proof.
- Automatically called by some methods.
    - Usually with option to disable by setting `:consolidate-rests` to `nil`.
- `consolidate-rests` does one pass only.
- `consolidate-rests-max` repeats until no more consolidation possible.

<!-- end list -->

        (consolidate-rests (get-bar +sc-object+ 2 'vn))

        (consolidate-rests-max (get-bar +sc-object+ 2 'vn))

----

#### `tie-over-rests`

- Extends duration of a note to include subsequent rests.
- Mandatory arguments:
    - slippery-chicken object.
    - Bar number.
    - Note number.
    - Player ID.

    `(tie-over-rests +sc-object+ 7 1 'fl)`

- Changes number of notes (non-rest events) in a bar.
    - If changing many at once, do them backwards.
    - And set `:consolidate-notes` to `nil`.

    `(tie-over-rests +sc-object+ 7 1 'fl :consolidate-notes nil)`

- Does not change durations in MIDI output.

---

#### `handle-ties`

- Reflect new durations from ties-over-rests in MIDI output.

        (handle-ties +sc-object+)

----

#### `map-over-bars`

- Apply a specified function to a range of bars in an sc object.
- Can specify start bar, end bar, player.
    - If these are `nil`, start = 1, end = last, players = all.
- Arguments of function can be passed as optional argument to `m-o-b`.

        (map-over-bars +sc-object+ nil nil nil #'consolidate-notes)

----

#### An example of post-gen-editing with rthm-chains

- *See example code minis*

----

### `add-voice`

- Add a new voice to an existing rthm-chain object.
- Uses existing rthm-seqs in rthm-chain object to make new voice.
- First analyses time-signatures of existing rthm-seqs.
    - Collects bars into groups of same meter in order they occur.
- Creates new voice from different rthm-seqs of identical meter to source
  voice.
    - Simple offset defaults to 1
    - Can be set with optional argument.
- Arguments:
    - rthm-chain object.
    - Player ID of source voice.
    - Player ID for new voice.

    `(add-voice rch '(1 cl) 'ob))`

----

### Exercise: RHYTHM CHAINS

See http://michael-edwards.org/sc/workshop-exercises.lsp

