### Programming Assignment Checklist: Digital Signal Processing

Special collaboration policy: For this assignment only, you may work jointly with a partner. That is, you may choose to develop and write your code with one COS 126 classmate. In that case, you should write and turn in individual readme.txt files, but only turn in one copy of the code. Of course, both partners are responsible for jointly working on and understanding everything that is turned in.

I'm having trouble with trigonometry. What could be wrong? It's fine to just use the formula provided. Note that a sine wave repeats every 2π radians or 360 degrees. In Java, the argument to Math.sin should be in radians, not degrees. Use Math.PI to get the mathematical constant π.

I can play CDs and MP3s using my favorite media player, but I don't get any sound out of Java. What could be wrong? First, be sure to try the JavaLayer Player javazoom.jl.player.jlp as suggested in the assignment - this will ensure that the problem is not in any of your code. If you don't get any sound, it may be because your operating system has turned off the sound device that Java uses. On my Windows XP machine, I had to go to Start -> Programs -> Accessories -> Multimedia -> Volume Control and unmute the Wave Out slider. The 017 labs in the Friend center may need a similar adjustment.

My program does not play any sound under Windows 2000. What's wrong? Sometimes the audio device gets "locked up" and programs (Winamp, Windows Media Player, the Java MP3 player) cannot play sound. This is a well-known bug in Windows 2000. You can usually work around it by logging off and logging back in.

How do I convert from a double to an int? Use an explicit cast: int n = (int) x; - this will truncate the real value x to an integer n.

How do I determine how many elements are in an array? If a is an array, then a.length gives its length.

How do I divide two integers and end up with a real number? In Java, when you divide two values of type int, the result is an int. This could lead to unintended results - a / 32768 is 0 for all values of a between 0 and 32767. If you make one of the operand a double (by an explicit cast or multiplying by 1.0) then you will get the desired result.

Why does the compiler complain when I try to set c = a + b; where all three variables are of type short? Java has some arcane type conversion rules. In this case the expression a + b is automatically promoted to be of type int. Assigning an int to a short requires an explicit cast: c = (short) (a + b);.

My echo filter sounds really weird on some inputs. Why is this? The raw data is stored as a short, which can only take on values between -32,768 and 32,767. The strange noise may be the result of overflowing these bounds by adding two waves.

I get an ArrayOutOfBounds or NullPointerException error. What could cause this? Do your constructors initialize all of the data members (left, right, and N)? Did you allocate memory for each of your arrays with new? Did you inadvertently redeclare int N or short[] left in a method or constructor, thereby hiding the data members with the same name?

Do I need to worry about adding two waves that have a different number of samples? Or a wave whose left and right channels have a different number of samples? No. It's fine to assume all waves within a given program will have the same length (but that number need not be 44,100 or 1,152), but it can't hurt to do some error checking.

Why do I need to include System.exit(0) at the end of my program? There is a documented bug in the Java VM that prevents the program from exiting cleanly when you interact with a sound card. This is the temporary work-around.

Why can't I just put Player.java in my working directory and avoid the classpath stuff as with StdDraw.java? You can, but Player.java relies on 78 other user-defined files, so you'd have to put them in the same place too.

Java complains that it can't find javazoom.j1.player.j1p even though player.jar is in the current directory. What am I doing wrong? It should be javazoom.jl.player.jlp with the letter l and not the number 1.

I can get the music to play, but I can't get the graphics to display, and I'm using Apple's Java 1.4.1_01. There appears to be a bug with either Player.java or Apple's JVM. Try putting StdDraw.create before Player.open. If this doesn't work, execute using Java 1.3.1. Compile as usual, but type the following command to execute

/System/Library/Frameworks/JavaVM.framework/Versions/1.3.1/Commands/java
-classpath .:player.jar MP3Viewer felten.mp3

 Input, Output, and Testing

Input.   Here are some sample input files.

Compilation.   Your programs must be named Wave.java, EchoFilter.java, and MP3Viewer.java. Don't forget to hit the "Run Script" button on the submission system to test that it compiles cleanly.

 Submission

Use the following readme file template.

 Possible Progress Steps

These are purely suggestions for how you might make progress. You do not have to follow these steps.

• Download the directory dsp to your system. It contains the MP3 Player library, and some sample client programs.

• Review the data type Waechter.java for N-dimensional real vectors. It is similar in many ways to Wave.java.

• We recommend defining the set of values as follows:
public class Wave {
private int N;             // number of samples per channel
private short[] left;      // samples for left channel
private short[] right;     // samples for right channel
}

• The design of your program should look like Wave.java, except that you will need to fill in all of the constructors and methods.

• Your constructors for Wave will need to allocate and initialize two arrays of short integers using new. Observe that you have to do this in the constructor (and not when you declare the data members) since otherwise you wouldn't know how big to make the array.

• This file contains the first short integers for the first 201 samples (approximately the first two sin waves in an A).

• Your plus method should return a new Wave object so you will need to call the Wave constructor by using the keyword new. The method should not modify either of its two inputs in any way.

• For the echo filter, copy MP3Player.java to EchoFilter.java, and replace the body of main to enable the echo effect. You will need to save the last 10 sound waves, so use an array of waves of size 10.

• The program MP3Viewer.java should be almost identical to MP3Player.java, except that you will call draw instead of play, and a few Turtle graphics commands (StdDraw.create and StdDraw.pause). Now make a draw method for your Wave class. Each instance call to draw() should plot out both channels of that wave. To implement draw() use StdDraw.go(x, y) and StdDraw.spot() for N points (typically 1152) per channel.

From the client program, call

StdDraw.create(576, 512);
StdDraw.setScale(0, -32768, 1152, 98304);

Then, when you write Wave.draw, it will be easy to scale x to match the sample index of the channel, and y to match the sample data. You will need an offset for the left channel so that its plot is in the upper half of the drawing window.
 Enrichment

felten.mp3. The song All My Trials was performed and recorded by Princeton professor Perry Cook after another Princeton professor Ed Felten was threatened with a lawsuit by the RIAA (Recording Industry Association of America) for presenting an academic paper that explained the inherent flaws in several digital watermarking schemes. Lifted by the spirits of Perry Cook's song, and With support from the EFF, Ed Felten was able to defeat the mighty RIAA.

MP3 file format. The MP3 file format stores digital audio in a compressed format. It compresses digital audio by eliminating (i) sounds that the human ear cannot hear, (ii) soudns that go unheard because there is another sound that masks it, and (iii) sounds that are not heard well at all. The net effect is a file that is 10-12 times smaller than the original, without sacrificing too much in fidelity. The mp3 file consists of frames. Each frame, when decoded, contains an array of 2,304 signed 16-bit integers that represent instantaneous amplitude. mp3 files interleave the left and right stereo channels: the first element of the array is the amplitude of the first sampling of the left stereo channel, and the second element is the amplitude of the first sampling of the right stereo channel, and so on.

Ripple echo effect. To get a ripple echo effect (where the sound echoes forever, but decays over time), take the average of the current Wave and the Wave you played 10 time steps ago (instead of the one you read in 10 steps ago).

Wave interference. Here's a fun and easy suggestion from a former student: set the right channel to be the opposite (negative) of the left channel; point your computer speakers at each other; and move them toward and away from each other. You should hear the effects of the waves cancelling each other out.

Frequencies of musical notes. Middle C is 240Hz. Each octave has a frequency that is twice the previous one. In Western culture, each octave is divided into twelve steps. Each note has a frequency that is the twelfth root of two times the previous one. This logarithmic scale is used to correlate with human hearing.

Music theory. For a massive overload in information regarding Music Theory, check out http://www.musictheory.net.

More data files. Here are some famous speeches and soundbytes.

Java sound. Java Sound Resources contains code samples ranging from ripping CDs to MIDI synthesis.