Eigen. Header Image

ChucK – Differential Equation System Solver

For several weeks, I have been playing around with ChucK: a Strongly-timed, Concurrent, and On-the-fly Audio Programming Language. I have actually been using the software, off and on, for over two years, but only recently started to really use it in the ways I had always wanted to: algorithmically-produced music.

My real dip into the code occured when I jumped on an extra credit assignment for my Differential Equations class, where I was tasked with programming a numerical solver for first-order DEs using the three major introductory algorithms for doing so: Euler’s, Improved Euler’s, and 4th-Order Runge-Kutta (the best of all). It was intended for me to use Mathematica or Matlab, but my program was able to solve the given problems, so it was still acceptable.

The next day, I modified my program for a more general use and to be capable of solving systems of differential equations. I did some research on Lorenz Attractors, and decided that they might be interesting to listen to. Here’s my resulting code and an audio snippet of what it can produce:

ChucK code follows:

3 => int a;
SinOsc osc1[a];
for(0 => int j; j < a; j++)
{
osc1[j] => dac;
(1.0 / a) => osc1[j].gain;
}

float k[a][4];
float x[a];

10.0 => x[0];
20.0 => x[1];
30.0 => x[2];
0.0 => float tt;
0.0001 => float h;

while(1)
{
//Print values to terminal
if( (tt % 0.01) < 0.0001){ <<< “tt=”,tt,”tx0=”,x[0],”tx1=”,x[1],”tx2=”,x[2] >>>; }

for(0 => int j; j < a; j++)
{ ((Std.fabs(x[j]) + 1) * j*20) + 20 => osc1[j].freq; }

h +=> tt;

for(0 => int j; j < a; j++){ h * f(j,tt,x[0],x[1],x[2]) => k[j][0]; }
for(0 => int j; j < a; j++){ h * f(j,tt + (0.5*h),x[0] + (0.5*k[0][0]),x[1] + (0.5*k[1][0]),x[2] + (0.5*k[2][0])) => k[j][1]; }
for(0 => int j; j < a; j++){ h * f(j,tt + (0.5*h),x[0] + (0.5*k[0][1]),x[1] + (0.5*k[1][1]),x[2] + (0.5*k[2][1])) => k[j][2]; }
for(0 => int j; j < a; j++){ h * f(j,tt,x[0] + k[0][2],x[1] + k[1][2],x[2] + k[2][2]) => k[j][3]; }
for(0 => int j; j < a; j++){ x[j] + (1.0 / 6.0) * (k[j][0] + (2.0*k[j][1]) + (2.0*k[j][2]) + k[j][3]) => x[j]; }

.1::ms => now;
}

fun float f(int sub, float t, float x, float y, float z)
{
if(sub == 0){ return 10.3*(y-x); }
if(sub == 1){ return x*(28.4-z)-y; }
if(sub == 2){ return x*y-(7.0/3.2)*z; }
}

My work continued quite a bit past that, and I’m debating whether to post the results here, or to keep it quiet until I have enough music to release my first album. That could be this Summer sometime, if ever.

I can only hope.

2 Comments

  1. Sam says:

    If you can record some of what you hear please share ;)

  2. drew says:

    I totally forgot to put the streamed files back after I had to re-make the blog; should be up now! Thanks, Sam!

Leave a Reply