Mapping Nonlinearity in
Chuck: the Henon and Lorenz Dynamical Systems
Mauricio Rodriguez
MUSIC 220a
Introduction
Two multidimensional generators (functions that return
at once 2 or more output values) are encoded in Chuck syntax to control the
different components and/or parameters of a digital audio process. The Henon
and Lorenz Nonlinear Dynamical Systems are described here through their
mathematical system of equations and later implemented in the Chuck
environment. Finally, some evaluations of those functions and their plots are
presented along with a sonified version of the data.
Henon
Generator
This is
a bi-dimensional dissipative chaotic system defined by the following iterated
formula:
x(n+1)=y(n)+1-Ax(n)^2
y(n+1)=Bx(n)
In
order to keep the system stable (to yield clear attractor points), X and Y
should be values near to zero. A and B are always constant positive values, preferably set to: A<=(2.0-B)
Henon System in Chuck:
//Henon map
//n values
20 => int n;
//function
fun void henon ( int num, float x, float y, float a, float b )
{
if (num >
1 )
henon ( num
- 1, 1 + (x * x * a * -1) + y, x * b, a, b );
<<< "x-value", x, "y-value",
y >>>;
500::ms => now;
}
//test
henon (n,
0.0, 0.0, 1.4, 0.3);
The evaluation of this function yields the following values in the
Console Monitor:

The following plot shows the first 1000 iterations under the same
initial conditions as before (0.0, 0.0, 1.4, 0.3):

Lorenz Generator
This is
a tri-dimensional dissipative chaotic system defined by the following iterated
formula:
x'= σ (y-x)
y'=Rx-y-xz
z'=xy-Bz
Higher
values for R and B increase the chaos; so it
happens for lower values for σ
Lorenz
System in Chuck:
//Lorenz map
//n values
20 => int n;
//function
fun void lorenz ( int num, float x, float y, float z, float sigma, float R, float B )
{
if (num >
1 )
lorenz ( num - 1,
(((sigma * y) - (sigma * x)) * 0.01) + x,
((((x * R)
- (x * z)) - y) * 0.01) + y,
(((x * y)
- (B * z)) * 0.01) + z,
sigma,
R,
B );
<<< "x-value", x, "y-value",
y, "z-value", z >>>;
500::ms => now;
}
//test
lorenz (n,
0.1, 0.1, 0.1, 10.0, 28.0, .375);
The evaluation of this function yields the following values in the
Console Monitor:

The following plot shows the first 1000 iterations under the same initial
conditions as before (0.1, 0.1, 0.1, 10.0, 28.0, 0.375):

Some audio examples
//Henon Map
//An oscillator whose frequency and duration are controlled by
the Henon-Map
SinOsc s => ADSR e => JCRev r => dac;
0.1 => r.mix;
0.0 => float x;
0.0 => float y;
1.4 => float a;
0.3 => float b;
20 => int n;
// set a, d, s, and r
e.set( 10::ms, 8::ms, .5, 200::ms );
// set gain
0.5 => s.gain;
//function
fun void henon ( int num, float x, float y, float a, float b )
{
if (num >
1 )
henon ( num
- 1, 1 + (x * x * a * -1) + y, x * b, a, b );
<<< "x-value", x, "y-value",
y >>>;
440.0
+ (220 * Std.fabs(x)) => s.freq;
e.keyOn();
//
advance time by 800 ms
100::ms => now;
//
key off - start release
e.keyOff();
//
advance time by 800 ms
200::ms => now;
10.0 + ((y - -0.5) * ((500.0 - 10.0) / (0.5 - -0.5))) => float currentY;
currentY::ms => now;
}
henon (n, x, y, a, b);
2::second => now;
//Lorenz map
Impulse i => Delay d => Pan2 p => JCRev r => dac;
d => Gain g => d;
0.05 => r.mix;
.99 => g.gain;
//n values
100 => int n;
//function
fun void lorenz ( int num, float x, float y, float z, float sigma, float R, float B )
{
if (num >
1 )
lorenz ( num - 1,
(((sigma * y) - (sigma * x)) * 0.01) + x,
((((x * R)
- (x * z)) - y) * 0.01) + y,
(((x * y)
- (B * z)) * 0.01) + z,
sigma,
R,
B );
<<< "x-value", x, "y-value",
y, "z-value", z >>>;
1
=> i.next;
50.0 + ((x - -10.0) * ((1000.0 - 50.0) / (22.0 - -10.0))) => float currentX;
currentX::samp => d.delay => d.max;
-1.0 + ((z - 0.1) * ((1.0 - -1.0) / (60.0 - 0.1))) => float currentZ;
currentZ => p.pan;
40.0 + ((y - -22.0) * ((40.0 - 05.0) / (30.0 - -22.0))) => float currentY;
currentY::ms => now;
}
//test
lorenz (n, 0.1, 0.1, 0.1, 10.0, 28.0, .3