Pitches
The user's interaction with specific pitches in
slippery chicken is managed through sets and their related
methods and functions. The make-slippery-chicken
function
has keyword arguments for interaction with sets, such
as :set-palette
, :set-map
and :set-limits-high
and -low
.
It is important to point out the distinction between set
objects, which are a static collection of pitches where actual pitches
are specified, and pitch-seq
objects and palettes, which
govern the general linear contour of pitch sequences chosen from
the sets, but which are not an interface for the
user for specific pitch selection.
This page provides information on both set-related
features as well as on the use of pitch-seq
objects and
palettes.
Separate documentation is also available for note-names and scales and chord functions.
set basics
+ set-palette
The user defines all the possible sets of pitches for a composition
in the set-palette
. Any number of set
objects can be defined in any order within this
palette. Each set is assigned an ID, which can be a
number, a symbol, or a string, with which it is later referenced from
within the set-map
.
:set-palette '((set1 ((c3 g3 cs4 e4 fs4 a4 bf4 c5 d5 f5 gf5 af5 ef6))) (set2 ((c3 fs3 cs4 e4 g4 a4 b4 c5 df5 f5 g5 af5 ef6))) (set3 ((d3 f3 cs4 e4 fs4 a4 b4 c5 d5 e5 fs5 af5 ef6))) (set4 ((d3 e3 cs4 ef4 fs4 a4 b4 c5 d5 e5 fs5 af5 d6))))
![]() |
The combination of the static set-palette
material and
the curves defined in the pitch-seq-palette
of each
given rthm-seq
will determine the linear attributes of
the music generated for each instrument. If a set
contains only a few pitches separated by large intervals, the
instruments will have either large leaps in their linear pitch
material or many consecutive repetitions of the same note.
NB: Because slippery-chicken interprets many
two-item lists as nested lists, it will issue an error if the user
attempts to create a set with only two pitches. To get around this
error, the user may specify the keyword
argument :recurse-simple-data
with the
value nil
with two-pitch sets, e.g.:
:set-palette '(((1 ((gs4 bf4)))) :recurse-simple-data nil)
+ set-map
The set-map
is where the sets are
assigned to each of the individual sequences (rthm-seqs
)
of the piece. It is made up of a list of the sections in the piece,
each paired with a list that consists of one set ID for
each of the sequences in that section. The set IDs
can be assigned to the sequences in any order. They can be repeated
within the set-map
as many times as the user would
like. Not all of the sets defined must be used in
the set-map
.
The pitches in a given set are the only pitches available to the ensemble for the duration of that sequence.
:set-map '((1 (set1 set1 set1 set1 set1)) (2 (set2 set3 set2 set3 set2 set3 set3)) (3 (set3 set3 set4 set3 set4 set3 set4 set4 set3 set4 set4)) (4 (set4 set4 set1 set4 set1 set4 set1 set1 set1)))
This set-map
, with the sets
defined in the set-palette
section above, will result
in the following progression:
![]() |
pitch-seq basics
+ Understanding pitch-seq curves
The linear contours of pitches automatically chosen by
slippery chicken from the current set for each
playing instrument are governed by pitch-seq
curves. These are defined by the user within
the pitch-seq-palette
of each
individual rthm-seq
object of
the rthm-seq-palette
, and are therefore only applied to
instances of that rthm-seq
in the music generated.
The pitch-seq
curves consist of integers, one for each
attacked rhythm (i.e. not for tied notes) of the
given rthm-seq
object. For example:
:rthm-seq-palette '((1 ((((4 4) - e e e e - - e e e e -)) :pitch-seq-palette ((1 4 3 2 5 7 8 6)))))
The numbers chosen by the user for the pitch-seq
can
span any arbitrary numerical range, including negative numbers. The
difference between two consecutive numbers in
the pitch-seq
indicates the direction and relative size
of the linear interval between the corresponding two pitches selected
by slippery chicken. Thus, a sequence of
(1 2 13 4 3)
indicates a linear pitch contour that has
one small interval at the beginning and end, with a larger leap
upwards and back down again in the middle.
The actual pitches chosen from the current set
by slippery chicken for each curve depend on a number of
factors (see the section on how slippery chicken selects
pitches below). One of these factors is the given instrument's
range. Each pitch-seq
curve is only applied to those
pitches within the current set that fall within the
instrument's range, as defined in the instrument-palette
being used for the piece. If there are fewer pitches within the
current set that fall within the instrument's range than
there are different integer values used to define
the pitch-seq
curve, then some of the pitches will be
repeated.
As an example, the following application of the
same pitch-seq
with 8 different integers to both the
flute and the bassoon parts, with a pitch set that has
relatively few low notes, results in the bassoon line having a
narrower range and a number of repeated pitches:
:set-palette '((1 ((b3 d4 g4 b4 e5 a5 d6 a6 b6)))) :rthm-seq-palette '((1 ((((4 4) - e e e e - - e e e e -)) :pitch-seq-palette ((1 2 3 4 5 6 7 8))))) :rthm-seq-map '((1 ((fl (1)) (bn (1)))))
![]() |
Avoiding melodic octaves
By default, slippery chicken will avoid melodic octaves
when selecting pitches for the players. This feature can be turned
off by setting the :avoid-melodic-octaves
slot
to NIL
.
Default output:
:set-palette '((1 ((c5 d5 e5 f5 g5 a5 b5 c6)))) :set-map '((1 (1 1 1))) :rthm-seq-palette '((1 ((((4 4) - e e e e - - e e e e -)) :pitch-seq-palette (1 2 3 4 5 6 7 8)))) :rthm-seq-map '((1 ((fl (1 1 1)))))
![]() |
Setting :avoid-melodic-octaves
to NIL
:
:set-palette '((1 ((c5 d5 e5 f5 g5 a5 b5 c6)))) :set-map '((1 (1 1 1))) :rthm-seq-palette '((1 ((((4 4) - e e e e - - e e e e -)) :pitch-seq-palette (1 2 3 4 5 6 7 8)))) :avoid-melodic-octaves nil :rthm-seq-map '((1 ((fl (1 1 1)))))
![]() |
Defining only one pitch-seq in a pitch-seq-palette
If only one pitch-seq
is defined for a
given rthm-seq
object, every instrument playing that
rthm-seq
will always have the same linear pitch contour
whenever that rthm-seq
appears in the piece. For
information on the use of multiple pitch-seq
curves, see
the section on multiple curves in the same
pitch-seq-palette below.
Indicating chords in the pitch-seq curve
Numbers in additional parentheses within a pitch-seq
indicate chords:
:rthm-seq-palette '((1 ((((4 4) - e e e e - - e e e e -)) :pitch-seq-palette ((1 (4) (3) 2 5 (7) 8 6)))))
If the given instrument is not capable of playing chords, as
indicated by its definition in the instrument-palette
being used for the piece, then single pitches are selected
by slippery chicken instead. More information on topics
related to chords can be found on the chord
functions page.
+ Multiple curves in the same :pitch-seq-palette
There can be as many separate pitch-seq
curves in
each pitch-seq-palette
as the user
likes. A pitch-seq-palette
with more than
one pitch-seq
will produce multiple linear pitch curves
for the same rhythmic material. Depending on the structure of
the rthm-seq-map
, these different curves may be played
by different players at the same time or by the same player at
different times (or both).
slippery chicken applies each different
pitch-seq
consecutively starting at the top of the
ensemble and moving downwards through the players. Thus, if three
players are assigned within the rthm-seq-map
to play
the same rthm-seq
at the same time, the
first pitch-seq
curve is given to the player that
appears first in the ensemble
list, the second to the
next player in the ensemble
list, and the third to the
player after that.
For example, this very brief slippery-chicken
piece has
three players and defines three different pitch-seq
curves with distinct contours within the
one pitch-seq-palette
of the one rthm-seq
in the rthm-seq-palette
. It then constructs the
composition using a rthm-seq-map
in which all three
players play the same rthm-seq
at the same time, only
once:
(make-slippery-chicken '+multi-ps+ :title "Multiple pitch-seqs" :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)))) :tempo-map '((1 (q 60))) :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))))))
The resulting score fragment shows how the
different pitch-seq
curves of the
above pitch-seq-palette
determine the linear contours
for each player. It also demonstrates the distinction between
pitch contours and actual pitch selection in
slippery chicken, as the numbers do not represent pitches,
but directionality and relative distance within the linear pitch
motion. Thus, the clarinet maintains the contour indicated by
1 2 1 2...
, even though its 2
is higher in
pitch than the oboe's 4
. (More detail on this can be
found in the section on how slippery chicken selects
pitches below.)
![]() |
Advanced pitch-seq and set topics
+ How slippery chicken selects pitches
General
It is important to emphasize that slippery chicken is not designed to allow the user to determine specific pitches for specific instruments at any given point in the piece prior to the generation of the musical data. Instead, it chooses pitches automatically from the current set based on a number of rules and conditions.
The sequence of rules and conditions
slippery chicken selects the pitches for each instrument in
a given sequence of the piece one instrument after the next. If no
other specification is given, the order in which it processes the
instruments defaults to the order in which the players are listed in
the ensemble
block. If the user would like to specify a
different order, this can be done using
the :instruments-hierarchy
keyword argument of
the make-slippery-chicken
function. When choosing
pitches for instruments, slippery chicken takes into account
which pitches have already been assigned to other instruments playing
at the same time in the same sequence, so the order in which it
processes the instruments is important for pitch allocation.
Once the order is determined, slippery chicken follows specific steps to select pitches from the current set for each instrument:
- slippery chicken first limits the current set to only pitches that fall within the instrument's range.
- It then removes any pitches that have already been allocated to other instruments.
- If the definition of the instrument specifies a value for
the
subset-id
slot, and the current set contains asubset
with that ID, the pitches are further limited to those common to both the specifiedsubset
and the pitches remaining from step 2. - If the ratio of the number of pitches now available to the
number of different numerical values in the
pitch-seq
is less than thepitch-seq-index-scaler-min
slot of theslippery-chicken
object (0.5 by default), slippery chicken will add pitches that have already been allocated to other instruments until this ratio is met or exceeded. (The user can change the value of thepitch-seq-index-scaler-min
by specifying the keyword argument of the same name within the call to themake-slippery-chicken
function). This ratio—which may indeed be greater than one—is then used to multiply the numbers in thepitch-seq
(which are subsequently rounded) to obtain the indices for getting the pitches for each number in thepitch-seq
from the list of available pitches. In this case, the lowest number in thepitch-seq
will be assigned to the lowest of the available pitches. - If after the first three steps there are enough pitches to cover
the different numbers in the
pitch-seq
, the pitch assigned to the lowest number in thepitch-seq
will depend on the value of theprefers-notes
slot of the instrument definition:- If the
prefers-notes
slot has been set tohigh
, the highest number in thepitch-seq
will be assigned to the highest of the available pitches. - If the
prefers-notes
slot has been set tolow
, the lowest number in thepitch-seq
will be assigned to the lowest of the available pitches. - If this slot has not been set (defaults to
NIL
), the range of pitches assigned to the numbers of thepitch-seq
will correspond to the middle of the available pitches, with two exceptions:- If the lowest
number in the
pitch-seq
is 5 or higher, this will have the same effect as theprefers-notes
slot being set tohigh
. - If the lowest number in the
pitch-seq
is 1, this will have the same effect as theprefers-notes
slot being set tolow
.
(setf +pitch-seq-lowest-equals-prefers-high+ 6)
(setf +pitch-seq-lowest-equals-prefers-low+ 0)
- If the lowest
number in the
- If the
- If at this point there are no available pitches, the function
will trigger an error and exit. This could happen, for example, if
the
set-limits-high
andset-limits-low
take the available pitches outside of the instrument's range.
NB: By default, slippery chicken
will also
prevent melodic octaves from being assigned to a player. Setting
the slippery-chicken
object's avoid-melodic-octaves
slot to NIL
will disable this feature, as described in the understanding pitch-seq curves section
above.
Changing notes post-generation
There are ways of narrowing the set of pitches available to an
instrument at a given point, such as by using
the set-limits-high
and set-limits-low
keywords of the make-slippery-chicken
function (see
below), or by
defining subsets
(see below) and setting
subset-ids
for the instrument
objects (see
the page on tailoring instrument
definitions).
However, if the user would like to change the specific pitches of
just a few notes here and there after a piece has been generated, a
number of methods are available for modifying the data of
existing slippery-chicken
objects. The post-generation
data-editing method double-events
, for example, allows
exact pitches and rhythms to be copied from one player to one or more
others. This method can only be applied to an
existing slippery-chicken
object, meaning that the
distribution of available pitches among the instruments is not
repeated. (See the page
on post-generation data
editing).
Since slippery chicken can also be used to produce MIDI
files from its data, importing these into commercial notation
software such as Finale or Sibelius is also always an option. With
a bit of searching, the corresponding pitch values can also be
found and modified in any LilyPond files created. (Some versions of
LilyPond also include a point-and-click feature by which clicking
on a note in the PDF output jumps automatically to that note in
the .ly
file.)
+ set-limits-high and -low
In addition to the definition of the highest and lowest pitches of
an instrument's absolute range (as defined in the
individual instrument
objects of
the instrument-palette
being used for a given piece),
the user can further constrain the pitches assigned to a given
instrument to sub-ranges for any number of consecutive sequences of a
piece. This is done using the keyword
arguments :set-limits-high
and :set-limits-low
with a list of 2-element lists, in
the format seen here:
:set-limits-high '((cl (0 c6 50 c5 100 c6)) (vc (0 g4 50 c5 100 g4)) (cb (0 f3 50 b3 100 f3)))
The first element of each 2-element list is the ID assigned by the
user to the given player
within
the ensemble
block of
the make-slippery-chicken
function (and not the ID of
the instrument within the instrument-palette
). If the
symbol all
is given here, the subsequent list of
breakpoint pairs will apply to all instruments, further constraining
the high and low limits of the individual curves if there is an
overlap, thus allowing tessitura shaping for the whole
ensemble over the course of the piece.
The second element of each 2-element list is a series of breakpoint pairs, each consisting of an x-axis number followed by either a note-name symbol or a MIDI note number. The pitch indicators refer to sounding pitches, not written (in the case of a transposing instrument). The x-axis range is arbitrary and will be scaled to fit the number of sequences in the entire piece. Since the x-axis numbers in this example span from 0 to 100, if the given piece consisted of 100 sequences, the second x-axis value here of 50 would indicate the 50th sequence in the piece.
The method interpolates a gradual curve between the values
associated with each x-axis number. In this example the upper range
of the instrument associated with player cl
would be
limited to C6 at the opening, gradually being lowered to C5 by the
middle sequence, and gradually increasing to C6 again by the last
sequence of the piece.
NB: Since the operations behind
the set-limits-
slots are based on interpolation, at
least two pair of breakpoint are
required. Correspondingly, set-limits-
values cannot be
used when generating a musical fragment that has only one sequence in
the rhtm-seq-map
. Attempting to do so will produce
a division by zero
error.
NB: If a single capping of an instrument's pitch range for
an entire piece is required rather than a curve for range limits that
change over the piece, another option for achieving this is to modify
the highest-
or lowest-written
or
-sounding
values of the given instrument
object instead. See the documentation
on changing instrument attributes
temporarily for more on this.
subsets and related-sets
+ Adding subsets and related-sets to a set
Each set in a set-palette
can also
contain subsets
and related-sets
. These
will only be used during automatic pitch selection if there is a
corresponding value set as the subset-id
in the
definition of an instrument
object (see the page
on tailoring instrument definitions
and the section on limiting an instrument's pitches
using subset-id below). They can also be very useful when writing
user-defined functions, such as for chord selection (see the page
on chord functions for more
detail).
The primary difference between subsets
and related-sets
is that all pitches specified in
the subsets
slot must also be members of the
primary set, whereas the related-sets
slot
can contain any pitch, whether part of the primary set or not.
When a subset
is specified with pitches that are not
members of the primary set, slippery chicken
will produce an error:
sc-set::check-subsets: Note C4 given in subset MBA1 of set SET1 is not part of the main set. [Condition of type SIMPLE-ERROR]
Both subsets
and related-sets
can be
entered as simple or nested key-data pairs, whereby the nested
approach must be reflected in the additional set of
parenthesis. Entry as simple key-data pairs would look like this:
:set-palette '((1 ((f3 g3 a3 bf3 c4 d4 e4 f4 g4 a4 b4 c5 d5 e5 f5 g5) :subsets ((pno1 (c4 e4 g4)) (pno2 (d4 f4 a4)) (mba1 (a3 c4 e4))) :related-sets ((pno3 (gs4 bf4 df5)) (mba2 (fs3 af3 cs4))))))
![]() |
Nested subsets
and related-sets
would be
entered such:
:set-palette '((1 ((c3 g3 cs4 e4 fs4 a4 bf4 c5 d5 f5 gf5 af5 ef6) :subsets ((piano ((pno1 (cs4 e4 fs4)) (pno2 (e4 fs4 a4)))) (marimba ((mba1 (c3 g3 cs4)) (mba2 (g3 cs4 e4))))) :related-sets ((piano ((pno3 (d3 a3 d5)) (pno4 (c3 g3 d5))))))))
![]() |
+ Limiting an instrument's pitches using subset-id
The subset-id
slot of an instrument
object
will cause slippery chicken to automatically limit an
instrument's pitches to the pitches in the
corresponding subset
of the
current set. This applies to both linear pitch contours
and any chords made (see the section on chord functions and
set-palette subsets of the chords
page for more on restricting only the chords for an instrument to
subsets without simultaneously limiting the linear pitch contours for
that instrument). If there is no subset
in the
current set with a matching ID, the
default
rules for pitch
selection
apply.
This example sets the subset-id
slots of
the flute
, oboe
,
and b-flat-clarinet
instruments that are contained in
the +slippery-chicken-standard-instrument-palette+
to flute-notes
, oboe-notes
,
and clarinet-notes
, and creates corresponding subsets
with the same ID in the set:
(set-slot 'subset-id 'flute-notes 'flute +slippery-chicken-standard-instrument-palette+) (set-slot 'subset-id 'oboe-notes 'oboe +slippery-chicken-standard-instrument-palette+) (set-slot 'subset-id 'clarinet-notes 'b-flat-clarinet +slippery-chicken-standard-instrument-palette+) (let ((subset-id-piece (make-slippery-chicken '+subset-id-piece+ :title "subset id piece" :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)))) :tempo-map '((1 (q 60))) :set-palette '((1 ((b3 c4 d4 e4 f4 g4 a4 b4 c5 d5 e5 f5 g5 a5 b5 c6 d6 e6 f6 g6 a6 b6) :subsets ((flute-notes (b5 c6 d6 e6 f6 g6 a6 b6)) (oboe-notes (a4 b4 c5 d5 e5 f5 g5 a5)) (clarinet-notes (b3 c4 d4 e4 f4 g4)))))) :set-map '((1 (1 1 1))) :rthm-seq-palette '((1 ((((4 4) - e. s - - e e - - +s s s s - - (s) s s s - )) :pitch-seq-palette ((2 2 3 1 1 2 1 2 2 2) (6 8 5 5 7 7 9 6 8 10) (5 4 3 1 1 2 3 3 4 4) (1 3 3 2 1 2 3 1 1 1))))) :rthm-seq-map '((1 ((fl (1 1 1)) (ob (1 1 1)) (cl (1 1 1)))))))) (write-lp-data-for-all subset-id-piece :base-path "/tmp/"))
When the piece is generated, each part will only contain pitches
from the corresponding subset
:
![]() |