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;

 

 

 

Henon-Map

 

 

 

 

//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