1 import javax.sound.midi.*;
4 * Functional representation of a MIDI note, which adds functionality to the existent MidiEvent class.
5 * Also provides a reference to the corresponding NoteOff event.
7 * @author Einar Pehrson
10 public class MooNote extends MidiEvent implements Cloneable {
12 private MidiEvent noteOffEvent;
13 private ShortMessage noteOnMsg, noteOffMsg;
16 * Creates a MooNote from the given NoteOn event in the current track and creates a reference to
17 * the corresponding NoteOff event.
18 * @param noteOnEvent the NoteOn event of the note
19 * @param noteOffEvent the NoteOff event of the note
21 public MooNote (MidiEvent noteOnEvent, MidiEvent noteOffEvent) {
22 super(noteOnEvent.getMessage(), noteOnEvent.getTick());
23 this.noteOffEvent = noteOffEvent;
24 noteOnMsg = (ShortMessage)getMessage();
25 noteOffMsg = (ShortMessage)noteOffEvent.getMessage();
29 * Creates a MooNote of the given pitch, velocity and duration in the current track.
30 * @param channel the channel of the note (1-16)
31 * @param pitch the pitch of the note (0-127)
32 * @param velocity the velocity of the note (0-127)
33 * @param timestamp the timestamp of the note in ticks (96 per beat)
34 * @param duration the duration of the note in ticks (96 per beat)
36 public MooNote (int channel, int pitch, int velocity, long timestamp, int duration) {
37 super(new ShortMessage(), timestamp);
38 noteOffEvent = new MidiEvent(new ShortMessage(), timestamp + duration);
39 noteOnMsg = (ShortMessage)getMessage();
40 noteOffMsg = (ShortMessage)noteOffEvent.getMessage();
42 noteOnMsg.setMessage(ShortMessage.NOTE_ON, channel, pitch, velocity);
43 noteOffMsg.setMessage(ShortMessage.NOTE_OFF, channel, pitch, 0);
44 } catch (InvalidMidiDataException e) {System.out.println("Invalid data!");}
48 * Sets the channel of the current note.
49 * @param channel the channel of the note (1-16)
51 public void setChannel(int channel) {
53 noteOnMsg.setMessage(noteOnMsg.getCommand(), (byte)channel, noteOnMsg.getData1(), noteOnMsg.getData2());
54 noteOffMsg.setMessage(noteOffMsg.getCommand(), (byte)channel, noteOffMsg.getData1(), noteOffMsg.getData2());
55 } catch (InvalidMidiDataException e) {}
59 * Sets the pitch of the current note.
60 * @param pitch the pitch of the note (0-127)
62 public void setPitch(int pitch) {
64 noteOnMsg.setMessage(noteOnMsg.getCommand(), noteOnMsg.getChannel(), (byte)pitch, noteOnMsg.getData2());
65 noteOffMsg.setMessage(noteOffMsg.getCommand(), noteOffMsg.getChannel(), (byte)pitch, noteOffMsg.getData2());
66 } catch (InvalidMidiDataException e) {}
70 * Sets the velocity of the current note.
71 * @param vel the velocity of the note (0-127)
73 public void setVelocity(int vel) {
75 noteOnMsg.setMessage(noteOnMsg.getCommand(), noteOnMsg.getChannel(), noteOnMsg.getData1(), (byte)vel);
76 noteOffMsg.setMessage(noteOffMsg.getCommand(), noteOffMsg.getChannel(), noteOffMsg.getData1(), noteOffMsg.getData2());
77 } catch (InvalidMidiDataException e) {}
81 * Sets the duration of the current note (or rather moves the note off event).
82 * @param n the duration of the note in ticks (96 per beat)
84 public void setDuration(int ticks) {
85 noteOffEvent.setTick(getTick() + ticks);
89 * Sets the timestamp of the current note.
90 * @param tick the timestamp of the note in ticks (96 per beat)
92 public void setTick(long tick) {
93 noteOffEvent.setTick(tick + getDuration());
98 * Transposes the current note the given number of halftones.
99 * @param halftones the number of halftones to transpose - positive for up, negative for down
101 public void transpose(int halftones) {
102 setPitch(getPitch() + halftones);
106 * Returns the channel of the current note.
107 * @return the channel of the note (1-16)
109 public int getChannel() {
110 return noteOnMsg.getChannel();
114 * Returns the pitch of the current note.
115 * @return the pitch of the note (0-127)
117 public int getPitch() {
118 return noteOnMsg.getData1();
122 * Returns the velocity of the current note.
123 * @return the velocity of the note (0-127)
125 public int getVelocity() {
126 return noteOnMsg.getData2();
130 * Returns the duration of the current note.
131 * @return the duration of the note (in ticks)
133 public int getDuration() {
134 return (int)(noteOffEvent.getTick() - getTick());
138 * Adds this note (both noteOn and noteOffEvents) to a track.
139 * @param track the track it'll be added to.
141 public void addTo(Track track) {
143 track.add(noteOffEvent);
147 * Removes this note (both noteOn and noteOffEvents) from a track.
148 * @param track the track it'll be removed from.
150 public void removeFrom(Track track) {
152 track.remove(noteOffEvent);
156 * Returns a clone of this note.
158 public Object clone() {
160 new MidiEvent((ShortMessage)getMessage().clone(), getTick()),
161 new MidiEvent((ShortMessage)noteOffEvent.getMessage().clone(), noteOffEvent.getTick())