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.
import jm.music.data.*; import jm.JMC; import jm.util.*; public final class MozartDiceGame implements JMC{ public static void main(String[] args){ MozartPhraseList MPL = new MozartPhraseList();
Score score = new Score("DiceGame"); Part piano = new Part("Piano", 0, PIANO);
for (int j=0; j<4; j++){
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); nextBar = MPL.barArray[i][randNum-2].copy(); nextBar.setStartTime((float)((i*3)+(j*24))); piano.addCPhrase(nextBar); } j++; 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);
nextBar = MPL.barArray2[i][randNum-2].copy(); nextBar.setStartTime((float)((i*3)+(j*24))); piano.addCPhrase(nextBar); } }
score.addPart(piano);
Write.midi(score, "mozart.mid"); } 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 { CPhrase[][] barArray = new CPhrase[8][11]; CPhrase[][] barArray2 = new CPhrase[8][11]; public MozartPhraseList() { 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).
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.
|