CS 1713 Section 1 Spring 2011, Homework 3
Draw Waveforms
Waves are an important part of science and engineering, not to mention
other aspects of life. Sound waves carry to us every auditory experience
imaginable, including music, car horns, birdsong, and the dulcet tones of
your instructor's voice explaining Java to you. Light waves bring us vision.
Waves in the water carry surfers. Etc. If you're not sold on waves yet,
just to pretend to be for the rest of this assignment.
For this assignment, you will write a Java applet that displays a
digitized waveform in a window. A waveform is just the
shape of a wave. Waves are represented digitally by sampling their
amplitude, or strength, at regular intervals. For instance, a
.WAV file or an audio CD contains a sequence of signed integers
sampled 44,100 times a second, i.e., sampled at a frequency of 44.1 KHz.
Each integer in the digital wave is called a sample.
See this file for an example of audio recorded at
44.1 KHz and represented as signed integers. Hey, extra credit if you
figure out what song this is from.
This program is due at 11:59pm, Monday, February 14, 2011.
We would like to display the entire waveform, from beginning to end, in
a window. To do this, we will have to scale the wave so that it
fits in the window. That is, we will have to find the minimum and maximum
sample values and do some math on them so they fit on the y-axis
between 0 and the height of the window and remain proportional to one
another. We also have to scale in the x-axis by choosing a number
of equally-spaced samples equal to the width of the window. So we'll draw
the waveform by converting the digital samples into (x,y)
coordinates and drawing lines between them.
For this assignment, you will develop the following classes:
- Waveform.java. This class will represent the digitally sampled wave. It will have
the following public methods:
- public Waveform () - This constructor will initialized
fields you need in the class. For instance, you should set up an
array to hold the digitally sampled wave, and a variable to keep
track of how many samples are in the wave.
- public void read () - This method should read the
digitally sampled wave from the standard input. That is, the user
can type in the numbers and press 'ctrl-D' when finished, or you
can run appletviewer with standard input redirected from
a text file containing the sampled wave. Important: the
Waveform class should be able to read in a digitized wave
with any number of samples up to the capacity of machine.
That is, there is no predetermined maximum number of samples.
- public int getSample (int i) - This method should
get the ith sample in the wave. If i
is less than 0, it should return the first sample. If i
is beyond the number of samples in the wave, it should return the
last sample. That way, any method that calls getSample
doesn't have to worry whether it is out of bounds.
- public int getMiny () - This method should find and
return value of the minimum sample.
- public int getMaxy () - This method should find and
return the value of the maximum sample.
- public int getNsamples () - This method should return
the number of samples.
So the Waveform class acts like a specialized array that reads
in a wave and provides specialized access to it.
- DrawWave.java. This class will extend JApplet.
It is the class that draws the waveform on the screen. It should have the following public methods:
- DrawWave(). This is the constructor. It should make an object
of class Waveform and invoke the read method to read in a wave.
The object should be a private field of the DrawWave class.
- paint (Graphics page). This is the method that overrides
JApplet's paint method and draws stuff on the graphics
window as in previous programs. This method should draw the waveform on the
window. The waveform should fit properly in the window so that the maximum
value is displayed at the bottom of the screen and the minimum value at the
top, with the first sample on the leftmost part of the screen and the last
sample on the rightmost part of the screen. When the screen is resized,
the waveform should be drawn properly again to fit within the new size. For example, when the
window is 400 × 400 and we use this simple input file, the
result should look like this>
When the window is resized to 800 × 200, the waveform should be
stretched and squashed to look like this:
Testing Your Program
You can test your program on the following digitized wave files in addition to any you make up on your own:
How do you get these files into your account? You can "save" them from your web browser, or try the wget command.
Important Issues to Think About
- How big should I make the array?
Start out with, say, 10 elements and expand the array as needed. How do
you do that? We go over that in class. Don't make the array huge
to begin with; that is very inefficient, and there is always a bigger file
that will break your program if you don't expand the array. Don't
expand the array for every sample; in class we see how to expand the
array very few times but continue to make efficient use of array storage.
Make sure to keep a separate number indicating the number of samples versus
the size of the array.
- How do I scale the waveform to fit in the window?
Let the number of samples be n, the maximum sample
value be ymax, the minimum sample value be
ymin, the width of the window in pixels be w,
and the height of the window in pixels be h.
In the x-axis, the question is: which sample should
be drawn at position x? The answer is given by
x × n / (w-1). That is, we want to scale
an index between 0 and n into x-positions between 0
and w-1.
In the y-axis, we need to scale values between
ymin and ymax to values between
0 and h-1. I'll let you guys figure this one out on your own,
but here's a hint: you'll want to subtract the minimum sample value from
every sample so you can get values between 0 and something, and then use
something similar to the scaling for x.
What To Turn In
Email your Waveform.java and DrawWave.java files as
attachments in the same email message to our teaching assistant. Make sure
you have put in comments such that a beginning Java programmer like you
can understand the logic of your program.
This program is due at 11:59pm, Monday, February 14, 2011.
Late assignments will not be accepted.
If you're not done with some part before it's due, turn in what you have
for partial credit. Don't cheat.