Project 3: Ride the Wave

Due by: Friday, October 20, 2023 at 11:59 p.m.

For this project you will write a program that processes audio files based on user input. You might be familiar with audio editing tools such as SoundForge or Cool Edit Pro. The program you will write will have some of the same functionality, only using text input commands instead of a GUI.

Background

This project is based around the manipulation of audio data inside a program. As you probably known from physics classes, sound travels as a wave. We can visualize this wave as something like a sine function.

Here is an image of several waves with different frequencies. Each is what is called a pure tone. At the top, the frequency is lower, making the equivalent note lower in pitch. The pitch of the notes increases as the waves go down the page. Of course, the representation of real sounds are more complex. Real sounds have chaotic looking wave forms because much more is going on than just a single pure tone, as shown below.

Of course, computers can't deal with with nice, smooth waves. To record or manipulate a sound in a computer, you need to turn the wave into a series of values. This is done with a process called sampling. Sampling means that the wave is chopped up into lots of equal sized time divisions. For each division, we pick one value to represent the wave at that point. In this way, we can approximate the wave with a series of numbers. Below is a picture showing a tiny section of a wave form. Each small blue box represents the sample value of that wave.

With CD quality sound, there are 44,100 samples per second. That's why CD audio takes up so much space. Every single second has 44,100 numbers giving the height of various parts of a wave. The StdAudio library developed by two Princeton professors lets us easily manipulate CD quality audio, but not MP3's. MP3's use a number of mathematical and psycho-acoustic techniques to use a lot fewer numbers to represent the waves. So, we're going to stick with CD quality audio, stored in the form of .wav files on your computer.

The StdAudio library provides a very easy way to load and save .wav files. When they are loaded, they will be represented as an array of double values. Each value represents one sample. So, for a song that is 3:56 long, the array will contain 10,407,600 double values. For this reason, we are going to stick to small .wav files. In the format used by StdAudio, each value in the array is between -1.0 and 1.0. Thus, a maximum volume sound has peaks at 1.0 and -1.0. A completely silent sound represented by samples at 0.

Overview

In this project, you will use your knowledge of loops, arrays, and the the StdAudio library to make a program that takes an audio file as input and then applies a number of audio processing tasks and effects to the file. Each task is indicated by a command such as p or n. Some commands require additional information to be read. All of these commands are given as input typed by the user. There is no limit to the number of commands that can be provided, and they should be processed in order.

There are 7 tasks in total, but each one is relatively simple. These tasks are:

TaskCommandDescription
PlaypPlay the audio
ReverserReverse the audio
Increase speedsSpeed up the audio by a specific factor
Add noisenAdd a specified amount of white noise to the audio
Change volumevScale the volume of the audio up or down
OutputoOutput the current version of the audio to a specified file
QuitqQuit the program

You must download StdAudio.java from here. You can either save it in your project src folder once you have created your project or you can add a StdAudio class to your project and paste the text in.

Sound Processing

Reversing Sounds

To reverse a sound, take the array of double values representing samples and reverse the order of its elements. The new array will effectively contain the audio backwards.


Speeding Up Sounds

First, create a new double array whose length is length/factor, where length is the original length and factor is the amount by which you are speeding up the audio. Then, loop through the new array filling it with values from the original array. Element i in the new array will correspond to element i*factor from the old array. That is, if factor is 2, you will use every other value from the original. Obviously, the index in the old array that you calculate will be a double. You will need to cast it to an int to use it. Anything other than very small values of factor will produce audio that is so fast as to be unlistenable. If you write your code correctly, it should be able to speed up and slow down sounds. A sound will be sped up with a factor greater than 1 and slowed down with a factor less than 1.


Adding Noise

Noise is essentially just random values added to the audio. For each value in the array of audio samples, add a random number between -amount and amount, where amount is the value specified by the user. Make sure that no value is greater than 1.0 or less than -1.0 after noise is added.


Changing the Volume of Sounds

Multiply each value in the array of audio samples by the scale supplied by the user. If the scale is larger than 1, the noise will get louder. If the scale is smaller than 1, the noise will get quieter. A value of 0 would make the sound completely inaudible. Make sure that no sample in the array is greater than 1.0 or less than -1.0 after scaling.


Samples

Here is a list of 24 sample sounds we have included for your use.

Note: You will need to put these sounds in your project directory of your project for your program to access them. They should be in the top level of the project directory, not in the out or src directories.

Your program should prompt the user to for the name of a wav file. After that, you should repeatedly prompt the user for commands until he or she chooses the quit (q) option.

For example, the following sample program execution loads whoa.wav, plays the file without changes, reverses the sound, speeds up the sound by a factor of 1.7, adds a 0.1 amount of noise, scale the volume by a factor of 1.4, play the song another time to hear how all the changes have gone, saves the current audio to the file name whoaChanged.wav, and then quits.

Enter wav file name: whoa.wav
Select command (p, r, s, n, v, o, q): p
	Playing sound
Select command (p, r, s, n, v, o, q): r
	Reversing sound
Select command (p, r, s, n, v, o, q): s
	Speed up by how much? 1.7
	Speeding up sound
Select command (p, r, s, n, v, o, q): n
	Add how much noise? 0.1
	Adding noise
Select command (p, r, s, n, v, o, q): v
	Scale volume by how much? 1.4
	Scaling volume
Select command (p, r, s, n, v, o, q): p
	Playing sound
Select command (p, r, s, n, v, o, q): o
	Save to what file name? whoaChanged.wav
	Saving file
Select command (p, r, s, n, v, o, q): q

Here you can download the final version of whoaChanged.wav to give an example of what the sample from above would sound like.

Here is an example of each command. We have included an audio example using only a single effect flag to make a helpful example, but your program should handle any number of commands.

TaskCommandDescriptionExample UsageSample Audio
Play p Play the current audio as it is, after all the effects up to this point have been added. This option uses a play() method from StdAudio.
Enter wav file name: coffee.wav
Select command (p, r, s, n, v, o, q): p
	Playing sound
No change in audio
Reverse r Reverse the audio so that it plays backwards.
Enter wav file name: shiny.wav
Select command (p, r, s, n, v, o, q): r
	Reversing sound
Select command (p, r, s, n, v, o, q): o
	Save to what file name? shinyReverse.wav
shinyReverse.wav
Increase speed s Speed up the audio by a specific factor. Note that you will have to prompt the user for a double to know how much to speed up the audio by.
Enter wav file name: pain.wav
Select command (p, r, s, n, v, o, q): s
	Speed up by how much? 2.5
	Speeding up sound
Select command (p, r, s, n, v, o, q): o
	Save to what file name? painSpeed.wav
painSpeed.wav
Add noise n Add a specified amount of white noise to the audio. Note that you will have to prompt the user for a double to know how much noise to add.
Enter wav file name: pacman.wav
Select command (p, r, s, n, v, o, q): n
	Add how much noise? 0.5
	Adding noise
Select command (p, r, s, n, v, o, q): o
	Save to what file name? pacmanNoise.wav
pacmanNoise.wav
Change volume v Scale the volume of the audio up or down. Note that you will have to prompt the user for a double to know how to scale the volume.
Enter wav file name: breakbeato.wav
Select command (p, r, s, n, v, o, q): v
	Scale volume by how much? 0.5
	Scaling volume
Select command (p, r, s, n, v, o, q): o
	Save to what file name? breakbeatoVolume.wav
breakbeatoVolume.wav
Output o Output the current version of the audio to a specified file. Note that you will have to prompt the user for a String to know the new file name. This option uses the save() method from StdAudio.
Enter wav file name: milkshake.wav
Select command (p, r, s, n, v, o, q): o
	Save to what file name? rename.wav
No change in audio
Quit q Quit the program.

Turn In

Your IntelliJ project should be called Project3, but the class you create inside should be called AudioProcessor. Upload the AudioProcessor.java file from the Project3\src folder wherever you created your project to Blackboard.

All work must be submitted before Friday, October 20, 2023 at 11:59 p.m. unless you are going to use a grace day.

All work must be done individually. You may discuss general concepts with your classmates, but it is never acceptable for you to look at someone else's code. Please refer to the course policies if you have any questions about academic integrity. If you have trouble with the assignment, I am always available for assistance.

Grading

Your grade will be determined by the following categories:

Category Weight
Play 10%
Reverse 20%
Increase speed 20%
Add noise 15%
Change volume 15%
File output 10%
Style and comments 10%

Under no circumstances should any student look at the code written by another student. Tools will be used to detect code similarity automatically.

Code that does not compile will automatically score zero points.