]> ruin.nu Git - moosique.git/blob - MooNote.java
no message
[moosique.git] / MooNote.java
1 import javax.sound.midi.*;
2
3 /**
4  * Functional representation of a MIDI note, which adds functionality to the existing MidiEvent class.
5  * Also provides a reference to the corresponding NoteOff event.
6  * 
7  * @author  Einar Pehrson
8  */
9  
10 public class MooNote extends MidiEvent implements Cloneable, Comparable {
11
12         private MidiEvent noteOffEvent;
13         private ShortMessage noteOnMsg, noteOffMsg;
14
15         /** 
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
20          */
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();
26         }
27
28         /** 
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)
35          */
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();
41                 try {
42                         noteOnMsg.setMessage(ShortMessage.NOTE_ON, channel, pitch, velocity);
43                         noteOffMsg.setMessage(ShortMessage.NOTE_OFF, channel, pitch, 64);
44                 } catch (InvalidMidiDataException e) {System.out.println("Invalid data!");}
45         }
46
47         /** 
48          * Returns the note off event of this note.
49          * @return the note off event
50          */
51         public MidiEvent getNoteOffEvent() {
52                 return noteOffEvent;
53         }
54
55         /** 
56          * Returns the channel of the current note.
57          * @return the channel of the note (1-16)
58          */
59         public int getChannel() {
60                 return noteOnMsg.getChannel();
61         }
62
63         /** 
64          * Returns the pitch of the current note.
65          * @return the pitch of the note (0-127)
66          */
67         public int getPitch() {
68                 return noteOnMsg.getData1();
69         }
70
71         /** 
72          * Returns the velocity of the current note.
73          * @return the velocity of the note (0-127)
74          */
75         public int getVelocity() {
76                 return noteOnMsg.getData2();
77         }
78
79         /** 
80          * Returns the duration of the current note.
81          * @return the duration of the note (in ticks)
82          */
83         public int getDuration() {
84                 return (int)(noteOffEvent.getTick() - getTick());
85         }
86
87         /** 
88          * Sets the channel of the current note.
89          * @param channel       the channel of the note (1-16)
90          */
91         public void setChannel(int channel) {
92                 try {
93                         noteOnMsg.setMessage(noteOnMsg.getCommand(), (byte)channel, noteOnMsg.getData1(), noteOnMsg.getData2());
94                         noteOffMsg.setMessage(noteOffMsg.getCommand(), (byte)channel, noteOffMsg.getData1(), noteOffMsg.getData2());
95                 } catch (InvalidMidiDataException e) {}
96         }
97
98         /** 
99          * Sets the pitch of the current note.
100          * @param pitch         the pitch of the note (0-127)
101          */
102         public void setPitch(int pitch) {
103                 try {
104                         noteOnMsg.setMessage(noteOnMsg.getCommand(), noteOnMsg.getChannel(), (byte)pitch, noteOnMsg.getData2());
105                         noteOffMsg.setMessage(noteOffMsg.getCommand(), noteOffMsg.getChannel(), (byte)pitch, noteOffMsg.getData2());
106                 } catch (InvalidMidiDataException e) {}
107         }
108
109         /** 
110          * Sets the velocity of the current note.
111          * @param vel   the velocity of the note (0-127)
112          */
113         public void setVelocity(int vel) {
114                 try {
115                         noteOnMsg.setMessage(noteOnMsg.getCommand(), noteOnMsg.getChannel(), noteOnMsg.getData1(), (byte)vel);
116                         noteOffMsg.setMessage(noteOffMsg.getCommand(), noteOffMsg.getChannel(), noteOffMsg.getData1(), noteOffMsg.getData2());
117                 } catch (InvalidMidiDataException e) {}
118         }
119
120         /** 
121          * Sets the duration of the current note (or rather moves the note off event).
122          * @param n     the duration of the note in ticks (96 per beat)
123          */
124         public void setDuration(int ticks) {
125                 noteOffEvent.setTick(getTick() + ticks);
126         }
127
128         /** 
129          * Sets the timestamp of the current note.
130          * @param tick  the timestamp of the note in ticks (96 per beat)
131          */
132         public void setTick(long tick) {
133                 noteOffEvent.setTick(tick + getDuration());
134                 super.setTick(tick);
135         }
136
137         /** 
138          * Transposes the current note the given number of halftones.
139          * @param halftones     the number of halftones to transpose - positive for up, negative for down
140          */
141         public void transpose(int halftones) {
142                 setPitch(getPitch() + halftones);
143         }
144
145         /**
146          * Adds this note (both noteOn and noteOffEvents) to a track.
147          * @param track the track it'll be added to.
148          */
149         public void addTo(Track track) {
150                 track.add(this);
151                 track.add(noteOffEvent);
152         }
153         
154         /**
155          * Removes this note (both noteOn and noteOffEvents) from a track.
156          * @param track the track it'll be removed from.
157          */
158         public void removeFrom(Track track) {
159                 track.remove(this);
160                 track.remove(noteOffEvent);
161         }
162
163         /**
164          * Returns a clone of this note.
165          */
166         public Object clone() {
167                 return new MooNote(
168                         new MidiEvent((ShortMessage)getMessage().clone(), getTick()), 
169                         new MidiEvent((ShortMessage)noteOffEvent.getMessage().clone(), noteOffEvent.getTick())
170                 );
171         }
172
173         /** 
174          * Compares this note to another note.
175          * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object
176          */
177         public int compareTo(Object o) {
178                 int diff = (int)(getTick() - ((MidiEvent)o).getTick());
179                 if (diff != 0) return diff;
180                 return (noteOnMsg.getData1() - ((ShortMessage)((MidiEvent)o).getMessage()).getData1());
181         }
182 }