Tea for two, or three, or.....

Row Your Boat

This tutorial looks at how we can write more than a single concurrent (meaning simultaneous) voice. It would be a very dull world indeed if we could not write polyphonic music. We also look at some of the ways that jMusic can work with data. It will be a pretty packed tutorial but by the end of it you should have most of the tools you will need to do some real work with jMusic.

There are two ways in which to write polyphonic music in jMusic, and these two paradigms are applied in much the same manner as in the real world. The first is to save multiple voices to a single part. This is analogous to organ fugue where a composer may write for two or more simultaneous parts for one hand to play. The second way in which we can write polyphonic music is to write for two or more parts, as for a woodwind quintet. Furthermore a combination of both techniques can be used.

An orchestral score works similarly to this by containing both monophonic (trumpets, flutes, clarinets etc.) and polyphonic parts like the harp, piano, marimba, and occasionally the string family.

To hear the result play the MIDI file below.

 

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

import jm.JMC;
import jm.music.data.*;
import jm.util.*;
import jm.music.tools.*;
 
/**
 * Plays a melody as a round in three parts
*/
 
public final class RowYourBoat implements JMC {

The first four lines indicate which Java packages (groups of classes) are required for this class. The central parts of Java are available automatically and the import statements indicate which extra Java classes (stored inside a 'package') we need.

Because we want to work with the jMusic additions to Java, the import statements are all parts of the jm package. The jm.JMC class contains all the constants like C4 and STACCATO. All the files in the jm.music.data directory are imported, this is what the * indicates. This directory has the Part, Phrase, Note classes and so on. The jm.util directory contains the utility classes for saving the jMusic composition as a file. The jm.music.tools package contains compositional classes, the one used in this program is the Mod class, which has all sorts of modifcation methods which can be applied to phrases, parts etc.

The final line above declares the class RowYourBoat. It is possible for this line to simply read public class RowYourBoat { but the other words add meaning. Starting at the end, implements JMC allows the class to reference the JMC constants directly. The final statement indicates to the compiler that there will be instances of this class and which allows certain optimisation.

	public static void main(String[] args){
	     //Create the data objects we want to use
	     Score score = new Score("Row Your Boat");
	     Part flute = new Part("Flute", FLUTE, 0);
	     Part trumpet = new Part("Trumpet", TRUMPET, 1);
	     Part clarinet = new Part("Clarinet", CLARINET, 2);	    

We need a score, so one score object is created. In order to have a number of instruments play the round three Part objects are declared, and set to different MIDI channels. An initial Phrase is declared with a start time of 0.0 and a flute (MIDI program change) timbre selected.

	     int[] pitchArray = {C4,C4,C4,D4,E4,E4,D4,E4,F4,G4,
                 C5,C5,C5,G4,G4,G4,E4,E4,E4,
			    C4,C4,C4,G4,F4,E4,D4,C4};
	     double[] rhythmArray = {C,C,CT,QT,C,CT,QT,CT, QT,
                 M, QT, QT, QT, QT, QT,QT, QT, QT, QT, QT, 
                 QT, QT, CT, QT, CT, QT,M};
		Phrase phrase1 = new Phrase(0.0);
		phrase1.addNoteList(pitchArray, rhythmArray);   

It would be very painful if, for a longish tune like this one, every time we wanted to make a Note object we had to type Note note = new Note(C4, CROTCHET); Luckily for us, jMusic has several nice ways of helping us with this.

A way to enter musical information into jMusic is by using arrays. As demonstrated above we can write pitch and rhythm values for each note we want to create into arrays. The number of elements in each array must match up so that the first note we create is a C4 (the first element of the pitchArray) and C (the first element of the rhythmArray), the second a C4 and C, the third a C4 and CT (crotchet triplet) etc...

Once we have written the arrays we can send them straight to a phrase as shown above using the addNoteList() method of the phrase class.

	     Phrase phrase2 = phrase1.copy();
		phrase2.setStartTime(4.0);
		Phrase phrase3 = phrase1.copy();
		phrase3.setStartTime(8.0);
	    

Now, we all know that to create a round that we need to start the melody again and again with a delay between each entry. In this example we want a three part round so we are going to need three phrases. We already have the first phrase so we just need two more. We'll call them phrase2 and phrase3 - very imaginative :)

Now we could create two empty phrases and add notes to them as we did for the first phrase but there is a nicer way to achieve this, we can just copy the first phrase. We do this by calling the first phrase's copy() method. Phrase phrase2 = phrase1.copy(); This method returns a copy of the phrase object which we assign to the new Phrase named phrase2. We can make a new phrase by copying an old phrase.

We also need to set start times for the new phrases because we don't want them to all start at the same time. We do this by calling the setStartTime() method of phrases 2 and 3.

		Mod.transpose(phrase1, 12);
		Mod.transpose(phrase3, -12);
		
		Mod.repeat(phrase1, 1);
		Mod.repeat(phrase2, 1);
		Mod.repeat(phrase3, 1);

So that we can hear our parts a little more clearly we are going to transpose them. With a call to the transpose() method from the static Mod class to do this. The second part is transposed down one octave (-12 means down twelve semitones). The third phrase is transposed up an octave.

We can repeat each phrases so that the round goes for a little bit longer. Mod.repeat(phrase1, 1); indicates that the modification 'repeat' should be applied to phrase1 with a repetition once only. Any positive number could be put in here insted of 1. Each phrase needs to be repeated.

		//add phrases to the parts
		flute.addPhrase(phrase1);		
		trumpet.addPhrase(phrase2);
		clarinet.addPhrase(phrase3);
 

The rest of the example might be familiar from previous tutorials. The part called 'flute' uses its addPhrase() method to put phrase1 into the flute part. So the flute part then contains one phrase, 'phrase1'. The trumpet and clarinet parts similarly add phrase2 and phrase3 to themselves.

The addPhrase() method is one of the methods of the Part class. Because the flute, trumpet, and clarinet objects are instances of the Part class they inherit (can utilise) all the Part methods including addPhrase. The 'dot' (period) between 'flute' and 'addPart' is the way in Java (and some other languages) that you reference methods. So you can read it as "the addPhrase method OF the flute Part" or in more detail as "execute the addPhrase method of the flute part with the phrase1 object as an argument".

		//add parts to the score
		score.addPart(flute);
		score.addPart(trumpet);	
		score.addPart(clarinet);

Notice that we can add as many parts as we like to a score with the addPart() method. If we wanted to we could add more than one phrase to a Part also. We could have one hundred voices playing the round if wanted, although this reminds me of a nightmare I had once about 100 oboes playing in the same place at the same time .....

		//OK now we do a SMF write 
		Write.midi(score, "rowboat.mid");
	}
}

This line exports the jMusic score as a standard MIDI file. The midi method of the Write class takes two arguments, a jMusic Score object (called 'score' in the case, funnily enough!) and the file name for the resulting MIDI file.

Before going on, try entering your own round and play with the transpositions and repeat lengths.

Well, we've come a long way in a short time and we shall give you a break now and let you go out and enjoy some sunshine. You should have enough basic knowledge of jMusic to let your imagination take over for a while. Remember that the only way to learn how to program is to program, so after that break get back into it. If you are at a bit of a loss about how all of this relates to music fear not, the tutorials which follow will provide an introduction to some standard computer music concepts.

In the mean time, play around with the examples, try to write some of your own, and try to find some information on the web and in books about computer and algorithmic music composition. Here are a few links to get you going. Have fun and we'll meet you back here in a while to go on with more tutorials.


jMusic Tutorial Index