[ Top ] [ rthm-chain ] [ Methods ]

DESCRIPTION

``` Add a new voice to an existing rthm-chain object based on the rhythmic
material and slot values already contained in that object.

The main rthm-chain algorithm generates only two voices. Rather than
generate further voices in the same fashion by which the first two were
created, this method uses the already created rthm-seqs in the given
rthm-chain object to create a new voice.

The challenge here is that each rthm-seq potentially has its own time
signature structure: There could be a 2/4 bar followed by 5/4 then 3/16,
for example, or any other combination of any meter. So the method first
analyses the time-signature structure of the existing rthm-seqs and saves
those with the same bar/meter structure together in the order in which they
occur. When creating the extra voice then, the method actually starts ahead
of the main voice by choosing <offset> number of similar rthm-seqs in
advance.  NB Your data might well produce only one rthm-seq with a
particular metric structure, which might mean that calling this method
produces rhythmic doubling instead of an independent part.  In that case
```

ARGUMENTS

``` - A rthm-chain object.
- The reference (key path) of the player within the given rthm-chain object
whose rthm-seq-map is to serve as the 'parent voice', e.g. '(1 cl).
- A symbol that will be the ID of the new player.
```

OPTIONAL ARGUMENTS

``` - An integer that indicates an offset into the group of similar rthm-seq
objects from which the new voice is to begin. (The generated voice will
thus be ahead of the main voice). Default = 1.
```

RETURN VALUE

``` Returns T.
```

EXAMPLE

```(let ((rch
(make-rthm-chain
'test-rch 150
'((((e) e) ; 4 in total
(- s (s) (s) s -)
({ 3 (te) - te te - })
((e.) s))
(({ 3 (te) te (te) }) ; what we transition to
({ 3 - te (te) te - })
({ 3 (te) - te te - })
({ 3 (te) (te) te })))
'((((q q) ; the 2/4 bars: 5 total
((q) q)
((q) q)
((q) (s) e.)
(- e e - (e) e))
(({ 3 te+te te+te te+te }) ; what we transition to
(q - s e. -)
(q (s) e.)
(q (s) - s e -)
({ 3 te+te te+te - te te - })))
((((e.) s (e) e (s) e.) ; the 3/4 bars: 4 total
(- e e - (e) e (q))
(- e. s - - +e e - (q))
(q (e.) s (q)))
(({ 3 (te) (te) te+te te+te } (q)) ; what we transition to
(- e. s - (q) (s) - s e -)
({ 3 te+te te } (q) q)
({ 3 - te te te - } (e) e { 3 (te) (te) te }))))
:players '(fl cl))))
```

SYNOPSIS

```(defmethod add-voice ((rc rthm-chain) parent new-player &optional (offset 1))
```

## rthm-chain/hash-least-used [ Functions ]

[ Top ] [ rthm-chain ] [ Functions ]

DESCRIPTION

``` Return the least used key in a hash table. This may be used to retrieve the
number of times the keys have been used as indices, for example.
```

ARGUMENTS

``` - A hash table. This must be a lisp hash table object whose keys and values
are all numbers.
```

OPTIONAL ARGUMENTS

``` keyword arguments:
- :start. The lowest key value we'll test. Default = 0.
- :end. The highest key value we'll test. Default = number of items in the
hash table.
- :ignore. A list of keys to ignore when processing. NIL = process all
keys. Default = NIL.
- :auto-inc. T or NIL to determine whether the function will automatically
increment the count of the returned key. T = automatically increment.
Default = T.
- :invert. T or NIL to invert the functionality i.e. to return the most
used rather than the least. Default = NIL.
```

RETURN VALUE

``` The key of the least used element in the hash table.
```

EXAMPLE

```(let ((h (make-hash-table)))
(loop for i below 100 do
(setf (gethash i h) 10000))
(setf (gethash 10 h) 5
(gethash 11 h) 4
(gethash 12 h) 3
(gethash 13 h) 2)
(print (hash-least-used h :auto-inc nil))
(print (hash-least-used h :auto-inc t))
(print (hash-least-used h :auto-inc t))
(print (hash-least-used h :auto-inc nil :start 12))
(setf (gethash 2 h) 0)
(print (hash-least-used h :auto-inc nil :start 3 :end 11))
(print (hash-least-used h :auto-inc nil :end 11))
(print (hash-least-used h :auto-inc nil :ignore '(2))))

=>
13
13
12
13
11
2
13
```

SYNOPSIS

```(defun hash-least-used (hash &key (start 0) end ignore (auto-inc t)
invert)
```

## rthm-chain/hash-least-useds [ Functions ]

[ Top ] [ rthm-chain ] [ Functions ]

DATE

``` Mary 26th 2016, Edinburgh
```

DESCRIPTION

``` Same as hash-least-used except it will return the <num> least used items (3
by default).
```

SYNOPSIS

```(defun hash-least-useds (hash &key (start 0) end ignore (auto-inc t)
invert (num 3))
```

## rthm-chain/make-rthm-chain [ Functions ]

[ Top ] [ rthm-chain ] [ Functions ]

DESCRIPTION

``` Create an instance of a rthm-chain object. The rthm-chain class enables the
algorithmic generation of a rthm-seq-map (with just one section) and its
associated rthm-seq-palette, which consists in turn of algorithmically
generated rthm-seq objects.

The rhythm-seq objects are made up of both faster material based on 1-beat
groups and slower-moving counterpoint based on 2- or 3-beat groups.

The rthm-chain class also allows for control of the degree of activity in
the parts over time through user-specified envelopes.

Rests are automatically inserted at regular but changing intervals.

Specified 'sticking points' cause individual rhythms to be repeated a
certain number of times. Sticking happens after rests and can also be
controlled with an activity envelope.

NB: Because this method uses the procession method internally, each
collection of 1-beat-rthms and slower-rthms defined must contain at
least four items.

NB: Since this method automatically inserts rests into the chains, the user
may like to implement the various tie-over-rests post-generation
editing methods. If this is done, the handle-ties method may also be
recommended, as the tie-over-rests methods only affect printed output
and not MIDI output.
```

ARGUMENTS

``` - A number, symbol, or string that is to be the ID of the new rthm-chain
object.
- An integer that is the number of beats to be generated prior to adding
additional material created from sticking points and the automatic
addition of rests.  For generating a whole piece this will generally be
in the hundreds, not dozens.  Lower numbers might create very limited
results or make the use of the add-voice method next to useless.
- A list with sublists of rhythms that are to be the 1-beat rhythms used to
construct the faster-moving material of the rthm-seq-palette. Each
sublist represents the repertoire of rhythms that will be used by the
procession method. Each sublist must contain the same number of rthms but
their number and the number of sublists is open. A transition will be
made from one group of rhythms to the next over the whole output
(i.e. not one unit to another within e.g. the 1-beat rhythms) according
to a fibonacci-transition method.  NB Here and below, at least two lists
are required: what we start with, and what we transition to.  If no
transition is required you could of course just duplicate the rhythms via
a let variable: (list rhythms rhythms).
- A list with sublists of 2-beat and 3-beat full bars of rhythms used to
construct the slower-moving counterpoint material of the
rthm-seq-palette. This will be turned into a rthm-chain-slow object, and
will therefore remain as lists of unparsed rhythms. Each sublist must
contain the same number of rthms but their number and the number of
sublists is open. A transition will be made from one group of rhythms to
the next over the whole output (i.e. not one unit to another within
e.g. the 1-beat rhythms) according to a fibonacci-transition method.
NB: The rhythm units of slower-rthms must be expressed in single beats;
e.g., a 2/4 bar must consist of q+q rather than h. The consolidate-notes
method can be called afterwards if desired.
```

OPTIONAL ARGUMENTS

``` keyword arguments:
- :players. A list of two player IDs. When used in conjunction with a
slippery-chicken object (which is the standard usage), these must be IDs
as they are defined in that object's ENSEMBLE slot. The first player will
play the 1-beat rhythms, the second the slower rhythms.
Default = '(player1 player2).
- :section-id. An integer that will be used as the ID of the rthm-seq-map
created. NB: rthm-chain only creates rthm-seq-maps with one section,
making it possible to create several different rthm-seq-map objects for
different sections in the given piece, and requiring that these be
manually assigned IDs. Additionally, any ID given here must match an
existing ID within the other maps. Default = 1.
- :activity-curve. A list of break-point pairs with y values from 1 to 10
indicating the amount of activity there should be over the course of the
piece. A value of 1 indicates that only 1 in 10 beats will have notes
in/on them, and a value of 10 indicates that all beats will have
notes. This process uses the patterns given in
activity-levels::initialize-instance, where 1 means 'play' and 0 means
'rest'. There are three templates for each level, so that if the curve
remains on one level of activity for some time it won't always return the
same pattern; these will be rotated instead. If the activity curve
indicates a rest for one of the slower-rhythms groups, the whole 2-3 beat
group is omitted. Default = '(0 10 100 10).
- :do-rests. T or NIL to indicate whether to apply the automatic
rest-insertion algorithm. T = use. Default = T.
- :rests. A list of rhythmic duration units from which the durations will
be drawn when using the automatic rest-insertion algorithm. The specified
rests are used in a sequence determined by a recurring-event
object. Default = '(e q q. w). NB: Each of these values must not resolve
to less than one-quarter of the beat basis, either alone or in
combination, as this could result in an attempt to create meters from
fractional beats (e.g. 3.25). An error message will be printed in such
cases.
- :rest-cycle. A list of 2-item lists that indicate the pattern by which
rests of specific rhythmic durations will be selected from the RESTS slot
for automatic insertion. The first number of each pair is a 0-based
position referring to the list of rests in the RESTS slot, and the second
number is the number of times the rest at that particular position should
be inserted. (This number does not mean that the selected rest will be
inserted that many times at once, but rather that each consecutive time
the rest algorithm selects one rest to be inserted, it will insert that
specific rest, for the specified number of consecutive times.) For
example, (0 3) indicates that for the next three times that the rest
algorithm selects one rest to insert, it will select the rest located at
position 0 in the list of rests in the RESTS slot (e by default).
Default ='((0 3) (1 1) (0 2) (2 1) (1 1) (3 1)).
- :rest-re. A list of 2-item lists that indicate the pattern by which rests
will be automatically inserted. The first number of each pair determines
how many events occur before inserting a rest, and the second number of
each pair determines how many times that period will be repeated. For
example, (2 3) indicates that a rest will be inserted every two events,
three times in a row. The list passed here will be treated as data for a
recurring-event object that will be repeatedly cycled through.
Default = '((2 3) (3 2) (2 2) (5 1) (3 3) (8 1)).
- :do-rests-curve. A list of break-point pairs with y values of either 0 or
1 indicating whether the do-rests algorithm is active or disabled. These
values are interpolated between each pair, with all values 0.5 and higher
being rounded up to 1 and all below 0.5 rounded to 0. Default = NIL.
- :do-sticking. T or NIL to indicate whether the method should apply the
sticking algorithm. T = apply. Default = T.
- :sticking-rthms. A list of rhythmic units that will serve as the rhythms
employed by the sticking algorithm. These are generated at initialization
if not specified here. NB: This list is used to create a list using the
procession algorithm at initialization, so it is best to apply something
similar to the default if not accepting the default. If a circular-sclist
object is provided here, it will be used instead of the default
procession. Default = '(e e e. q e s).
- :sticking-repeats. A list of integers to indicate the number of
repetitions applied in sticking segments. When the values of this list
have been exhausted, the method cycles to the beginning and continues
drawing from the head of the list again. NB: This list is made into a
circular-sclist object when the given rthm-chain object is initialized
unless a circular-sclist object is explicitly provided.
Default = '(3 5 3 5 8 13 21).
- :sticking-curve. A list of break-point pairs that acts as an activity
envelope to control the sticking, which always occurs after rests. As
with the activity curve, this curve can take y values up to 10, but also
allows 0. A y value of 0 or 1 here refers to either a specific number of
repeats (1) or none (0). The number of repeats may be determined, for
example, by use of the procession method, such as
(procession 34 '(2 3 5 8 13) :peak 1 :expt 3). Every sticking point is
accompanied by a slower group, which is simply chosen in sequence and
repeated for the duration of the sticking period.
Default = '(0 2 100 2).
- :do-sticking-curve. A list of break-point pairs that can be used,
alternatively, to control whether the sticking algorithm is being applied
or not at any given point over the course of the piece. The y values for
this curve should be between 0 and 1, and the decimal fractions achieved
from interpolation will be rounded. The 1 values resulting from this
curve will only be actively applied to if do-sticking is set to T.
Default = NIL.
- :harmonic-rthm-curve. A list of break-point pairs that indicates how many
slower-rthms will be combined into one rthm-seq (each rthm-seq has a
single harmony). The default is 2 bars (slower-rthms) per rthm-seq,
i.e. '(0 2 100 2).
- :split-data. NIL or a two-item list of integers that are the minimum and
maximum beat duration of bars generated. If NIL, the bars will not be
split. These values are targets only; the method may create bars of
different lengths if the data generated cannot be otherwise split.
NB: The values given here will apply to a different beat basis depending
on time signature of each individual bar, rather than on a consistent
beat basis, such as quarters or eighths. Since this method produces bars
of different lengths with time signatures of differing beat bases
(e.g. 16, 8, 4 etc.) before it applies the split algorithm, a minimum
value of 4, for example, can result in bars of 4/16, 4/8, 4/4 etc.
Default = '(2 5)
- :1-beat-fibonacci. T or NIL to indicate whether the sequence of 1-beat
rhythms is to be generated using the fibonacci-transitions method or the
processions method. T = use fibonacci-transitions method. Default = NIL.
- :slow-fibonacci. T or NIL to indicate whether the sequence of the slow
rhythms will be generated using the fibonacci-transitions method or the
processions method. This affects the order in which each 2- or 3-beat
unit is used when necessary, not the order in which each 2- or 3-beat
unit is selected; the latter is decided by the next element in the DATA
slot of the rthm-chain-slow object, which simply cycles through
'(2 3 2 2 3 2 2 3 3 3). T = use fibonacci-transitions method.
Default = NIL.
```

RETURN VALUE

``` A rthm-chain object.
```

EXAMPLE

```;; An example using a number of the keyword arguments.
(make-rthm-chain
'test-rch 23
'((((e) e) ; 4 in total
(- s (s) (s) s -)
({ 3 (te) - te te - })
((e.) s))
(({ 3 (te) te (te) }) ; what we transition to
({ 3 - te (te) te - })
({ 3 (te) - te te - })
({ 3 (te) (te) te })))
'((((q q) ; the 2/4 bars: 5 total
((q) q)
((q) q)
((q) (s) e.)
(- e e - (e) e))
(({ 3 te+te te+te te+te }) ; what we transition to
(q - s e. -)
(q (s) e.)
(q (s) - s e -)
({ 3 te+te te+te - te te - })))
((((e.) s (e) e (s) e.) ; the 3/4 bars: 4 total
(- e e - (e) e (q))
(- e. s - - +e e - (q))
(q (e.) s (q)))
(({ 3 (te) (te) te+te te+te } (q)) ; what we transition to
(- e. s - (q) (s) - s e -)
({ 3 te+te te } (q) q)
({ 3 - te te te - } (e) e { 3 (te) (te) te }))))
:players '(fl cl)
:slow-fibonacci t
:activity-curve '(0 1 100 10)
:harmonic-rthm-curve '(0 1 100 3)
:do-sticking t
:do-sticking-curve '(0 1 25 0 50 1 75 0 100 1)
:sticking-curve '(0 0 100 10)
:sticking-repeats '(3 5 7 11 2 7 5 3 13)
:sticking-rthms '(e s. 32 e.)
:split-data '(4 7))

=>
RTHM-CHAIN: 1-beat-rthms: (((E E) (S S S S) (TE TE TE) (E. S))
((TE TE TE) (TE TE TE) (TE TE TE) (TE TE TE)))
slower-rthms: ((((Q Q) ((Q) Q) ((Q) Q) ((Q) (S) E.)
(- E E - (E) E))
(({ 3 TE+TE TE+TE TE+TE }) (Q - S E. -) (Q (S) E.)
(Q (S) - S E -) ({ 3 TE+TE TE+TE - TE TE - })))
((((E.) S (E) E (S) E.) (- E E - (E) E (Q))
(- E. S - - +E E - (Q)) (Q (E.) S (Q)))
(({ 3 (TE) (TE) TE+TE TE+TE } (Q))
(- E. S - (Q) (S) - S E -) ({ 3 TE+TE TE } (Q) Q)
({ 3 - TE TE TE - } (E) E { 3 (TE) (TE) TE }))))
1-beat-fibonacci: NIL
num-beats: 23
slow-fibonacci: T
num-1-beat-rthms: 4
num-1-beat-groups: 2
sticking-curve: (0.0 0 22 10)
harmonic-rthm-curve: (0.0 1 22 3)
beat: 4
do-sticking: T
do-rests: T
do-sticking-curve: (0.0 1 5.5 0 11.0 1 16.5 0 22 1)
do-rests-curve: NIL
sticking-al: (not printed for brevity's sake)
sticking-rthms: (E S. E S. 32 E 32 E E E. S. 32 S. E. S. 32 S. 32
E. E)
sticking-repeats: (3 5 3 5 7 3 7 3 3 11 5 7 5 11 5 7 5 7 11 3 7 3 3
11 5 7 5 11 3 7 3 7 11 5 7 5 5 11 3 11 3 2 11 2
11 2 7 2 7 2 2 5 5 3 5)
activity-curve: (0.0 1 22 10)
main-al: (not printed for brevity's sake)
slower-al: (not printed for brevity's sake)
num-slower-bars: 22
rcs: (not printed for brevity's sake)
rests: (E Q Q. W)
rest-re: (not printed for brevity's sake)
rest-cycle: ((0 3) (1 1) (0 2) (2 1) (1 1) (3 1))
num-rthm-seqs: 19
section-id: 1
split-data: (4 7)
RTHM-SEQ-MAP: num-players: 2
players: (FL CL)
SC-MAP: palette id: RTHM-CHAIN-RSP
[...]
```

SYNOPSIS

```(defun make-rthm-chain (id num-beats 1-beat-rthms slower-rthms &key
(1-beat-fibonacci nil)
(slow-fibonacci nil)
(players '(player1 player2))
(section-id 1)
(rests '(e q q. w))
(do-rests t)
(do-rests-curve nil)
(rest-re '((2 3) (3 2) (2 2) (5 1) (3 3) (8 1)))
(rest-cycle '((0 3) (1 1) (0 2) (2 1) (1 1) (3 1)))
(activity-curve '(0 10 100 10))
(sticking-curve '(0 2 100 2))
(harmonic-rthm-curve '(0 2 100 2))
(do-sticking t)
(do-sticking-curve nil)
(sticking-repeats '(3 5 3 5 8 13 21))
(sticking-rthms '(e e e. q e s))
(split-data '(2 5)))
```

## rthm-chain/procession [ Functions ]

[ Top ] [ rthm-chain ] [ Functions ]

DATE

``` 26-Jan-2010
```

DESCRIPTION

``` Generate a list of a specified length consisting of items extrapolated from
a specified starting list. All elements of the resulting list will be
members of the original list.

The method generates the new list by starting with the first 3 elements of
the initial list and successively adding consecutive elements from the
initial list until all elements have been added.
```

ARGUMENTS

``` - An integer that is the number of items in the list to be generated.
- A list of at least 4 starting items or an integer >=4. If an integer is
given rather than a list, the method will process a list of <integer>
consecutive numbers from 1 (by default).
```

OPTIONAL ARGUMENTS

``` keyword arguments:
- :peak. A decimal number >0.0 and <=1.0. This number indicates the target
location in the new list at which the last element is to finally occur,
whereby e.g. 0.7 = ~70% of the way through the resulting list. This is an
approximate value only. The last element may occur earlier or later
depending on the values of the other arguments. In particular, initial
lists with a low number of items are likely to result in new lists in
which the final element occurs quite early on, perhaps even nowhere near
the specified peak value. Default = 0.7.
- :expt. An exponent (floating point number) to indicate the "curve" that
determines the intervals at which each successive element of the initial
list is introduced to the new list. A higher number indicates a steeper
exponential curve. Default = 1.3.
- :start-at. The number to start counting from if the 2nd argument is an
integer instead of a list. Default = 1.
- :orders. The patterns by which the elements are added. The method
cyclically applies these orders, the numbers 1, 2, and 3 representing the
three least used elements at each pass. These orders must therefore
contain all of the numbers 1, 2, and 3, and those numbers only.
Default = '((1 2 1 2 3) (1 2 1 1 3) (1 2 1 3)).
```

RETURN VALUE

``` Returns two values, the first being the new list, with a secondary value
that is a list of 2-item lists that show the distribution of each element
in the new list.
```

EXAMPLE

```(procession 300 30 :peak 0.1)

=>
(1 2 1 2 3 4 5 4 4 6 7 8 7 9 10 11 10 11 12 13 14 13 13 15 16 17 16 18 19 20 19
20 21 22 23 22 22 24 25 26 25 27 28 29 28 29 30 3 5 3 3 6 8 9 8 12 14 15 14
15 17 18 21 18 18 23 24 26 24 27 1 2 1 2 30 5 6 5 5 7 9 10 9 11 12 16 12 16
17 19 20 19 19 21 23 25 23 26 27 28 27 28 29 4 6 4 4 30 7 8 7 10 11 13 11 13
14 15 17 15 15 20 21 22 21 24 25 26 25 26 29 1 2 1 1 30 3 6 3 8 9 10 9 10 12
14 16 14 14 17 18 20 18 22 23 24 23 24 27 28 29 28 28 30 2 5 2 6 7 8 7 8 11
12 13 12 12 16 17 19 17 20 21 22 21 22 25 26 27 26 26 29 3 4 3 30 5 6 5 6 9
10 11 10 10 13 15 16 15 18 19 20 19 20 23 24 25 24 24 27 1 29 1 30 2 4 2 4 7
8 9 8 8 11 13 14 13 16 17 18 17 18 21 22 23 22 22 25 27 28 27 29 3 5 3 5 30
6 7 6 6 9 11 12 11 14 15 16 15 16 19 20 21 20 20 23 25 26 25 28 1 29 1 29 30
2 4 2 2 7 9 10 9 12 13 14 13 14 17 18), ((2 12) (20 11) (14 11) (13 11)
(9 11) (6 11) (1 11) (29 10) (25 10) (22 10) (18 10) (17 10) (16 10) (15 10)
(12 10) (11 10) (10 10) (8 10) (7 10) (5 10) (4 10) (3 10) (30 9) (28 9)
(27 9) (26 9) (24 9) (23 9) (21 9) (19 9))

(procession 300 30 :peak 0.9)

=>
(1 2 1 2 3 1 3 1 1 4 2 3 2 4 3 4 3 4 5 2 4 2 2 5 1 3 1 5 3 4 3 4 5 1 5 1 1 6 2
5 2 6 4 5 4 5 6 3 6 3 3 7 5 6 5 7 2 6 2 6 7 6 7 6 6 8 4 7 4 8 7 8 7 8 9 7 8
7 7 9 8 9 8 10 8 9 8 9 10 8 9 8 8 10 9 10 9 11 9 10 9 10 11 10 11 10 10 12
10 11 10 12 11 12 11 12 13 11 12 11 11 13 12 13 12 14 12 13 12 13 14 13 14
13 13 15 13 14 13 15 11 14 11 14 15 14 15 14 14 16 15 16 15 17 15 16 15 16
17 16 17 16 16 18 16 17 16 18 17 18 17 18 19 17 18 17 17 19 18 19 18 20 18
19 18 19 20 19 20 19 19 21 15 20 15 21 20 21 20 21 22 20 21 20 20 22 21 22
21 23 21 22 21 22 23 22 23 22 22 24 23 24 23 25 23 24 23 24 25 24 25 24 24
26 23 25 23 26 25 26 25 26 27 26 27 26 26 28 25 27 25 28 27 28 27 28 29 27
28 27 27 29 28 29 28 30 24 29 24 29 30 26 29 26 26 30 28 29 28 30 19 29 19
29 30 22 25 22 22 30 12 27 12 30 14 16 14 16 30 17), ((8 12) (22 11)
(16 11) (14 11) (12 11) (11 11) (10 11) (4 11) (3 11) (2 11) (26 10)
(19 10) (17 10) (15 10) (13 10) (9 10) (7 10) (6 10) (5 10) (1 10)
(29 9) (28 9) (27 9) (25 9) (24 9) (23 9) (21 9) (20 9) (18 9) (30 8))
```

SYNOPSIS

```(defun procession (num-results items
&key
;; what proportion of the way through should we aim to
;; reach the max number of items?  NB This is approximate
;; only: you may find the first occurrence of the highest
;; element earlier or later depending on the values of the
;; other arguments.  In particular, with a low number of
;; items the highest element will be hit very early on,
;; perhaps nowhere near the peak argument.
(peak 0.7)
;; for an exponential curve going from 3 to num <items>
(expt 1.3)
;; MDE Thu Sep 17 16:11:03 2020, Heidhausen -- allow
;; counting from another number if items is an integer
(start-at 1)
;; these are the orders we'll use at the beginning
;; (cyclically). They will then be used when we've gone
;; beyond 3 items by always using the 3 least used items.
;; NB This must contain the numbers 1, 2, and 3 only but
;; there can be 1 or any number of sublists.
(orders '((1 2 1 2 3) (1 2 1 1 3) (1 2 1 3))))
```

## rthm-chain/procession-mirror [ Functions ]

[ Top ] [ rthm-chain ] [ Functions ]

DESCRIPTION

``` Perform the same operation as the procession function, but instead of just
```

ARGUMENTS

``` The same as for procession.
```

RETURN VALUE

``` A list of the procession. Note that at the mirror point there is no
repetition, and we don't include the first element at the end. Note also
that we don't return statistics as we do with procession.
```

EXAMPLE

```(procession-mirror 33 '(1 2 3 4 5 6 7))
--> (1 2 1 2 3 3 4 3 3 5 4 6 4 7 5 6 5 6 6 5 7 4 6 4 5 3 3 4 3 3 2 1 2)
```

SYNOPSIS

```(defun procession-mirror (&rest args)
```

## rthm-chain/reset [ Methods ]

[ Top ] [ rthm-chain ] [ Methods ]

DESCRIPTION

``` Reset the various circular-sclist objects within the given rthm-chain
object to their initial state.
```

ARGUMENTS

``` - A rthm-chain object.
```

OPTIONAL ARGUMENTS

``` (- :where. This argument is ignored by the method as it is only present due
to inheritance.)
```

RETURN VALUE

``` Returns T.
```

EXAMPLE

```;;; Print the results of applying get-next to the STICKING-RTHMS slot of the
;;; given rthm-chain object, repeat, reset, and print again to see that the
;;; get-next now begins at the beginning of the slot again.

(let ((rch
(make-rthm-chain
'test-rch 150
'((((e) e) ; 4 in total
(- s (s) (s) s -)
({ 3 (te) - te te - })
((e.) s))
(({ 3 (te) te (te) }) ; what we transition to
({ 3 - te (te) te - })
({ 3 (te) - te te - })
({ 3 (te) (te) te })))
'((((q q) ; the 2/4 bars: 5 total
((q) q)
((q) q)
((q) (s) e.)
(- e e - (e) e))
(({ 3 te+te te+te te+te }) ; what we transition to
(q - s e. -)
(q (s) e.)
(q (s) - s e -)
({ 3 te+te te+te - te te - })))
((((e.) s (e) e (s) e.) ; the 3/4 bars: 4 total
(- e e - (e) e (q))
(- e. s - - +e e - (q))
(q (e.) s (q)))
(({ 3 (te) (te) te+te te+te } (q)) ; what we transition to
(- e. s - (q) (s) - s e -)
({ 3 te+te te } (q) q)
({ 3 - te te te - } (e) e { 3 (te) (te) te })))))))
(print
(loop repeat 19
collect (data (get-next (sticking-rthms rch)))))
(print
(loop repeat 19
collect (data (get-next (sticking-rthms rch)))))
(reset rch)
(print
(loop repeat 19
collect (data (get-next (sticking-rthms rch))))))

=>
(E E E E E. E E. E E Q E E. E Q E. Q E. Q E)
(E E E E E E. E E. E E Q E E. E Q E. Q E. Q)
(E E E E E. E E. E E Q E E. E Q E. Q E. Q E)
```

SYNOPSIS

```(defmethod reset ((rc rthm-chain) &optional ignore1 ignore2)
```

## rthm-chain/rthm-chain-gen [ Methods ]

[ Top ] [ rthm-chain ] [ Methods ]

DESCRIPTION

``` Generate a chain of rhythms using the procession function (internally).

The basic algorithm for generating a rthm-chain object of two parts is as
follows: The user provides an arbitrary number of 1-beat rthms (e.g. s s
(e)) and 2-3 beat slower-moving counterpoints. The method generates a
sequence from these using the procession function. Next the activity curve
is applied to this, and after that the insertion of rests. Then the
'sticking points' are generated: These come after the rests, and the
activity curves applied to these count inserted rests not seqs or beats.

NB: Rests are put into the given rthm-seq object mid-sequence, so sticking
points won't come directly after the rests, rather, at the end of the
seq.

The activity curves that turn notes into rests will be queried every beat,
so if an activity level is changed, the method won't wait until the end of
the previous level's ten beats.

NB: This method is not generally called by the user (though it can be of
course); rather, it's called by the init function.
```

ARGUMENTS

``` - A rthm-chain object.
```

OPTIONAL ARGUMENTS

``` keyword arguments:
- :rests. T or NIL to indicate whether rests are to be automatically
inserted. T = automatically insert. Default = T.
- :stick. T or NIL to indicate whether to generate the sticking points. T =
generate sticking points. Default = T.
- :num-beats. NIL or an integer to indicate how many beats are to be used
for the algorithm. NB: The method will generate considerably more beats
if also generating sticking points and inserting rests; this number
merely refers to the number of standard 1-beat rhythms to be generated.
If NIL, the method will obtain the number of beats from the NUM-BEATS
slot of the rthm-chain instance. Default = NIL.
- :use-fibonacci. T or NIL to indicate whether to use the
fibonacci-transitions method when generating the sequence from the 1-beat
rhythms (in which case these will be repeated) or the procession
algorithm (in which case they'll be alternated). T = use the
fibonacci-transitions method. Default = T.
- :section-id. An integer that is the section ID of the rthm-chain object
to be generated. This will determine the section of the rthm-seq-map into
which the references will be placed. The rthm-seq objects themselves will
also be parcelled up into an object with this ID, so ID conflicts can be
avoided if combining two or more sections generated by separate
rthm-chain objects. Default = 1.
- :wrap. An integer or NIL to determine the position within the list of
1-beat rhythms and slow rhythms from which the generated rhythm chain
will begin. NIL = begin at the beginning. Default = NIL.
- :split. T or NIL to indicate whether to split up longer generated bars
(e.g. 7/4) into smaller bars. If this is a two-element list it represents
the min/max number of beats in a bar (where a 6/8 bar is two compound
beats). Default = '(2 5).
```

RETURN VALUE

``` the number of rthm-seqs we've generated
```

SYNOPSIS

```(defmethod rthm-chain-gen ((rc rthm-chain)
&key
(use-fibonacci t)
(rests t)
(stick t)
(section-id 1)
num-beats
wrap)
```

## rthm-chain/split [ Methods ]

[ Top ] [ rthm-chain ] [ Methods ]

DATE

``` 29-Jan-2011
```

DESCRIPTION

``` Split the longer generated bars into smaller ones where possible.
```

ARGUMENTS

``` - A rthm-chain object.
```

OPTIONAL ARGUMENTS

``` keyword arguments:
- :min-beats. An integer that is the minimum number of beats in the
resulting bars. This is a target-length only, and may not be adhered to
strictly if durations do not allow. Default = 2.
- :max-beats. An integer that is the maximum number of beats in the
resulting bars. This is a target-length only, and may not be adhered to
strictly if durations do not allow. Default = 5.
- :warn. T or NIL to indicate whether to print a warning to the listener if
the current bar cannot be split. T = print. Default = NIL.
- :clone. T or NIL to indicate whether the rthm-seq of the given rthm-chain
object should be changed in place or changes should be made to a copy of
that object. T = create a copy to be changed. Default = T.
```

RETURN VALUE

``` Returns T.
```

EXAMPLE

```;;; Make a rthm-chain object using make-rthm-chain with the :split-data
;;; argument set to NIL and print the number of bars in each resulting rthm-seq
;;; object. Apply the split method and print the number of bars again to see
;;; the change.

(let* ((rch
(make-rthm-chain
'test-rch 150
'((((e) e) ; 4 in total
(- s (s) (s) s -)
({ 3 (te) - te te - })
((e.) s))
(({ 3 (te) te (te) }) ; what we transition to
({ 3 - te (te) te - })
({ 3 (te) - te te - })
({ 3 (te) (te) te })))
'((((q q) ; the 2/4 bars: 5 total
((q) q)
((q) q)
((q) (s) e.)
(- e e - (e) e))
(({ 3 te+te te+te te+te }) ; what we transition to
(q - s e. -)
(q (s) e.)
(q (s) - s e -)
({ 3 te+te te+te - te te - })))
((((e.) s (e) e (s) e.) ; the 3/4 bars: 4 total
(- e e - (e) e (q))
(- e. s - - +e e - (q))
(q (e.) s (q)))
(({ 3 (te) (te) te+te te+te } (q)) ; what we transition to
(- e. s - (q) (s) - s e -)
({ 3 te+te te } (q) q)
({ 3 - te te te - } (e) e { 3 (te) (te) te }))))
:split-data nil)))
(print
(loop for rs in (data (get-data-data 1 (palette rch)))
collect (num-bars rs)))
(split rch :min-beats 1 :max-beats 3 :clone nil)
(print
(loop for rs in (data (get-data-data 1 (palette rch)))
collect (num-bars rs))))

=>
(1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 1 1 2 2 1 1 2 2 2 2 1 1 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2
2 2)
(1 1 4 4 2 7 4 4 3 3 4 4 2 9 7 7 2 5 5 5 2 6 1 1 2 13 3 3 4 4 5 5 2 7 5 5
7 7 9 9 2 7 2 9 3 3 2 9 1 1 5 5 9 9 3 3 2 7 5 5 4 4 2 11 1 1 2 10 2 9 2 6
7 7 7 7)
```

SYNOPSIS

```(defmethod split ((rc rthm-chain) &key
(min-beats 2) (max-beats 5) warn (clone t))
```

## rthm-seq-map/rthm-chain [ Classes ]

[ Top ] [ rthm-seq-map ] [ Classes ]

NAME

``` rthm-chain

File:             rthm-chain.lsp

Class Hierarchy:  named-object -> linked-named-object -> sclist ->
circular-sclist -> assoc-list -> recursive-assoc-list ->
sc-map -> rthm-seq-map -> rthm-chain

Version:          1.0.12

Project:          slippery chicken (algorithmic composition)

Purpose:          Algorithmic generation of rthm-seqs that include
slower-moving counterpoint and a means to control
activity development through curves.  Here we generate a
rthm-seq-map and its associated palette algorithmically.

Say we have 9 irregular 1 beat duration patterns; these
would enter in the sequence defined by (procession x 9)
where x would be the number of patterns to generate.

Rests are inserted at regular but changing intervals e.g

3x every 2 beats (6)
2x every 3 beats (6)
3x every 5 beats (15)
2x every 8 beats (16)

e, q, and q. rests are used by default, in a sequence
determined by a recurring-event instance.

In order to make music that 'progresses' we have curves
with y values from 1-10 indicating how much activity
there should be: 1 would mean only 1 in 10 beats would
have notes in/on them, 10 would indicate that all do.  We
use the patterns given in
activity-levels::initialize-instance, where 1 means
'play', 0 means 'rest'.  There are three examples of each
level so that if we stick on one level of activity for
some time we won't always get the same pattern: these

A slower moving (bass) line is also added that is made up
of 2 or 3 beat groups---if the activity curve indicates a
rest, then the whole 2-3 beat group is omitted.

There are also 'sticking points' where a rhythm will be
repeated a certain number of times (either s, e, e., or q
by default).  Sticking happens after rests.  This can be
controlled with an activity envelope too, also indicating
one of the 10 patterns above (but also including 0).  A 0
or 1 unit here would refer to a certain number of repeats
(1) or none (0).  How many repeats could be determined by
something like: (procession 34 '(2 3 5 8 13) :peak 1
:expt 3) There's always a slower group to accompany the
sticking points: simply the next in the sequence,
repeated for as long as we stick

The harmonic-rthm curve specifies how many slower-rthms
will be combined into a rthm-seq (each rthm-seq has a
single harmony).  The default is 2 bars (slower-rthms)
per rthm-seq.

Author:           Michael Edwards: m@michael-edwards.org

Creation date:    4th February 2010