Mozart Dice Game

Algorithmic recombinatorial music has a long heritage, even as far back as Mozart. His Musikalisches Würfelspiel was a dice game where the results of throws choose amongst possible prewritten bars of music. Depending upon the numbers thrown, different, but similar, pieces can result. Read about it in the Computer Music Tutorial (Roads 1996) starting on page 823. The full music for it can be found in the Appendix of Schwanauer & Levitt (1993) 'Machine Models of Music' The MIT press. There is also a discussion of it in Roads, C. 1996. 'The Computer Music Tutorial'.

This demo is a realisation of Mozart's design in jMusic by Andrew Troedson.

Click here to view source part 1

Click here to view source part 2

To hear the result play the MIDI file below.

Andrew Troedson's comments:

An Overview

W.A.Mozart's Musikalisches Wurfelspiel (Musical Dice Game) is one of the earliest examples of chance music. It sets out a series of short phrases which are selected randomly (based on the rolls of a dice), and combined to form a two-part waltz. This approach to the generation of music is known as the combinatorial approach because it involves the combination of a series of pre-composed musical elements.

Technicalities

Utilizing the jMusic structure, this realization of Mozart's Dice Game automates the dice rolling process, and allows waltzes to be generated using Mozart's original rules and phrases.

It is set out in two classes - MozartDiceGame.java, and MozartPhraseList.java. The MozartPhraseList class holds all the phrases (actually stored as CPhrases) which are combined to form the finished waltz, and the MozartDiceGame class automates the dice rolling process which accomplishes this. The default name of the generated MIDI file is "mozart.mid".

Observations

There is no doubt that the process is effective - an (almost) infinite number of waltzes can be generated, and each one has the distinct sound that is attributed to Mozart. Unfortunately, this means that one cannot really take credit for the composition of a new work as each one is obviously a composition of Mozart.

It is also disappointing to realize that, while each generated new work does have its subtle differences, nothing extraordinary or excitingly new will ever be produced. This is mainly because Mozart has composed the phrases to follow a strict harmonic structure that remains unchanged in every new generation. The reason that he has done this is obvious - it is the easiest way to guarantee that each generation will sound correct (however this does come at the cost of spontaneity).

As well as the realization that Mozart made things easy for himself by enforcing this rigid harmonic structure on the phrases he composed, I was heartened to discover that such a great composer could be accused of "cheating" a little, and of "cutting corners". The last bar of the first part of the waltz (bar 8) is not in fact chosen by chance - this is because the eight options given by Mozart to fill this bar are identical! Mozart uses a similar tactic in the last bar of the second part (bar 16), and provides only three differing options for this bar. Again, the reasons behind this little deceit are obvious (as are the costs to the spontaneity of the music produced) - to guarantee that each generation will sound correct.


The code:

Let's have a closer look.

/**
* A realization of Mozart's Dice Game
* @author Andrew Troedson
*/

 
import jm.music.data.*;
import jm.JMC;
import jm.util.*;
 
public final class MozartDiceGame implements JMC{

public static void main(String[] args){

//the class in which all the phrases are stored

MozartPhraseList MPL = new MozartPhraseList();
//Create the data objects we want to use

Score score = new Score("DiceGame");

//Parts can have a name, channel, and instrument.

Part piano = new Part("Piano", 0, PIANO);
//repeates the full waltz twice (ie form ABAB)
	for (int j=0; j<4; j++){ 
//create the first part of the waltz

	    for (int i=0; i<8; i++){ 
//roll the dice

int randNum = (int)rollDice(2);
System.out.println("roll " + (i+1) + ": " + randNum);
CPhrase nextBar = new CPhrase(0.0);
//get the appropriate phrase
nextBar = MPL.barArray[i][randNum-2].copy();
//set the phrases start time
nextBar.setStartTime((float)((i*3)+(j*24)));
//add it to the main part
piano.addCPhrase(nextBar);

}
//required to set the correct start times
//in the second section of the waltz

j++;
//create the second part of the waltz
for (int i=0; i<8; i++){
int randNum = (int)rollDice(2);
System.out.println("roll " + (i+1) + ": " + randNum);
CPhrase nextBar = new CPhrase(0.0);

                //get the phrase from the second phrase table
nextBar = MPL.barArray2[i][randNum-2].copy();
nextBar.setStartTime((float)((i*3)+(j*24)));
piano.addCPhrase(nextBar);
}
}

//add the main piano part (instrument) to the score

score.addPart(piano);

Write.midi(score, "mozart.mid");
}

//method which automates the rolling of a specified number of die

static int rollDice(int dieNum){
int roll = 0;
for (int i=0; i<dieNum; i++){
roll += ((int)(java.lang.Math.random()*6)) + 1;
}
return roll;
}
}
The code is adequately commented such that you should be able to follow it thorugh. The MPL (MozartPhraseList) variable is an instance of the other class with all the bars of music in it. The main part of this class consists of interative loops which step through each bar of the piece selecting a CPhrase from the eight availible for that bar.

import jm.music.data.*;
import jm.JMC;
import jm.util.*
 
public class MozartPhraseList implements JMC {

//Phrase array which stores all the phrases

CPhrase[][] barArray = new CPhrase[8][11];
CPhrase[][] barArray2 = new CPhrase[8][11];

//the phrase tables and individual phrases are
//initialized upon the creation of a new instance

public MozartPhraseList() {

//bar 1

int[] pitchArray1a = {f2,f4};
CPhrase bar1 = new CPhrase(0.0);
bar1.addChord(pitchArray1a, C);

int[] pitchArray1b = {d2,d4};
bar1.addChord(pitchArray1b, C);
 
int[] pitchArray1c = {g2,g4};
bar1.addChord(pitchArray1c, C);

more . . .

This is the first part of the data base class. It employs two dimensional arrays of Chord Phrases. The first bar is shsown and each other bar is filled similarly. There are 8x16 bars!! (minus some Mozart repeats).

			// Add the phrases to the phrase tables 
// (two-dimensional arrays) first part
// of the waltz)

barArray[0][0] = bar96;
barArray[0][1] = bar32;
barArray[0][2] = bar69;
barArray[0][3] = bar40;
barArray[0][4] = bar148;
barArray[0][5] = bar104;
barArray[0][6] = bar152;
barArray[0][7] = bar119;
barArray[0][8] = bar98;
barArray[0][9] = bar3;
barArray[0][10] = bar54;
 

more . . .
Toward the end of the class the individual bars are instered into the arrays. The main class makes an instance of this data and gets bars from the arrays.



J Music Tutorial Index