Question
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
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started