slippery chicken documentation - slippery chicken and clm

## slippery chicken and CLM

### + Associated example files

- sc-and-clm-examples.lsp

close

NB: An exercise relating to the material covered in this tutorial can be found on the Exercises page.

slippery chicken's `clm-play` method allows the user to generate sound files based on the data structures of a `slippery-chicken` object. The method takes one or more source sound files specified in the `sndfile-palette` and uses them (or segments of them) to create a new sound file based on the rhythms and certain aspects of the pitch material of a specified player or players within a given `slippery-chicken` object.

### + Setting the output directory

The user must first designate the output path for the new sound file. This is done by setting the `slippery-chicken` object's `snd-out-dir` slot:

    :snd-output-dir "/tmp/"

close

### + The sndfile-palette

The user must then define a `sndfile-palette` consisting of source sound files from which the new sound file will be created. The `sndfile-palette` takes a list containing at least one group, each group in turn containing a list with the name of at least one source sound file. The sound file names can be given without their file extensions if desired. If the user chooses to omit the extensions here, they must be specified in a list as the last element in the `sndfile-palette` (see below).

The list of groups is followed by a list of paths to the disk locations where the source sound files are stored. The source sound files can be located in any of the specified disk locations. NB Paths are not recursively searched so if some files are in subfolders, the paths to those subfolders must be in the list.

If the user has chosen to omit the file extensions from the file names, they must then be provided (minus the dot) as strings in a list as the last element of the `sndfile-palette`.

    :sndfile-palette '(((developing-group
                                  ((test-sndfile-1)
                                   (test-sndfile-2)
                                   (test-sndfile-3)))
                                 (percussive-group
                                  ((test-sndfile-4)
                                   (test-sndfile-5)
                                   (test-sndfile-6))))
                                ("/path/to/source-sndfiles/")
                                ("aiff"))

Only one group (or a maximum of two if a transition is to be made) can be used in each call to `clm-play`, but different groups can be used in separate calls to the method to generate output files with the same rhythm and pitch characteristics but different sound qualities (see the section on source sound file groups below.)

More detail can be found on the `sndfile-palette` class itself in its source code documentation. Each of the sound files named within the palette are used by slippery chicken to create `sndfile` objects. More detail on the `sndfile` class can be found in its robodoc page.

close

### + The call to clm-play

In its most straightforward form, the `clm-play` method takes as its arguments a `slippery-chicken` object (which can be passed as a local variable or as the global variable defined as the first argument to the `make-slippery-chicken` function), the ID of the starting section in that `slippery-chicken` object on which the new sound file is to be based, the IDs of the players whose `events` are to be used as the basis for the new sound file, and the ID of the sound file group within the `sndfile-palette` whose source sound files are to be used to generate the new sound file, e.g.:

    (clm-play +sc-object+ 1 '(player-one player-two) 'source-sndfile-grp-1)

If instead of a list of player IDs the user sets the third argument of the `clm-play` method to `NIL`, the `event` data will be drawn from all players in the ensemble.

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

close

### + How it produces the new sound files

The `clm-play` method passes through the specified section (or sections, if more than one is indicated; see below), and for each attacked note in the parts of each of the players specified it triggers the playback of a source sound file from the specified group in the `sndfile-palette`.

#### Cycles through source sound files

The source sound files are triggered in cyclical sequence on a note-by-note, sequence-by-sequence, and player-by-player basis, following the order of the players as listed in the `ensemble`. Each consecutive attacked (i.e. not tied to) note in the given player's part triggers the next source sound file from the specified group in the `sndfile-palette`. By default, the method starts at the beginning of the list of source sound files in the specified group with each new `rthm-seq`, triggering them in sequence each time, and cycling back to the beginning again if all source sound files have been triggered before the end of the given `rthm-seq`. Once all of the notes have been processed for one player, the method moves to the next player.

#### Omits initial rests

The `clm-play` method begins its output with the first attacked note in the specified sequence. Thus, if the first event of the given sequence is an attacked note, the new sound file will be exactly rhythmically synchronous with the parts of the specified players. This is especially audible if the source sound files are percussive in nature. (This synchronicity can be obscured, if desired, by methods such as setting the `inc-start` etc., as described below.)

If the specified sequence begins with one or more rests, the method will ignore those rests, and the new sound file will begin with the first attacked event at 0.0 seconds. The resulting sound file in such cases will therefore be rhythmically synchronous to the given players' parts, but with a minor offset at the beginning.

#### Simple playback

The `clm-play` method does not process the source sound files it is given by any means other than shifting their pitch, assembling a sequence of sound files or file fragments for playback, and distributing the individual sound files or fragments amongst the channels for spatialized playback. There is no synthesis or filtering involved.

close

### + Start times, end times, and durations

Unless otherwise indicated, the `clm-play` method triggers the source sound files from their beginning and continues playback of the same source sound file until the next attacked note in the given player's part, ignoring rests. By default, if the given source sound file is longer than the duration between two attacked notes, playback of the source sound file will be interrupted at the next attacked note. If the source sound file is shorter than the duration between two attacked notes, it will play out in full.

Three optional keyword arguments are available to the `clm-play` method to modify this default behavior, namely `:inc-start`, `:duration-scaler`, and `:ignore-rests`. Three additional keyword arguments can be specified within the `sndfile-palette` that have a related effect, namely `:start`, `:end`, and `:duration`.

#### clm-play arguments for start times, end times, and durations

If the `:inc-start` argument is set to `T`, the `clm-play` method will automatically start playback of each source sound file from an increasingly later point in that file each time the file is triggered. The increment interval is auto-calculated, so that it reaches the end of the input sound file by the last time it is triggered. The `:inc-start` argument is set to `NIL` by default.

The `:duration-scaler` argument causes `clm-play` to scale the duration of each source sound file segment by a specified factor. If the argument is given a value less than `1.0`, the segments played back will end before the next attacked note, and if it is set to a value greater than `1.0`, the playback of the segments will not end until after the next attacked note (should they be long enough), causing the segments to overlap. Overlapping segments will only be generated for events within the same sequence, but will not overlap from one sequence to the next. The `:duration-scaler` argument only affects the duration of the segment played back; it does not alter pitch or implement time-stretching. This argument is set to `1.0` by default.

If the `:ignore-rests` argument is set to `NIL`, the `clm-play` method will mute playback of the source sound file segments at points that correspond with rests in the given player's part. This argument is set to `T` by default. Similar to the `:duration-scaler`, ignoring rests only has an effect within the same sequence. All sounds will end at the end of a sequence, even if the next sequence begins with rests.

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

#### Specifying start and end times within the sndfile-palette

The user can indicate that only a specified segment of a given source sound file is to be played back using the `:start` and `:end` or `:duration` keyword arguments within the `sndfile-palette`. These arguments correspond to the identically named slots of the `sndfile` class. Each of these arguments takes either a single numerical value consisting of time in seconds, or a list of numbers indicating `(mins secs millisecs)`.

The same source sound file can be listed in the `sndfile-palette` multiple times with different `:start` and `:end` or `:duration` times (or with the same values to get a repeat). This has the same effect as listing multiple separate source sound files, as the `clm-play` method will cycle through these in the same manner by which it cycles through separate sound files.

The `:duration` argument automatically determines the end time of the given segment by adding the specified number of seconds to the start time. The user should apply either the `:end` or `:duration` argument to a given source sound file, but not both.

If a `:start` time is indicated with no `:end` or `:duration` time, the end time will default to the end of the source sound file. Correspondingly, if only an `:end` or the `:duration` time is specified, the segment will begin playback at the beginning of the source sound file.

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

NB: The `:duration` argument within the `sndfile-palette` is only used to demarcate a segment within a source sound file; the actual duration played back will be decided by the rhythms of the corresponding player part and the values of the `:duration-scaler` and `:ignore-rests` arguments.

close

### + Base frequency

slippery chicken has two options for influencing the speed (transposition via sample-rate conversion) at which it plays back the various source sound files. Both of these options make use of the `frequency` slot when determining these speeds.

Some sounds have a prominent fundamental pitch that can be used as a reference for transposition. Setting the `frequency` slot to this fundamental pitch, either in the form of a number in Hertz or a note-name symbol, will determine the sample-rate conversion factor when transposing. If no pitch is specified for the `frequency` slot, the value defaults to `C4`.

The `frequency` value can be defined for each source sound file within the `sndfile-palette`.

    :sndfile-palette '(((percussive-models-group
                         ((source-sndfile-1 :start 0.000 :end 2.308)
                          (source-sndfile-1 :start 2.274 :duration 0.1
                                                         :frequency 524)
                          (source-sndfile-1 :start 4.748 :frequency c3)
                          (source-sndfile-1 :end 7.255 :frequency c5)
                          (source-sndfile-1 :duration 2.1 frequency d4))))
                       ("/path/to/source-sndfiles/")
                       ("aif"))

#### Non-pitch-synchronous transposition

The first option available to the user regarding transposition, which is slippery chicken's default behavior, is to determine the sample-rate conversion based on the pitches of the current set. In this option, slippery chicken will not attempt to match the transpositions of the source sound files to the exact pitches in the parts of the given players. It will still, however, use the `:note-number` argument to access chord notes from the bottom up.

#### Pitch-synchronous transposition

In the second option, slippery chicken scales the playback speed of the source sound files to match the specific pitches of the given players' parts. The pitches in the resulting output file will only match those of the players' parts if the source sound file has a perceptible fundamental pitch and this has been defined accurately within the `sndfile-palette` using the `frequency` slot. This option will also result in chords from the players' parts being reflected in the sound file output.

This second option will only be applied if the `:pitch-synchronous` argument of the `clm-play` method is set to `T`.

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

#### Specifying a frequency for sounds with no fundamental

The `frequency` slot can also be an effective tool for source sound files with no perceptible fundamental pitch. In general, setting a higher `frequency` value will cause the source sound file to be played back at a lower pitch, while setting it lower will cause the source sound file to play back higher.

#### Both pitch and duration are affected

Transposition by sample-rate conversion is a time-domain process, so as with changing the speed of a tape recorder or turntable, both pitch and timing of events is altered.

close

### + Source sound file groups

The `sndfile-palette` definition can consist of multiple groups of source sound files. As described above, the `clm-play` method is designed to only utilize one of these groups for any given output file, with the exception of the fibonacci-transition option described in the next section. The approach of calling the `clm-play` method several times, specifying a different source sound file group for each call, is demonstrated here.

    (clm-play +sc-object+ 1 '(player-one player-two) 'source-sndfile-grp-1
              :duration-scaler 0.7
              :inc-start nil)
    (clm-play +sc-object+ 1 '(player-one player-two) 'source-sndfile-grp-2
              :duration-scaler 1.3
              :inc-start t)
    (clm-play +sc-object+ 1 '(player-three) 'source-sndfile-grp-3
              :ignore-rests nil)

The resulting sound files can then be combined and mixed using a third-party digital audio workstation, such as Logic, Cubase, or the open-source alternative Ardour.

#### Fibonacci-transitioning between two sound file groups

The one native option that slippery chicken has available for incorporating more than sound file group into the same output file consists of a `fibonacci-transition` between two groups in the same sndfile-palette. This is done by specifying the first group as usual and the second group as the value of the optional keyword argument `:sound-file-palette-ref2`.

    (clm-play +sc-object+ 1 '(player-one player-two) 'source-sndfile-grp-1
              :sound-file-palette-ref2 'source-sndfile-grp-2)

close

### + Other useful sndfile class slots

Two other useful slots of the `sndfile` class that can be given values within the `sndfile-palette` are `amplitude` and `description`.

#### amplitude

The `amplitude` slot sets the relative amplitude of the given source sound files (or segments of the same source file if using `:start` and `:end` or `:duration`). Since `clm-play` by default instructs CLM to normalize the new sound file to just below the highest sample value, this argument can take a number of any arbitrary value, and the amplitudes will be scaled accordingly.

#### description

The `description` slot allows the user to add a comment about the given source sound file or segment defined. This value is not used for any purposes other than information.

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

close

### + Other useful clm-play arguments

The `clm-play` method takes 4 mandatory arguments and has 36 optional keyword arguments. A description of each of these arguments can be found in the source code documentation for `clm-play`. A number of the more frequently used optional keyword arguments are given here in brief.

- `num-sections`: This argument takes an integer that indicates the total number of consecutive sections on which the new sound file is to be based, including the first section indicated as the second mandatory argument. If the piece has sub-sections, these will be included in the total; i.e., if section 1 has 3 subsections and `:num-sections` is 2, we'll generate data from the first two subsections of section 1, not all subsections of main sections 1 and 2. If this argument is set to `NIL`, all sections in the piece will be used. Default = `NIL`.

      (clm-play +sc-object+ 1 nil 'source-sndfile-grp-1 :num-sections 2)

- `from-sequence` and `num-sequences`: These two arguments take numbers that indicate the first `rthm-seq` and total number of `rthm-seqs` within the specified section on which the new sound file will be based. As these arguments only function within one section, the `num-sections` argument must be set to `1`.

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

- `reset-snds-each-rs` and `reset-snds-each-player`: By default, slippery chicken starts at the beginning of each list of source sound files with each new `rthm-seq` and each new player it processes. This behavior can be changed by setting one or both of these arguments to `NIL`.

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

- `time-scaler`: The `time-scaler` argument takes a number that is the factor by which the durations of the segments in the new sound file will be scaled. The resulting sound file will have the same rhythmic structure as the players' parts on which it is based but at a different tempo. Use of this argument only affects durations; it does not apply pitch-shifting or time-stretching. The resulting sound file will no longer be synchronous with the events of the given `slippery-chicken` object.

      (clm-play +sc-object+ 2 nil 'source-sndfile-grp-2 :time-scaler 1.7)

- `src-scaler`: The `src-scaler` value will scale the playback speed of all individual sound file segments being written to the new sound file by the specified factor. This argument does not affect durations or apply time-stretching, nor does it modify the playback speed or duration of the new sound file as a whole.

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

- `rev-amt`: The `rev-amt` value indicates how much digital reverberation is to be applied to the output file. The `clm-play` method uses the `nrev` reverb instrument, for which a value of `0.1` is relatively high.

      (clm-play +sc-object+ 3 nil 'source-sndfile-grp-2 :rev-amt 0.1)

close

### + clm-play arguments for output format

The `clm-play` method produces stereo sound files by default, with the header type, data format, and sample rate that are stored in CLM's global `*clm-header-type*`, `*clm-data-format*`, and `*clm-srate*` variables. CLM's default data format and sample rate are `16 bit signed integer` and `44100` kHz. The default header-type is dependent on the user's operating system. slippery chicken will automatically attach the sound file extension it determines to be best suited to the header type, though this parameter too can be specified by the user.

These attributes can be specified by providing values for the following keyword arguments:

- `channels`: The number of interleaved channels in the output file. The `clm-play` method will automatically distribute the source sound material across the channels in a manner reflecting a linear periphery of consecutively numbered loudspeakers. The number of output channels is only limited by the sound file output format used.
- `srate`: The sample rate of the new output file.
- `header-type:` The value given here is used to set CLM's global `*clm-header-type*` variable and must be preceded by the `clm::` package qualifier. Setting this to `clm::mus-riff` will produce files in `.wav` format; `clm::mus-aiff` will produce `.aiff` files.
- `data-format`: The value given here is used to set CLM's global `*clm-data-format*` variable and must be preceded by the `clm::` package qualifier. Setting this to `clm::mus-lfloat` will produce audio files with a format of 32-bit little-endian floating-point. Setting it to `clm::mus-l24int` produces little-endian 24-bit integer files. `clm::mus-bshort` will produce 16-bit big-endian files, and `clm::mus-bfloat` will produce 32-bit floating-point big-endian files. NB: AIFF and AIFC files are not compatible with little endian formats.
- `sndfile-extension`: The extension to be added to the new output file. If `NIL`, slippery chicken will automatically attach the extension that it determines to be best suited to the header type. NB: The extension does not determine the output sound file format; `header-type` does that.

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

close

### + Tape parts with independent rhythmic structures

Since `clm-play` creates its output files based on the `events` of one or more players in the `ensemble`, if the user wishes to create an output file that is not synchronous in rhythmic structure to any of the instrumental parts, or if the user would like to create an electroacoustic composition with no instrumental players, "silent" computer-part players can be added to the `ensemble`. A corresponding `computer` instrument exists for this purpose in the `+slippery-chicken-standard-instrument-palette+`.

Specific `rthm-seq` IDs can then be given for these players in the `rthm-seq-map`, and these "silent" players can be passed as the `player` argument to the `clm-play` method to generate the desired tape part.

As the `computer` instrument is defined to encompass the full MIDI pitch range (C-1 to G9), the use of `set-limits-high` and `-low` may be recommended for limiting transposition registers.

Adding a computer part to the `ensemble`:

    :ensemble '(((fl (flute :midi-channel 1))
                 (ob (oboe :midi-channel 2))
                 (cl (b-flat-clarinet :midi-channel 3))
                 (cp (computer))))

Limiting transposition register:

    :set-limits-high '((cp (0 c6 100 c6)))
    :set-limits-low '((cp (0 f3 100 f3)))

Defining a separate rhythmic structure for the computer part within the `rthm-seq-map`:

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

Calling `clm-play` for just the `rhtm-seq-map` data of the `cp` part:

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

#### Excluding computer players from the score and MIDI

If this approach is chosen, the "silent" players of the ensemble can then be excluded from the MIDI output by specifying `voices` to the `midi-play` method, and excluded from printable score output by calling `cmn-display` or `write-lp-data-for-all` with the `players` argument.

Specifying only a selection of the players for the `midi-play` method (excluding the computer player):

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

Specifying only a selection of the players for the `cmn-display` and `write-lp-data-for-all` methods (excluding the computer player):

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

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

close