-
Login to your home directory and launch a terminal window. Use the
cd command to change your default directory to
csci/273.002/labs. Keep this window open for future reference.
-
Launch the NetBeans IDE
and raise the New Project dialog. Define the
project to be a Java Application named Lab06.
Make sure that the project folder will be created within your
csci/273.002/labs folder. As in your previous labs, you should
also uncheck the Create Main Class
checkbox before you click Finish.
-
Now
download the textbook library classes
StdIn.java,
StdDraw.java
, and
StdAudio.java
into the default
package for your project.
As in Lab 05, you will use these library classes
without having to modify them in any way. In fact, you should be
careful not to edit them.
Next find and download the Booksite source file PlayThatTune.java
(Program 1.5.7 in your text). In this lab you will also want
to leave this program intact, but you will shortly be writing new
programs similar to this one.
Now use either the terminal window or the NetBeans Files
view of your project to create a new subfolder of Lab06,
named
input. Assuming that the default directory in your terminal
window is still csci/273.002/labs, the terminal command
to create this folder would be
mkdir Lab06/input
Finally, download the textfiles
elise.txt,
chromatic.txt,
major.txt,
and
minor.txt
into your new input folder. Note: these textfiles
are provided by your kindly instructor, not the Booksite. However,
elise.txt is taken from the listing
on page 150 in your text.
-
Build the project. This step should cause you no problems,
since at this stage you are just compiling several unedited Booksite
files. But if anything goes wrong, check immediately with your lab
instructor before proceeding.
Important reminder: for our purposes it is not sufficient
merely to compile individual source files. Instead you want to use
either the Build or Clean and Build option. This compiles
all the source files and creates the dist subfolder
containing the distribution JAR file named Lab06.jar. As usual,
we will be using this JAR file to run individual project files from
the terminal window.
-
Now return to your terminal window, and enter the command
cd Lab06 to set your default directory to be the Lab06
project folder. As a check, use the ls dist command to list the
contents of the project subfolder dist. (Note that the ls
command does not change your default directory.) You should see the file
Lab06.jar. If not, it's again time to consult with your lab
instructor.
-
At this point you should make sure that either the speaker in your
computer is turned on, or that your earphones are plugged in. Get help
from your lab instructor if necessary to make sure your computer is
audio-ready. Then enter the command
java -cp dist/Lab06.jar PlayThatTune
... Hmmm... nothing seems to be happening, right?...
-
To understand what is going on, leave the terminal window just as it is
for the moment and return to NetBeans. Open the source code for
PlayThatTune.java in the NetBeans editor and read through it.
You should soon discover that your terminal-window program is quietly
waiting for some numbers to be delivered to its
standard input stream.
So return to the terminal window and try entering the following
lines, waiting a few seconds between each one:
0 1.0
1 1.0
2 1.0
As you may have already deduced by now, the first number on each
line (an integer) is a code for a musical tone.
The second number (a real value) specifies the
duration of that tone,
in seconds. PlayThatTune accepts an arbitrary sequence
of these pairs, until it reaches the end of its standard input
stream. Remember that for keyboard input on Linux systems,
this occurs whenever you type ctrl-D.
Now for some background:
- As you may already have noted,
each tone in PlayThatTune is represented as
an array of double values, obtained by sampling
a pure sine wave at fixed time intervals. The sampling
rate is high (44100 samples per second), so the listener
has the impression of listening to a continous wave.
-
The integer codes that specify distinct
tones can be thought of as an index into a logarithmic scale in
which each successive tone is 21/12 times higher in
frequency than its predecessor. The frequency corresponding to
index 0 is just 440 Hz, which in musical terms is known
as concert A (A above middle C on the piano). The correspondence
between musical notes and the index values spanning one complete
octave are shown in the following table:
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
A |
A♯ (B♭) |
B |
C |
C♯ (D♭) |
D |
D♯ (E♭) |
E |
F |
F♯ (G♭) |
G |
G♯ (A♭) |
A |
-
As you can see, index 12 corresponds to twice the
base frequency, or one octave higher.
Of course this scale may be continued indefinitely above and below
the twelve tones that span a single octave. For example,
try entering values like
14 1.0
-12 1.0
-
By now you must realize that you could create a tune or
melody by entering a suitable sequence of tone-duration
pairs. However, it is just not practical to play a tune in real
time by entering values from the keyboard. But if you first write
out your tune in a textfile, then you can simply use
input redirection to make this textfile become the
standard input stream for PlayThatTune. In fact, the file
elise.txt
that you downloaded
earlier is a short example copied from p. 150 in your text. To play the
tune encoded in that file, simply change the
previous command to
java -cp dist/Lab06.jar PlayThatTune < input/elise.txt
-
Now use the textfile
chromatic.txt, which you
also downloaded
earlier,
as standard input to PlayThatTune. You should hear
a chromatic scale, namely a sequence of tones starting with
concert A and proceeding up one index at a time to the next
octave (the tone with twice the starting frequency).
There are many other scales used in Western music,
which all consist of some subsequence of the chromatic scale.
That is, these other scales just skip some of the index values,
while the chromatic scale contains all the values.
For instance, the file
major.txt contains the sequence
known as a major scale. Specifically, if you run
PlayThatTune with this file you will hear the notes
in A major.
-
Actually, the notion of a major scale is not tied to any particular
starting tone. In fact you can play a major scale starting from
any tone. Thus if you start from C and skip the same
pattern of tones as with A major, you get the C major scale.
Of course the same principle applies to other types of scales.
Now these observations just naturally lead up to your next task:
write a variation of PlayThatTune named PlayScale,
which
-
accepts a starting or base tone as its only
command-line argument
-
reads any "scale" from its standard input
stream
-
plays that scale starting from the base tone.
-
By this time you may have noticed that the tones you have been
hearing sound a bit flat or dull. That is in fact all you can get
from a pure sine wave, which is just what PlayThatTune
generates and samples. But you can make these tones sound more
musical by adding harmonics, which are just admixtures
of sine waves at multiples (or submultiples) of the base
frequency. It turns out you can do this quite easily, so your
next task is to edit your program PlayScale as follows:
-
Find the statement that actually computes the pure sine wave
in the existing code.
-
Change the statement so that the wave becomes a superposition
of the original wave and another sine wave with doubled frequency.
In music terminology, this second wave is known as an overtone.
-
Rescale the two components, so that the original wave contributes
70% of the full amplitude and the second wave contributes 30%.
This last step ensures that the overall amplitude or
volume of the wave will be unchanged.
After you make these changes, try running the program and see if you
can notice the difference in the quality of the tone.
As an optional subtask, you might also try adding an undertone,
such as a harmonic at half the original frequency. As before, you
should multiply each sine-wave component by coefficients that add up to
unity.
-
As the final phase of this project, create another Java main class in
the default package named DrawTone. This one will use the
StdDraw library class from the
Booksite,
which you should already have downloaded and added to this project.
In the main() method for this class, start by
copying all the statements from your PlayScale program that
are actually used to create and sample the complete sequence of tones
read in from standard input. Then modify this code so that it
generates just one tone at 440 Hz, for a duration of only
0.01 seconds. (Basically you only need to remove the
input-reading loop
in the original code, and provide the single tone and duration by direct
assignment instead of standard input.)
Next include statements that use StdDraw to plot all the points
in the sampling array. Set the X scale to range from 0 to the
number of points in the array, and set the Y scale to range from
-2 to 2. Then plot all the points in the array,
where each (index, component) pair is taken as an (x,y) point.
As soon as you can run this program successfully, you should try it
out with different combinations of the pure tone and harmonics. One way
to do this is to edit the code to change coefficients and rebuild
between each run, but of course you should feel free to improve the
program so that you can make these changes with less effort...
When your project is complete and working correctly, demonstrate it
to your lab instructor. Then, before you exit NetBeans, clean
your Lab06 project. Finally, before you logout, switch
back to your terminal and set your default directory back to
csci/273.002/labs. Then create a JAR file of your Lab06
project folder, using the command