Assignment 8

COMP102 2020 Tri 1: Assignment 8

  • Due 11 Jun 10am

Goals

By the end of the assignment, you will have gained experience in writing programs using ArrayLists and will also have had more practice at designing programs using loops.

Preparation

Download the zip file for assignment 8 and extract it to your home folder. It should contain templates for the Java program you are to complete. Read through the whole assignment to see what you need to do. You can view the demo videos.

Look again at your answer and/or the model answer to the GraphPlotter program from assignment 4 and go over the code examples in slides from the lectures on ArrayLists.

Summary

Programs with ArrayLists

Overview

The FireworksDisplay program is based on the fireworks program developed in lectures, but it uses an ArrayList of Firework objects to have lots of fireworks going at the same time.

The WaveformAnalyser program involves dealing with an ArrayList of numbers representing samples from a waveform (for example, from a mp3 or wav file). It displays the list of numbers as a waveform, and then displays the amplitude, the peaks, and the distortion. It also lets the user edit the waveform in limited ways. It is a simple version of the features in some music player programs that will display the sound wave while playing, plus very basic functions of a sound editor program.

To Submit:

Submit your best version of FireworksDisplay.java, WaveformAnalyser.java and your UnderstandingJava.txt files by the due date. Remember to click the button for the final step of the submission process after you have uploaded the files (which does some automated checking for you).

Fireworks Display (15%)

In the lectures, we wrote a FireworksDisplay program that made two fireworks go up and then explode. For this assignment, you need to write a different FireworksDisplay.java program which will have waves of lots of fireworks that all go up together. The GUI should have a slider to set the number of fireworks in the next wave.

You will need to complete
  • the setWaveSize method, to change the number of fireworks that should be made in the next wave
  • the runDisplay method, which should repeatedly send up waves of fireworks. It has a variable containing an ArrayList of the Firework objects in the current wave. (The version in the lecture had two separate variables for the two fireworks.)
    You need to create the list of Fireworks, make each firework take a step, and then check whether they have all finished.

Watch the demo video to make sure you know what the program should do.

The Firework class is written for you. It has a constructor and two methods you can call:
  • new Firework() to create a new random firework
  • void step() to make a firework take one more step
  • boolean isFinished() to determine if a firework has finished

Core

  • One Wave: Intialise the ArrayList with a collection of Firework objects and repeatedly make step.

Completion
  • Multiple Waves: in addition to the Core, check each time round the loop if the fireworks have all finished, and if so, make a new wave of fireworks.

Challenge
  • Nicer Fireworks: The fireworks given are boring - they just draw expanding coloured circles. Make the fireworks explode in a more realistic way, with a collection of "sparks" that expand outwards in a cloud.

Waveform Analyser (75%)

Many music players will allow you to display the sound being played. One of the displays is typically the waveform. For this program you will write a very simple waveform display.

There are several things about a waveform that one may be interested in:
  • The highest and lowest (most negative) points on the waveform are significant.
  • The distortion level: if the signal is too large (positive or negative), the sound might get distorted. Reporting on the points gone over the distortion level becomes then useful.
  • The peaks of the waveform which are all the points that are greater than both their neighbouring points.
  • The envelope, which is the line linking all the upper peaks and the line linking the lower peaks of the signal.
  • Editing the waveform, eg by changing the frequency, scaling parts of it up or down, removing segments of the waveform, and duplicating segments of the waveform.

WaveformAnalyser reads its data from a file (eg waveform1.txt or waveform2.txt) into an ArrayList of numbers stored in the waveform field, displays it, and lets the user edit it and display it in different ways. Note, the program will initialise waveform to contain a simple triangular waveform.

The code that sets up and responds to the buttons and the mouse is provided for you - the parts of the program you have to complete are the ones involving the ArrayList. The mouse allows the user to select a region of the waveform.

Core

For the core, you should complete the following methods:

  • display(): Displays the waveform as a line graph with an x-axis. If the data goes beyond the edge of the window, that is OK. The selected region is shown by a red bar along the axis. The horizontal positions of the points on the waveform should be 1 pixel apart.

  • read(): asks the user for a waveform file and reads data from the file into the waveform. (Should start a new waveform - it should not add the values to the end of the current waveform.)

  • showSpread(): Displays two horizontal lines on the waveform, one green line for the maximum value and one red line for the minimum (most negative) value, as in the demo.

waveform-display.png waveform-spread.png

  • increaseRegion and decreaseRegion: increases/decreases all the values in the selected region of the waveform by 10%. The user selects a region using the mouse and the fields regionStart and regionEnd contain the indexes of the start and end of the region.

  • doubleFrequency(): Doubles the frequency of the waveform by removing every second value in the list.

Completion

For the completion, you should complete the following methods:

  • highlightPeaks(): draws small green circles on all the peaks. A peak is defined as a point that is greater or equal to both neighbouring points.

  • displayDistortion(): Shows in red the distorted part of the signal. A distorted value is defined as one that is either greater than the positive value of the threshold or less than the negative value of the threshold. This method should draw in red every line that has either end point beyond the distortion threshold. Note that the threshold value is stored in the constant THRESHOLD.

waveform-peaks.png waveform-distortion.png

  • deleteRegion(): Deletes all the values in the selected region (from regionStart up to, but not including regionEnd) from the waveform. Needs to reset the selected region.

Challenge:

For the challenge, you should complete the following methods:

  • duplicateRegion(): inserts a copy of the selected region into the waveform, immediately following the selected region. Needs to reset the selected region.

  • displayEnvelope(): displays the envelope with green lines connecting all the upper peaks, as in the demo.

waveform-envelope.png

  • save(): asks the user for a filename and saves the current waveform to that file.

It would also be nice to be able to edit real sound files. The WaveformLoader class (in the zip file) has a method that will load a wav file into an arraylist of numbers that could be used in your program. The problem is that 1 second of sound from a 1 channel wav file typically has 44,100 numbers, so that it won't fit in the window nicely without more complicated scaling than the WaveformAnalyser program does. Extend WaveformAnalyser so that it loads wav files, scales the data to fit the window, and allows the user to zoom in and out. There is also a save method to write it back as a wav file so you can listen to the result of your edits. There are lots of WAV files on the web; http://bbcsfx.acropolis.org.uk/ has a bunch of sound effect WAV files you could use.

Understanding Java (10%)

Answer the following questions in the UnderstandingJava.txt file, and make sure you submit it.

0. List which methods of the WaveformAnalyser you completed. (This will help the marker.)

1. This method is supposed to remove every negative value in an ArrayList of numbers. Why will it crash with an error if there are any negative numbers in the list?

     public void removeNegatives1(ArrayList<Double> numbers){
         for(double num : numbers){
             if (num < 0) {
                 numbers.remove(num);
             }
         }
     }

2. This method is also supposed to remove every negative value in an ArrayList of numbers? It does not crash, but it may not do the right thing. Give an example of a list of numbers that it would not work on, and explain why.
     public void removeNegatives2(ArrayList<Double> numbers){
         for(int i=0; i<numbers.size(); i++){
             if (numbers.get(i) < 0) {
                 numbers.remove(i);
             }
         }
     }

3. Complete the following method to replace every negative number in an ArrayList by 0:
(For example [ 4, -1, -7, 8] turns into [4, 0, 0, 8])
     public void replaceNegatives(ArrayList<Double> numbers){
         //Your code here

     }