My Library of reusable methods

This tutorial outlines two classes. One which has a bunch of useful methods, and the other which creates a jMusic score by calling those library methods as required and structuring the results into a completed piece.

Click here to view MyLibrary source ..

Click here to view UseMyLibrary source ..

Let's have a closer look.

import jm.JMC;
import jm.music.data.*;
import jm.midi.*;
import jm.util.*;
 

/**
* A skeleton for your own class of library routines to reuse
* @author Andrew Brown
*/

 
public final class MyLibrary implements JMC{
 
//This method produces one bar of alternating kick and snare
public static Phrase basicDrums() {
Phrase drumPhrase = new Phrase();
for(int i=0; i<2;i++) {
Note n = new Note(36, QUAVER);
drumPhrase.addNote(n);
n = new Note(42, QUAVER);
drumPhrase.addNote(n);
n = new Note(38, QUAVER);
drumPhrase.addNote(n);
n = new Note(42, QUAVER);
drumPhrase.addNote(n);
}
return drumPhrase;
}

// This method returns a major triad crotchet

public static CPhrase majorChord(int root) {
CPhrase chordPhrase = new CPhrase();
int[] chordPitches = new int[3];
chordPitches[0] = root;
chordPitches[1] = root+4;
chordPitches[2] = root+7;

chordPhrase.addChord(chordPitches, QUAVER);
chordPhrase.addChord(chordPitches, CROTCHET);
chordPhrase.addChord(chordPitches, CROTCHET);
chordPhrase.addChord(chordPitches, QUAVER);
chordPhrase.addChord(chordPitches, CROTCHET);
return chordPhrase;
}

// This method returns a one bar bass walk

public static Phrase bassPhrase(int root) {
Phrase bassPhrase = new Phrase();
Note n = new Note(root,C);
bassPhrase.addNote(n);
n = new Note(root+4,C);
bassPhrase.addNote(n);
n = new Note(root+7,C);
bassPhrase.addNote(n);
n = new Note(root+9,C);
bassPhrase.addNote(n);

return bassPhrase;
}
}

The above class consists of three methods: basicDrums(), majorChord(), andbassPhrase().  These methods contain algorithms for constructing Phrases.  The theory is that when building your piece you can simply call upon these methods to do the work for you, minimising code and maximising reusability.  In the class below (UseMyLibrary) we are able to call upon these mthods to quickly and easily retrieve the parts.

basicDrums() simply returns a basic rock drum beat.  When we call majorChord() or bassPhrase(),we pass the methods a note which these methods can use to base their construction upon (i.e. so that a chord or bass line is built that suits the current key).  By declaring each method as 'static', we are able to use these methods without having to instantiate a MyLibrary object.  Infact, we havn't even bothered writing a constructor for the class as doing so would be pointless!

Now we will look at using the methods. Below is the class 'UseMyLibrary'.  In this class we want to create a simple 8-bar Blues progression (the Blues progression has the advantage of using only major chords).  Firstly, we must define the chord progression.  This is done by creating an array of integers.  Within this array we store the values of the root note of each chord we wish to use, in order (i.e. if a chord repeats, we must repeat the entry).  Since we have implemented JMC, we could use actual names here instead of numbers, such as 'C4' etc.  Next we create a Score object to store our Parts in, and in turn our Phrases.
Next we  will address each Part.  Firstly, the drums.  After making the Part object, we need to add a Phrase of musical data to the object.  This is easy now, since we have a library to do all this for us.  Therefore we can simply say phr = MyLibrary.basicDrums();.  Since the drums dont have a key we don't need to pass it anything.  Now, using the Mod.repeat() method, we can extend this Phrase to last for the entire 8 bars.  Then we simply add this Phrase to the Part, and add the Part to the Score.
The next two parts are essentially the same, the only difference being that one creates a piano chord part and the other a bass part.  For both, a  for loop is started, which loops once for every chord in the chordProgression.  Each time the loop is run, we simply call the appropriate MyLibrary method and send as a parameter the current chord (the chord is stored in the current position within the chordProgression array).  Once all three Parts are added to the Score, we can simply create a midi file of the data.  Try it and see what you get!

import jm.JMC;
import jm.music.data.*;
import jm.midi.*;
import jm.music.tools.*;
import jm.util.*;
 
public final class UseMyLibrary implements JMC {
private static int[] chordProgression =
{60, 60, 65, 60, 67, 65, 60, 60};

public static void main(String [] args){
Score s = new Score("Score", 130);

//drums

Part p = new Part("Drums", 0, 9);
Phrase phr = new Phrase();
phr = MyLibrary.basicDrums();
Mod.repeat(phr, 7);
p.addPhrase(phr);
s.addPart(p);

//chords

Part p2 = new Part("Chords", PIANO, 1);
for(int c = 0; c < chordProgression.length; c++) {
p2.addCPhrase(MyLibrary.majorChord(
chordProgression[c]));
}

s.addPart(p2);

//bass

Part p3 = new Part("Bass", BASS, 2);

Phrase Bphr = new Phrase();
for(int c = 0; c < chordProgression.length; c++) {
Bphr = MyLibrary.bassPhrase(
chordProgression[c] - 24);
p3.addPhrase(Bphr);
}

s.addPart(p3);

//write the score as a MIDI file to disk

Write.midi(s, "UseMyLibraryTest.mid");
}
}

 As you can probably see, using a library can make the code a lot easier to read.  In addition, you can use these methods in any new class you write, without having to copy/paste code.  Reusing existing code and methods is one of the great advantages of Java and Object-Orientated (OO) programming!



J Music Tutorial Index