CS100J Spring 2008   Assignment A6.  Mozart's Musikalisches Würfelspiel.  Due 11:59PM, Saturday, 12 Apr

This assignment uses two-dimensional arrays and random-number generation in an interesting setting. Inspiration for it comes from an assignment given by Kevin Wayne and Robert Sedgewick in Computer Science at Princeton. We have used this assignment before in CS100J, and, although we have made a few modifications, it is easy to cheat. We ask you not to do so. You won't learn anything that way, we have to do extra unnecessary grading, and if you are caught it makes more work for all of us.

Please keep track of the time you spend on this assignment. At the end, we ask you to put a comment at the top of file WurfelSpiel.java that indicates how much time you spent.

In 1787, Wolfgang Amadeus Mozart created a dice game (Mozart's Musikalisches Würfelspiel). One composes a two-part waltz by pasting together 32 of 272 pre-composed musical elements at random. The waltz consists of two parts: a minuet and a trio. Each is composed of 16 measures, which are generated at random according to a fixed set of rules, as described below.

Minuet. The minuet consists of 16 measures. The 176 possible Minuet measures are named m1.wav through m176.wav. To determine which one to play, roll two dice and use the following table. The dice roll (a row number) tells you what to play for a measure (a column number). For example, if you roll 11 for measure 3, then play wav file m165.wav.

       1    2    3    4    5    6    7    8    9   10   11   12   13   14   15   16
-----------------------------------------------------------------------------------
  2   96   22  141   41  105  122   11   30   70  121   26    9  112   49  109   14
  3   32    6  128   63  146   46  134   81  117   39  126   56  174   18  116   83
  4   69   95  158   13  153   55  110   24   66  139   15  132   73   58  145   79
  5   40   17  113   85  161    2  159  100   90  176    7   34   67  160   52  170
  6  148   74  163   45   80   97   36  107   25  143   64  125   76  136    1   93
  7  104  157   27  167  154   68  118   91  138   71  150   29  101  162   23  151
  8  152   60  171   53   99  133   21  127   16  155   57  175   43  168   89  172
  9  119   84  114   50  140   86  169   94  120   88   48  166   51  115   72  111
 10   98  142   42  156   75  129   62  123   65   77   19   82  137   38  149    8
 11   54  130   10  103   28   37  106    5   35   20  108   92   12  124   44  131
 12    3   87  165   61  135   47  147   33  102    4   31  164  144   59  173   78

Trio. The trio consists of 16 measures. The 96 possible Trio measures are named T1.wav through T96.wav. To determine which one to play, roll one die and use the following table. For example, if you roll 1 for measure 21, then play file T81.wav.

    17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32
------------------------------------------------------------------
 1  72   6  59  25  81  41  89  13  36   5  46  79  30  95  19  66
 2  56  82  42  74  14   7  26  71  76  20  64  84   8  35  47  88
 3  75  39  54   1  65  43  15  80   9  34  93  48  69  58  90  21
 4  40  73  16  68  29  55   2  61  22  67  49  77  57  87  33  10
 5  83   3  28  53  37  17  44  70  63  85  32  96  12  23  50  91
 6  18  45  62  38   4  27  52  94  11  92  24  86  51  60  78  31

Example. Here is a sample waltz generated using this process and the accompanying musical score. There are 11^16 * 6^16 different possible waltzes. Since this is over 10^23 different possibilities, each time you play the game you are likely to produce music that has never been heard before! Mozart carefully constructed the measures to obey a rigid harmonic structure, so each waltz reflects Mozart's distinct style.

About this assignment. To help you learn as much as possible in a short amount of time as possible, and also to give you advice on how to go about writing and testing programs, we lead you through this assignment in a series of steps. Please study the code we have given you; be conscious of style, specifications, etc.

Follow the directions carefully. Many people have had more points off because they failed to follow instructions than because of programming errors. When doing one step, don't go on to the next one until the current one is done and the method you wrote for it works!

Step 1. Download the following and place them all in a new folder for the assignment.
File StdAudio.java. Class StdAudio contains methods for manipulating and playing music in wave (.wav) format.
File WurfelSpiel.java. You will be writing class WurfelSpiel. We have provided a few components in it to help out.
File WurfelSpielTester.java. We have provided you with stubs of test methods and with some testing instructions in the bodies.
File measures.zip (34MB). After downloading this file, unzip it —into a folder measures that contains all the .wav files for the measures used in Mozart's Musikalisches Würfelspiel. Put folder measures in the folder with the two .java files.

Load StudioAudio.java into DrJava and become familiar with its methods. Call method playScale just to see what sounds come out.

Step 2. Generating rolls of a die. Your program will have to "roll a die" to produce a random number in the range 1..6. At the beginning of class WurfelSpiel, there is a declaration of a static Random variable generator. An object of class generator has functions for generating "random" numbers. The one you will use is function nextInt. Evaluation of a call generator.nextInt(t) yields an integer i that satisfies 0 <= i < t. Use function nextInt in writing the body of method WurfelSpiel.throwDie. The method body need be only a single return statement.

Class Random is in API package java.util. Use link java.sun.com/javase/6/docs/api/java/util/Random.html to obtain the API specs for this class and spend some time becoming familiar with it.

Function throwDie seems extremely simple! Nevertheless, it has to be tested to make sure that (1) it produces only integers in the range 1..6 and (2) can produce all integers in 1..6. In order to help you do this, we have written part of method WurfelSpielTester.testThrowDie. Study what we have written in the specification and the body of this method, complete the method, and test throwDie.

Step 3. A method for printing a String array. Later, you will be writing a function that produces a String array of file names corresponding to measures to be played. In order to see that the method works, you have to see the array of Strings. For that purpose, we have partially written function toString(String[]). Study what we have written in the specification and function body and complete the function. Then test it by completing test method WurfelSpielTester.testToString.

Step 4. Generating a waltz. Before you work on creating a random waltz, first create a waltz assuming that each die thrown has the value 1, so that all the file names in row 2 of array minuet and row 1 of array trio are chosen. This allows you to concentrate on the idea of constructing a file name. To do this, write the body of function WurfelSpiel.create1Spiel().

We have given you arrays minuet and trio in class WurfelSpiel. Each element of these arrays is an integer that indicates a file that represents a measure. For example, minuet[2][1] = 96, which represents file measures/m96.wav. So, you have to put the String "measures/m96.wav" into the array that this function returns. minuet[2][1] is one of the musical phrases that can be used in measure 1 of the minuet part. Note that "/" is used to separate folder name measures from file name m96.wav. Even if you have a PC, you must use "/" and not a backslash.

After writing this function, complete procedure WurfelSpielTester.testCreate1Spiel(). We put in a test to make sure that the first array element is correct so that you have some idea how to do this. You must make sure that all array elements are correct. You should also print the array of strings in the interactions pane, using function toString(String[]), so that you can see it; this latter step is just for your benefit.

Step 5. Listen to the music! Complete procedure WurfelSpiel.play(String[]), which will play all the files whose names are in an array such as that calculated by function createSpiel. You will notice pauses between measures when the music is played. We investigate eliminating the pauses later. Playing your array should produce the same music as this file: mozart12.wav.

Step 6. We can get rid of the pause between measures by building a single file that contains the music in the files given by an array like s in the past two steps. To do this, complete the body of function WurfelSpiel.build(String).

To do this, you have to read a .wav file and place its contents into a double array; use function StdAudio.read(String) to read one file at a time. To help you out, we give an outline for the body of WurfelSpiel.build(String), and we also give you method WurfelSpiel.copy. You figure out how to check this function; as long at it is correct, we will not look at your test cases.

Step 7. Creating a Mozart Musikalisches Würfelspiel. Finally, write the the body of function WurfelSpiel.createRandomSpiel(), which will create a random waltz. It should produce a random waltz as described at the beginning of this document. In this method, you can use throwDie, which you wrote earlier, to throw a die to get a number in the range 1..6. Also, use arrays minuet and trio in class WurfelSpiel when generating random names of files, as in method create1Spiel.

Step 8. Saving a file. You don't have to do anything here. We want you to know that method StdAudio.save allows you to save a double array in a .wav file, so that you can play it later ---or email it home to let your family know that you have been turned on by classical music and Musikalisches Würfelspiel. You can use any file name you want, as long as it ends in ".wav". The file will be stored on your desktop.

Step 9. Submitting your assignment. Place at the top of file WurfelSpiel.java a comment that says how many hours you spent on this assignment. Submit files WurfelSpiel.java and WurfelSpielTester.java on the CMS by the due date.