Fractal Computation in ChucK - The Julia Class

From CCRMA Wiki
Revision as of 00:10, 10 December 2008 by Cweil (Talk | contribs) (DESIGN)

Jump to: navigation, search


To create a class that utilizes proper fractal computation as a means for generating a well-defined array that, in use, sounds random or chaotic but is entirely deterministic and thus perfectly repeatable, while still containing more varied content than a standard recursion function.


A fractal is a geometric shape that, when split into parts, will look approximately (or exactly, if framed perfectly) like the whole. Some can even be scale-invariant. They are 'produced' through iterations of an equation. The recursion is what produces the self-similarity.

The two most popular set of fractal-generating processes are known as the Julia set and the Mandelbrot set. While both produce fractals that are infinitely complex, the Julia set allows for much more variation in the resultant fractal with very small changes in the constants given (it is more chaotic).

The calculation of the shape is fairly simple, but requires a few inputs. It takes a recursive equation and plots the number of iterations necessary at each point before the equation hits a max value (generally seen to be when it's growth will become wildly exponential). Since some points will only reach this value after an infinite number of iterations, the calculation will either stop at the max value or at a given max number of iterations.

To make the calculation, then, we need to give it: an equation, initial constants, max output, max number of iterations, plot boundaries and plot grid density (the plot's subdivisions; ie, how many points to begin iteration at).

The equation for the Julia set is:

Zn+1 = Zn2 + c

Fractals are drawn in the complex plane (thus points in the plane will take the form z = a+bi). For the equation above, this means that the Zn is the point in the plot where the iteration starts/takes place, and c is the constant defined in your initial conditions; both are in a+bi form.

The boundaries of the real and complex axes on the plane can be whichever you choose, as they can be infinitely small or large. Given fractals self-similar nature, simple plot numbers are often chosen, such as both axes being bounded between -1 and 1.

The plot grid density is the number of divisions that you break each axis into. Choosing 2 for each axis will make your plot resemble the standard Cartesian coordinate drawing (four squares), but will be much too course of a resolution for any useful application. Somewhere in the range of 10-20 in each axis should be basically sufficient. The finer the resolution, the more expensive the computation, so be careful.

A standard convention for the max iteration value, Zmax, is generally two. After this point it will increase exponentially, so a higher number is usually unnecessary.

The max number of iterations taken at each grid point until Zmax is reached is up to the user. The higher the number gives you finer resolution on the printed image, which depending on your other chosen constants may or may not be necessary. A very large iteration max is very computationally expensive, however, so experiment with the set of constants you chose to find what's appropriate. Sometimes nothing in the picture will take more than 5 iterations, while sometimes they may infinitely many. Start small, work your way up. More than 200 is generally useless for audio applications.

Now that those are established, it's necessary to explain how images of fractals are actually produced. They are done the same way as explained above- making a defined grid in a defined coordinate system, with all other constants defined- and using the Z value at the centroid of each grid square to calculate the number of iterations taken to either reach Zmax or the max number of iterations and storing that to each grid location. Then, in the programming, a range of iteration numbers are mapped to colors to produce the image.

In the case below, for example, the black may have been mapped to 1-2 iterations, crimson to 3-6 iterations, red-brown to 6-12 iterations, red-orange to 12-20 iterations, etc etc, to the baby blue which may have been 150-200 iterations. The largest number of iterations generally occur near the plot origin as they will grow the slowest because the initial point is the smallest in magnitude.

Excessively large example: Julia (Fractal).png


Instead of plotting the gridded iteration counts to colors, we can use the array as an output to control sound. And thus the Julia set is born!

The output array will literally be the iteration count at the point mapped to the [row][column] specified in the initial parameters. So if you picked an 20 subdivisions on the real axis and 20 in the complex, you will have 400 grid squares and therefore 400 points in the array in [20][20] form.

How the output array is utilized is up to the end user. The nice part is that very small variations in the equation's input constants yield wildly different outputs so there is an infinite amount of variation in both size/scope/length and magnitude difference between plotted points. It can be as simple or as complex as desired and as constant or 'random' as desired. In any case, though, if you return the constants to a known set that produced an output that you liked, you can go back to it and get the same results each time because it is completely deterministic.