Following Phrases: Repeating phrases and algorithms

In this class you will see an example of how one phrase can be repeated to create a dense texture. This is not new to the tutorials, the Row Your Boat tutorial introduced cannonic writing. In this tutorial that process is automated to a greater extent, and the use of random elements creates a somewhat variable outcome.

To take advantage of the variety of outcomes, this class produces several versions of the score in one go. This technique can save considerable time, because running this program once makes several MIDI files which can then be auditioned as a batch to select the most interesting one.

To hear one possible result play the MIDI file below.

 

Click here to view source

Lets have a closer look at what just happened.
import jm.JMC;
import jm.music.data.*;
import jm.util.*;

 
/**
* A class that creates cannonic pulse based music, in spades.
* @author Benn Woods and Andrew Brown
*/

 
public final class FollowMusic implements JMC {

 
The basic jm libraries used by the class are imported first. The JMC has the note constants and so on. The jm/music/data directory has the jm data structure classes, such as Phrase, Score, and Part. The jm/util directory contains the classes used to write, read, and display the score.

There is a comment to describe the class and acknowledge the creators.

The FollowMusic class declared to be public (availible to all other classes) final (no subclasses of this class can be made) and it implements (uses) the JMC class (to access jMusic's constants).

  			// create a phrase to hold the melody  
Phrase phr = new Phrase(0.0);

// create a random walk melody

int pitch = C4;
for(int i=0;i<60;i++){
Note n = new Note(pitch,0.5, (int)(Math.random()*127));
phr.addNote(n);
pitch += (int)(Math.random()*10-5);
}
This section of the code creates the melody.

First an empty Phrase object is declared with the name 'phr'.

Second, a variable named 'pitch' is declared. It is of type 'int' and given and initial value of C4, which is the JMC constant for 60 (middle C in MIDI pitch speak).

Thirdly, a for-loop creates notes named 'n' and adds them to the phrase 'phr'. The note constructor is passed three arguments, pitch (the variable declared earlier), 0.5 (the rhythm value - we could have used QUAVER or EIGHTH_NOTE instead), and (int)(Math.random()*127) which results in a random number between 0 and 126 which will be the note's dynamic value.

The phrase 'phr' calls its addNote() method with the note object 'n' as an argument. This adds 'n' to the end of the noteList inside 'phr'.

Finally, the 'pitch' variable is updated by adding a random number between -5 and +4 to its current value. in this way the melody meanders along in intervals no larger than 5 semitones.

  			// copy and repeat the melody numerous times  
for(int i=0;i<9;i++){
Part p = new Part("inst 1", XYLOPHONE, i);
Phrase tempPhrase = new Phrase();
tempPhrase = phr.copy();
tempPhrase.setStartTime((double)i/4.0+i*2);
p.addPhrase(tempPhrase);
s.addPart(p);
}
The next part of the main() method makes lots of copies of the melody and positions them a little bit later in time, creating a cannon affect.

A for-loop is set up to go around 9 times.

A new Part object is created called 'p' and given the name 'inst 1', its instrument is set to the general MIDI number for XYLOPHONE, and the channel is set to the current value of i (the first time around that will be zero, then one, then two, and so on).

Next and new Phrase object is declared, called 'tempPhrase'. Then the start time of that phrase is set to a new value (the copy function would mean that it originally had the same start time of the phrase 'phr' from which it is a copy.) The math to calculate the new start time uses the variable i which changes each time around the for-loop ensuring that each time the copied phrase has a different start time.

The Part 'p' then adds the Phrase 'tempPhrase' to itself.

The score 's' then adds the part 'p' to itself by calling its addPart()method.

 	 public static void main(String[] args) {  
// repeat the whole compositional process several times

for(int j=0;j<10;j++){

// create a score to hold the composition

Score s = new Score("Follow Music Demo "+j);

// create a phrase to hold the melody

Phrase phr = new Phrase(0.0);

// create a random walk melody

int pitch = C4;
for(int i=0;i<60;i++){
Note n = new Note(pitch,0.5, (int)(Math.random()*127));
phr.addNote(n);
pitch += (int)(Math.random()*10-5);
}


// copy and repeat the melody numerous times

for(int i=0;i<9;i++){
Part p = new Part("inst 1", XYLOPHONE, i);
Phrase tempPhrase = new Phrase();
tempPhrase = phr.copy();
tempPhrase.setStartTime((double)i/4.0+i*2);
p.addPhrase(tempPhrase);
s.addPart(p);
}


// save a MIDI file of the result

Write.midi(s, "FollowMusic"+j+".mid");

// display a visual score of the result

View.show(s, j*10, j*20);
}
}
This code segment shows all of the main() method. The melody creation code we saw above is marked in red and the phrase copying and shifting code is marked in blue.

Toward the top of the main() method is a for-loop (coloured yellow) that encases the whole compositional process. Thus repeating the composition 10 times. The variable 'j' is used as a counter.

This variable 'j' turns up in the Write.midi() line as part of the file name. "FollowMusic"+j+".mid" This results in file names such as FollowMusic0.mid and FollowMusic1.mid and so on, as the value of 'j' changes each time through the loop. This is a useful technique for creating many similar files in the one go.

Likewise, the variable 'j' is used in the View.show line to set the position at which the showScore window will appear on the screen. This results in a offset-stacking of the windows for neat appearance.

Try modifying the class to produce longer melodies with fewer or more copies. You might like to change the instrument for each copy as a challenge.



jMusic Tutorial Index