A Fractal Melody
This demo will show how to use the mathematics of fractals to generate
music.
Fractals are based on a set of probabilistic mathematical systems which
have some interesting properties.
The output is 'noisy' but features aspects of self similarity, that is,
patterns reoccur at different levels of detail which provides a sense
of coherence not found in other probabilistic processes.
Fractals are often represented visually, most famously in the 'bug-like'
picture of the Mandelbrot set.
For an overview of Fractals and their musical uses read:
The Computer Music Tutorial (Roads 1996) from p.880. Also read Computer
Music (Dodge & Jerse 1997) from p.370.
To hear the result play the MIDI file below.
View / download source
Lets have a closer look.
2 import jm.JMC;
3 import jm.music.data.*;
5 import jm.util.*; |
These lines import useful packages that we need to use in the program.
The first import statement gets a standard Java class used for error messages.
The rest of the statements import the jMusic classes (take another look
at the package documentation to work out what gets imported from where
-> PACKAGES).
13 public final class Fractal implements JMC { 14 public static void main(String[] args){ 15 Score score = new Score("JMDemo - Fractal"); 16 Part inst = new Part("Piano", PIANO); 17 Phrase phr = new Phrase(); 18 float sum; 19 float[] rg = new float[16]; 20 int k, kg, ng, threshold; 21 int np = 1; 22 int nbits = 1; 23 int npts = 48; 24 float nr = (float)(npts); 25 26 nr = nr/2; |
All the work is done in the main method started here. This section of
the method sets up the attributes to be used.
First the usual suspects of Score, Part, and Phrase. Then a number of
variables which will be used by the fractal algorithm are set up.
The details of the algorithm will not be discussed here - refer to the
references above (or others) for details on the math.
28 29 System.out.println("Calculating fractal melody. . ."); 30 31 while (nr > 1) { 32 nbits++; 33 np = 2 * np; 34 nr = nr/2; 35 } 36 37 for(kg=0; kg<nbits; kg++) { 38 rg[kg] = (float)(Math.random()); 39 } 40 41 for(k=0; k<npts; k++) { 42 threshold = np; 43 ng = nbits; 44 while(k%threshold != 0) { 45 ng--; 46 threshold = threshold / 2; 47 } 48 sum = 0; 49 for(kg=0; kg<nbits; kg++) { 50 if(kg<ng) {rg[kg]=(float)(Math.random());} 51 sum += rg[kg]; 52 } 53 Note note = new Note((int)(sum/nbits*127), Q); 54 phr.addNote(note); 55 }
|
After printing a reassuring comment to the screen this part of the code
does the hard work of the Fractal math.
The many FOR loops indicate that the algorithm is highly iterative, that
is, the output of once cycle affects the next.
Previous results affect future events.
Like all probabilistic processes the random function is used to generate
ever-changing values within certain constraints.
At the end of this section of code the result of the each fractal calculation
becomes the pitch of a new note which is added to the phrase.
The fractal calculation produces a two dimensional output (x and Y), but
only the one (x) dimension is used by the program.
All notes are Quavers [eighth notes] in this example. One possible extension
would be to use the Y dimension as the rhythmic value, but the musical
result would be less 'organised' than a steady pulsed melody.
57 58 inst.addPhrase(phr); 59 score.addPart(inst); 60 61 62 Write.midi(score, "fractal.mid"); 63 } 64 }
|
The singles phrase created in the previous section is then added to a
Part called 'inst' which in turn is added to the score.
This should be a familiar jMusic process for you by now.
As with other jMusic demo files, this code creates a MIDI file from the
score.
Once created the fractal.mid file can be played by any MIDI file player
and will sound correctly using a General MIDI sound source, such as most
PC sound cards.
|