This assignment is inispired by a Nifty Assignment introduced by Kevin Wayne (Princeton University) and refined by Stuart Reges (University of Washington).
When a piano wire is struck, the wire vibrates and creates sound. The vibration can be measured by sampling the displacement of the wire at equally spaced points. These displacement measurements can be stored digitally, say in a list or queue structure, then used to recreate the sound wave over a speaker.
For this assignment, you will store the displacement values for a piano wire in a queue structure. When at rest, the wire can contain energy at any frequency. This is modeled by assigning the queue to contain random real numbers between -1/2 and +1/2. After the wire is struck, it vibrates causing a displacement that spreads wave-like over time. The Karplus-Strong algorithm simulates this vibration using a fairly simple update process: it repeatedly deletes the first sample from the queue and adds to the end of the queue the average of the first two samples, scaled by an energy decay factor of 0.996.
This simple algorithm provides an effective model of the wire vibration due to two features: the queue feedback mechanism and the averaging operation.
For the first part of this assignment, you are to implement a class that models a single piano wire. Your
PianoWire class should provide the following constructor and methods:
public PianoWire(int wireNum)
SAMPLE_RATE * 2(22 - wireNum)/12 / 440
Here, SAMPLE_RATE is a constant defined in the StdAudio class, which was developed at Princeton.
public void strike()
public double sample()
You should test your class thoroughly by creating an object with a short queue and displaying the results of each update. Once you are convinced that the class is behaving as desired, you may integrate it with the provided Piano class. This class implements a simple piano, with keyboard keys mapping to individual wires. The routines for rendering the vibrations using your computer's sound card are contained in the utility class StdAudio. The routines for processing keyboard events are contained in the utility class StdDraw, which was also developed at Princeton.
A player piano is a mechanical piano that uses some medium (often paper rolls with patterns of holes) to encode the notes and chords of a composition. The player piano mechanism interprets the pattern and automates the playing of that composition. You are to implement a
PlayerPiano class that automates the playing of a composition on a
Piano object. The main method of your class should prompt the user for the name of a text file, read in the contents of the file, and play the notes/chords.
Your class should utilize a piano with 3 octaves. The 12 notes in the middle octave are denoted:
"C", "C#" or "Db", "D", "D#" or "Eb", "E", "F", "F#" or "Gb", "G", "G#" or "Ab", "A", "A#" or "Bb", "B"
Note that the black keys in an octave can be denoted in two ways, as a sharp (using "#") or a flat (using "b"). The notes in the lower octave are the same but with a "-" character at the end (e.g., "C-" is low-C). Similarly, the notes in the higher octave are the same but with a "+" character at the end (e.g., "Eb+" is high-E-flat). Notes that appear on the same line of the file should be played simultaneously. This is accomplished by striking all of the corresponding wires, then calling the
Piano.play method in a loop to control the duration. Each note/chord should play for 0.5 seconds (i.e., repeatedly play the notes SAMPLE_RATE/2 times).
Files that encode Chopsticks and Mary had a Little Lamb are provided for you.