Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

note.java /* * The Immutable Class Note. */ public class Note { /** Static Constants */ public static final int DEFAULT_INTENSITY = 50; public static

note.java

/*

* The Immutable Class Note.

*/

public class Note {

/** Static Constants */

public static final int DEFAULT_INTENSITY = 50;

public static final int REST_PITCH = 128; // First illegal pitch, used for rests.

private static final int PITCHES_PER_OCTAVE = 12;

private static final String[] NOTE_LETTERS = {"c","c#","d","d#","e","f","f#","g","g#","a","a#","b"};

private static final double MIN_DURATION = 1.0/64, // One sixty-fourth

MAX_DURATION = 8.0; // Eight whole notes

/** Fields (Immutable) */

private final String pitch;

private final int midiValue;

private final double duration;

/**

* Instantiates a new note based on a string denoting note letter and octave.

*

* @param pitch the pitch (e.g. "f6")

* @param duration the duration

* @throws NullPointerException if pitch is null

* @throws IllegalArgumentException if:

* 1. The pitch parameter is malformed or out of range.

* 2. The duration parameter is out of range.

*/

public Note(String pitch, double duration) {

pitch = this.pitch;

duration = this.duration;

}

if(pitch==null) {

throw new NullPointerException("It can't be null");

if(pitch<0 && (duration>Note.MIN_DURATION ||duration> Note.MAX_DURATION)) {

throw new IllegalArgumentException("It's out of range");

}

// TODO

// Recommended: First implement toMidi(String).

}

/**

* Instantiates a new note based on MIDI value.

*

* @param midiValue the MIDI value (e.g. 68)

* @param duration the duration

* @throws IllegalArgumentException if:

* 1. The MIDI pitch parameter is out of range.

* 2. The duration parameter is out of range.

*/

public Note(int midiValue, double duration) {

// TODO

// Recommended: First implement toPitch(int).

}

/**

* Instantiates a new note from a String matching the format of Note's toString() method.

*

* @param note the string representation

*

* @throws IndexOutOfBoundsException if parameter isn't in correct format

* @throws NumberFormatException if duration representation cannot be parsed as double

* @throws IllegalArgumentException if the elements in the format are not permitted.

*/

public Note(String note) {

this(note.split(" x ")[0], Double.parseDouble(note.split(" x ")[1]));

}

/**

* Converts a pitch string to a MIDI value.

* The pitch "rest" should return {@link #REST_PITCH}.

*

* @param pitch the pitch to convert

* @throws NullPointerException if pitch is null

* @throws IllegalArgumentException is the String is not a legal pitch

* @return the MIDI value

*/

public static int toMidi(String pitch) {

// TODO

return -1;

}

/**

* Converts a MIDI value to a pitch string.

* The MIDI value 128 should return "rest".

*

* @param midiValue the MIDI value to convert

* @throws IllegalArgumentException if the MIDI value is outside of legal range

* @return the pitch string

*/

public static String toPitch(int midiValue) {

// TODO

String rest;

if(midiValue ="128") {

return rest;

}

return null;

}

/**

* Gets the pitch string of this note.

*

* @return the pitch

*/

public String getPitch() { return pitch; }

/**

* Gets the MIDI value of this note.

*

* @return the MIDI value

*/

public int getMidiPitch() { return midiValue; }

/**

* Gets the duration of this note.

*

* @return the duration

*/

public double getDuration() { return duration; }

/**

* Returns a new note with the same pitch, but with its duration multiplied by the parameter.

*

* @param factor the amount to scale by

* @throws IllegalArgumentException if resultant duration is outside of valid range

* @return the stretched note

*/

public Note stretch(double factor) {

// TODO

return null;

}

/**

* Returns a (new) note with the same duration, but transposed by the given interval.

*

* @param interval the interval to transpose by

* @throws IllegalArgumentException if note is transposed beyond valid bounds [c0, g10]

* @return the transposed note

*/

public Note transpose(int interval) {

// TODO

return null;

}

/**

* Returns a string representation of this Note.

* It should follow the format found in songs/InMyLife.song, namely:

* For a Note with pitch "g#4" and duration 1.0625 -> "g#4 x 1.0625"

* NB1: Identical spacing and format are important!

* NB2: For a "rest" note, the same format must be used (including duration).

*

* @return the string representation

*/

@Override

public String toString() {

// TODO

return "a+ " + "b + b";

return printf("")

return null;

}

/* (non-Javadoc)

* @see java.lang.Object#equals(java.lang.Object)

*/

@Override

public boolean equals(Object o) {

if(o instanceof Note) {

Note candidate = (Note) o;

return candidate.midiValue == midiValue && candidate.duration == duration;

}

// TODO: Return equal if the argument is a Note and the midiValue and duration are equal

return false;

}

@Override

public int hashCode() {

return (int)(7*midiValue()+23*y());

// TODO: Compute hash using pieces. (Don't take hash code of strings.)

return -1;

}

}

MusicBox.java

import javax.sound.midi.*; import java.io.File; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.util.Scanner;

/** * The Class MusicBox. */ public class MusicBox implements MetaEventListener {

/** Static Constants */ private static final int TICKS_PER_QUARTER_NOTE = 512; // each tick is a 16th note public static final int END_OF_TRACK_MESSAGE = 47;

/** MIDI fields */ private Synthesizer synthesizer; private Sequencer sequencer; /** * The main method. * * @param args the arguments to launch (ignored) */ public static void main(String[] args) { try { String filename = args[0]; double multiplier = 1.0; int interval = 0; int i = 0; while (++i < args.length) { if (args[i].startsWith("stretch=")) multiplier = Double.parseDouble(args[i].split("=")[1]); else if (args[i].startsWith("transpose=")) interval = Integer.parseInt(args[i].split("=")[1]); else{ throw new IllegalArgumentException("Unknown argument: "+args[i]); } }

new MusicBox().play(filename, multiplier, interval); } catch (Exception e) { PrintWriter pw = new PrintWriter(System.out); pw.println("Usage: Main [Arguments]"); pw.println("Arguments:"); pw.println(" stretch="); pw.println(" transpose= "); e.printStackTrace(pw); pw.flush(); pw.close(); System.exit(1); } } /** * Constructs a new MusicBox Midi System. */ public MusicBox() { try { synthesizer = MidiSystem.getSynthesizer(); synthesizer.open(); sequencer = MidiSystem.getSequencer(false); sequencer.open(); sequencer.getTransmitter().setReceiver(synthesizer.getReceiver()); sequencer.addMetaEventListener(this); for (Instrument instrument : synthesizer.getAvailableInstruments()) { if (instrument.getName().trim().toLowerCase().equals("fingered bs.")) { synthesizer.loadInstrument(instrument); synthesizer.getChannels()[0].programChange(instrument.getPatch().getProgram()); break; } } } catch (Exception e) { e.printStackTrace(); } } /** * Reads, parses, and plays the given song file. * @param filename the song file to play */ private void play(String filename, double multiplier, int interval) { Sequence sequence = null; try (Scanner s = new Scanner(new File("./songs/"+filename))) { String name = s.nextLine().trim(); float bpm = Float.parseFloat(s.nextLine().trim().split(" ")[0]); sequencer.setTempoInBPM(bpm); sequence = new Sequence(Sequence.PPQ, TICKS_PER_QUARTER_NOTE); Track track = sequence.createTrack(); long timestamp = 0; while (s.hasNextLine()) { String line = s.nextLine().trim(); if (line.equals("") || line.startsWith("[")) continue;

Note note = new Note(line).stretch(multiplier).transpose(interval); putNote(track, note, timestamp); timestamp += toTicks(note.getDuration()); } sequencer.setSequence(sequence); sequencer.start(); System.out.println("Playing " + name + (multiplier != 1.0 ? ", stretched by " + multiplier : "") + (interval != 0 ? ", transposed by " + interval : "") + "..."); } catch (FileNotFoundException e) { e.printStackTrace(); System.exit(1); } catch (InvalidMidiDataException e) { e.printStackTrace(); System.exit(1); } }

/** * Puts the note into the track at the timestamp. * * @param track - the track to add the note to * @param note - the note to add * @param timestamp - tick value at which to place the note * @throws InvalidMidiDataException if midiNote is outside range [0, 127] or * intensity is outside range [0, 127] */ private static void putNote(Track track, Note note, long timestamp) throws InvalidMidiDataException { int midiValue = note.getMidiPitch(); int intensity = Note.DEFAULT_INTENSITY; if (midiValue == 128) { midiValue = 0; // rest note intensity = 0; } ShortMessage noteOn = new ShortMessage(ShortMessage.NOTE_ON, 0, midiValue, intensity); ShortMessage noteOff = new ShortMessage(ShortMessage.NOTE_OFF, 0, midiValue, 0); track.add(new MidiEvent(noteOn, timestamp)); track.add(new MidiEvent(noteOff, timestamp + toTicks(note.getDuration()))); } private static int toTicks(double duration) { return (int) Math.round(duration / 0.25 * TICKS_PER_QUARTER_NOTE); } /* (non-Javadoc) * @see javax.sound.midi.MetaEventListener#meta(javax.sound.midi.MetaMessage) */ @Override public void meta(MetaMessage msg) { if (msg.getType() == END_OF_TRACK_MESSAGE) { System.out.println("Done."); sequencer.stop(); sequencer.close(); synthesizer.close(); System.exit(0); } } }

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Students also viewed these Databases questions

Question

Apply your own composing style to personalize your messages.

Answered: 1 week ago

Question

Format memos and e-mail properly.

Answered: 1 week ago