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 {
12 protected MidiEvent noteOffEvent;
13 protected ShortMessage noteOnMsg, noteOffMsg;
16 * Creates a MooNote from the given NoteOn event in the current track.
17 * @param noteOnEvent the NoteOn event of the note
19 public MooNote (MidiEvent noteOnEvent) {
20 super(noteOnEvent.getMessage(), noteOnEvent.getTick());
21 noteOnMsg = (ShortMessage)getMessage();
25 * Creates a MooNote from the given NoteOn event in the current track and creates a reference to
26 * the corresponding NoteOff event.
27 * @param noteOnEvent the NoteOn event of the note
28 * @param noteOffEvent the NoteOff event of the note
30 public MooNote (MidiEvent noteOnEvent, MidiEvent noteOffEvent) {
31 super(noteOnEvent.getMessage(), noteOnEvent.getTick());
32 this.noteOffEvent = noteOffEvent;
33 noteOnMsg = (ShortMessage)getMessage();
34 noteOffMsg = (ShortMessage)noteOffEvent.getMessage();
38 * Creates a MooNote of the given pitch, velocity and duration in the current track.
39 * @param channel the channel of the note (1-16)
40 * @param pitch the pitch of the note (0-127)
41 * @param velocity the velocity of the note (0-127)
42 * @param timestamp the timestamp of the note in ticks (96 per beat)
43 * @param duration the duration of the note in ticks (96 per beat)
45 public MooNote (int channel, int pitch, int velocity, long timestamp, int duration) {
46 super(new ShortMessage(), timestamp);
47 noteOffEvent = new MidiEvent(new ShortMessage(), timestamp + duration);
48 noteOnMsg = (ShortMessage)getMessage();
49 noteOffMsg = (ShortMessage)noteOffEvent.getMessage();
51 noteOnMsg.setMessage(ShortMessage.NOTE_ON, channel, pitch, velocity);
52 noteOffMsg.setMessage(ShortMessage.NOTE_OFF, channel, pitch, 0);
53 } catch (InvalidMidiDataException e) {System.out.println("Invalid data!");}
57 * Sets the channel of the current note.
58 * @param channel the channel of the note (1-16)
60 public void setChannel(int channel) {
62 noteOnMsg.setMessage(noteOnMsg.getCommand(), (byte)channel, noteOnMsg.getData1(), noteOnMsg.getData2());
63 if(hasNoteOffEvent()) noteOffMsg.setMessage(noteOffMsg.getCommand(), (byte)channel, noteOffMsg.getData1(), noteOffMsg.getData2());
64 } catch (InvalidMidiDataException e) {}
68 * Sets the pitch of the current note.
69 * @param pitch the pitch of the note (0-127)
71 public void setPitch(int pitch) {
73 noteOnMsg.setMessage(noteOnMsg.getCommand(), noteOnMsg.getChannel(), (byte)pitch, noteOnMsg.getData2());
74 if(hasNoteOffEvent()) noteOffMsg.setMessage(noteOffMsg.getCommand(), noteOffMsg.getChannel(), (byte)pitch, noteOffMsg.getData2());
75 } catch (InvalidMidiDataException e) {}
79 * Sets the velocity of the current note.
80 * @param vel the velocity of the note (0-127)
82 public void setVelocity(int vel) {
84 noteOnMsg.setMessage(noteOnMsg.getCommand(), noteOnMsg.getChannel(), noteOnMsg.getData1(), (byte)vel);
85 if(hasNoteOffEvent()) noteOffMsg.setMessage(noteOffMsg.getCommand(), noteOffMsg.getChannel(), noteOffMsg.getData1(), noteOffMsg.getData2());
86 } catch (InvalidMidiDataException e) {}
90 * Sets the duration of the current note (or rather moves the note off event).
91 * @param n the duration of the note in ticks (96 per beat)
93 public void setDuration(int ticks) {
94 if (hasNoteOffEvent()) noteOffEvent.setTick(getTick() + ticks);
98 * Sets the timestamp of the current note.
99 * @param tick the timestamp of the note in ticks (96 per beat)
101 public void setTick(long tick) {
102 if (hasNoteOffEvent()) noteOffEvent.setTick(tick + getDuration());
107 * Returns the channel of the current note.
108 * @return the channel of the note (1-16)
110 public int getChannel() {
111 return noteOnMsg.getChannel();
115 * Returns the pitch of the current note.
116 * @return the pitch of the note (0-127)
118 public int getPitch() {
119 return noteOnMsg.getData1();
123 * Returns the velocity of the current note.
124 * @return the velocity of the note (0-127)
126 public int getVelocity() {
127 return noteOnMsg.getData2();
131 * Returns the duration of the current note.
132 * @return the duration of the note (in ticks)
134 public int getDuration() {
135 if (!hasNoteOffEvent()) return 0;
136 return (int)(noteOffEvent.getTick() - getTick());
140 * Returns whether the NoteOff event was found.
141 * @return the note off MidiEvent
143 public boolean hasNoteOffEvent() {
144 return noteOffEvent != null;
148 * Adds this note (both noteOn and noteOffEvents) to a track.
149 * @param track the track it'll be added to.
151 public void addTo(Track track){
153 if (hasNoteOffEvent()) track.add(noteOffEvent);
157 * Removes this note (both noteOn and noteOffEvents) from a track.
158 * @param track the track it'll be removed from.
160 public void removeFrom(Track track){
162 if (hasNoteOffEvent()) track.remove(noteOffEvent);