Piano Phase - After Steve Reich

Steve Reich's "Piano Phase" piece requires two parts to run at different tempi. This is achieved in this example by reducing the note lengths of one part slightly to simulate the difference in tempo. It can also be done by setting different parts or phrases to different  speeds using the setTempo() method. The compositional principle is that as the 3 beat phrase is repeated over and over the slight tempo difference results in a 'phasing' offset between the parts. This continues until they meet up again some time later one beat apart. The last few bars of this example have the parts in sync again but at a one beat displacement. In Reich's score this process continues through all beats of the phrase.

To hear the result play the MIDI file.

Here is the source code.

The first technique we will investigate is writing for a single part containing multiple lines/voices. Take a good look at it as it contains many things that you will not have seen before.

The fisrt thing is to bring in the jMusic classes required for this program:

import jm.music.data.*;
import jm.JMC;
import jm.util.*;
import jm.music.tools.Mod;


Create the jMusic data objects to hold the score. One part for each of the two pianos, and the first phrase:

public class PianoPhase implements JMC {
public static void main(String[] args){

//Create the data objects we want to use

Score score = new Score("Piano Phase", 120.0);
Part p1 = new Part("Piano1", PIANO, 0);
Part p2 = new Part("Piano2", PIANO, 1);
Phrase phrase1 = new Phrase(0.0);


There is only one phrase in the composition and the treatment of it is what is of interest. This is the basis of 'minimalism' as a style - minimal amounts of material treated in interesting ways, often with lots of repetition.

After the phrase is created it is repeated and added to the part, and score:

	//Lets write the music in a convenient way.	       
int[] pitchArray = {E4,FS4,B4,CS5,D5,FS4,E4,CS5,B4,FS4,D5,CS5};
double[] rhythmArray = {SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ};

//add the notes to the first phrase

phrase1.addNoteList(pitchArray, rhythmArray);

// repeat the stable piano part and add it to a part and score

Mod.repeat(phrase1, 52);
p1.addPhrase(phrase1);
score.addPart(p1);


The second phrase, like all others, is a copy of the first. The 'trick' is that it plays slightly faster than the original phrase.
This is done by shortening the length of each of the notes slightly:

	//Make two new phrases and change starttimes to make a round	       
Phrase phrase2 = (Phrase) phrase1.copy();
phrase2.setStartTime(0.0);

// Phrase 3 is the one which extends phrase two at a different tempo

for(int i = 1; i<rhythmArray.length;i++) {
rhythmArray[i] = rhythmArray[i] * 0.975;
}


Other phrases are created, transposed, and repeated as required to meet the score. This example simply mimics the first minute of Steve reich's piece:

        Phrase phrase3 = new Phrase(0.0);
phrase3.addNoteList(pitchArray, rhythmArray);
phrase3.setStartTime(24.0);

//Phrse four is played after the offset period

Phrase phrase4 = (Phrase) phrase1.copy();
phrase4.setStartTime(141.0);
//one beat short of the start of bar 13
//Play different parts in different octaves for more audible clarity
Mod.transpose(phrase2, 12);
Mod.transpose(phrase3, 12);
Mod.transpose(phrase4, 12);
//loop phrases
Mod.repeat(phrase2, 7);

// stable

Mod.repeat(phrase3, 30);
/
/ accellerated
Mod.repeat(phrase4, 7);

//stable again


The phrases are added to the parts, then parts to the score. Finally, the score is rendered to a standard MIDI file.

	//add phrases to the two instruments	       
p1.addPhrase(phrase1);
p2.addPhrase(phrase2);
p2.addPhrase(phrase3);
p2.addPhrase(phrase4);

//add second piano instrument to the score

score.addPart(p2);
//OK now we SMF write
Write.midi(score, "PianoPhase.mid");
Play.midi(score);
}
}


The Play.midi() method plays the score back using Java's inbuilt software synthesizer.

 


© 2000 Andrew R Brown