This assignment is inspired by a Nifty Assignment introduced by Kevin Wayne (Princeton University) and refined by Stuart Reges (University of Washington).
A hammered dulcimer is percussion instrument with rows of strings, stretched out over a trapezoidal base. A musician plays the instrument by striking the strings with small mallets, or hammer.
Note that in each dulcimer shown above, there are two internal bridges that hold up the strings. The bridge on the right is known as the bass bridge and the strings to the right of it are the bass strings. The bridge to the left is known as the treble bridge, and the strings to the left and right of it are the treble1 and treble2 strings, respectively. The strings can be tuned to different patterns, but the most common arrangement is shown below (where '+' after a note denotes a higher octave and '-' denotes a lower octave):
The physics behind stringed instruments is rather interesting. When a dulcimer string is struck by a hammer, the string vibrates and creates sound. The vibration can be measured by sampling the displacement of the string 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 dulcimer string in a queue structure. When at rest, the string 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 string 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 adds to the end of the queue the average of the first two samples, scaled by an energy decay factor of 0.996, and removes the first sample from the queue.
This simple algorithm provides an effective model of the string 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 dulcimer string. Your DulcimerString
class should provide the following constructor and methods:
public DulcimerString(String note)
The constructor should initialize a queue containing N zeros, where N is the nearest integer to:
SAMPLE_RATE * 2(22 - offsetFromMiddleC)/12 / 440
Here, SAMPLE_RATE is a constant defined in the StdAudio class, which was developed at Princeton. See below for details on calculating a note's offset from middle-C.
public String getNote()
public int getOffsetFromMiddleC()
One approach to calculating the offset is the following:
public void strike()
public double sample()
You should test your class thoroughly by creating dulcimer strings and inspecting their contents after each update. Once you are convinced that the class is behaving as desired, you may integrate it with the provided Dulcimer and DulcimerDriver classes. The Dulcimer
class is a working (but incomplete) implementation of a virtual dulcimer, with only the bass strings represented. The DulcimerDriver
class allows you to play the bass strings by hitting keys on the keyboard.
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.
Currently, the dulcimer can only play the bass strings. You are to modify your Dulcimer
and DulcimerDriver
classes so that all three rows of strings are represented and playable. The treble1 strings should be played using the keys on the top row of the keyboard ("1234567890-="), while the treble2 keys should be played with the next row of keys ("qwertyuiop[]").
As part of your modifications, you should add text to the display window that informs the user of the key mappings for the treble strings.