# sc and CLM

## Creating sound files based on data of slippery-chicken objects

- One or more source sound files.
- Create a new sound file from one or more players' parts.
    - Rhythms.
    - Certain aspects of pitch material.

----

## Setting the output directory

- Must designate output path for new sound file.
- Set slippery-chicken object's snd-out-dir slot.

        :snd-output-dir "/tmp/"

----

## The sndfile-palette

- List of source sound files grouped in sublists.
    - don't need extensions (e.g. ".wav") but no harm adding them
- Each group must contain at least one source sound file.
- Different groups cannot be used in the same call to `clm-play`.
    - Except when transitioning between two groups (see below).
    - Can be used in separate calls.
- List of groups followed by list of paths where sound files are stored.

        :sndfile-palette '(((percussive-models-group
                             ((source-sndfile-1.aif)
                              (source-sndfile-2.aif)
                              (source-sndfile-3.aif)))
                            (sustained-pads-group
                             ((source-sndfile-4.aif)
                              (source-sndfile-5.aif)
                              (source-sndfile-6.aif))))
                           ("/path/to/source-sndfiles/sndfiles-dir-1/"
                            "/path/to/source-sndfiles/sndfiles-dir-2/"))

----

## The call to `clm-play`

### Simplest form

- slippery-chicken object.
- ID of starting section in sc object.
- ID(s) of player(s) whose events will be basis for new sound file.
- ID of sound file group to use.

        (clm-play +sc-object+ 1 '(fl ob) 'sndfile-grp-1)

- If player IDs = NIL, event data drawn from all players.

        (clm-play +sc-object+ 1 nil 'sndfile-grp-1)

----

## What it does

- Passes through specified section(s) and player(s).
- Triggers playback of a source sound file for each attacked note.
- Begins output with first attacked note.
    - If first event is attacked note, output will be rhythmically synchronous.
    - If first event is rest, output is offset by duration of that rest.
- Source files triggered in cyclical sequence.
    - Note-by-note, sequence-by-sequence, player-by-player.
- By default: begins with first source sound file of group at each new rthm-seq.

----

## Start times, end times, and durations

### Default:

- Triggers source sound files at their beginning.
- Continues playback until next attacked note.
    - If source file is shorter than duration between attacks, it will play in
      full. 
- Ignores rests.

----

### Arguments for start times, end times, and durations

- `:inc-start`. If `T`, starts at later point in source file each time
   triggered. 
    - increment is calculated so that we arrive at the end of the sound file by
   the time of its last triggering
- `:duration-scaler`. Scales duration of source file segment by specified
  factor.
    - If < 1.0, sound file segments end before next attacked note.
    - If > 1.0, sound file segments overlap next attacked note (if long
      enough).
    - Overlapping: within same sequence only, not from one sequence to next.
    - Does not alter pitch or implement time-stretching.
- `:ignore-rests`. If `NIL`, adds silence to correspond with rests.
    - Only within same sequence. 
    - All sounds end at end of sequence.

<!-- end list -->

    (clm-play +sc-object+ 1 'fl 'sndfile-grp-1 
              :inc-start t :duration-scaler 1.3 :ignore-rests nil)

----

### Specifying segments of source sound files

- Use `:start` and `:end` or `:duration` keywords in sndfile-palette.
    - Either single number (seconds) or list of numbers (mins secs ms).
- `:duration` automatically determines end time.
    - Don't use both `:end` and `:duration`.
- `:start` with no `:end` or `:duration` plays to end of source file. 
- `:end` or `:duration` with no `:start` starts at beginning of source file.
- Same source file can be used multiple times with different values.
- Method cycles through these in same manner as separate sound files.

---- 

#### Examples of :start, :end, and :duration in sndfile-palette

    :sndfile-palette '(((sustained-pads-group
                         ((source-sndfile-1.aif :start 0.000 :end 2.308)
                          (source-sndfile-1.aif :start 2.274 :duration 0.1)
                          (source-sndfile-1.aif :start (0 4 748))
                          (source-sndfile-1.aif :end 7.255)
                          (source-sndfile-1.aif :duration 2.1))))
                       ("/path/to/source-sndfiles/"))

----

## Base frequency

- Two options:
    - Transposition of sound files synchronous to player's pitches.
    - Pitches based on pitches from the set.
- Both use `frequency` slot of sndfile object.
    - Reference pitch for sample-rate conversion.
    - Default: `C4`.
- Frequency can be given as note-name symbol or number of Hertz.

        :sndfile-palette '(((percussive-models-group
                             ((source-sndfile-1.aif :start 0.000 :end 2.308 
                                                    :frequency 524)
                              (source-sndfile-1.aif :end 7.255 
                                                    :frequency c5))))
                   ("/path/to/source-sndfiles/"))

----

###  Non-pitch-synchronous vs. pitch-synchronous

#### Non-pitch-synchronous (default)
- Playback speed (sample-rate conversion) based on pitches of current set.
- No attempt to match transpositions to exact pitches of players. 

#### Pitch-synchronous
- Playback speed scaled to match specific pitches of players.
- Pitches of output only match players if source has perceptible fundamental.
    - Must be specified in `frequency` slot.

<!-- end list -->

        (clm-play +sc-object+ 1 'fl 'sndfile-grp-1 :pitch-synchronous t)

----

## Source sound file groups

- Method only uses exactly one or two groups per call to `clm-play`.

- Option 1: Specify a different group for each call.

        (clm-play +sc-object+ 1 '(fl ob) 'sndfile-grp-1)

        (clm-play +sc-object+ 1 '(fl ob) 'sndfile-grp-2)

        (clm-play +sc-object+ 1 '(fl ob) 'sndfile-grp-3)

----

### Fibonacci-transitioning between two sound file groups

- Option 2: Only option for using more than one group in one output file.
- Two groups only.
- Uses `fibonacci-transition` to transition between specified groups.
    - From beginning to end of output file.

<!-- end list -->

        (clm-play +sc-object+ 1 nil 'sndfile-grp-1  
              :sound-file-palette-ref2 'sndfile-grp-2)

----

## Two other useful sndfile slots

- `:amplitude`. Sets relative amplitude of given source file or segment.
    - Can be any arbitrary number (floating point) value since CLM normalizes
    at the end. 

- `:description`. Comment about given source sound file or segment.
    - Not used for any purposes other than information. 

<!-- end list -->

    :sndfile-palette '(((percussive-models-group
                         ((source-sndfile-1.aif
                           :description "initial attack"
                           :start 0.000 :end 2.308 :frequency 524 
                           :amplitude 0.1) 
                          (source-sndfile-1.aif
                           :description "snap"
                           :start 2.274 :duration 0.1 :frequency e4 
                           :amplitude 1.0))))
                       ("/path/to/source-sndfiles/"))

----

## Other useful clm-play arguments

- `:from-sequence` and `:num-sequences`. Within specified section.

        (clm-play +sc-object+ 1 nil 'grp-1 :from-sequence 2 :num-sequences 2)

- `:num-sections`. Including specified starting section.
    - If given section has subsections, "num-sections" applies to these.
    - i.e. If section 1 has 3 subsections and :num-sections is 2, generates
      data from first two subsections of section 1.
      
    `(clm-play +sc-object+ 2 nil 'grp-1 :num-sections 2)`
    
- `:reset-snds-each-rs` and `:reset-snds-each-player`. `NIL` = don't reset.

        (clm-play +sc-object+ 1 nil 'grp-1
                  :reset-snds-each-rs nil
                  :reset-snds-each-player nil)

----

- `:time-scaler`. Affects tempo of output file. 
    - Output still has same rhythmic structure as players.
    - Affects durations only; does not apply pitch-shifting or time-stretching.

    `(clm-play +sc-object+ 1 nil 'grp-1 :time-scaler 1.7)`

- `:src-scaler`. Scale playback speed of all *individual* source sound files.
    - Does not affect durations or apply time-stretching.
    - 1.0 = no scaling

    `(clm-play +sc-object+ 1 nil 'grp-1 :src-scaler 1.9)`

- `:rev-amt`. Uses `nrev`, for which `0.1` is already a lot.

    `(clm-play +sc-object+ 1 nil 'grp-1 :rev-amt 0.1)`

----

## clm-play arguments for output format

### `*clm-header-type*`, `*clm-data-format*`, and `*clm-srate*`

- CLM default data format: 16 bit signed integer.
- CLM default sample rate: 44100 kHz.
- CLM default header-type: OS-dependent.
- `clm-play` automatically adds file extension based on header type.
    - This can also be specified by the user.   

----

- `:channels`. Number of interleaved channels in output file. 
    - We can have an arbitrary number of output channels in the output file.
    - Source material automatically distributed across all channels. 
- `:srate`. Sample rate of output file.
- `:header-type`. Sets CLM's global `*clm-header-type*` 
    - Must be preceded by `clm::` package qualifier. 
    - `mus-riff` produces `.wav` files.
    - `mus-aiff` produces `.aiff` files (with `.aif` extension by default). 
- `:data-format`. Sets CLM's global `*clm-data-format*`
    - Must be preceded by `clm::` package qualifier. 
    - `mus-lfloat` produces 32-bit little-endian floating-point files. 
    - `mus-bfloat` produces 32-bit big-endian floating-point files. 
    - `mus-bshort` produces 16-bit big-endian files.
    - *NB: AIFF and AIFC not compatible with little endian.*
- `:sndfile-extension`: If `NIL`, `clm-play` adds extension based on header type.
    -  Specifying extension does not affect sound file format.

----

### Example of output arguments

    (clm-play +sc-object+ 1 nil 'grp-1 
              :channels 8
              :srate 44100
              :header-type clm::mus-aiff
              :data-format clm::mus-bshort
              :sndfile-extension ".aiff")

----

## Creating tape parts with independent rhythmic structures

- Add "silent" computer players to ensemble. 

        :ensemble '(((fl (flute :midi-channel 1))
                     (ob (oboe :midi-channel 2))
                     (cp (computer))))

- May choose to use `:set-limits-` to control transposition registers.

- Add separate rthm-seq IDs for computer player(s) to rthm-seq-map. 

        :rthm-seq-map '((1 ((fl (1 2 3 1 3 2))
                            (ob (2 3 1 3 2 1))
                            (cp (1 3 2 1 2 3)))))

- Specify computer as player argument to `clm-play`.

        (clm-play +sc-object+ 1 'cp 'sndfile-grp-1)

----

### Excluding computer parts from MIDI and score output

- Use `:voices` argument for `midi-play`.

        (midi-play +sc-object+ :voices '(fl ob) 
                               :midi-file "/tmp/output.mid") 

- Use `:players` argument for `cmn-display` and `write-lp-data-for-all`.

        (cmn-display +sc-object+ :players '(fl ob) 
                                 :file "/tmp/output.eps")

        (write-lp-data-for-all +sc-object+ :players '(fl ob) 
                                           :base-path "/tmp/")

----

### Exercise: SC AND CLM

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

