Assignment 6: The Music Editor:   Second Movement
1 Harmonizing the models
2 Views:   Time to face the music
2.1 View interface(s)
2.2 A textual view:   seeing is believing
2.3 A visual view
2.4 Behavior of the visual view
2.5 An audible view:   it’s playback time
2.6 Assignment
3 Running and Testing
3.1 Reading from files
3.2 The main() event
3.3 Testing
4 Grading standards
5 Submission
6.3

Assignment 6: The Music Editor: Second Movement

Due: Tue 03/21 at 8:59pm; self-evaluation due Wed 03/22 at 8:59pm

Starter files: code.zip

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

In this assignment will implement several views for your model from the last assignment. 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 models

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 View interface(s)

Start by planning your views, and observing which operations you need. Although different views look and behave differently, there are some common aspects to all views. The design of the actual interface(s) is left up to you. Keep in mind the following SOLID principle from Lecture 1: Why object-oriented design?: Interface Segregation (No client should be forced to depend on methods that it does not use). In other words you should avoid having a view that offers methods that are not relevant to any of its users. Keep this in mind as you come up with a design for your views.

2.2 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. The frame surrounding the text above is not part of the rendering.

You may achieve this by moving your code to generate this rendering from the model to the appropriate view.

2.3 A visual view

Below is the visual view that you must replicate as much as possible:

In the upper half 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.

In the lower half is a keyboard layout. Each key on the keyboard corresponds to a pitch. The keyboard above shows 10 octaves. Please follow the keyboard map provided here to design this view accordingly.

To implement this view, you will need to use Java 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 and the examples from class give you a basic beginning using Swing. You will likely need to look up documentation on Graphics, Panels and Frames.

2.4 Behavior of the visual view

You should control the red line in this view using the left and right arrow keys on your keyboard. When the red line is at a particular beat, the keyboard should show which keys are pressed to play the notes being played at that beat (shown above in orange). You are free to choose any colors you want. The left and right arrow keys advance and go back by a beat respectively.

When the beat reaches the end of the range of the visible beats, the upper half should scroll accordingly. However this scrolling feature is optional for this assignment. You will have to implement this eventually, so you may choose to do so in this assignment itself.

2.5 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.

Another viable option is to use the Sequencer setup, also included in the above documentation.

2.6 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. Think of this builder as adapting from the model interface that the MusicReader expects and the one your model actually has.

  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
      }
    }

  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.2 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.3 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 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 add notes to play, 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://handins.ccs.neu.edu/ by the above deadline. Then be sure to complete your self evaluation by the second deadline.