The goal of this assignment is to use loops to solve a variety of problems.
Starting
- In Eclipse, create a new project or use an existing one. Add a package a3, and a class LoopsAndSound to that package.
- Add the example sound file from lab to the package.
- Add StdAudio.java from lab to the package. Make sure the package statement at the top of the StdAuido file changes to a3. This should happen if you drag the file into the package in Eclipse. If you do not do this and start to use the methods from the file, Eclipse may suggest a quick-fix that imports this file from your lab. This will not work on the autograder. Bring the file into your package.
- In your Java class, implement the static methods specified below.
- All methods you write should have a Javadoc comment with a description of what the method does and a @param for each parameter and a @return describing what information is returned. Your class should have a Javadoc with a general description and @author tag.
- Add a main method with tests for each method. Your tests should cover possible return values (such as true or false) as well as special cases where allowed (for example, empty strings). Your tests should print which method is being tested, what is being tested, and the actual result from the method in a neatly formatted way. For the sound processing methods, you should do two things to test it. First, make a simple small array of double values and send it to the sound method being tested. You should structure this test like the other ones in this assignment. Then, you should hear what the method does to the sound by loading a sound file, sending the samples to the method, and playing the samples that are returned. An example is at the bottom of this assignment page.
- You do not need to test for cases that are prohibited in the description. If the description says that there is at least X in the parameter, then you do not need to test for the truth of that constraint.
- None of your methods except for main may print anything to the console. While developing your other methods, you are encouraged to print values in those methods to the console to help debug your code. Those print statements in those other methods should be removed before submission.
- None of the sound methods may play the sound in the method. This will break the autograder. Your testing code in main should call the play method so you can hear how the sound changes after applying your method.
- Ensure you have consistent spacing in your file, proper and consistent indenting, and meaningful variable names. Make small one line comments to describe any multi-step process in your methods.
Required Methods
You must implement each of the described methods with method name, return type and parameters carefully checked against the specification. When parameters are specified you must use the order they are listed in. You may implement additional methods if they aid your problem-solving.
Some methods are void, so they do not return anything. However, they do something in the method, like change the values in an array. This action is described in a Post-Condition, which means the state of the data after the method finishes. There is not a formal Post-Condition in Javadocs - you can add to the general description of the method.
In the descriptions of the methods, arrays and their example values are represented with [] with a comma-separated list of values inside. You cannot call the method like that in your tests - you need to create an array, set the values of its elements, and pass the array as an argument. In other words, you cannot call a method literally like addUpValues([1,2,3,4]).
Finally, you should only use constructs we have learned in this course to solve these problems. You should not search for "how do I replace characters in a Java String" and copy what you find. That is not getting clarification on how some small part of Java works, that is looking for a solution to the problem, which is plagiarism.
Here are the required methods. Some of these methods have a new level of complexity compared to what we have seen so far. Be patient with yourself. Read the description. See if you can recreate any example by hand. Pay attention to the process you use to solve it by hand. Finally, translate that process to code.
- Method name: clearArray
Parameter(s): An int array of at least length 0. You do not need to check for a null reference.
Return value: Nothing. The method return type is void.
Post-Condition: The array parameter has every element in the original array set to 0.
Example: After calling clearArray([1, 2]), the array has its elements changed to [0,0]. I want you to use a loop to set the elements - you may not use any Arrays fill method or related. The point of this method is to see that the array can be changed in the void method.
- Method name: arrayToString
Parameter(s): An int array of at least length 0. You do not need to check for a null reference.
Return value: A String containing a textual representation of the parameter. The return String should start with a curly brace, then have all the numbers in the array with a comma and space between numbers, and then end with an end curly brace. Arrays.toString or its variants may not be used in this method. Think about how to elegantly handle the last number.
Post-Condition: The array parameter is not changed.
Example: Calling arrayToString([1, 2]) should return "{1, 2}".
- Method name: hideLetterA
Parameter(s): A String. An empty string is allowed. You do not need to check for a null reference.
Return value: A String that has the same characters as the String parameter except every letter 'a' has been changed to an '*'.
Example: hideLetterA("A rabbit has a carrot") would return
"A r*bbit h*s * c*rrot".
Note: The letter 'A' is not 'a'.
- Method name: hasMoreEvenThanOdd
Parameter(s): An int array. An empty array is allowed. You do not need to check for a null reference.
Return value: A boolean value true if the number of even numbers in the array is greater than the number of odd numbers and false otherwise.
Example: hasMoreEvenThanOdd([1, 3, 4, 6, -8]) would return true as there are 3 even numbers and 2 odd.
Note: The % operator can be used to check if a number is evenly divisible by 2, which is what being even means. Second note: 0 is not a special case for being even or odd. Neither is being negative.
- Method name:averageArrayValues
Parameter(s): An int array of at least length 1. You do not need to check for a null reference.
Return value: Returns a double value that is the sum of the array elements divided by the array length.
Post-Condition: The array parameter is not changed.
Example: CallingaverageArrayValues([1,2]) should return 1.5.
Note: Be careful and do not use an int for the sum - an int divided by an int length will not give a correct answer. The requirement of at least one value is to prevent a divide by zero possibility, so you do not need to check for that.
- MethodName: frequencyCount
Parameter(s): An int array. The elements of the array can only be numbers from 0 to (and including) 9. You do not need to check for a null reference or if the numbers are only from 0 to 9. A length 0 array is allowed.
Return value: A new int arrayof 10 integers. The value in the new array at index n is the number of times value n appears in the parameter array.
Post-Condition: The original array parameter is not changed.
Example:CallingfrequencyCount([0,0,1,1,1,7]) would return [2,3,0,0,0,0,0,1,0,0] since there are2 zeroes and 3 ones and 1 seven, and no other numbers in the parameter array.
Hint: If the number 3 is found, you want to change the count at index 3 in the frequency array. If 4 is found, you want to change the count at index 4. There is a pattern here you can exploit to concisely solve this problem.
The following methods should be done after doing the lab, which will introduce you to the sound code.
- Method name: reverseSound
Parameter(s): A double array. You do not need to check for a null reference.
Return value: Returns a double array that has its elements in reversed order from the parameter array.
Post-Condition: The array parameter is not changed.
Example: CallingreverseSound([0.1, 0.2, 0.3, 0.5]) should return a new array [0.5, 0.3, 0.2, 0.1]. You may not use Collections.reverse() or similar for this.
- Method name: scaleSound
Parameter(s): A double array and a double value. You do not need to check for a null reference.
Return value: Returns a new double array that has as its elements each of the original array elements scaled by the second parameter.
Post-Condition: The array parameter is not changed.
Example: Calling scaleSound([0.0, -0.1, 0.3], 2.0) should return a new array [0.0, -0.2, 0.6] as each of the elements are scaled by 2.0.
Note: The play method for sounds keeps all values in the required -1.0 to 1.0 range, so you do not need to check if the samples scale out of that range.
- Method name: echoSound
Parameter(s): A double array, an int specifying how many samples offset the echo starts at, and a double giving a weight to the echo. The double array will have at least as many values as the offset value. You do not need to check for a null reference.
Return value: A double array as long as the original array parameter plus the offset parameter. The first offset samples will be the same as the first offset samples as the parameter array. The last offset samples will be the same as the last offset samples from the parameter array scaled by the weight parameter. The middle samples will be the sample from the parameter array plus the sample from the parameter array back the offset amount scaled by the weight parameter. Here is the logic of it. An echo is a diminished sound delayed from bouncing off a distant object. So if you yell, I first only hear your original sound. Then when the bounce comes back, I hear what you are currently saying plus a scaled down version of what you said from back in time. Then, when you stop talking, I only hear the scaled down version of what you said from back in time.
Post-Condition: The array parameter is not changed.
Example: Calling echoSound([0.1, 0.2, 0.3, 0.4], 1, 0.5) should return a new array of length 5 (the original array plus the offset). The new array is [0.1, 0.25, 0.4, 0.55, 0.2].
The 0.1 is from before the echo starts and is unchanged.
The 0.25 comes from 0.2 + (0.1 * 0.5) - the current value plus the value from 1 back in time, 0.1, scaled by the weight, or 0.5.
The 0.4 comes from 0.3 + (0.2 * 0.5).
The 0.55 comes from 0.4 + (0.3 * 0.5).
The last value is all echo, and is 0.4 * 0.5, the value from 1 back in time scaled by the 0.5 weight.
Hint: This is a complicated method to understand. Go through the example until you understand every part of it, then convert this process to code.
- Method name: smoothSound
Parameter(s): A double array with at least 3 elements in it. You do not need to check for a null reference.
Return value: Returns a double array that has as its elements a sliding average of the parameter array elements. More precisely:
- The first and last elements of the new array are the same as the average of the first two and last two elements of the parameter array, respectively.
- For the other elements of the new array, for an element at index i, it is equal to the average of elements from the parameter array at indices i-1, i, and i+1.
- Post-Condition: The array parameter is not changed.
Example: Calling smoothSound([0.0, 0.2, 0.7, 0.2]) should return a new array [0.1, 0.3, 0.3666...,0.45]. When played, noise in the sound should be reduced.
Trying the Sound Methods
If you want to hear the effect of these sound methods, you can add code in main like this:
double[] samples = StdAudio.read("asyouwish2.wav");
StdAudio.play(samples);
double[] reversed = reverseSound(samples);
StdAudio.play(reversed);
Note that this isn't really a test - it is to help you appreciate the kinds of effects we can generate pretty easily in code. A test has an expected output for a given input to a method.
Submitting
Submit your LoopsAndSound.java to gradescope. You will see some tests to help you understand if you are meeting the specification. Gradescope will be available Wednesday.
Issues with StdAudio?
If you have issues with StdAudio, it may be that you never successfully used a modern Java in your Eclipse. In the Package Explorer, when you look at a project, it should show the JRE that project is using. This class is using version 14, although slightly older ones are likely to be OK. If you show a very old one like 1.6, the sound file will not work. Please review the page on installing Java and setting up Eclipse.
Another issue seems to be eclipse complaining about importing javax.sound. Basically eclipse has underlined a bunch of lines of code in red and for some people running the main method produces an error.
If you are having issues, the fix below seems to be working OK:
In the main menu bar navigate to project > properties > Java Build Path. Double click JRE System Library to open up a new window. Change the execution from CDC-1.0 to JavaSE-14 which is located at the bottom