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:
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:p4 no ra(10 .75 [ef3 g5] .25 c4)
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]) |
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 |
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 |
* (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:
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).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.
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:
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.ho(T 54.2)
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)
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. |
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
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
For example:
ORp4 s2(T .5 48:52:60:63 .5 [55:56:57:58 49:56:64:71 27 38:45:67])
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.).p4 no s2(T 1. [c4:e:b f3:cs4:e d3:g3:ef4:fs af5])
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]).
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
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. |
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
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
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]Be careful with the order as [1 + 2 * 4] = 12 but [4 * 1 + 2] = 6.
evaluates to:
((((A o B) o C) o D) o E)
where "o" is a one of the following operations +, -, *, /, % (modulus)
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