Lab Assignment #8
Overview
- Part A: Speaking backwards – reversing a Sound array and what happens when you "run out of space" in a Sound array.
- Part B: Echo a Sound (Chap 9).
- Quiz: Each person will individually take a short quiz.
Part A
Copy
In Part A we're going to have you write a method to reverse a sound file – say "Hello World" backwards. The idea here is that we'll take a Sound as a parameter and modify the calling object (we will use the blank 3 second sound file) and fill it in "in reverse order". Let's make up a Sound array and calculate what it would look like after being filled in in reverse order:
- Right click on the Desktop and Select "Open a Terminal"
- Paste the following lines of code into the terminal
- cd ../public/Lab8
- make directories
- make install
- cd
- cd Lab8
- mv Lab8.java.empty Lab8.java
- mv Sound.java.empty Sound.java
- ls
- The previous command should print out five filenames: CSE8ARocks.wav Lab8.java Sound.java echo.txt reverse.txt
- Open Sound.java file (open in Dr. Java)
- Open reverse.txt (right click, open with text editor). Copy and paste the method called reverseInto() into Sound.java
- Open echo.txt (right click, open with text editor). Copy and paste the method called echo() into Sound.java
In Part A we're going to have you write a method to reverse a sound file – say "Hello World" backwards. The idea here is that we'll take a Sound as a parameter and modify the calling object (we will use the blank 3 second sound file) and fill it in "in reverse order". Let's make up a Sound array and calculate what it would look like after being filled in in reverse order:
So – what's the index of -14 in source? And what index should it be copied into in result?
Fill that in for all the locations (there should be 5 lines in this table):
Index in source goes into Index in result
Fill that in for all the locations (there should be 5 lines in this table):
Index in source goes into Index in result
Code, Compile, Test:
- OK – so one index is counting down and one is counting
up. We need to fill in the rest of the
code to:
- Declare the source and result arrays (hint, this is just like what you just did with clipInto() in Lab 7)
- Look at the for loop that controls the looping in the method reverseInto(). It has three parts:
- Initialization: Two parts separated by a comma to initialize sourceIndex to its last element and resultIndex to its first element
- Loop Control: Loops until sourceIndex counts all the way down to the first element in the source array
- Loop Update: At the end of each for loop, updates sourceIndex and resultIndex appropriately. The loop update does 2 updates, separated by a comma
- Compile Lab8.java , Debug, and Run. Select Elliot-hello.wav for both the original and result
- AFter hearing the original file, you should be able to make out some "background noise", then "World" backwards, then "Hello" backwards. COOL! Note: you may want to comment out the playing of the previous Sound object – original
Test, Debug, Test
- Alright it works for this set of inputs (sec3silence.wav and Elliot-hello.wav) but this code isn't yet ready for you to "sell" to a customer. Testing just on one input is never enough. Let's try this. What might happen if our result file was shorter – say only 1 second? What might happen? (Take a look at the code and see if you can guess a possible error!)
- Run the code again and try picking sec1silence.wav (and then Elliot-hello.wav). What happens? (Look in the interactions pane).
- What is our runtime error and what line in Sound.java is it on?
- Why are you getting it? To find out – uncomment our two helpful print statements before the loop. They tell you the "size" of the two sound files you are working with. Can you say NOW what the problem is?
- Let's fix it. We need to make sure that as we are counting down in the source array, we don't try to count "too far" up in the result array. That is, we want to keep looping while we haven't gone past 0 in the source array AND while we haven't reached the "end" (or length) of the result array. Add to the boolean expression controlling the loop to make it keep looping only as long as BOTH of those conditions hold true (often we just say – as long as those conditions "hold").
- Compile and run! Now you should just hear some of the "background" noise "backwards" and not get a runtime exception.
Part B
Switch driver and navigator: if you've been controlling the mouse and keyboard, it's time for your partner to do so.
Read and Understand the Code
Read and Understand the Code
- Comment out the parts of Lab8.java you used in Part A, and uncomment the code for Part B. Compile and run. When prompted for a file, choose CSE8ARocks.wav
- Now look at the code for echo() and try to understand it.
- The
code modifies the calling object making it have echos. Why, then, do you think the method makes a
copy of the calling object on the first line? In answering this question,
consider this. What if you had the
(silly) SoundSample array below and set a delay of 2?
Let's test your prediction. Copy and paste the line in the echo() method that calculates the value. Comment out the original line. Modify your new line so that instead of getting the sample from the copy s, it gets it from the calling object this. Compile and run. Can you now explain really well better (or at least better) what the rationale for needing a copy of the original Sound is? (Hint: count the number of times you can hear "CSE")
When you are done, change the code back to the original line using the copy to assign to value.
When you are done, change the code back to the original line using the copy to assign to value.
Modify, Compile, Test
Will this code work for all legal start and stop indexes? For all delays? Why or why not? How would you fix it to work even if someone asked for a VERY long delay (say longer than the entire Sound)?
- Next, we want to modify this code to make it more controllable by the user. Right now, this code makes the entire sound be echoed – the user can only control the delay from speech to echo.
- We'd like to allow the user to control the time in the Sound which should have the echo applied – so that only that part of the Sound might be echoed. Here – we'll set it up to echo just the part where Beth says "8A", but your code should work for any part of the sound
- To get started, we need to find the "location" in the
SoundSample array where she says "8A". That is the approximate index right before
she says "8" and the approximate index after she is done saying "A". Uncomment the call to explore() in Lab8.java to
let you find these indexes. Write them
down.
- Now, we need to allow the method call to pass in those values as arguments. What file/method will you change? If you are not positive you are right – ask. Then make the change.
- Now make the change to the method header of echo() to accept those new values as parameters. Finally, you will need to change the loop in
the echo() method. You no longer need to
loop over the whole array.
- What index should you start at? (write the expression here):
- What index should you end at? (write the expression here):
- Run the method to show how
only the "8A" part is echoed.
- Now to see if you really understand, try adding an additional echo for the "8A" portion of the wave file, but this time decrease the amplitude of the echo to .4.
- It should be delayed longer than the first echo (you decide if you want the same interval as the first).
- When you are finished, you should be able to hear two echoes with the second one quieter than the first
Will this code work for all legal start and stop indexes? For all delays? Why or why not? How would you fix it to work even if someone asked for a VERY long delay (say longer than the entire Sound)?
Log Out
Click on System > Log Out cs8wzz... > Log Off
Complete Your Lab Quiz
See the instructor to get your individual lab quiz.
The quizzes are open book & note, but closed Dr Java and partner.
The quizzes are open book & note, but closed Dr Java and partner.
Sample Code
public
class Lab8
{
public static void main(String[] args)
{
// Pick sec3silence.wav for this one
Sound result = new Sound(FileChooser.pickAFile());
// Pick Elliot-hello.wav for this one
Sound original = new Sound(FileChooser.pickAFile());
// original.explore();
original.blockingPlay();
result.reverseInto(original);
result.play();
/**** Uncomment for Part B
// Pick CSE8ARocks.wav for this one - you should have copied it to
// LABS/mediasources
Sound s = new Sound(FileChooser.pickAFile());
// s.explore();
s.echo(15000);
s.blockingPlay();
****/
}
}
public void reverseInto(Sound mySound)
{
// System.out.println("The last indexable value in result is: " + (result.length-1));
// System.out.println("The last indexable value in source is: " + (source.length-1));
for ( int resultIndex = 0, sourceIndex = source.length-1;
sourceIndex >= 0;
resultIndex++, sourceIndex-- )
{
int value = source[sourceIndex].getValue();
result[resultIndex].setValue(value);
}
}
public void echo(int delay)
{
Sound s = new Sound(this.getFileName());
int value = 0;
for (int i = delay; i < this.getLength(); i++)
{
value = (int) (s.getSampleValueAt(i-delay) * 0.6);
this.setSampleValueAt(i,this.getSampleValueAt(i) + value);
}
{
public static void main(String[] args)
{
// Pick sec3silence.wav for this one
Sound result = new Sound(FileChooser.pickAFile());
// Pick Elliot-hello.wav for this one
Sound original = new Sound(FileChooser.pickAFile());
// original.explore();
original.blockingPlay();
result.reverseInto(original);
result.play();
/**** Uncomment for Part B
// Pick CSE8ARocks.wav for this one - you should have copied it to
// LABS/mediasources
Sound s = new Sound(FileChooser.pickAFile());
// s.explore();
s.echo(15000);
s.blockingPlay();
****/
}
}
public void reverseInto(Sound mySound)
{
// System.out.println("The last indexable value in result is: " + (result.length-1));
// System.out.println("The last indexable value in source is: " + (source.length-1));
for ( int resultIndex = 0, sourceIndex = source.length-1;
sourceIndex >= 0;
resultIndex++, sourceIndex-- )
{
int value = source[sourceIndex].getValue();
result[resultIndex].setValue(value);
}
}
public void echo(int delay)
{
Sound s = new Sound(this.getFileName());
int value = 0;
for (int i = delay; i < this.getLength(); i++)
{
value = (int) (s.getSampleValueAt(i-delay) * 0.6);
this.setSampleValueAt(i,this.getSampleValueAt(i) + value);
}