Common Music Reference Manual
 

Top Objects Processes IO Scales Data Patterns Plotter Utilities Index

4  Working with Parameterized Data

This chapter presents a variety of different strategies for working with various types of parameterized data in music composition. For a discussion about frequency and scales see the separate chapter Frequency, Tunings and Modes in the documentation.

4.1 Time and Rhythm

Time values can be expressed as seconds, milliseconds, or as proportional quantities scaled by a tempo factor. The rhythm function converts proportional values to time in seconds suitable for event parameters such as time or duration or as wait values in a process definition.

A proportional value can be a Lisp ratio (such as 1/4, 7/8, 1/3, 2 and so on) or a rhythmic symbol. A rhythmic symbol consists of a letter: M=maxima, L=longa, B=brevis, W=whole, H=half, Q=quarter, E=eighth, S=sixteenth, T=thirty-second, X=sixty-fourth. This symbol may be optionally preceded by T (triplet) or Q (quintuplet) and optionally followed by any number of dots. Mensural symbols also support simple "expressions" that add, subtract and multiply.

Example 4-1

q
e.
tq
h...
qh
s+tq
w-ts
w*4

rhythm &optional tempo beat [Function]

Returns the value of rhythm converted to seconds. rhythm can be a number, a rhythmic symbol or list of the same. tempo provides the metronome speed and defaults to the value of *tempo*, initially set to 60.0. beat specifies the metronome's pulse and defaults to the value of *beat*, initially set to .25 (quarter note.) If tempo and beat are both rational then rhythm will return rational values.

Example 4-2

? (rhythm 'q)
1.0

? (rhythm 'te 60 1/4)
1/3

? (rhythm 1/4 120.0)
.5

? (rhythm 1/4 60 1/3)
3/4

? (rhythm '(q th e.. x) 90)
(2/3 8/9 7/12 1/24)

? (setf *tempo* 120.0)
120.0

? (rhythm '(q th e.. x) )
(0.5 0.6666666666666666 0.4375 0.03125)

*tempo* [Variable]

The default metronome factor used by the rhythm function. Defaults to 60 beats per minute.

*beat* [Variable]

The default metronome beat used by the rhythm function. Defaults to .25, or quarter note.

4.2 Logical Amplitude

Amplitude values can be specified directly or by using logical amplitudes in conjunction with the amplitude function.

amplitude amp &optional softest loudest power [Function]

Converts logical amplitude amp to a value between softest and loudest according to the power curve. A logical amplitude is a number between 0 and 1 or an amplitude symbol: niente, pppp, ppp, pp, p, mp, mf, f, ff, fff, ffff. The values of softest, loudest and power default to the value of the global variables *softest*, *loudest* and *power*.

Example 4-3

? (amplitude 'mp)
.5

? (amplitude 'mp 0 127)
63.5

? (amplitude 1/2 0 127 1)
127/2

? (amplitude .5 0 1 4)
0.0625

*softest* [Variable]

The default minimum amplitude value when the logical amplitude is 0.0. Defaults to 0.0.

*loudest* [Variable]

The default maximum amplitude value when the logical amplitude is 1.0. Defaults to 1.0.

*power* [Variable]

The power curve for calculating amplitude values from logical amplitudes. The default value is 1.0. which means that amplitude values increase linearly from *softest* to *loudest*. Values greater than 1.0 cause the power curve to become increasing exponential toward the maximum value.

4.3 Scaling and Offsetting

rescale number old-min old-max new-min new-max [Function]

Returns a value between new-min and new-max that is proportional to number between old-min and old-max.

Example 4-4

? (rescale .51 0 1 0 100)
51.0

? (rescale 1.2 1 2 80 90)
85.0

fit number min max &optional mode [Function]

Forces number to lie between min and max according to mode. If mode is :reflect (the default), then the min and max boundaries reflect the value back into range. If mode is :wrap then fit returns the remainder of number modulus the boundary range.

Example 4-5

? (loop for i from -20 to 20 by 5 collect (fit i 0 10))
(0 5 10 5 0 5 10 5 0)

expl power &key :y0 :y1 :base [Function]

Returns an exponential value between :y0 and :y1 according to power, which ranges from 0 to 1. When power is 0 :y0 is returned, when power is 1 :y1 is returned. :y0 and :y1 default to 0 and 1, respectively. :base determines the slope of the exponential curve, if it is less than 1 then the exponential curve is concave, otherwise a convex curve is produced. The default value of :base is 2.

Example 4-6

? (expl 0 5 1 1/256)
0.0

? (expl 1 5 1 1/256)
5.0

? (expl .5 5 1 1/256)
1.235

;;; create envelope ramping from 3 to .5

? (loop for i to 1 by .2 append (list i (expl i 3 .5 1/256)))
(0 3.0 0.2 1.31 0.4 0.76 0.6 0.58 0.8 0.51 1.0 0.5)

explseg i length sum power [Function]

Returns the ith segment of length number of exponential segments that add up to sum. The exponential curve is defined by power, where 0<power<1 yields concave slopes and power>1 yields convex slopes.

explsegs length sum power [Function]

Like explseg but returns a list of length number of exponential segments.

Example 4-7

? (setf l (explsegs 4 10 2))
(1.8920711500272102 2.250064473703739 2.6757926813433408
  3.18207169492571)

? (apply #'+ l)
10.0

quantize value step [Function]

Rounds value to the nearest multiple of step.

Example 4-8

? (loop repeat 10 collect (quantize (random 1.0) .2))
(0.8 0.4 0.2 0.2 0.6 0.8 0.8 0.2 0.4 0.4)

decimals number places [Function]

Rounds number to places number of decimal places.

Example 4-9

? (decimals 0.5931282184890065 3)
0.593
? (decimals 1/3 3)
0.333

4.4 Envelopes and Interpolation

An envelope is a list of x y values. Plotter can be used to create and edit envelopes graphically. Use Plotter's Import and Export commands to convert between envelopes and their graphical displays.

lookup x list &key :test [Function]

Returns the "y value" of x in list according to :test. The default test function is <. Since lookup does not perform interpolation the y entries in list do not need to be numeric values.

Example 4-10

? (lookup .5 '(0 c4 .4 c5 .7 c6))
C6

interp x &rest coords [Function]

Returns a linear interpolated y value for x in coords.

Example 4-11

? (interp 75 0 0 50 .5 100 0)
.25

interpl x envelope &key :scale :offset :base :min :max [Function]

Returns the y value of x in envelope, a list of x y coordinates. The value returned can be optionally scaled and offset according to the :scale and :offset arguments. :scale and :offset can also be specified as :min and :max, in which case :min becomes the offset and :scaler is set to max-min. If :base is 1 (the default) then linear interpolation is performed. If :base is greater than one then the y value is interpolated along an exponential curve; values greater than 1 produce concave curves, values less than 1 but greater than 0 produce convex curves.

Example 4-12

? (interpl 50 '(0 0 100 1) :scale 2 :offset 3)
4.0

tendency x low high &key :scale :offset :min :max :state [Function]

Returns a random y value that lies between the value of x in low and high envelopes. If low or high are unchanging they may be expressed as a single value. Use :random to provide a random generator other than the random function. This generator is passed two arguments: the floating point range high to low and the :state, a random state object that defaults to *random-state* The value returned by tendency can be optionally scaled and offset according to the :scale and :offset arguments. :scale and :offset can be alternately specified as :min and :max, in which case :min is the offset and :scaler is set to (max-min).

Example 4-13

? (loop for i by .2 to 2
        collect (tendency i '(0 0 1.5 .5) '(0 1 1.5 .75))
(.37 .77 .62 .50 .44 .34 .75 .48 .55 .66 .69)

rescale-envelope env &key :x-min :x-max :y-min :y-max [Function]

Returns a copy of env with x and y values optionally rescaled to lie between new minima and maxima.

Example 4-14

? (rescale-envelope '(0 0 .5 .5 1 1) :y-min 100 :y-max 200 )
(0 100 0.5 150.0 1 200)

? (rescale-envelope '(0 0 .5 .5 1 1) :x-min 0 :x-max 100 )
(0 0 50.0 0.5 100 1)

? (rescale-envelope '(0 0 .5 .5 1 1) :x-max 100 :y-max 100 )
(0 0 50.0 50.0 100 100)

4.5 Random Selection

ran &key :below :from :type :a :b :state [Function]

Generates random numbers in a variety of different distributions.

ran accepts the following keyword arguments:

:below number
Sets the exclusive upper bounds for random number generation. Defaults to a value specific to the type of distribution specified to ran, usually 1.0.
:from number
Sets the inclusive upper bounds for random number generation. Defaults to a value specific to the type of distribution specified to ran, usually 0.0.
:type
Sets the distribution for random number generation to type specified as a symbol or keyword. Defaults to :uniform.

ran supports the following distribution types:

:uniform
Numbers are evenly distributed between :from and :below. :uniform can also be specified as :u.
:low-pass
Prefers lower numbers between :from and :below. Density = f(x)=2*(1-x) for {x 0<1}. Mean = .2929. :low-pass can also be specified as :lp.
:high-pass
Prefers higher numbers between :from and :below. Density = f(x)=2*(1-x) for {x 0<1}. Mean = .2929. :high-pass can also be specified as :hp.
:band-pass
Prefers middle numbers between :from and :below. Mean = n/2. :band-pass can also be specified as :bp.
:beta
The :a and :b parameters to ran determine beta density behavior. When a=b=1 uniform distribution results. When a=b, the distribution is symmetric around .5. When a<1 and b<1 then density of large and small numbers increases. When a>1 and b>1, density is similar to the gaussian distribution.
:exponential
Returns a floating point value >0. The :a parameter to ran is a stretching factor (lambda). Increasing :a prefers smaller numbers. The value returned is unbounded but when :a=1 then %99.9 of the time the value is less than 6.9077554, ie -log(.001). Density = f(x)=(exp -x). Mean=1.0 :exponential can also be specified as :exp.
:gaussian
Gaussian (normal) distribution returns an unbounded value. The spread (standard deviation) is 1.0 centered at 0, so 68.26% of the results are -1<=x<=1, and 99.74% of the results are -3<=x<=3. :gaussian can also be specified as :gauss.
:cauchy
Returns an unbounded value. The density function is a bell shaped curve centered at 0 similar to a normal distribution but with more values at the extremes. The mean and standard deviation of the Cauchy distribution are undefined. If the parameter :a is non-nil, only positive values are returned. Density = f(x)=1/(pi(1 + x^2))
:poisson
A discrete distribution: returns positive integer values, theoretically unbounded but practically limited by the shape parameter. :a is a shape parameter which must be positive. The mean is a and the standard deviation is sqrt(a)
:gamma
Returns a floating point value >0. :a is the shape parameter which must be positive. In this implementation, a can only take integer values. If a non-integer is provided, the value is rounded. When a=1, the distribution is the same as exponential. As a increases, the probability density function becomes a curve with mean = a and standard deviation = sqrt(a)

The :type argument may also be specified as :distribution.

:a number
An optional control parameter whose interpretation depends on the distribution type.
:b number
An optional control parameter whose interpretation depends on the distribution type.
:state random state
The random state object to use. Defaults to the Lisp variable *random-state*.

between lb ub &optional exclude state [Function]

Returns a random number equal to or greater than lb but less than ub. If excludeis specified that value will not be selected. state is an optional random state object and defaults to *random-state*.

Example 4-15

? (between 1 2)
1

? (between 1 2.0)
1.234551

? (loop  repeat 10 for n = (between 1 5 n) collect n)
(4 2 3 4 1 4 2 3 1 4)

vary value pct &optional fit state [Function]

Returns a random number that deviates from value by up to pct percentage. fit determines how the variance is to be offset from value; :above returns a percentage variance with value at the minimum, :below returns a percentage variance with value at the maximum and :around returns a percentage variance with value in the middle. The default value is :around.

Example 4-16

? (vary 100 .05 :around)
98.2
(vary 100 .05 :above)
103.237
(vary 100 .05 :below)
96.933

odds prob &optional true false state [Function]

Returns true if a randomly generated number is less than prob, a number between 0.0 and 1.0. Otherwise returns false. The default values for true and false are t and nil, respectively. state is the random state object and defaults to *random-state*

Example 4-17

? (odds 1)
t

? (odds .2 "Yup" "Nope")
"Nope"

pick &rest args [Function]

Returns a randomly chosen argument to the function.

Example 4-18

? (pick 1 2 3 4 :foo 5)
3

? (pick 1 2 3 4 :foo 5)
:foo

pickl list &key :end :start :avoid :state [Function]

Returns a randomly chosen element from list, which may be a list or array. :start is the lower selection bound and defaults to 0. :end is the upper selection bound and defaults to the length of list. Use :avoid to specify an element that cannot be directly reselected. :state defaults to *random-state*.

Example 4-19

? (pickl '(1 two 3 four 5))
3

? (pick "foobar" :start 1)
#\a

shuffle list &key :start :end :state :copy [Function]

Returns a random reordering of list, which can be a list or sequence. Reordering takes place between :start and :end, which default to the full length of the sequence. If :copy is t (the default) then a reordered copy of list is returned, otherwise seq is destructively modified and returned. :state defaults to *random-state*.

Example 4-20

? (shuffle '(a b c d e))
(b a e d c)

drunk n width &key :low :high :mode :state [Function]

Returns a random value constrained to lie between n-width and n+width. Passing in previous values of n implements a random walk (brown noise). If :low and :high are specified then the random walk is bounded and values that exceed either value are automatically adjusted to lie within bounds according to :mode. If :mode is :reflect (the default) then the outlying value is reflected back in bounds. If :mode is :limit then the closest boundary is returned. If :mode is :reset then the outlier is centered between :low and :high. If :mode is :jump the a random value between :low and :high is selected. :state defaults to *random-state*.

Example 4-21

? (loop with i = .5 repeat 10 collect (setf i (drunk i .25)))
(0.58 0.72 0.57 0.72 0.64 0.85 1.03 1.05 1.22 1.19)

? (loop with i = 60 repeat 10 collect (setf i (drunk i 3 :low 54 :high 66)))
(60 60 61 61 62 64 63 64 64 63)

? (drunk 11 1 :low 0 :high 10 :mode :reset)
5

4.6 Analysis Tools

The following functions are provided to assist in compositional analysis.

histogram data min max slots [Function]

Returns a histogram of numbers. min and max are the lower and upper bounds for values in numbers. slots is the number of sampling segements between low and high to count.

Example 4-22

? (histogram (loop repeat 100 collect (random 700)) 0 700 7)
(17 15 13 12 11 19 13)

markov-analyze sequence &amp;key :order :print? :pattern? :key [Function]

Performs an analysis of sequence then prints and/or returns the analysis results according to :print? and :pattern?.

markov-analyze supports the following keyword arguments:

:order number
The order of the Markov analysis, defaults to 1.
:print {t | :table | :pattern | nil}
The value t (the default) means to print both the transition table detailing the of distribution of inputs and outputs as well as the markov pattern description that would instantiate that table. Otherwise :print can be specified as just :table or :pattern if only that information is wanted, or nil if no printing is desired.
:pattern {nil | t}
If nil (the default) then markov-analyze does not return values. If :pattern? is t then a markov pattern based on the analysis transition table is returned.
:key function
A Lisp function to apply to each item in sequence. function should take one argument and return the actual datum to be analyzed.
:sort {list | function}
Specifies the order of labels in the columns and rows of the table. If a list of labels is specified its ordering determines the column order of the table. If :sort is a function it is passed to sort to sort the table labels.
:decimals {number}
Specifies the number of decimals to use when printing the table. Defaults to 3.

Example 4-23

? (defparameter happy-birthday 
    #n(c4 c d c f e c c d c g f c c c5 a4 f e d bf bf a f g f))
happy-birthday

? (markov-analyze happy-birthday :order 2)

          D4    C4    F4    E4    G4    C5    A4    BF4   
(D4 C4)   ----- ----- 0.500 ----- 0.500 ----- ----- ----- 
(D4 BF4)  ----- ----- ----- ----- ----- ----- ----- 1.000 
(C4 D4)   ----- 1.000 ----- ----- ----- ----- ----- ----- 
(C4 C4)   0.667 ----- ----- ----- ----- 0.333 ----- ----- 
(C4 F4)   ----- ----- ----- 1.000 ----- ----- ----- ----- 
(C4 G4)   ----- ----- 1.000 ----- ----- ----- ----- ----- 
(C4 C5)   ----- ----- ----- ----- ----- ----- 1.000 ----- 
(F4 C4)   ----- 1.000 ----- ----- ----- ----- ----- ----- 
(F4 E4)   0.500 0.500 ----- ----- ----- ----- ----- ----- 
(F4 G4)   ----- ----- 1.000 ----- ----- ----- ----- ----- 
(E4 D4)   ----- ----- ----- ----- ----- ----- ----- 1.000 
(E4 C4)   ----- 1.000 ----- ----- ----- ----- ----- ----- 
(G4 F4)   ----- 1.000 ----- ----- ----- ----- ----- ----- 
(C5 A4)   ----- ----- 1.000 ----- ----- ----- ----- ----- 
(A4 F4)   ----- ----- ----- 0.500 0.500 ----- ----- ----- 
(BF4 A4)  ----- ----- 1.000 ----- ----- ----- ----- ----- 
(BF4 BF4) ----- ----- ----- ----- ----- ----- 1.000 ----- 

(MARKOV (D4 C4 -> (F4 0.5) (G4 0.5))
        (D4 BF4 -> (BF4 1.0))
        (C4 D4 -> (C4 1.0))
        (C4 C4 -> (D4 0.667) (C5 0.3333333333333333))
        (C4 F4 -> (E4 1.0))
        (C4 G4 -> (F4 1.0))
        (C4 C5 -> (A4 1.0))
        (F4 C4 -> (C4 1.0))
        (F4 E4 -> (C4 0.5) (D4 0.5))
        (F4 G4 -> (F4 1.0))
        (E4 D4 -> (BF4 1.0))
        (E4 C4 -> (C4 1.0))
        (G4 F4 -> (C4 1.0))
        (C5 A4 -> (F4 1.0))
        (A4 F4 -> (E4 0.5) (G4 0.5))
        (BF4 A4 -> (F4 1.0))
        (BF4 BF4 -> (A4 1.0)))


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