Band Machine

Band machine is an algorithmic band. A kind of Band in a Java Box. It produces rhythm section jMusic scores for Drum Kit, Bass, and Piano. You can choose which parts paly, the style if music generated, the length of the score, and wheather or not to have a fade in or fade out. Band Machine will do the rest (like it or not!). If you don't like it - edit it.

Band Machine appears like this when run:

This demo is a good example of the FadeIn and FadeOut jm music methods. Andrew T wrote them for this program.

This program was written by Andrew Troedson.

Here are the source files - all classes are required.

Click here to view source - BandMachine.java

Click here to view source - BandMachineGUI.java

Click here to view source - BassMachine.java

Click here to view source - DrumMachine.java

Click here to view source - PianoMachine.java

Click here to view source - ChordProgression.java

Click here to view source - ProbabilityTest.java

Click here to view source - PhraseTools.java

Click here to view source - CPhraseTools.java

To hear the result play the MIDI file below.

Andrew Troedson's comments:

Band Machine is a composition engine which draws on a series of other tools to generate music using a mixture of algorithmic and combinational processes. It also allows for the user to define a number of settings which have an important effect on the outcome.

Technicalities

Utilizing the jMusic structure, Band Machine incorporates several different tools whose relationships are shown in Figure 3.1 below:

The main class, BandMachine.java, draws upon the ChordProgression class to establish the root and tonality of the next chord, and then uses this information to transpose the phrases which it receives from the Piano, Bass and Drum Machines as appropriate. The class BandMachineGUI.java provides a GUI interface for the BandMachine tool which allows for easy selection of a variety of settings, and it is actually this class that should be run.

The ChordProgression tool selects the next chord in a progression based on the root and the tonality (i.e. whether it is major or minor) of the previous chord. It is based on a probability table which gives the probability of any major or minor chord occurring after the specified chord. The different chord styles (ROCK, SWING and JAZZ) are simply representative of different probability table settings. The ChordProgression class uses the ProbabilityTest tool to make all its probability-based decisions.

The Piano, Bass and Drum Machines each produce phrases (or CPhrases) of the particular instrument that they represent. The PianoMachine and BassMachine do this in a combinational manner as each have a list of both major and minor phrases which they choose from as appropriate (i.e. as fits the selected style for that instrument). The DrumMachine produces its phrases algorithmically &endash; again by using a series of probability-based rules.

The default name of the generated MIDI file is "bandmachine.mid", although this can be easily changed using the BandMachineGUI interface.

Observations

One thing that was especially noticeable with the ChordProgression tool was that the best results were achieved when the rules were set to restrict the possible chords to only about 8 of the 24 possible options. Any more than this and the resulting chord progressions became somewhat unstable as the root (or key) became confused. This again is logical as most pieces of music are based around only a small number of chords -especially rock music that is most commonly based on four chord riffs which repeat for the duration of a song.

Another important point can be made about the decision to treat the PianoMachine and BassMachine combinatorially. Although (as was pointed out in the use of this technique in Mozart's Dice Game) using this method tends to restrict the possibilities of the final composition, it is the easiest way to ensure that the result sounds "correct". Also, because of the algorithmic nature of both the chord progressions produced by the ChordProgression tool, and the drum phrases created by the DrumMachine, the repetitive nature of the combinatorial PianoMachine and BassMachine phrases tends to be somewhat hidden. This is further helped by the option to select different styles for each instrument, and the ability to "mix and match" these styles.

As with the wordMusic tool, further development of BandMachine is definitely feasible. Enhancements could be made both within and above the existing structure such as: the creation of a wider variety of instruments and styles; the taking into account of voice leading; the enabling of individual instrument machines to interact with each other; and the conversion of the PianoMachine and BassMachine so that they generate phrases algorithmically rather than combinatorially. These are all possibilities, and each would provide various challenges in their implementation. However, this basic model demonstrates some of the possibilities and issues that can arise from both the combinatorial and the algorithmic methods of generating music.


Take a look at the GUI.


The code:

Let's have a closer look.

/* --------------------
* BANDMACHINE - a class that creates a piece of music
* using the DrumMachine, BassMachine and PianoMachine,
* as well as the ChordProgression class
* @author Andrew Troedson
* ---------------------
*/
 
import jm.music.data.*;
import jm.JMC;
import jm.midi.SMF;
 
public final class BandMachine implements JMC{
	
	public static void compose(int pieceLength, 
								double fadeInLength, 
								double fadeOutLength,
								String progressionStyle, 
								boolean pianoPart,
								String pianoStyle,
								boolean bassPart,
								String bassStyle,
								boolean drumsPart,
								String drumsStyle,
								String[] firstChord,
								String[] lastChord,
								String fileName){
		System.out.println("BAND MACHINE STATS:");
		System.out.println("Piece length: " + pieceLength);
		System.out.println("fade in over " + fadeInLength + " bars");
		System.out.println("fade out over " + fadeOutLength + " bars");
		System.out.println(progressionStyle + " style chord progression");
		if (pianoPart) {System.out.println(pianoStyle + " piano part");}
		if (bassPart) {System.out.println(bassStyle + " bass part");}
		if (drumsPart) {System.out.println(drumsStyle + " drum part");}
		System.out.println("First chord: " + firstChord[0] + " " + firstChord[1]);
		System.out.println("Last chord: " + lastChord[0] + " " + lastChord[1]);
		System.out.println("Output file: " + fileName);
		//Create the data objects we want to use
		Score score = new Score("MainScore");
		//Parts can have a name, channel, and instrument.
		Part piano = new Part("Piano", 0, PIANO);
		Part bass = new Part("Bass", 1, BASS);
		Part drums = new Part("Drums",9);
		
		int progressionLength = pieceLength;	
		
		//set the root and tonality of the first bar
		int root = Integer.parseInt(firstChord[0]);
		String tonality = firstChord[1];		
		
	  for (int j=0; j<progressionLength; j++){
			
			//don't get a new chord for the first bar
			if (j>0) {
				String[] nextChord = ChordProgression.nextChord(root, tonality, progressionStyle);
				root = Integer.parseInt(nextChord[0]);
				tonality = nextChord[1];
			}
			//set the last chord
			if (j == progressionLength - 1) {
				root = Integer.parseInt(lastChord[0]);
				tonality = lastChord[1];
			}
			System.out.println(root + " " + tonality);
			
			if (pianoPart) {
				CPhrase nextBar = PianoMachine.getBar(tonality, pianoStyle);
				nextBar.setStartTime((float)(j*4));
				nextBar.transpose(root);
  				piano.addCPhrase(nextBar);
  			}
 
			if (bassPart) {
				Phrase nextBassBar = BassMachine.getBar(tonality, bassStyle);
				nextBassBar.setStartTime((float)(j*4));
				nextBassBar.transpose(root);
  				bass.addPhrase(nextBassBar);
			}
			
			if (drumsPart) {
				CPhrase nextDrumBar = DrumMachine.getBar(drumsStyle);
				nextDrumBar.setStartTime((float)(j*4));
  				drums.addCPhrase(nextDrumBar);	
  			}		
	  }
	
		//add part (instrument) to the score
		score.addPart(piano);
		score.addPart(bass);
		score.addPart(drums);
		score.fadeIn(fadeInLength);
		score.fadeOut(fadeOutLength);
			
		//OK now we test SMF write and read
 
		Write.midi(score, filename);
	}
}
This is the main BandMachine class which is called by the BandMachineGUI class. The class above coordinates all the individual algorithmic generators - DrumMachine, Piano Machine, and BassMachine. There is not room in this tutorial to show all the code, check it out for yourself from the links above.


jMusic Tutorial Index