Dynamic Data Functions (DDFs)

Dynamic data functions (DDFs), such as mo, will create a stream of changing values over a specified time or number of events, based on a particular algorithm.  The data will be generated for a the period found in the "time" field (first field in all DDFs) -- negative numbers will create a specific number of events of generated data, while positive number will create a stream of data lasting for a specific number of beats (similar to the i-block header's duration field).

Each command starts with two letters (e.g., "ex", "mo", "ra", "rw", "se") and is followed by a pair of parentheses ().  The contents of the parentheses are specific to each command but, in all cases, the first parameter is the number of beats (+ real number) or events (- integer) for which the dynamic data function will generate material.

The first parameter after the time (number of beats/events or "T" variable gives the percentage that this particular data will occur. This will usually be "1." (for 100%) but, at times, you may wish to specify weighted data. For example:

p4 no ra(10 .75 [ef3 g5] .25 c4)
will generate a value from two random distributions simultaneously: 75% of the time it will choose a value between E-flat3 and G5 and 25% of the time (that is, over 10 beats) it will generate C4. For example, the following table lists three different ways to call DDFs:

Beats Events Using the T variable
mo(30, 1. -12.2 -58.668) mo(-30, 1. -12.2 -58.668) mo(T, 1. -12.2 -58.668)
rw(30 1. [0 1], .1, .5) rw(-30, 1. [0 1], .1, .5) rw(T, 1. [0 1], .1, .5)
ex(30, 1. [p4 * .5 + 2]) ex(-30, 1. [p4 * .5 + 2]) ex(T, 1. [p4 * .5 + 2])
Different ways to specify the time parameter in DDFs.


The T Variable

The T variable is a shortcut for specifying time in a DDF -- it holds the value of the instrument duration (the last number) specified in the iblock header (e.g.., i1 = 4 0 10 or i1 = 4 0 -48).  By using the T variable the iblock time can be adjusted without having to edit all the DDF's time parameters.  Additionally, the T variable may be immediately followed by a * and a scaling value (there cannot be any spaces in this sequence). For example: mo(T*.25, 1. -12.2 -58.668) (note the T*.25) will create a move command that lasts for 25% of the entire iblock duration (this can be stated in the header as beats or events).


Data Transformations

Three commands (MO, SE, and TE) allow for the transformation of data (i.e., moved or mapped onto a specific curve) over time. There are many ways that this can be accomplished including 5 preset transformation curves as well as a user-defined type. In the following table, the "code" column specifies the code that is used in one of these commands (MO, MS, TE) to specify the desired transformation (curve).

Code Transformation
F Flat (Linear)
E Exponential
L Logarithmic (Inv. Exp.)
S Sine (270-360 deg.)
C Inverse Sine (180-90 deg.)
Vn User Defined Curve (based on exponents)
    n=1 Linear (same as "F")
    n=2 Exponential (same as "E")
    n=.5 Logarithmic (same as "L")
    n=3 Steep Exponential
    n=.25 Steep Logarithmic
Move Types for MO (move), MS (move sets), and TE (tempo)

The user-defined types are specifed by the letter "v" followed immediately by a positive number (n) representing the steepness of the curve. A value of 1 specifies linear. Adjusting the value above 1 will create an exponential curve of increasing steepness, while values < 1 will create logarithmic curves of increasing steepness. The following table shows the half-data point for increasing values of n -- the half-data value is the 50th value that occurs in a curve of one-hundred events plotted from 0 to 1.

n Value Type Half-data Point in Curve (0-1) Approx.
.2 log .87
.25 log .84
.5 log .7
1 lin .5
2 exp .3
3.5 exp .085
5 exp .03
7 exp .008
10 exp .001
Examples of User-Defined Curves

* (The Time Hook)
The MO and MS commands have a new flag (*) that will create a temporal data change based on the current position in time. In version 1.0 all "moves" (MO and SE) were based on the current index within a total number of events. In version 2.0 you can opt for a MO or MS that interpolates between two values based on the current position in beats. N.B. This feature only works when the i-block duration is in beats (not events). For example:

mo(T*.5 1. V3 * 1 100) ^ this specifies to calculate the current value based on the current temporal position in the move, rather than the current event in the move.
will move for have the i-block duration (beats) from 1 to 100 with a steep exponential curve. The values created will be made according to their position in time (not the current event number). This feature will not work in P2 since start times are always created with respect to their position in time (since there are no other events in the note-list when they are created).


The Hold Command (HO)

Format
ho(time value)

time
- = events, + = beats

Summary
The hold command is a short-cut for holding a single value and is essentially the same as: "mo(time 1. val val)" or "ra(time 1. val)". For example:

ho(T 54.2)
is the same as "mo(T 1. 54.2 54.2)" or "ra(T 1. 54.2)" but is more intuitive and involves a little less typing.

Consider the following for generating a "sample hold" process:


p4 ra(T*.1667 1. [0 100]) ho(T*.1667 z) 
   ra(T*.1667 1. [0 100]) ho(T*.1667 z) 
   ra(T*.1667 1. [0 100]) ho(T*.1667 z)


The Move Command (MO)

Summary
The Move command will move between two values (v1 and v2) or two ranges (v1a to v1b and v2a to v2b).  Additionally, the type of interpolation -- linear, exponential, or logarithmic,  can be specified and there can be several"moves" nested in the same time period (see examples below).

Format
mo(time %1 [transformation type] [*] Val1 Val2 [%2 [trans. type] [*] Val1 Val2 ... %n [trans. type] [*] Val1 Val2])

time
- = events, + = beats

* (time hook) (optional)
The optional "*" character may be used before the range data (ValX/ValY) to indicate that the data should be calculated according to its position in time rather than its event position (the default). The * (time hook) can only be used in p-fields above p2.

transition type (optional)
Specifies the move type (curve). See transformation type above for deatiled information.   During a move statement there may be one or multiple "moves" interwoven.  If more than one move is specified each may be of a different type.  If the type is not specified the move will be linear.

Additionally, Val1 and/or Val2 may be replaced with a range of data in the following manner: [type Val1a Val1b] where type is a particular random distribution (see below) and Val1a is one "anchor" of the range and Val1b the other. When using these ranges in both the MO and RA commands the following random distributions are available and need to be called using the characters on the left:

Random Distribution Flags (for range data -- data enclosed in []s -- only, see [4] below, for an example)
Code Probability Distribution
F flat (default)
L Low: distributed near the low anchor (lowest) value with a sharp roll-off (exponential) toward the high anchor.
H High: distributed near the high anchor (highest) value with a sharp roll-off (exponential) toward the low anchor.
G Gaussian/Normal/Bell: the mean is in the center
X Bilateral exponential: the mean is in the center with exponential roll-offs to the low and high values.
B Beta: most values occur at either anchor (i.e. on outside edges) with a sharp exponential roll-off toward the center
T Triangular: the mean is in the center with a linear roll-off toward each anchor.
Probablity Distribtions available with RA and MO DDFs

Examples

[1] Simple Move

nGen file:

  
i1 = 4 0 -20 
{ p2 .5 
  p3 1 
  p4 mo(-10   1.E 1 10) ; move exponentially from 1 to 10 
     mo(-10   1.  10 1) ; move linearly from 10 to 1 
} 

Output Score:

i1   0.0000  0.500    1.0000 
i1   0.5000  0.500    1.1111 
i1   1.0000  0.500    1.4444 
i1   1.5000  0.500    2.0000 
i1   2.0000  0.500    2.7778 
i1   2.5000  0.500    3.7778 
i1   3.0000  0.500    5.0000 
i1   3.5000  0.500    6.4444 
i1   4.0000  0.500    8.1111 
i1   4.5000  0.500   10.0000 
i1   5.0000  0.500   10.0000 
i1   5.5000  0.500    9.0000 
i1   6.0000  0.500    8.0000 
i1   6.5000  0.500    7.0000 
i1   7.0000  0.500    6.0000 
i1   7.5000  0.500    5.0000 
i1   8.0000  0.500    4.0000 
i1   8.5000  0.500    3.0000 
i1   9.0000  0.500    2.0000 
i1   9.5000  0.500    1.0000 
e 

[2] Nested Move
You can also have multiple moves embedded or nested within one another.  Suppose you wanted to create an "X" of values both increasing and decreasing and crossing in the middle:

nGen file:

  
i1 = 4 0 -30 
{ p2 .5 
  p3 1 
  p4 mo(-30 .5 -15 15 .5 15 -15) 
} 

Output Score:

i1   0.0000  0.500  -15.0000 
i1   0.5000  0.500  -13.9655 
i1   1.0000  0.500  -12.9310 
i1   1.5000  0.500   11.8966 
i1   2.0000  0.500  -10.8621 
i1   2.5000  0.500    9.8276 
i1   3.0000  0.500   -8.7931 
i1   3.5000  0.500   -7.7586 
i1   4.0000  0.500    6.7241 
i1   4.5000  0.500    5.6897 
i1   5.0000  0.500   -4.6552 
i1   5.5000  0.500   -3.6207 
i1   6.0000  0.500    2.5862 
i1   6.5000  0.500   -1.5517 
i1   7.0000  0.500    0.5172 
i1   7.5000  0.500    0.5172 
i1   8.0000  0.500   -1.5517 
i1   8.5000  0.500    2.5862 
i1   9.0000  0.500   -3.6207 
i1   9.5000  0.500   -4.6552 
i1  10.0000  0.500    5.6897 
i1  10.5000  0.500   -6.7241 
i1  11.0000  0.500   -7.7586 
i1  11.5000  0.500   -8.7931 
i1  12.0000  0.500    9.8276 
i1  12.5000  0.500   10.8621 
i1  13.0000  0.500  -11.8966 
i1  13.5000  0.500   12.9310 
i1  14.0000  0.500  -13.9655 
i1  14.5000  0.500  -15.0000 
e 

[3] Moving within Ranges
In this example, a "move" is made over 20 beats, two events occurring per beat.  The initial value of P4 is 0 and it moves exponentially to the range -100 to 100.  Note that in this example, the range values are chosen randomly and that the entire range might not be represented (as in this example).  If you don't like this, you can reseed the random number generated with "rs" to get a new sequence that you like.

nGen file:

  
i1 = 4 0 20 
{ p2 .5 
  p3 1 
  p4(in) mo(20 e 1. 0 [-100 100]) ; move from 0 to range of -100 to 100 
} 

Output Score:

i1   0.0000  0.500     0 
i1   0.5000  0.500     0 
i1   1.0000  0.500     0 
i1   1.5000  0.500     0 
i1   2.0000  0.500    -1 
i1   2.5000  0.500     0 
i1   3.0000  0.500    -2 
i1   3.5000  0.500     1 
i1   4.0000  0.500    -2 
i1   4.5000  0.500     1 
i1   5.0000  0.500    -6 
i1   5.5000  0.500     5 
i1   6.0000  0.500     4 
i1   6.5000  0.500    -7 
i1   7.0000  0.500     8 
i1   7.5000  0.500    15 
i1   8.0000  0.500     0 
i1   8.5000  0.500    -8 
i1   9.0000  0.500   -14 
i1   9.5000  0.500    13 
i1  10.0000  0.500   -20 
i1  10.5000  0.500    24 
i1  11.0000  0.500    13 
i1  11.5000  0.500    15 
i1  12.0000  0.500     5 
i1  12.5000  0.500   -40 
i1  13.0000  0.500   -23 
i1  13.5000  0.500    12 
i1  14.0000  0.500    30 
i1  14.5000  0.500    37 
i1  15.0000  0.500    -5 
i1  15.5000  0.500    18 
i1  16.0000  0.500   -37 
i1  16.5000  0.500   -61 
i1  17.0000  0.500   -64 
i1  17.5000  0.500   28 
i1  18.0000  0.500   -36 
i1  18.5000  0.500   -26 
i1  19.0000  0.500    80 
i1  19.5000  0.500    83 
e 

[4] Morphing Random Distributions
In this example, the move command is used to morph between two different random distributions.  In the example, [L 0 10] specifies a "low" biased distribution between 0 and 10 (the values near 0 will occur most often).  Over 100 events (-100),  the original distribution will gradually change into a "high" biased distribution between 0 and 10 ([h 0 10]).

nGen file:

  
i1 = 4 0 -100 
{ 
  p2 .25 
  p3 2 
  p4 mo(-100 1. [L 0 10] [H 0 10]) 
} 

Output Score:

i1    0.000  0.500     0.176 
i1    0.250  0.500     1.696 
i1    0.500  0.500     0.237 
i1    0.750  0.500     0.270 
i1    1.000  0.500     3.785 
i1    1.250  0.500     0.545 
i1    1.500  0.500     0.722 
i1    1.750  0.500     1.576 
i1    2.000  0.500     1.155 
i1    2.250  0.500     0.941 
i1    2.500  0.500     2.270 
i1    2.750  0.500     1.431 
i1    3.000  0.500     2.205 
i1    3.250  0.500     6.212 
i1    3.500  0.500     4.233 
i1    3.750  0.500     2.240 
i1    4.000  0.500     3.579 
i1    4.250  0.500     7.203 
i1    4.500  0.500     3.273 
i1    4.750  0.500     1.185 
i1    5.000  0.500     6.433 
i1    5.250  0.500     4.278 
i1    5.500  0.500     3.489 
i1    5.750  0.500     2.264 
i1    6.000  0.500     4.426 
i1    6.250  0.500     4.070 
i1    6.500  0.500     2.876 
i1    6.750  0.500     2.774 
i1    7.000  0.500     3.200 
i1    7.250  0.500     2.857 
i1    7.500  0.500     4.605 
i1    7.750  0.500     4.610 
i1    8.000  0.500     4.886 
i1    8.250  0.500     3.057 
i1    8.500  0.500     5.488 
i1    8.750  0.500     4.787 
i1    9.000  0.500     3.418 
i1    9.250  0.500     3.872 
i1    9.500  0.500     4.167 
i1    9.750  0.500     4.005 
i1   10.000  0.500     3.886 
i1   10.250  0.500     5.214 
i1   10.500  0.500     4.698 
i1   10.750  0.500     3.348 
i1   11.000  0.500     4.278 
i1   11.250  0.500     5.341 
i1   11.500  0.500     6.785 
i1   11.750  0.500     5.083 
i1   12.000  0.500     4.487 
i1   12.250  0.500     4.920 
i1   12.500  0.500     6.295 
i1   12.750  0.500     5.182 
i1   13.000  0.500     5.639 
i1   13.250  0.500     2.937 
i1   13.500  0.500     4.901 
i1   13.750  0.500     3.728 
i1   14.000  0.500     5.931 
i1   14.250  0.500     6.835 
i1   14.500  0.500     5.754 
i1   14.750  0.500     5.401 
i1   15.000  0.500     4.631 
i1   15.250  0.500     7.602 
i1   15.500  0.500     6.809 
i1   15.750  0.500     6.792 
i1   16.000  0.500     7.612 
i1   16.250  0.500     6.241 
i1   16.500  0.500     7.632 
i1   16.750  0.500     7.123 
i1   17.000  0.500     3.628 
i1   17.250  0.500     7.167 
i1   17.500  0.500     7.353 
i1   17.750  0.500     6.517 
i1   18.000  0.500     7.385 
i1   18.250  0.500     6.365 
i1   18.500  0.500     7.703 
i1   18.750  0.500     5.563 
i1   19.000  0.500     7.629 
i1   19.250  0.500     7.600 
i1   19.500  0.500     5.120 
i1   19.750  0.500     8.025 
i1   20.000  0.500     7.308 
i1   20.250  0.500     6.287 
i1   20.500  0.500     7.416 
i1   20.750  0.500     8.078 
i1   21.000  0.500     7.706 
i1   21.250  0.500     7.814 
i1   21.500  0.500     8.633 
i1   21.750  0.500     7.823 
i1   22.000  0.500     8.681 
i1   22.250  0.500     7.260 
i1   22.500  0.500     7.408 
i1   22.750  0.500     8.930 
i1   23.000  0.500     7.982 
i1   23.250  0.500     8.287 
i1   23.500  0.500     9.568 
i1   23.750  0.500     7.249 
i1   24.000  0.500     9.126 
i1   24.250  0.500     9.328 
i1   24.500  0.500     7.411 
i1   24.750  0.500     9.838 
e 


The Sets Command (SE)

Summary
This command is a special case of the Random (RA) command.  It randomly chooses a succession of elements taken from a "set" of listed materials (this is similar to using "ra" to specify equal weighted distributions of selected values).  Each set listed must have a weighted percentage strength and all must add up to 1.

Format
se(time %1 o [v1 v2 v3 ... vn] %2 o [v1 v2 v3 ... vn] ... %n o [v1 v2 v3 ... vn] )

time
- = events, + = beats

special options (optional)
"o" in the above format structure stands for x or *. These are optional special flags for telling the SE command to distribute the set data in two special ways.

x: if an "x" occurs before a "set" (i.e., x[c4, e, fs]), the listed set will be iterated with no contiguous repetitions (see Example 2 below).

*: if a "*" occurs before a "set" (i.e., *[c4, e, fs, g, b]), the listed set will be iterated cyclically without reptitions (until the cycle has ended). This is similar to Max/MSP's "Urn" object (see Example 3 below).

Example 1: Regular Use
This example uses two "sets", the first is weighted at 90% probability and the second 10% probability.  Additionally, I have specified a new "seed value" for the random number generator and am formatting the final output into octave.pitch-class notation from note-name input.  N.B. I don't have to use the commas or slashes I used to separate the data in the "se" function.  The "bfff2" in the second set stands for B-triple-flat (A-flat).

nGen file:

i1 = 4 0 11 
{ 
  p2 .5 
  p3 1 

  /* 
     For p4, output octave-point-pitch-class 
     but use note-name input. 
  */ 
  p4(op) rs(39) ;reseed the random number generator 

  no se(10 .9 [c4, cs3, fs4, g5] .1 [df2/bfff2]) 
} 

Output Score:

i1   0.0000  0.500 6.01 
i1   0.5000  0.500 9.07 
i1   1.0000  0.500 8.06 
i1   1.5000  0.500 8.06 
i1   2.0000  0.500 7.01 
i1   2.5000  0.500 8.06 
i1   3.0000  0.500 8.00 
i1   3.5000  0.500 9.07 
i1   4.0000  0.500 8.06 
i1   4.5000  0.500 9.07 
i1   5.0000  0.500 6.08 
i1   5.5000  0.500 7.01 
i1   6.0000  0.500 7.01 
i1   6.5000  0.500 6.01 
i1   7.0000  0.500 8.06 
i1   7.5000  0.500 8.00 
i1   8.0000  0.500 9.07 
i1   8.5000  0.500 8.06 
i1   9.0000  0.500 7.01 
i1   9.5000  0.500 6.01 
i1  10.0000  0.500 6.01 
i1  10.5000  0.500 6.01 
e 

Example 2: Special Option "x"
This example uses demonstrates the "x" special option. This option will restrict any repetitions between contiguous elements.

i1 = 4 0 -24 
{
p2 1
p3 1
p4  se(T 1. x[1 2 3 4 5 6])
}
i1    0.000  1.000     5.000 
i1    1.000  1.000     2.000 
i1    2.000  1.000     6.000 
i1    3.000  1.000     3.000 
i1    4.000  1.000     2.000 
i1    5.000  1.000     1.000 
i1    6.000  1.000     5.000 
i1    7.000  1.000     2.000 
i1    8.000  1.000     3.000 
i1    9.000  1.000     5.000 
i1   10.000  1.000     2.000 
i1   11.000  1.000     3.000 
i1   12.000  1.000     4.000 
i1   13.000  1.000     5.000 
i1   14.000  1.000     1.000 
i1   15.000  1.000     4.000 
i1   16.000  1.000     6.000 
i1   17.000  1.000     4.000 
i1   18.000  1.000     5.000 
i1   19.000  1.000     1.000 
i1   20.000  1.000     4.000 
i1   21.000  1.000     2.000 
i1   22.000  1.000     1.000 
i1   23.000  1.000     5.000
e

Example 3: Special Option "*"
This example uses demonstrates the "*" special option. The 6-element set is cycled through 4xs. The "*" specifies that each element is to be used once until all have been used once, then the cycle starts again. This is similar to Max/MSP's URN object and could be used to create Carter-style aggregate completion (among other things)...

i1 = 4 0 -24 
{
p2 1
p3 1
p4  se(T 1. *[1 2 3 4 5 6])
}
i1    0.000  1.000     5.000    cycle 1 
i1    1.000  1.000     2.000    cycle 1
i1    2.000  1.000     6.000    cycle 1
i1    3.000  1.000     3.000    cycle 1
i1    4.000  1.000     4.000    cycle 1
i1    5.000  1.000     1.000    cycle 1
i1    6.000  1.000     5.000    cycle 2
i1    7.000  1.000     3.000    cycle 2
i1    8.000  1.000     6.000    cycle 2
i1    9.000  1.000     4.000    cycle 2
i1   10.000  1.000     1.000    cycle 2
i1   11.000  1.000     2.000    cycle 2
i1   12.000  1.000     1.000    cycle 3
i1   13.000  1.000     5.000    cycle 3
i1   14.000  1.000     4.000    cycle 3
i1   15.000  1.000     2.000    cycle 3
i1   16.000  1.000     3.000    cycle 3
i1   17.000  1.000     6.000    cycle 3
i1   18.000  1.000     5.000    cycle 4
i1   19.000  1.000     3.000    cycle 4
i1   20.000  1.000     4.000    cycle 4
i1   21.000  1.000     6.000    cycle 4
i1   22.000  1.000     2.000    cycle 4
i1   23.000  1.000     1.000    cycle 4
e


The Sets2 Command (S2)

Summary
This command is a special case of the Sets (SE) command.  Its only difference is that it can include fused data (e.g., chords). IMPORTANT: It can only be used in p-fields above (>) p3.

For example:


p4 s2(T .5 48:52:60:63 .5 [55:56:57:58 49:56:64:71 27 38:45:67])
OR

p4 no s2(T 1. [c4:e:b   f3:cs4:e   d3:g3:ef4:fs   af5])
This will function exactly like the SE command (it will choose among the listed elements). When fused data (chords or simultaneities) is encountered, the original event will be copied and duplicated in the note-list (the data from previous p-fields will be copied to the new events.).

Format
se(time %1 o [v1 v2 v3 ... vn] %2 o [v1 v2 v3 ... vn] ... %n o [v1 v2 v3 ... vn] )

N.B. vn can be a single value or fused data (e.g., c4:cs:fs)

time
- = events, + = beats

special options (optional)
"o" in the above format structure stands for x or *. These are optional special flags for telling the SE command to distribute the set data in two special ways.

x: if an "x" occurs before a "set" (i.e., x[c4, e, fs]), the listed set will be iterated with no contiguous repetitions (see Example 2 below).

*: if a "*" occurs before a "set" (i.e., *[c4, e, fs, g, b]), the listed set will be iterated cyclically without reptitions (until the cycle has ended). This is similar to Max/MSP's "Urn" object (see Example 3 of the SE command [above]).


The Move Sets Command (MS)

Summary
This command is a combination of the MO (move) and SE (sets) commands.   Like MO, MS will allow for the interpolation between two sets of values that may differ in cardinality.  Interpolation is controlled through a moving probability of the occurrence of set1 over time.  Therefore, the output will consist of values completely from set1 at the onset, gradually inserting values from set2 until ending with values only from set2. There are three modes of interpolation available: (F) flat or linear (the default), (E) exponential (a 50% mixture occurs closer to the end), and (L) logarithmic (a 50% mixture occurs closer to the beginning).  As with the MO command, there may be multiple (embedded) moves each specified with a percentage weighting.

Format

  
                                  SET1              SET2
ms(time % [transformation type] [*] [v1 v2 v3 ... vn] [v1 v2 v3 ... vn] ...)

time
- = events, + = beats (or use the "T" variable)

* (time hook) (optional)
The optional "*" character may be used before set1 to indicate that the data should be calculated according to its position in time rather than its event position (the default). The * (time hook) can only be used in p-fields above p2.

Example
nGen file:

  
i1 = 5 0 25 { 

  p2   .5 
  p3   1 
      ;move linearly between these sets 
  p5   ms(T, 1. [-1 -2 -3] 4000.55) 

  ;move exponentially between these sets 
  p4   ms(T, 1. E [1, 2, 3, 4, 5] [100/200/300/400/500]) 

  ;N.B. P5 is not in numerical order but that's okay. :-) 
} 

Output Score:

i1    0.000  0.500     5.000    -1.000 
i1    0.500  0.500     2.000    -3.000 
i1    1.000  0.500    2.000    -3.000 
i1    1.500  0.500     1.000    -1.000 
i1    2.000  0.500     3.000    -3.000 
i1    2.500  0.500     1.000    -2.000 
i1    3.000  0.500     3.000  4000.550 
i1    3.500  0.500   200.000    -2.000 
i1    4.000  0.500     5.000    -2.000 
i1    4.500  0.500     2.000    -2.000 
i1    5.000  0.500     2.000    -3.000 
i1    5.500  0.500     5.000    -1.000 
i1    6.000  0.500     1.000    -1.000 
i1    6.500  0.500     5.000    -3.000 
i1    7.000  0.500     1.000  4000.550 
i1    7.500  0.500     4.000    -3.000 
i1    8.000  0.500     2.000  4000.550 
i1    8.500  0.500     1.000  4000.550 
i1    9.000  0.500     5.000  4000.550 
i1    9.500  0.500     4.000    -1.000 
i1   10.000  0.500     4.000  4000.550 
i1   10.500  0.500     3.000  4000.550 
i1   11.000  0.500     5.000    -3.000 
i1   11.500  0.500     3.000  4000.550 
i1   12.000  0.500     1.000    -2.000 
i1   12.500  0.500   500.000  4000.550 
i1   13.000  0.500     1.000    -3.000 
i1   13.500  0.500   500.000    -3.000 
i1   14.000  0.500   500.000    -3.000 
i1   14.500  0.500   300.000    -3.000 
i1   15.000  0.500     4.000    -1.000 
i1   15.500  0.500     1.000  4000.550 
i1   16.000  0.500     3.000  4000.550 
i1   16.500  0.500   100.000    -1.000 
i1   17.000  0.500   500.000  4000.550 
i1   17.500  0.500   300.000  4000.550 
i1   18.000  0.500     5.000  4000.550 
i1   18.500  0.500   100.000    -2.000 
i1   19.000  0.500   100.000  4000.550 
i1   19.500  0.500   500.000  4000.550 
i1   20.000  0.500   500.000    -3.000 
i1   20.500  0.500     4.000    -1.000 
i1   21.000  0.500     2.000  4000.550 
i1   21.500  0.500   200.000  4000.550 
i1   22.000  0.500   300.000  4000.550 
i1   22.500  0.500   400.000  4000.550 
i1   23.000  0.500   100.000  4000.550 
i1   23.500  0.500     3.000  4000.550 
i1   24.000  0.500   200.000  4000.550 
i1   24.500  0.500   400.000  4000.550 
e 


The Random Command (RA)

Summary
The Random command is used to create a stream of random values over the specified number of beats or events.  Each value (or range of values) must be preceded by a percentage value specifying the weighting of that value (or range) and all percentage values must add to 1.  (At the moment you can create kludges of any distribution by weighting the individual values or ranges to a specific distribution).   If you aren't happy with the resulting distribution, try another run with a new random seed value.

Format

ra(time % V ...)

where V =  <value> OR [<optional distribution flag> <range anchor> <range anchor>]

Random Distribution Flags (optional: for range data -- data enclosed in []s -- only, see [3] below, for an example)
Code Probability Distribution
F flat (default)
L Low: distributed near the low anchor (lowest) value with a sharp roll-off (exponential) toward the high anchor.
H High: distributed near the high anchor (highest) value with a sharp roll-off (exponential) toward the low anchor.
G Gaussian/Normal/Bell: the mean is in the center
X Bilateral exponential: the mean is in the center with exponential roll-offs to the low and high values.
B Beta: most values occur at either anchor (i.e. on outside edges) with a sharp exponential roll-off toward the center
T Triangular: the mean is in the center with a linear roll-off toward each anchor.
Probablity Distribtions available with RA and MO DDFs

Examples

[1] Random Ranges

nGen file:

  
i1 = 4 0 -25 
{ 
  p2 1  ;one event each second 
  p3 .5 ;duration is half of interval between events 
  p4 ra(T, .5 [-1 -2] .5 [1 2]) ;note the use of "T" 
} 

Output Score:

i1   0.0000  0.500    1.0031 
i1   1.0000  0.500    1.2689 
i1   2.0000  0.500   -1.3865 
i1   3.0000  0.500   -1.5811 
i1   4.0000  0.500    1.2798 
i1   5.0000  0.500   -1.8052 
i1   6.0000  0.500   -1.3339 
i1   7.0000  0.500   -1.2404 
i1   8.0000  0.500   -1.0543 
i1   9.0000  0.500   -1.9837 
i1  10.0000  0.500   -1.4098 
i1  11.0000  0.500   -1.0739 
i1  12.0000  0.500   -1.9747 
i1  13.0000  0.500   -1.4049 
i1  14.0000  0.500   -1.1971 
i1  15.0000  0.500   -1.2490 
i1  16.0000  0.500    1.8894 
i1  17.0000  0.500    1.7360 
i1  18.0000  0.500   -1.5316 
i1  19.0000  0.500   -1.1306 
i1  20.0000  0.500   -1.4840 
i1  21.0000  0.500    1.2532 
i1  22.0000  0.500   -1.7013 
i1  23.0000  0.500    1.8863 
i1  24.0000  0.500    1.0428 
e 

[2] Simple Value Weighting

nGen file:

  
te(120) 
i1 = 4 0 20 
{ 

  rs(3021) 
  rd(.05) ; more humanistic rhythms 
  p2 rh <4/4/6/6/6 
  rd(0) 

  p3 1.1 ;legato 

  p4(hz) /* output Hertz values 
            but use note-name input   */ 

  no ra(20 .1 c3, .1 df, .3 e,  .1 f,  .1 g,  .1 af, .2 b) 
} 

Output Score:

i1   0.0000  0.562   246.9416 
i1   0.5107  0.540   207.6523 
i1   1.0014  0.366   130.8127 
i1   1.3343  0.364   130.8127 
i1   1.6656  0.360   164.8137 
i1   1.9929  0.550   195.9977 
i1   2.4929  0.550   138.5913 
i1   2.9929  0.367   174.6141 
i1   3.3262  0.367   195.9977 
i1   3.6595  0.367   164.8137 
i1   3.9929  0.550   246.9416 
i1   4.4929  0.550   130.8127 
i1   4.9929  0.367   164.8137 
i1   5.3262  0.367   207.6523 
i1   5.6595  0.367   164.8137 
i1   5.9929  0.550   164.8137 
i1   6.4929  0.550   164.8137 
i1   6.9929  0.367   130.8127 
i1   7.3262  0.367   164.8137 
i1   7.6595  0.367   164.8137 
i1   7.9929  0.550   246.9416 
i1   8.4929  0.550   174.6141 
i1   8.9929  0.367   164.8137 
i1   9.3262  0.367   195.9977 
i1   9.6595  0.367   246.9416 
i1   9.9929  0.550   138.5913 
e 

[3] Specific Distributions
This example uses a specific random distribution within a random range.  The "x" in [x c3 c5] is a "flag" telling the program to use the bilateral exponential distribution. Notice also that the note names in P4 encoded in the "no" input mode will be output as octave.pitch-class (p4(op)) in the resulting score file. The resulting output in P4 of the score file (below) will fall between 7.00 (C3) and 9.00 (C5) but will be centric around 8.00 (C4).  Due to the sharp exponential roll-off of this distribution most values that occur will be closest to 8.00.

nGen file:

  
i1 = 4 0 -25 
{ 
  p2     rh < 16//8/4x3 > 
  p3     mo(-12 1. E .25 2) 
         mo(-13 1. L 2 .25) 
  p4(op) no ra(-25 1 [x c3 c5]) 
} 

Output Score:

i1    0.000  0.062 8.06 
i1    0.250  0.066 8.01 
i1    0.500  0.154 7.11 
i1    1.000  0.380 7.11 
i1    2.000  0.481 7.11 
i1    3.000  0.612 8.00 
i1    4.000  0.193 8.01 
i1    4.250  0.240 8.00 
i1    4.500  0.588 7.09 
i1    5.000  1.421 8.03 
i1    6.000  1.696 8.00 
i1    7.000  2.000 8.00 
i1    8.000  0.500 8.01 
i1    8.250  0.382 7.11 
i1    8.500  0.625 7.11 
i1    9.000  1.054 7.05 
i1   10.000  0.902 7.11 
i1   11.000  0.778 8.00 
i1   12.000  0.168 8.00 
i1   12.250  0.145 8.00 
i1   12.500  0.250 7.11 
i1   13.000  0.429 8.01 
i1   14.000  0.364 8.06 
i1   15.000  0.305 7.11 
i1   16.000  0.062 8.00 
e 


The Random Window Command (RW)

Summary
The RW command is useful for creating sequences of random numbers where each successive number lies within a constrained distance from the previous (similar to 1/f noise).  This is accomplished through a percentage generation window and a specific starting value.  If you aren't happy with the resulting distribution, try another run with a new random seed value.

Format
rw(time %1 [V1 V2] window_size, starting_value %2 [V1 V2] window_size, starting_value %3 ...)

V1 and V2 can be any two numbers and will also work with any input mode (no, rh, op, etc.).  The window size parameter, specifies the size of the random generation window for the subsequent value generated -- it must lie within the range 0 >= x <= 1.  Values near 0 will be fairly static with those approaching 1 will behave more like a flat distribution.  A value between .1 and .3 will create a slowly changing set of values reminiscent of a mountain range contour.  The starting value must lie within the V1 - V2 range.

Examples

[1] Changing Amplitudes

nGen file:

  
i1 = 4 0 -50 { 
  p2 1 
  p3 1.5 
  p4 rw(T, 1. [0 32767], .25 16000) ;amplitudes 
} 

Output Score:

i1    0.000  1.500 16000.000 
i1    1.000  1.500 16735.000 
i1    2.000  1.500 18554.000 
i1    3.000  1.500 20614.000 
i1    4.000  1.500 18086.000 
i1    5.000  1.500 20143.000 
i1    6.000  1.500 24168.000 
i1    7.000  1.500 23528.000 
i1    8.000  1.500 25378.000 
i1    9.000  1.500 21445.000 
i1   10.000  1.500 21480.000 
i1   11.000  1.500 18422.000 
i1   12.000  1.500 14821.000 
i1   13.000  1.500 16205.000 
i1   14.000  1.500 19113.000 
i1   15.000  1.500 21118.000 
i1   16.000  1.500 20079.000 
i1   17.000  1.500 23826.000 
i1   18.000  1.500 22310.000 
i1   19.000  1.500 24752.000 
i1   20.000  1.500 28764.000 
i1   21.000  1.500 29287.000 
i1   22.000  1.500 26962.000 
i1   23.000  1.500 23918.000 
i1   24.000  1.500 21935.000 
i1   25.000  1.500 24435.000 
i1   26.000  1.500 28103.000 
i1   27.000  1.500 25622.000 
i1   28.000  1.500 21671.000 
i1   29.000  1.500 17624.000 
i1   30.000  1.500 16046.000 
i1   31.000  1.500 19302.000 
i1   32.000  1.500 18013.000 
i1   33.000  1.500 20659.000 
i1   34.000  1.500 22701.000 
i1   35.000  1.500 19574.000 
i1   36.000  1.500 19374.000 
i1   37.000  1.500 22670.000 
i1   38.000  1.500 26004.000 
i1   39.000  1.500 29655.000 
i1   40.000  1.500 26481.000 
i1   41.000  1.500 26524.000 
i1   42.000  1.500 25560.000 
i1   43.000  1.500 22308.000 
i1   44.000  1.500 24893.000 
i1   45.000  1.500 26345.000 
i1   46.000  1.500 30180.000 
i1   47.000  1.500 28250.000 
i1   48.000  1.500 26596.000 
i1   49.000  1.500 30360.000 
e 

[2] Changing Pitches

nGen file:

  
i1 = 4 0 -50 { 
  p2 rh <8/8./16/32/4/2.> 
  p3 401 
  p4(op) no rw(T, 1. [df2 a6], .15 c5) ;pitches 
} 

Output Score:

i1    0.000  1.000 9.00 
i1    0.500  1.000 8.11 
i1    1.250  1.000 8.08 
i1    1.500  1.000 9.00 
i1    1.625  1.000 8.09 
i1    2.625  1.000 8.11 
i1    5.625  1.000 9.00 
i1    6.125  1.000 9.01 
i1    6.875  1.000 9.01 
i1    7.125  1.000 9.01 
i1    7.250  1.000 9.00 
i1    8.250  1.000 9.01 
i1   11.250  1.000 8.11 
i1   11.750  1.000 9.02 
i1   12.500  1.000 9.03 
i1   12.750  1.000 9.07 
i1   12.875  1.000 9.11 
i1   13.875  1.000 10.01 
i1   16.875  1.000 10.01 
i1   17.375  1.000 10.01 
i1   18.125  1.000 10.00 
i1   18.375  1.000 10.05 
i1   18.500  1.000 10.06 
i1   19.500  1.000 10.01 
i1   22.500  1.000 10.02 
i1   23.000  1.000 9.11 
i1   23.750  1.000 10.00 
i1   24.000  1.000 9.08 
i1   24.125  1.000 9.09 
i1   25.125  1.000 9.10 
i1   28.125  1.000 9.10 
i1   28.625  1.000 9.08 
i1   29.375  1.000 9.07 
i1   29.625  1.000 9.10 
i1   29.750  1.000 10.01 
i1   30.750  1.000 9.10 
i1   33.750  1.000 10.00 
i1   34.250  1.000 10.00 
i1   35.000  1.000 10.02 
i1   35.250  1.000 10.01 
i1   35.375  1.000 10.00 
i1   36.375  1.000 10.00 
i1   39.375  1.000 10.03 
i1   39.875  1.000 10.07 
i1   40.625  1.000 10.04 
i1   40.875  1.000 10.06 
i1   41.000  1.000 10.03 
i1   42.000  1.000 10.06 
i1   45.000  1.000 10.04 
i1   45.500  1.000 10.01 
e 


The P-field Extraction Command (EX)

Summary
The EX command will extract previous p-fields; these can optionally be scaled with an equation.  This command is particularly useful for creating scores where one p-field is dependent on the data from a previous p-field (for example, you may wish to make the frequency, specified in a certain p-field of your instrument, connected to the duration (p3) p-field of your instrument so that the longer the duration the lower the frequency -- the frequency is inversely proportion to the duration).  Additionally, in some circumstances, you may wish to set up a series of "scratch" p-fields. A scratch p-field is an ordinary p-field that is not written to the output file (this is achieved with the XX output command).  See the discussion below on how to do this.

N.B. In nGen, p-fields do not have to be listed in numerical order.  If, when using the EX command, you want to have a lower numbered p-field extract data from a higher numbered p-field (e.g. P3 takes data from P9), simply list the higher p-field before the lower p-field in your i-block.  For example:

  
i1 = 4 0 10 { 
  p2 1 
  p4 mo (T 1. 1000 2000) 
  p3 ex(T, 1. [2000 - p4 * .01])  ; moves 100 to 0 over 10 beats 
} 

Format
ex(time %1 o X %2 o X %3 o X ...)

Where X can be:
a previous p-field number (such as p5).
OR
a left-evaluated equation enclosed in []s. (such as [1 - p4 + 2 * .3]).
"o" represents an optional typecast specifier:

When using an equation at least one previous p-field must be referenced (BTW, all entries may be p-fields).

Using Equations
When using an equation, it must be enclosed in []s and will be left-evaluated. In other words:

[A o B o C o D]
evaluates to:
((((A o B) o C) o D) o E)
where "o" is a one of the following operations +, -, *, /, % (modulus)
Be careful with the order as [1 + 2 * 4] = 12 but [4 * 1 + 2] = 6.

Examples

[1] Scaling and Type-Casting a Previous P-Field

In this example, p4 generates random numbers between 0 and 1. EX is used in p5 to scale p4's value x 100; 50% of the time EX will round the p4 value to the nearest integer and 50% it will return it "as is" (floating-point).

nGen file:

i100 = 5 0 10 {
    p2 .1
    p3 2
    p4(re) ra(10 1. [0 1])                 ;random numbers 0-1
    p5(re) EX(T .5 i[p4*100] .5 f[p4*100]) ;extract p4
}  

Output Score:

i100    6.300  0.200     0.783    78.299 
i100    6.400  0.200     0.006     0.634 
i100    6.500  0.200     0.067     7.000 
i100    6.600  0.200     0.216    22.000 
i100    6.700  0.200     0.659    65.905 
i100    6.800  0.200     0.280    28.029 
i100    6.900  0.200     0.686    69.000 
i100    7.000  0.200     0.104    10.380 
i100    7.100  0.200     0.221    22.000 
i100    7.200  0.200     0.160    16.027 
i100    7.300  0.200     0.051     5.060 
i100    7.400  0.200     0.520    52.000 
i100    7.500  0.200     0.286    28.594 
i100    7.600  0.200     0.578    58.000 
i100    7.700  0.200     0.057     6.000 
i100    7.800  0.200     0.002     0.166 
i100    7.900  0.200     0.378    37.755 
i100    8.000  0.200     0.739    73.896 
i100    8.100  0.200     0.036     3.559 
i100    8.200  0.200     0.188    19.000 
i100    8.300  0.200     0.608    60.761 
i100    8.400  0.200     0.954    95.000 
i100    8.500  0.200     0.974    97.425 
i100    8.600  0.200     0.424    42.000 
i100    8.700  0.200     0.245    24.000 
i100    8.800  0.200     0.452    45.185 
i100    8.900  0.200     0.117    11.657 
i100    9.000  0.200     0.547    54.697 
i100    9.100  0.200     0.599    59.936 
i100    9.200  0.200     0.687    68.741 
i100    9.300  0.200     0.124    12.364 
i100    9.400  0.200     0.080     8.035 
i100    9.500  0.200     0.934    93.000 
i100    9.600  0.200     0.769    76.911 
i100    9.700  0.200     0.672    67.000 
i100    9.800  0.200     0.036     3.637 
i100    9.900  0.200     0.563    56.000 

[2] Glissando Pitches
This example assumes an instrument that glisses from an initial pitch in p5 to a pitch in p6.  The EX command has been used to extract values in P5 and add one semi-tone 50% of the time while subtracting one semi-tone the other 50%.  A word should be mentioned about the internal calculation of the values:  The "no" (notes) command in p5 will internally store values as adjacent real-numbers (60.0 is C4).  By adding or subtracting 1 to each value in p5 the "no" value changes by a half step.  Note that the output is in octave-point-pitch-class (e.g.., 8.00 = C4). nGen will convert to any output type specified by the initial p-field in ()s at the time of printing to the file.  Therefore, the p6 EX command sees the internal codes (such as 60 for C4) and not the octave-point-pitch-class values.

nGen file:

  
i1 = 6 0 -50 { 
  p2 rd(.1) rh <16x4/4//> 
  p3 rd(0) .9 

; AMP: move from -18dB to 0dB to -18dB 
  p4(in) db mo(T*.5 1. 72 90) mo(T*.5 1. 90 72) 

;GLISS START PITCH: Some 1/f pitches 
  p5(op) no rw(T, 1. [df2 a6], .15 c5) ;pitches 

;GLISS END PITCH: + or - 1 semitone from p5 
  p6(op) ex(T .5 [p5 + 1] .5 [p5 - 1]) ;half the time do "p5 + 1" 
  the other do "p5 - 1"
} 

Output Score:

i1    0.000  0.214  3981 9.00 8.11 
i1    0.238  0.214  5133 9.01 9.00 
i1    0.475  0.221  6284 8.10 8.11 
i1    0.721  0.214  7436 8.08 8.09 
i1    0.960  0.887  8588 8.08 8.09 
i1    1.945  0.875  9740 8.10 8.09 
i1    2.917  0.226 10891 8.10 8.09 
i1    3.168  0.218 12043 8.10 8.09 
i1    3.410  0.230 13195 9.01 9.00 
i1    3.665  0.235 14346 8.09 8.10 
i1    3.926  0.880 15498 8.11 8.10 
i1    4.904  0.895 16650 8.11 9.00 
i1    5.898  0.216 17802 8.08 8.07 
i1    6.139  0.229 18953 8.05 8.04 
i1    6.394  0.226 20105 8.07 8.06 
i1    6.645  0.215 21257 8.06 8.07 
i1    6.884  0.870 22408 8.07 8.08 
i1    7.850  0.928 23560 8.09 8.10 
i1    8.882  0.229 24712 9.01 9.00 
i1    9.136  0.231 25863 9.05 9.04 
i1    9.393  0.232 27015 9.04 9.03 
i1    9.651  0.235 28167 9.03 9.04 
i1    9.913  0.875 29319 9.07 9.06 
i1   10.885  0.893 30470 9.05 9.04 
i1   11.877  0.235 31622 9.09 9.08 
i1   12.139  0.233 31622 9.06 9.05 
i1   12.397  0.235 30470 9.06 9.07 
i1   12.658  0.232 29319 9.03 9.04 
i1   12.915  0.896 28167 9.07 9.08 
i1   13.911  0.909 27015 9.11 10.00 
i1   14.921  0.229 25863 9.08 9.09 
i1   15.175  0.227 24712 9.06 9.07 
i1   15.428  0.226 23560 9.05 9.04 
i1   15.679  0.230 22408 9.03 9.02 
i1   15.934  0.865 21257 9.03 9.02 
i1   16.896  0.892 20105 9.02 9.03 
i1   17.886  0.216 18953 9.05 9.06 
i1   18.127  0.229 17802 9.08 9.07 
i1   18.381  0.224 16650 9.07 9.08 
i1   18.630  0.225 15498 9.04 9.05 
i1   18.880  0.906 14346 9.00 8.11 
i1   19.887  0.886 13195 9.01 9.02 
i1   20.871  0.233 12043 9.01 9.02 
i1   21.130  0.220 10891 9.01 9.02 
i1   21.374  0.218  9740 8.11 9.00 
i1   21.616  0.223  8588 9.00 8.11 
i1   21.865  0.918  7436 8.08 8.07 
i1   22.884  0.870  6284 8.06 8.05 
i1   23.850  0.226  5133 8.05 8.04 
i1   24.101  0.228  3981 8.04 8.05 
e 

[3] Using a series of "scratch" p-fields with EX.
In the following example, I have used three p-fields as scratch buffers for creating pitch data.  While these p-fields will be written to memory and calculated exactly as any other p-field, they will be ignored when the data is written to the output file.   To declare a scratch p-field you use the XX output filter.  CAUTION: you can name these p-fields using any number <= your total number of p-fields, but it's best to use numbers higher than the highest numbered output p-field (if you don't what you call Pn may be seen as Pn-1 in your output file).  Here's an example:

nGen file:

  
i1 = 8 
0 -12 
{ 
  p2 .5    p3 1    p4(in) 15000 

  /* Scratch P-fields (not printed in output score)*/ 
  p6(xx) nox <c4/gs+/b-/d5/ef5/g-/d+6/f->   ;gen. looped microtonal line 
  p7(xx) op  rw(T 1. [7.00 9.07] .25 8.00)  ;1/F "tuned" oct.pc values 
  p8(xx) no  ra(T 1. [g c2 c7])             ;Gaussian val. bet. C2 and C7 

  /* extraction from the "scratch" p-fields */ 
  p5(op) ex(T .33 p6 .33 p7 .34 p8) 
} 

Output Score:

;I-block #1 (i1):                   /* not actually printed */ 
i1    0.000  0.500 15000  8.090    (48.000    48.000    57.000) 
i1    0.500  0.500 15000  9.070    (56.500    44.000    67.000) 
i1    1.000  0.500 15000  9.000    (58.500    48.000    60.000) 
i1    1.500  0.500 15000  9.020    (62.000    45.000    57.000) 
i1    2.000  0.500 15000  7.090    (63.000    45.000    62.000) 
i1    2.500  0.500 15000  7.070    (66.500    43.000    60.000) 
i1    3.000  0.500 15000 10.025    (74.500    44.000    53.000) 
i1    3.500  0.500 15000 10.045    (76.500    42.000    54.000) 
i1    4.000  0.500 15000  8.000    (48.000    44.000    66.000) 
i1    4.500  0.500 15000  7.040    (56.500    40.000    33.000) 
i1    5.000  0.500 15000  8.105    (58.500    44.000    33.000) 
i1    5.500  0.500 15000  9.020    (62.000    44.000    28.000) 
e