Assignment 6: The Music Editor:   Second Movement
1 Harmonizing the models1Puns fully intended throughout this assignment...
2 Views:   Time to face the music
2.1 A textual view:   seeing is believing
2.2 A visual view:   a picture is worth a thousand...notes
2.3 An audible view:   it’s playback time
2.4 Assignment
3 Running and Testing
3.1 Reading from files
3.2 Switching among multiple views
3.3 The main() event
3.4 Testing
4 Grading standards
5 Submission
6.7

Assignment 6: The Music Editor: Second Movement

Due: Mon 11/07 at 8:59pm; self-evaluation due Tue 11/08 at 8:59pm

Starter files: code.zip

This assignment is to be completed with a partner. Please make sure you’ve emailed Sam Berin (berin.s@husky) with both your usernames. You will not be able to submit your homework without doing so

This week you will implement several views for your model from last week. A view is responsible for rendering (some or all of) the data in a model in a form that is understandable to whomever is actually trying to use the data.

As with the model, in the abstract sense, a view is an interface; particular concrete views implement that interface. Accordingly, your work this week should carefully distinguish between any one particular implementation of a view and the common interface to which they should all adhere. Moreover, if your model from last week failed to have a similar interface/implementation split, you must fix that this week.

1 Harmonizing the models1Puns fully intended throughout this assignment...

Before you and your partner can begin working on views, you must first come to consensus on the design of your model.

  1. Unify the designs of your models. Incorporate the best ideas from both, or any methods that one of you may not have thought of.

  2. Refactor your model so that it resides in the cs3500.music.model package. Similarly, your tests should be in cs3500.music.tests. If this requires correcting visibility on your code so far, fix it.

  3. Document any changes made to your models from the previous assignment: explain what was added, removed or changed (besides the package declaration), and why.

2 Views: Time to face the music

Once your models are reconciled, it’s time to see what they look like.

2.1 A textual view: seeing is believing

Implement the textual view from last week’s assignment, as a proper view: here, the view is shown rendering Mary Had a Little Lamb.

╔══════════════════════════════════════════════════════════════════════════════════╗
║    E3   F3  F#3   G3  G#3   A3  A#3   B3   C4  C#4   D4  D#4   E4   F4  F#4   G4 ║
║ 0                 X                                            X                 ║
║ 1                 |                                            |                 ║
║ 2                 |                                  X                           ║
║ 3                 |                                  |                           ║
║ 4                 |                        X                                     ║
║ 5                 |                        |                                     ║
║ 6                 |                                  X                           ║
║ 7                                                    |                           ║
║ 8                 X                                            X                 ║
║ 9                 |                                            |                 ║
║10                 |                                            X                 ║
║11                 |                                            |                 ║
║12                 |                                            X                 ║
║13                 |                                            |                 ║
║14                 |                                            |                 ║
║15                                                                                ║
║16                 X                                  X                           ║
║17                 |                                  |                           ║
║18                 |                                  X                           ║
║19                 |                                  |                           ║
║20                 |                                  X                           ║
║21                 |                                  |                           ║
║22                 |                                  |                           ║
║23                 |                                  |                           ║
║24                 X                                            X                 ║
║25                 |                                            |                 ║
║26                                                                             X  ║
║27                                                                             |  ║
║28                                                                             X  ║
║29                                                                             |  ║
║30                                                                             |  ║
║31                                                                             |  ║
║32                 X                                            X                 ║
║33                 |                                            |                 ║
║34                 |                                  X                           ║
║35                 |                                  |                           ║
║36                 |                        X                                     ║
║37                 |                        |                                     ║
║38                 |                                  X                           ║
║39                 |                                  |                           ║
║40                 X                                            X                 ║
║41                 |                                            |                 ║
║42                 |                                            X                 ║
║43                 |                                            |                 ║
║44                 |                                            X                 ║
║45                 |                                            |                 ║
║46                 |                                            X                 ║
║47                 |                                            |                 ║
║48                 X                                  X                           ║
║49                 |                                  |                           ║
║50                 |                                  X                           ║
║51                 |                                  |                           ║
║52                 |                                            X                 ║
║53                 |                                            |                 ║
║54                 |                                  X                           ║
║55                 |                                  |                           ║
║56  X                                       X                                     ║
║57  |                                       |                                     ║
║58  |                                       |                                     ║
║59  |                                       |                                     ║
║60  |                                       |                                     ║
║61  |                                       |                                     ║
║62  |                                       |                                     ║
║63  |                                       |                                     ║
╚══════════════════════════════════════════════════════════════════════════════════╝

Your output should be identical to that above, as was specified in Assignment 5: beat numbers run down the left side and are right-justified (so, a piece that is a few thousand beats long would use four columns of characters). Pitches are named and run along the first line of text. Each pitch’s column is 5 characters wide. Noteheads are marked with X, and note continuations are marked using |. There must be columns sufficient to render all pitches between the lowest and highest notes in the piece, and there must be sufficient beats to render from beat zero through the end of the last note in the piece. Every line is exactly the same length, and there is a trailing newline even on the last line. The frame surrounding the text above is not part of the rendering.

2.2 A visual view: a picture is worth a thousand...notes

Below is one possible rendering of a visual view of the same piece of music:

Higher pitches are higher vertically, and time increases to the right. Every row is a particular pitch, and beat numbers are marked at the top. In this piece, vertical bars mark measure lines every four beats. Here, the onset of a note is drawn black, while all remaining beats of the note are drawn green. You may adjust the visual styling in your own views, so long as the information is clear.

To implement this view, you will need to use one of Java’s GUI libraries, namely Swing. (You are not permitted to use the javalib library we used in Fundies II, as it conflates the notions of model, view and controller into a single World class. Additionally, Java’s other GUI library, JavaFX, is overly complicated for our purposes.) The skeleton code provided above gives you a very bare-bones beginning using Swing. You will likely need to look up documentation on Graphics, Panels and Frames.

2.3 An audible view: it’s playback time

Only the best musicians can simply glance at a score of music and hear it in their heads; the rest of us prefer to actually listen to the music. To this end, you’re going to use MIDI to play back your compositions. Java has support for MIDI as part of its standard library.

The skeleton code provided to you gives the basic outline for obtaining a reference to a MIDI synthesizer, obtaining from it a receiver, and sending that receiver instructions to turn a note on and off. You may be interested in the documentation on how to transmit and receive MIDI messages, and possibly chapters 8–11 in the guide as well.

2.4 Assignment

  1. Implement the views above. Place all the code of your views in the cs3500.music.view package.

  2. Document any further changes made to your models from the previous assignment: explain what was added, removed or changed (besides the package declaration), and why.

3 Running and Testing

You probably want to run your code. This entails:

3.1 Reading from files

The skeleton code above provides you with a utility class, MusicReader, that can read the music files supplied for you to use. Because we do not know in advance what you’ve named your compositions, or precisely how your constructors work, MusicReader in turn requires a CompositionBuilder<T> object that describes constructing any music composition, note by note.

  1. Implement this builder interface, where the T parameter should be specialized to whatever your main interface is named that describes an entire composition:

    import cs3500.music.util.*;
    
    public final class WhateverYourCompositionImplementationIsNamed implements YourCompositionInterface {
      ...
      public static final class Builder implements CompositionBuilder<YourCompositionInterface> {
        // FILL IN HERE
      }
    }

3.2 Switching among multiple views

If your views all conform to the same interface, then you should be able to switch among any of them with hardly any changes to your code.

  1. Implement a factory of views, with a single method that takes in a String name for a view (e.g. “console” or “visual” or “midi”), and constructs an instance of the appropriate concrete view.

3.3 The main() event

Add the following class to your project:

package cs3500.music;
public final class MusicEditor {
  public static void main(String[] args) {
    // FILL IN HERE
  }
}

This main() method will be the entry point for your program. You need to create an Application run configuration that chooses cs3500.music.MusicEditor as its main class. In this run configuration, you can also specify command-line arguments, such as the file you want to read in, and the view name you want to use.

  1. Complete the main() method, so that running your program with arguments "mary.txt" and "console" will produce the text output above, and running it will arguments "mystery-1.txt" and "midi" will play the first mystery file via MIDI.

Congratulations, you now have a running Java program!

3.4 Testing

You still need to test your code. You should be able to test your text-based view sufficiently by parameterizing it over alternate input and output sources. We did the same thing with the WhistController in Assignment 3 and it was in the Controller, in that assignment, because we didn’t have an explicit View as part of our architecture. To test your MIDI or visual views, you’ll need to “do the same thing” and parameterize them with a mock object. This mock object will implement the same interface as the object you would normally use, but will log each method call to some debugging output. For this assignment you must test your MIDI view sufficiently; testing your visual view as thoroughly is optional.

You must implement a mock MidiDevice to emulate the default MIDI Synthesizer. It must implement at minimum the getReceiver() method and return a mock Receiver that emulates actual MIDI receivers. This object in turn should log every call to send(). Your mock classes should share a StringBuilder for use as the log.

You must implement either a builder or convenience constructors for your MIDI view, so that by default the view uses the actual MIDI synthesizer, but for testing can be run with your mock instead. If you create a StringBuilder, and pass to the mock-synth, you can then read out the contents of the StringBuilder to confirm that you’ve played all the right notes.

Hint: Remember that you are not testing whether Java’s Receiver, MidiDevice, etc. are working correctly: they do. You are testing whether your program is using them correctly to provide the correct inputs to these classes so that they may play them.

(How might you implement a similar mocking strategy for the graphical views?)

4 Grading standards

For this assignment, you will be graded on

5 Submission

To create a JAR file, do the following:

Please submit your homework to https://cs3500.ccs.neu.edu/ by the above deadline. Then be sure to complete your self evaluation by the second deadline.

1Puns fully intended throughout this assignment...