Common Music Reference Manual
 

Top Objects Processes IO Scales Data Patterns Plotter Utilities Index

5  Patterns

Patterns are containers that generate data according to pattern specific ordering rules. Patterns can organize any type of lisp data and may also include nested subpatterns that define different local orderings inside the surrounding pattern. Patterns organize their data into chunks. The period length of a pattern determines the number of elements that make up each chunk of data. Elements can be read one at a time or in chunks using the next function. Patterns may also have repeat factors that set a ceiling on the number of periods, or chunks, that the pattern returns. If a pattern reaches its repeat limit it will return an end of data marker for all subsequent calls to next. Pattern properties such as the period length and repeat limit are specified when the pattern is created with new. Most pattern properties may be specified as single values or as patterns of values. Property patterns are read once each period of the pattern.

See the section Working with Patterns for information about creating patterns and accessing elements from patterns.

5.1 Pattern Classes

The pattern class is the root for a number of genericn pattern classes:
  1. cycle
  2. line
  3. palindrome
  4. heap
  5. random
  6. markov
  7. graph
  8. funcall
  9. accumulation
  10. rotation
  11. rewrite
In addition to this set of generic pattern classes there are several specialized pattern classes that implement more restricted functionality:
  1. range
  2. transposer
  3. chord
  4. pval

All patterns support the following slot initializations:

of list
Sets the elements of the pattern to the data in list.
notes list
Like of but parses list as notes.
keynums list
Like of but parses list as keynums.
rhythms list
Like of but parses list as rhythms.
amplitudes list
Like of but parses list as amplitudes.
for {number | pattern}
Sets the period length of the pattern to number or pattern of numbers.
repeat {number | pattern}
Sets the repetition factor of the pattern to number or pattern of numbers.
name {string | symbol}
Sets the name of the pattern to string or the print name of symbol. A named pattern can be references as an element inside another pattern using the #! read macro.
parsing function
Sets the pattern parser to function. This function is called on successive elements passed to the pattern when the pattern is created. The function should accept one argument, the element to parse.
returning function
Sets the pattern's return function to function. This function is called each time an element is read from the pattern and should return a value to use in place of the element. The function is passed one or two arguments, depending on the number of lambda parameters the function has. If function has one lambda parameter it is passed the pattern value that will be returned. If function has two lambda parameters it is passed the value and the state of the pattern.

cycle [Class]

Enumerates data in sequential order and loops back to the first element after the last element has been reached.

Example 5-1

? (setf x (new cycle of '(a b c d)))
#<cycle @ x112323>

? (next x 12)
(a b c d a b c d a b c d)

? (setf x (new cycle keynums '(c5 d e f g a) for 12))
#<cycle @ x112323>

?(next x t)
(72 74 76 77 79 81 72 74 76 77 79 81)

line [Class]

Enumerates data in sequential order and sticks on the last element once it has been reached.

Example 5-2

? (setf x (new pattern of '(a b c d) in line))
#<line @ x112323>

? (next x 12)
(a b c d d d d d d d d d)

? (setf x (new line of (list 'a 'b 'c (new random of '(d e)))))
#<line @ x112323>

? (next x 12)
(a b c e e d e d e d d d)

palindrome [Class]

Enumerates data in palindromic order. Subpatterns continue to produce their own ordering.

palindrome supports the following slot initializations:

elide {t | :first | :last}
If elide is t then the first and last elements in the pattern are not directly repeated when the pattern reverses direction. If the value is :first then only the first element is elided, otherwise if the value is :last then only the last element is elided.

Example 5-3

? (setf x (new palindrome of '(a b c d)))
#<palindrome @ x54F5AD6>

? (next x 16)
(a b c d d c b a a b c d d c b a)

? (setf x (new palindrome a b c d elide t))
#<palindrome @ x54F5AD6>

? (next x 12)
(a b c d c b a b c d c b a b c d)

heap [Class]

Enumerates data by random permutation (sampling without replacement).

heap supports the following slot initializations:

state random-state
Sets the random state object of the pattern to random-state. Defaults to *random-state*.

Example 5-4

? (setf x (new heap notes '(a b c d)))
#<heap @ x54F5AD6>

? (next x 12)
(a4 b4 c4 d4 b4 c4 a4 d4 d4 b4 a4 c4)

random [Class]

Enumerates data in random order (sampling with replacement).

random supports the following slot initializations:

state random-state
Sets the random state object of the pattern to random-state. Defaults to *random-state*.

By default, each element in a random pattern has an equal probability of selection and each element may be repeated in direct succession any number of times. This behavior can be modified for any element by specifying the element as a node, a list of the element to be returned by the pattern followed by zero or more properties and values:

(element {property value}*)

random supports the following node properties:

weight {number | pattern}
Sets the probability of the node relative to the probabilities of the other nodes to number. The default weight for each node is 1. The weight may also be specified as a pattern of numbers, in which case a new weight will be selected for each period in the random pattern.
min number
Sets a floor on how many direct repetitions element must be made before a new element might be selected.
max number
Sets a ceiling on how many direct repetitions of the element might be made before a new element must be selected.

Example 5-5

? (setf x (new random of '((a max 1)
                           b
                           (c weight 4)
                           d)))
#<random @ x554816E>

? (next x 12)
(a c c c a c c c d b c c)

markov [Class]

Implements 0 to nth order Markov chains.

markov supports the following slot initializations:

past ({id}*)
Initializes the pattern with an explicit list of past choices expressed as node identifiers.

Each element in a markov pattern is specified as transition rule:

({past}* -> {next | (next weight)}+)
past is zero or more identifiers that define the "left side" of the transition rule. Values nearer the -> are more recent past choices. The number of past values in the left-hand side determines the Markov order of the pattern. Any order is possible but every transition rule must have the same number of past values. Values to the right of -> define the set of outcomes. By default each outcome has the same probability of being selected. To alter the weight of an outcome specify it in a list together with its weight. For example the transition rule:
(c -> a (b 2) c)
defines a 1st order Markov transition whose outcomes a, b or c are triggered if c was the last value generated. Outcome b has twice the probability of being selected as either a or c. The transition rule:
(q w a -> e r (d 3) g)
describes a third-order transition in which a is the most recent past outcome. The transition rule:
(* x a -> foo bif zuz)
demonstrates the * "wildcard" that matches any value in its position. * allows multiple transitions with identical outcomes to be collapsed to a single rule. Finally, the transition rule:
(-> a (b .1) c)
describes a 0th order Markov transition, equivalent to weighted random selection. Only a single transition rule should be specified in a 0th order Markov pattern.

Example 5-6

;; a second order Markov pattern of Happy Birthday
(setf x (new markov
             of '((d4 c4 -> (f4 .5) (g4 .5))
                  (d4 bf4 -> bf4)
                  (c4 d4 -> c4)
                  (c4 c4 -> (d4 .667) (c5 0.333))
                  (c4 f4 -> e4)
                  (c4 g4 -> f4) 
                  (c4 c5 -> a4)
                  (f4 c4 -> c4) 
                  (f4 e4 -> (c4 .5) (d4 .5))
                  (f4 g4 -> f4)
                  (e4 d4 -> bf4)
                  (e4 c4 -> c4)
                  (g4 f4 -> c4)
                  (c5 a4 -> f4)
                  (a4 f4 -> (e4 .5) (g4 .5))
                  (bf4 a4 -> f4)
                  (bf4 bf4 -> a4))))
#<markov @ x558488E>

? (next x 20)
(g4 f4 c4 c4 d4 c4 g4 f4 c4 c4 d4 c4 f4 e4 d4 bf4 bf4 a4 f4 e4)

See markov-analyze for more information about markov patterns.

graph [Class]

Enumerates data according to transition rules associated with each element.

graph supports the following slot initializations:

selector function
Sets the node selection function of the graph. The function is passed three values, the pattern, the last node and the list of ids representing the past selections. Defaults to the system's graph traversal function #'default-graph-node-select.
props list
Sets the property list of the graph to list. This list can be used to cache information for a specific selector function.
last ({id}*)
Initializes the graph to a specific list of ids representing past node choices.

Elements in a graph are represented as nodes. Each node must be specified as a list:

(element {property value}+)
where element is the element to return from the node.

graph supports the following node properties:

-> {id | pattern}
Sets the transition link for the graph node. This option is required for each node. The value may be a single identifier or a pattern of identifiers.
id datum
Sets datum to be the unique identifier for the node in the pattern. The identifier may be any LISP datum as long as its uniquely represented in the pattern. If omitted, the identifier defaults to the element itself. It is good practice to provide each node with an explicit id that is independent of the actual element returned by the node.

funcall [Class]

Implements user defined patterns by calling a function each time a new period of items is needed. The function is passed no arguments and should return a list of elements representing the next period in the pattern or else nil if there are no more elements.

Example 5-7

? (setf x (new funcall of #'(lambda () (list 1 2 (random 10000)))))
#<funcall @ x560EDA6>

? (next x 12)
(1 2 9693 1 2 1292 1 2 1777 1 2 9518)

accumulation [Class]

Enumerates data together with the set of items that have been enumerated so far. The process starts over when all the items have been accumulated.

Example 5-8

? (setf x (new accumulation of '(a b c d)))
#<accumulation @ x560EDA6>

? (next x t)
(a a b a b c a b c d)

rotation [Class]

Enumerates items in a rotation. Elements are rotated each period in the pattern by swapping pairs of elements belonging to a specific rotational scheme.

rotation supports the following slot initializations:

rotations (start step width end)
The list that describes the rotational characteristics of the pattern. The list contains up to four independent parameters: start is the starting index (zero based) in the elements for swapping to begin, step is the distance to move after each swap. width is the distance between each pair to swap, and end marks the position to end element swapping. The rotation list defaults to (0 1 1 *), which causes elements in the pattern to rotate leftward.

Example 5-9

? (setf x (new rotation of '(a b c d)))
#<rotation @ x565D46E>

? (loop repeat 4 collect (next x t))
((a b c d) (b c d a) (c d a b) (d a b c))

The file "cm:examples;ring.cm" contains example rotations that implement change ringing patterns developed by church bell ringers in England.

rewrite [Class]

Enumerates elements from successive generations of elements according to user specified rewrite rules.

rewrite supports the following slot initializations:

rules list
Sets the rewrite rules of the pattern to list.
generations number
Sets the number of generations to actually generate. After number of generations the pattern simply reuses elements from the last generation, as if the pattern were a cycle.

Rewrite rules are expressed in terms of nodes and node identifiers. Two different styles of rule specification are supported.

1. Context-free Rules (rules associated with nodes) The first style of rule specification associates a rewrite rule with each node in the pattern. This method is capable of describing many sorts of context-free morphologies. The form of each node is similar to the graph pattern:

({element} {property value}+)
where element is the element to return from the pattern followed by one or more property value pairs.

rewrite supports the following node qualifiers:

id datum
Sets datum to be the unique identifier for the node in the pattern. The identifier may be any LISP datum as long as its uniquely represented in the pattern. If omitted, the identifier defaults to the element itself. It is good practice to provide each node with an explicit id that is independent of the actual element returned by the node.
-> {id | ({id}+) | pattern | nil}
Sets the rewrite expression for the node. The value may be a single identifier, a list of identifiers, a pattern or nil. If the value is nil the node is terminal, ie. it produces no successor(s) in the pattern's next generation. If the value is a pattern then the pattern is read to produce a successor term each time the node is rewritten. Otherwise the value should be an id or list of ids that identify successor node(s) in the next generation.

2. Context-sensitive Rules (rules applied to nodes) The second style of rule specification permits context-sensitive rules (rules involving more than one node in their left hand side) to be defined. In this method a list of rules is associated with the entire pattern rather than with the nodes in the pattern. This means that there may be more or fewer rules than there are nodes. The rule list is interpreted as an ordered set; to produce a new generation, each node in the current generation is matched against the rule list to find the successor rule to apply to the node. The first rule that matches is triggered and the id(s) in the right-hand side of the rule produce the successor node(s) in the next generation.

Node specification for the second method is similar to the first except that:

Each rule in the second style of rule specification is a list of the form:
({id}+ -> {id}*)
The -> operator divides each rule into two sides. The left-hand side of the rule defines the "matching target" and the right-hand side defines the rewrite succession. Either or both sides may contain more than one id. If the left-hand side of the rule is a single id then the rule matches any node with the same id. If the left-hand side has more than one id (a context-sensitive rule) then the rule matches if the "strict predecessor" in the left-hand side matches the current node and the nodes around the current node in the generation match the ids around the strict predecessor in the left-hand side. The strict predecessor id is marked as a list. Every context rule must contain exactly one strict predecessor in its left hand side.

Three examples of context sensitive rules:

(1 (1) 2 -> 3)
Means node 1 rewrites to node 3 wherever 1 is preceded by itself and followed by 2 in the current generation.
(1 * (2) -> 1 2)
means node 2 rewrites to 1 and 2 whenever 1 occurs two positions earlier in the current generation.
(5 (3) 3 4 ->)
means node 3 rewrites to nothing if preceded by 5 and followed by itself and 4 in the current generation. Note that the right-hand side may be empty and that the left-hand side may contain the wild card * which matches any single element in the current generation.

Example 5-10

? (setf x (new rewrite
               of '((a -> (a b a)) 
                    (b -> (b b a)))
               initially 'b))
#<rewrite @ x555746E>

? (next x 20)
(b b b a b b a b b a a b a b b a b b a a)

5.2 Specialized Pattern Classes

range [Class]

Enumerates numbers in a range.

range supports the following slot initializations:

from {number | pattern}
The start value to return from the range. Defaults to 0. from is reset each time it exceeds range boundaries or at the end of each period if there are no boundaries on the range.
initially {number}
Like from but specifies that the value should not reset at the end of each period. initially can only appesar if the range has no upper or lower boundary.
to {number | pattern}
Optional inclusive upper bound on the range. If this bound is exceeded the the range is reset to from.
below {number | pattern}
Like to except that the upper bound is exnclusive.
downto {number | pattern}
Optional inclusive lower bound for the enumeration. If this bound is exceeded the range is reset to from.
above {number | pattern}
Like downto except that the lower bound is exlusive.
by {number | pattern}
The increment between numbers in the range. If by is a pattern its value is reselected each time from is reset.
stepping {pattern}
Like by but the increment value changes each selection.
For bounded ranges the default period length is the number of values enumerated between the boundaries. For unbounded ranges the default period length is 1. Note that a single range may contain both an upper and a lower bounds. Combining these with a random stepping value implements bounded random walks.

Example 5-11

? (setf x (new range to 10))
#<range @ x4050B9E>

? (next x t)
(0 1 2 3 4 5 6 7 8 9 10)

? (setf x (new range from 60 for 5))
#<range @ x4050B9E>

? (next x 10)
(60 61 62 63 64 60 61 62 63 64)

? (setf x (new range initially 60 for 5))
#<range @ x4050B9E>

? (next x 10)
(60 61 62 63 64 65 66 67 68 69)

? (setf x (new range from 10 downto -10 by 2))
#<range @ x4050B9E>
(10 8 6 4 2 0 -2 -4 -6 -8 -10)

? (setf x (new range from (new cycle 1 5) to 10))
#<range @ x4050B9E>

? (next x t)
(1 2 3 4 5 6 7 8 9 10)

? (next x t)
(5 6 7 8 9 10)

? (setf x (new range from 60 
               stepping (new random -2 -1 1 2)
               to 65 downto 55))
#<range @ x4050B9E>

? (next x t)
(60 59 58 59 60 62 64 62 64 65)

? (next x t)
(60 61 62 64 62 64)

transposer [Class]

A pattern that return notes, keynums or lists of the same by combining transposition data with a transposition offset. Transposed data may be optionally retrograded and inverted.

transposer supports the following slot initializations:

of {list | pattern}
The data to transpose. If the data is a pattern then successive elements are read from the pattern and transposed. These elements can be notes, keynums or lists of the same. List are treated as single units by the transposer.
by {note | keynum | pattern}
Sets the transposition offset. If by is a pattern a new offset is selected each period of the transposition data. by may also be specified as on.
stepping {pattern}
Like by execept that the transposition offset is read each time an element is transposed rather than each period.
form {p i r ri | pattern}
A symbol or pattern of symbols that specifies the "row form" for list data returned by the transposer. p stands for prime, i for inversion, r for retrogade and ri for retrograde-inversion. Either symbols or keywords can be used to specify the row form. The row form is read once each period or once each element according to by or stepping.
mod {number | pattern}
Optional modulus on list data.
scale {scale}
The scale to use to transpose data in. Detaults to *scale*, the standard chromatic scale.

chord [Class]

A chord is a special type of pattern that returns a list of chord data each time it is read by the next function. If chord data is specified as a single pattern the chord can generate different data each time it is read.

The braces [] are a read macro that creates a chord pattern out of the enclosed items..

Example 5-12

;; a process that plays mostly chords. The middle chord selects
;; different chord members each time it is picked. 

(defprocess dochords ()
  (process with pat = (new heap
                           [c4 e4 g4]
                           [(new heap df4 ef4 gf4 af4 bf4 df5 ef5 for 3)]
                           [e4 a4 cs5]
                           (new cycle bf6 bf2 for 1))
           repeat 32
           do (doeach (k (next pat)) 
                (output (new midi keynum k time (now))))
           wait .5))

? (events (dochords) "midi.port")

pval [Class]

Holds a LISP expression to be evaluated each time it is read from the pattern.

Example 5-13

? (setf x (new cycle 
               a 
               (new pval (between 1000 5000))
               b))
#<cycle @ x57EDACE >

? (next x 12)
(a 2760 b a 3589 b a 1175 b a 1515 b)

5.3 Working with Patterns

Patterns are created using make-instance or the new macro.
(new heap of '(a b c))

(make-instance 'heap :of '(a b c) )

Once a pattern has been created successive elements can be enumerated, or read, using the next function.

next pattern &optional length [Function]

Returns one or more elements from pattern according to length. The default value of length is nil which means that just the next element from pattern is returned together with a second value marking the pattern's state as a result of the read. (The second value can simply be ignored if it is not of interest to the caller.) If length is t then next returns a list containing the next period chunk from the pattern. Otherwiselength should be the number of elements to return in a list.

Example 5-14

? (setf x (new cycle of '(a b) repeat 2))
#<cycle @ x112323>

? (next x)
a
nil

? (next x)
b
:end-of-period

? (next x t)
(a b)

? (next x )
:end-of-data
:end-of-period

pattern? object [Function]

Returns true if object is a pattern.

eop? state [Function]

Returns true if state is at end-of-period. state can be the state returned from a pattern or the pattern object itself.

eod? value [Function]

Returns true if value is at end-of-data. value can be the value returned from a pattern or a pattern object itself.

pattern-last-value pattern [Function]

Returns the last value returned by the pattern.

pattern-last-state pattern [Function]

Returns the last state returned by the pattern.

map-pattern-data function pattern [Function]

Maps function over each element in pattern. (Note: the elements in a pattern may be stored in a different that what the user specified to the pattern.)

*patterns* [Variable]

The list of implemented pattern classes.


Common Music Homepage  |  © 2002 Heinrich Taube Last Modified: 20 May 2002