OVERVIEW:

1. Download and review the provided interfaces, Loadable, Player, StillImage, and AudioStream.

2. Implement the exception type LoadException which will be used to signal errors while loading multimedia files.

3. Implement the class LoadableImage which would allow loading a still image from a text file.

4. Implement the abstract class ImageViewer and concrete subclass Text ImageViewer, which allows a StillImage to be viewed in a terminal using text art. Test your viewer with the provided sample images.

5. Implement the class LoadableAudio which would allow loading an audio stream from a text file.

6. Implement the abstract class AudioPlayer and concrete subclass TextAudioPlayer, which allows an AudioStream to be viewed as a wave output in a terminal using text art. Test your viewer with the provided sample.

7. Students in the honors section will have an additional subclass and functionality to complete for full credit.

8. Download and use the tester module to ensure that your program is correct.

9. Prepare the assignment for submission and submit it.

A multimedia player is a piece of software which needs no introduction. We're all likely to have used one to do anything from playing CDs or DVDs, to audio or video files. One thing we might notice is that when we do this, we don't have to think too hard about what kind of file we're clicking on. We just click on it, and then it opens up in the player, whatever the format and whatever the type of media it is (because if we think about it, images and sound are two different things). This is something we can do thanks in part to object-oriented programming. When we select a file, we don't have to care too much about what it is, so long as it's something which is loadable by the player. And whatever kind of media it is, the player figures out the right thing to do with it.

For this project, we will write a simplified version of this sort of interface. We will write our own multimedia player, which is capable of playing different kind of media files. We will of course make a few simplifications to fit this project within a two week window, but it will still be enough to demonstrate the mechanism. For example, we will only be implementing an audio and still image player; we will use our own text-only media file formats, and our output will all be done visually on the terminal using text art.

When we implement this project, we will practice two main language features: interfaces and exceptions. We will see the power of interfaces to abstractly define the types of things our classes will do, which leaves us free to perform the tricks we were talking about earlier - being able to load files without worrying too closely about the type, and being able to play a media type without knowing in advance what kind of media we're dealing with. We also see how exceptions are useful in reporting errors without disrupting the flow of code.

The interfaces can be described as follows:

  • Loadable: a media format which can be loaded. We're assuming that we've read the contents of a file into an array of integers already, and are passing that integer data into this interface to try to load the media. Any class which implements this interface would need to be able to do two things: to match the data to the format (in other words, to check the format of the input data, and see if it matches this media format), and to load the data and use it to create a new instance of this loadable. We can see an example of how it could be used below:
Loadable xyzImageLoader = new XyzImageLoader();
int[] data1 = mediaPlayer.read("image1.xyz");
int[] data2 = mediaPlayer.read("image2.xyz");
Loadable img1 = null, img2 = null;
if(xyzImageLoader.match(data1)) img1 = xyzImageLoader.load(data1);
if(xyzImageLoader.match(data2)) img2 = xyzImageLoader.load(data2);
  • Player: once we've loaded some piece of media, we'd like to be able to play it. This class describes some kind of media player (although the kind of player isn't specified - it could be audio, for instance, but it could be something else). Classes which implement this interface are ready to play media which has been loaded already. Any such class would need to be able to do the following two things: to check if the player canPlay the loaded media; and also to actually play the media. For example:
Loadable media = mediaPlayer.load("media_file.fmt");
Player videoPlayer = new VideoPlayer();
Player audioPlayer = new SystemAudioPlayer();
if (videoPlayer.canPlay (media)) videoPlayer.play (media);
else if (audioPlayer.canPlay (media)) audioPlayer.play(media);
  • StillImage: this represents an ordinary, still image, like something you'd take with your camera. It has three methods: its width in pixels, its height in pixels, and a getPixel which gets the value of the pixel at the chosen coordinates. The coordinates (, ) represent the value of the pixel in the upper left of the image; the x coordinate goes from left to right, and the y coordinate goes from top to bottom. The pixel value returned by getPixel is a number which we assume to be in the range of brightness from 0 to 999, where 0 is black and 999 is white.
  • AudioStream: this represents a stream of audio data. The audio data itsell' will be a stream of numbers representing the amplitude of the audio wave; we will assume that it ranges from -999 to 999. The interface has three methods: a freq method which indicates the playback frequency of the audio (since we will do text output in this project instead of true audio, this method won't have much practical effect, but we still include it for completeness); a next method to retreive the next point from the audio wave; and a hasNext method to tell us if we've reached the end of the audio data. Since streaming data is known for updating on the fly, we use next/hasNext to read the next data point, instead of using some kind of getValueAt to retrieve audio from anywhere in the sound wave.

Now that we know what each of these interfaces are for, let's use them to write some classes.

Academic Honesty!
It is not our intention to break the school's academic policy. Posted solutions are meant to be used as a reference and should not be submitted as is. We are not held liable for any misuse of the solutions. Please see the frequently asked questions page for further questions and inquiries.
Kindly complete the form. Please provide a valid email address and we will get back to you within 24 hours. Payment is through PayPal, Buy me a Coffee or Cryptocurrency. We are a nonprofit organization however we need funds to keep this organization operating and to be able to complete our research and development projects.