24 */ |
24 */ |
25 |
25 |
26 package javax.sound.midi; |
26 package javax.sound.midi; |
27 |
27 |
28 /** |
28 /** |
29 * A <code>ShortMessage</code> contains a MIDI message that has at most |
29 * A {@code ShortMessage} contains a MIDI message that has at most two data |
30 * two data bytes following its status byte. The types of MIDI message |
30 * bytes following its status byte. The types of MIDI message that satisfy this |
31 * that satisfy this criterion are channel voice, channel mode, system common, |
31 * criterion are channel voice, channel mode, system common, and system |
32 * and system real-time--in other words, everything except system exclusive |
32 * real-time--in other words, everything except system exclusive and |
33 * and meta-events. The <code>ShortMessage</code> class provides methods |
33 * meta-events. The {@code ShortMessage} class provides methods for getting and |
34 * for getting and setting the contents of the MIDI message. |
34 * setting the contents of the MIDI message. |
35 * <p> |
35 * <p> |
36 * A number of <code>ShortMessage</code> methods have integer parameters by which |
36 * A number of {@code ShortMessage} methods have integer parameters by which you |
37 * you specify a MIDI status or data byte. If you know the numeric value, you |
37 * specify a MIDI status or data byte. If you know the numeric value, you can |
38 * can express it directly. For system common and system real-time messages, |
38 * express it directly. For system common and system real-time messages, you can |
39 * you can often use the corresponding fields of <code>ShortMessage</code>, such as |
39 * often use the corresponding fields of {@code ShortMessage}, such as |
40 * {@link #SYSTEM_RESET SYSTEM_RESET}. For channel messages, |
40 * {@link #SYSTEM_RESET SYSTEM_RESET}. For channel messages, the upper four bits |
41 * the upper four bits of the status byte are specified by a command value and |
41 * of the status byte are specified by a command value and the lower four bits |
42 * the lower four bits are specified by a MIDI channel number. To |
42 * are specified by a MIDI channel number. To convert incoming MIDI data bytes |
43 * convert incoming MIDI data bytes that are in the form of Java's signed bytes, |
43 * that are in the form of Java's signed bytes, you can use the |
44 * you can use the <A HREF="MidiMessage.html#integersVsBytes">conversion code</A> |
44 * <a href="MidiMessage.html#integersVsBytes">conversion code</a> given in the |
45 * given in the <code>{@link MidiMessage}</code> class description. |
45 * {@link MidiMessage} class description. |
46 * |
|
47 * @see SysexMessage |
|
48 * @see MetaMessage |
|
49 * |
46 * |
50 * @author David Rivas |
47 * @author David Rivas |
51 * @author Kara Kytle |
48 * @author Kara Kytle |
52 * @author Florian Bomers |
49 * @author Florian Bomers |
|
50 * @see SysexMessage |
|
51 * @see MetaMessage |
53 */ |
52 */ |
54 |
|
55 public class ShortMessage extends MidiMessage { |
53 public class ShortMessage extends MidiMessage { |
56 |
54 |
57 |
|
58 // Status byte defines |
55 // Status byte defines |
59 |
56 |
60 |
|
61 // System common messages |
57 // System common messages |
62 |
58 |
63 /** |
59 /** |
64 * Status byte for MIDI Time Code Quarter Frame message (0xF1, or 241). |
60 * Status byte for MIDI Time Code Quarter Frame message (0xF1, or 241). |
|
61 * |
65 * @see MidiMessage#getStatus |
62 * @see MidiMessage#getStatus |
66 */ |
63 */ |
67 public static final int MIDI_TIME_CODE = 0xF1; // 241 |
64 public static final int MIDI_TIME_CODE = 0xF1; // 241 |
68 |
65 |
69 /** |
66 /** |
70 * Status byte for Song Position Pointer message (0xF2, or 242). |
67 * Status byte for Song Position Pointer message (0xF2, or 242). |
|
68 * |
71 * @see MidiMessage#getStatus |
69 * @see MidiMessage#getStatus |
72 */ |
70 */ |
73 public static final int SONG_POSITION_POINTER = 0xF2; // 242 |
71 public static final int SONG_POSITION_POINTER = 0xF2; // 242 |
74 |
72 |
75 /** |
73 /** |
76 * Status byte for MIDI Song Select message (0xF3, or 243). |
74 * Status byte for MIDI Song Select message (0xF3, or 243). |
|
75 * |
77 * @see MidiMessage#getStatus |
76 * @see MidiMessage#getStatus |
78 */ |
77 */ |
79 public static final int SONG_SELECT = 0xF3; // 243 |
78 public static final int SONG_SELECT = 0xF3; // 243 |
80 |
79 |
81 /** |
80 /** |
82 * Status byte for Tune Request message (0xF6, or 246). |
81 * Status byte for Tune Request message (0xF6, or 246). |
|
82 * |
83 * @see MidiMessage#getStatus |
83 * @see MidiMessage#getStatus |
84 */ |
84 */ |
85 public static final int TUNE_REQUEST = 0xF6; // 246 |
85 public static final int TUNE_REQUEST = 0xF6; // 246 |
86 |
86 |
87 /** |
87 /** |
88 * Status byte for End of System Exclusive message (0xF7, or 247). |
88 * Status byte for End of System Exclusive message (0xF7, or 247). |
|
89 * |
89 * @see MidiMessage#getStatus |
90 * @see MidiMessage#getStatus |
90 */ |
91 */ |
91 public static final int END_OF_EXCLUSIVE = 0xF7; // 247 |
92 public static final int END_OF_EXCLUSIVE = 0xF7; // 247 |
92 |
93 |
93 |
|
94 // System real-time messages |
94 // System real-time messages |
95 |
95 |
96 /** |
96 /** |
97 * Status byte for Timing Clock message (0xF8, or 248). |
97 * Status byte for Timing Clock message (0xF8, or 248). |
|
98 * |
98 * @see MidiMessage#getStatus |
99 * @see MidiMessage#getStatus |
99 */ |
100 */ |
100 public static final int TIMING_CLOCK = 0xF8; // 248 |
101 public static final int TIMING_CLOCK = 0xF8; // 248 |
101 |
102 |
102 /** |
103 /** |
103 * Status byte for Start message (0xFA, or 250). |
104 * Status byte for Start message (0xFA, or 250). |
|
105 * |
104 * @see MidiMessage#getStatus |
106 * @see MidiMessage#getStatus |
105 */ |
107 */ |
106 public static final int START = 0xFA; // 250 |
108 public static final int START = 0xFA; // 250 |
107 |
109 |
108 /** |
110 /** |
109 * Status byte for Continue message (0xFB, or 251). |
111 * Status byte for Continue message (0xFB, or 251). |
|
112 * |
110 * @see MidiMessage#getStatus |
113 * @see MidiMessage#getStatus |
111 */ |
114 */ |
112 public static final int CONTINUE = 0xFB; // 251 |
115 public static final int CONTINUE = 0xFB; // 251 |
113 |
116 |
114 /** |
117 /** |
115 * Status byte for Stop message (0xFC, or 252). |
118 * Status byte for Stop message (0xFC, or 252). |
|
119 * |
116 * @see MidiMessage#getStatus |
120 * @see MidiMessage#getStatus |
117 */ |
121 */ |
118 public static final int STOP = 0xFC; //252 |
122 public static final int STOP = 0xFC; //252 |
119 |
123 |
120 /** |
124 /** |
121 * Status byte for Active Sensing message (0xFE, or 254). |
125 * Status byte for Active Sensing message (0xFE, or 254). |
|
126 * |
122 * @see MidiMessage#getStatus |
127 * @see MidiMessage#getStatus |
123 */ |
128 */ |
124 public static final int ACTIVE_SENSING = 0xFE; // 254 |
129 public static final int ACTIVE_SENSING = 0xFE; // 254 |
125 |
130 |
126 /** |
131 /** |
127 * Status byte for System Reset message (0xFF, or 255). |
132 * Status byte for System Reset message (0xFF, or 255). |
|
133 * |
128 * @see MidiMessage#getStatus |
134 * @see MidiMessage#getStatus |
129 */ |
135 */ |
130 public static final int SYSTEM_RESET = 0xFF; // 255 |
136 public static final int SYSTEM_RESET = 0xFF; // 255 |
131 |
137 |
132 |
|
133 // Channel voice message upper nibble defines |
138 // Channel voice message upper nibble defines |
134 |
139 |
135 /** |
140 /** |
136 * Command value for Note Off message (0x80, or 128) |
141 * Command value for Note Off message (0x80, or 128). |
137 */ |
142 */ |
138 public static final int NOTE_OFF = 0x80; // 128 |
143 public static final int NOTE_OFF = 0x80; // 128 |
139 |
144 |
140 /** |
145 /** |
141 * Command value for Note On message (0x90, or 144) |
146 * Command value for Note On message (0x90, or 144). |
142 */ |
147 */ |
143 public static final int NOTE_ON = 0x90; // 144 |
148 public static final int NOTE_ON = 0x90; // 144 |
144 |
149 |
145 /** |
150 /** |
146 * Command value for Polyphonic Key Pressure (Aftertouch) message (0xA0, or 160) |
151 * Command value for Polyphonic Key Pressure (Aftertouch) message (0xA0, or |
|
152 * 160). |
147 */ |
153 */ |
148 public static final int POLY_PRESSURE = 0xA0; // 160 |
154 public static final int POLY_PRESSURE = 0xA0; // 160 |
149 |
155 |
150 /** |
156 /** |
151 * Command value for Control Change message (0xB0, or 176) |
157 * Command value for Control Change message (0xB0, or 176). |
152 */ |
158 */ |
153 public static final int CONTROL_CHANGE = 0xB0; // 176 |
159 public static final int CONTROL_CHANGE = 0xB0; // 176 |
154 |
160 |
155 /** |
161 /** |
156 * Command value for Program Change message (0xC0, or 192) |
162 * Command value for Program Change message (0xC0, or 192). |
157 */ |
163 */ |
158 public static final int PROGRAM_CHANGE = 0xC0; // 192 |
164 public static final int PROGRAM_CHANGE = 0xC0; // 192 |
159 |
165 |
160 /** |
166 /** |
161 * Command value for Channel Pressure (Aftertouch) message (0xD0, or 208) |
167 * Command value for Channel Pressure (Aftertouch) message (0xD0, or 208). |
162 */ |
168 */ |
163 public static final int CHANNEL_PRESSURE = 0xD0; // 208 |
169 public static final int CHANNEL_PRESSURE = 0xD0; // 208 |
164 |
170 |
165 /** |
171 /** |
166 * Command value for Pitch Bend message (0xE0, or 224) |
172 * Command value for Pitch Bend message (0xE0, or 224). |
167 */ |
173 */ |
168 public static final int PITCH_BEND = 0xE0; // 224 |
174 public static final int PITCH_BEND = 0xE0; // 224 |
169 |
175 |
170 |
176 /** |
171 // Instance variables |
177 * Constructs a new {@code ShortMessage}. The contents of the new message |
172 |
178 * are guaranteed to specify a valid MIDI message. Subsequently, you may set |
173 /** |
179 * the contents of the message using one of the {@code setMessage} methods. |
174 * Constructs a new <code>ShortMessage</code>. The |
180 * |
175 * contents of the new message are guaranteed to specify |
|
176 * a valid MIDI message. Subsequently, you may set the |
|
177 * contents of the message using one of the <code>setMessage</code> |
|
178 * methods. |
|
179 * @see #setMessage |
181 * @see #setMessage |
180 */ |
182 */ |
181 public ShortMessage() { |
183 public ShortMessage() { |
182 this(new byte[3]); |
184 this(new byte[3]); |
183 // Default message data: NOTE_ON on Channel 0 with max volume |
185 // Default message data: NOTE_ON on Channel 0 with max volume |
233 super(null); |
233 super(null); |
234 setMessage(status, data1, data2); // can throw InvalidMidiDataException |
234 setMessage(status, data1, data2); // can throw InvalidMidiDataException |
235 } |
235 } |
236 |
236 |
237 /** |
237 /** |
238 * Constructs a new {@code ShortMessage} which represents a channel |
238 * Constructs a new {@code ShortMessage} which represents a channel MIDI |
239 * MIDI message that takes up to two data bytes. If the message only takes |
239 * message that takes up to two data bytes. If the message only takes one |
240 * one data byte, the second data byte is ignored. If the message does not |
240 * data byte, the second data byte is ignored. If the message does not take |
241 * take any data bytes, both data bytes are ignored. |
241 * any data bytes, both data bytes are ignored. The contents of the message |
242 * The contents of the message can be changed by using one of |
242 * can be changed by using one of the {@code setMessage} methods. |
243 * the {@code setMessage} methods. |
243 * |
244 * |
244 * @param command the MIDI command represented by this message |
245 * @param command the MIDI command represented by this message |
245 * @param channel the channel associated with the message |
246 * @param channel the channel associated with the message |
246 * @param data1 the first data byte |
247 * @param data1 the first data byte |
247 * @param data2 the second data byte |
248 * @param data2 the second data byte |
248 * @throws InvalidMidiDataException if the command value, channel value or |
249 * @throws InvalidMidiDataException if the command value, channel value |
249 * all data bytes belonging to the message do not specify a valid |
250 * or all data bytes belonging to the message do not specify |
250 * MIDI message |
251 * a valid MIDI message |
|
252 * @see #setMessage(int) |
251 * @see #setMessage(int) |
253 * @see #setMessage(int, int, int) |
252 * @see #setMessage(int, int, int) |
254 * @see #setMessage(int, int, int, int) |
253 * @see #setMessage(int, int, int, int) |
255 * @see #getCommand() |
254 * @see #getCommand() |
256 * @see #getChannel() |
255 * @see #getChannel() |
262 throws InvalidMidiDataException { |
261 throws InvalidMidiDataException { |
263 super(null); |
262 super(null); |
264 setMessage(command, channel, data1, data2); |
263 setMessage(command, channel, data1, data2); |
265 } |
264 } |
266 |
265 |
267 |
266 /** |
268 /** |
267 * Constructs a new {@code ShortMessage}. |
269 * Constructs a new <code>ShortMessage</code>. |
268 * |
270 * @param data an array of bytes containing the complete message. |
269 * @param data an array of bytes containing the complete message. The |
271 * The message data may be changed using the <code>setMessage</code> |
270 * message data may be changed using the {@code setMessage} method. |
272 * method. |
|
273 * @see #setMessage |
271 * @see #setMessage |
274 */ |
272 */ |
275 // $$fb this should throw an Exception in case of an illegal message! |
273 // $$fb this should throw an Exception in case of an illegal message! |
276 protected ShortMessage(byte[] data) { |
274 protected ShortMessage(byte[] data) { |
277 // $$fb this may set an invalid message. |
275 // $$fb this may set an invalid message. |
278 // Can't correct without compromising compatibility |
276 // Can't correct without compromising compatibility |
279 super(data); |
277 super(data); |
280 } |
278 } |
281 |
279 |
282 |
|
283 /** |
280 /** |
284 * Sets the parameters for a MIDI message that takes no data bytes. |
281 * Sets the parameters for a MIDI message that takes no data bytes. |
285 * @param status the MIDI status byte |
282 * |
286 * @throws InvalidMidiDataException if <code>status</code> does not |
283 * @param status the MIDI status byte |
287 * specify a valid MIDI status byte for a message that requires no data bytes. |
284 * @throws InvalidMidiDataException if {@code status} does not specify a |
|
285 * valid MIDI status byte for a message that requires no data bytes |
288 * @see #setMessage(int, int, int) |
286 * @see #setMessage(int, int, int) |
289 * @see #setMessage(int, int, int, int) |
287 * @see #setMessage(int, int, int, int) |
290 */ |
288 */ |
291 public void setMessage(int status) throws InvalidMidiDataException { |
289 public void setMessage(int status) throws InvalidMidiDataException { |
292 // check for valid values |
290 // check for valid values |
295 throw new InvalidMidiDataException("Status byte; " + status + " requires " + dataLength + " data bytes"); |
293 throw new InvalidMidiDataException("Status byte; " + status + " requires " + dataLength + " data bytes"); |
296 } |
294 } |
297 setMessage(status, 0, 0); |
295 setMessage(status, 0, 0); |
298 } |
296 } |
299 |
297 |
300 |
298 /** |
301 /** |
299 * Sets the parameters for a MIDI message that takes one or two data bytes. |
302 * Sets the parameters for a MIDI message that takes one or two data |
300 * If the message takes only one data byte, the second data byte is ignored; |
303 * bytes. If the message takes only one data byte, the second data |
301 * if the message does not take any data bytes, both data bytes are ignored. |
304 * byte is ignored; if the message does not take any data bytes, both |
302 * |
305 * data bytes are ignored. |
303 * @param status the MIDI status byte |
306 * |
304 * @param data1 the first data byte |
307 * @param status the MIDI status byte |
305 * @param data2 the second data byte |
308 * @param data1 the first data byte |
306 * @throws InvalidMidiDataException if the the status byte, or all data |
309 * @param data2 the second data byte |
307 * bytes belonging to the message, do not specify a valid MIDI |
310 * @throws InvalidMidiDataException if the |
308 * message |
311 * the status byte, or all data bytes belonging to the message, do |
|
312 * not specify a valid MIDI message. |
|
313 * @see #setMessage(int, int, int, int) |
309 * @see #setMessage(int, int, int, int) |
314 * @see #setMessage(int) |
310 * @see #setMessage(int) |
315 */ |
311 */ |
316 public void setMessage(int status, int data1, int data2) throws InvalidMidiDataException { |
312 public void setMessage(int status, int data1, int data2) throws InvalidMidiDataException { |
317 // check for valid values |
313 // check for valid values |
377 throw new InvalidMidiDataException("channel out of range: " + channel); |
369 throw new InvalidMidiDataException("channel out of range: " + channel); |
378 } |
370 } |
379 setMessage((command & 0xF0) | (channel & 0x0F), data1, data2); |
371 setMessage((command & 0xF0) | (channel & 0x0F), data1, data2); |
380 } |
372 } |
381 |
373 |
382 |
374 /** |
383 /** |
375 * Obtains the MIDI channel associated with this event. This method assumes |
384 * Obtains the MIDI channel associated with this event. This method |
376 * that the event is a MIDI channel message; if not, the return value will |
385 * assumes that the event is a MIDI channel message; if not, the return |
377 * not be meaningful. |
386 * value will not be meaningful. |
378 * |
387 * @return MIDI channel associated with the message. |
379 * @return MIDI channel associated with the message |
388 * @see #setMessage(int, int, int, int) |
380 * @see #setMessage(int, int, int, int) |
389 */ |
381 */ |
390 public int getChannel() { |
382 public int getChannel() { |
391 // this returns 0 if an invalid message is set |
383 // this returns 0 if an invalid message is set |
392 return (getStatus() & 0x0F); |
384 return (getStatus() & 0x0F); |
393 } |
385 } |
394 |
386 |
395 |
387 /** |
396 /** |
388 * Obtains the MIDI command associated with this event. This method assumes |
397 * Obtains the MIDI command associated with this event. This method |
389 * that the event is a MIDI channel message; if not, the return value will |
398 * assumes that the event is a MIDI channel message; if not, the return |
390 * not be meaningful. |
399 * value will not be meaningful. |
391 * |
400 * @return the MIDI command associated with this event |
392 * @return the MIDI command associated with this event |
401 * @see #setMessage(int, int, int, int) |
393 * @see #setMessage(int, int, int, int) |
402 */ |
394 */ |
403 public int getCommand() { |
395 public int getCommand() { |
404 // this returns 0 if an invalid message is set |
396 // this returns 0 if an invalid message is set |
405 return (getStatus() & 0xF0); |
397 return (getStatus() & 0xF0); |
406 } |
398 } |
407 |
399 |
408 |
|
409 /** |
400 /** |
410 * Obtains the first data byte in the message. |
401 * Obtains the first data byte in the message. |
411 * @return the value of the <code>data1</code> field |
402 * |
|
403 * @return the value of the {@code data1} field |
412 * @see #setMessage(int, int, int) |
404 * @see #setMessage(int, int, int) |
413 */ |
405 */ |
414 public int getData1() { |
406 public int getData1() { |
415 if (length > 1) { |
407 if (length > 1) { |
416 return (data[1] & 0xFF); |
408 return (data[1] & 0xFF); |
417 } |
409 } |
418 return 0; |
410 return 0; |
419 } |
411 } |
420 |
412 |
421 |
|
422 /** |
413 /** |
423 * Obtains the second data byte in the message. |
414 * Obtains the second data byte in the message. |
424 * @return the value of the <code>data2</code> field |
415 * |
|
416 * @return the value of the {@code data2} field |
425 * @see #setMessage(int, int, int) |
417 * @see #setMessage(int, int, int) |
426 */ |
418 */ |
427 public int getData2() { |
419 public int getData2() { |
428 if (length > 2) { |
420 if (length > 2) { |
429 return (data[2] & 0xFF); |
421 return (data[2] & 0xFF); |
430 } |
422 } |
431 return 0; |
423 return 0; |
432 } |
424 } |
433 |
425 |
434 |
426 /** |
435 /** |
427 * Creates a new object of the same class and with the same contents as this |
436 * Creates a new object of the same class and with the same contents |
428 * object. |
437 * as this object. |
429 * |
438 * @return a clone of this instance. |
430 * @return a clone of this instance |
439 */ |
431 */ |
440 public Object clone() { |
432 public Object clone() { |
441 byte[] newData = new byte[length]; |
433 byte[] newData = new byte[length]; |
442 System.arraycopy(data, 0, newData, 0, newData.length); |
434 System.arraycopy(data, 0, newData, 0, newData.length); |
443 |
435 |
444 ShortMessage msg = new ShortMessage(newData); |
436 ShortMessage msg = new ShortMessage(newData); |
445 return msg; |
437 return msg; |
446 } |
438 } |
447 |
439 |
448 |
440 /** |
449 /** |
441 * Retrieves the number of data bytes associated with a particular status |
450 * Retrieves the number of data bytes associated with a particular |
442 * byte value. |
451 * status byte value. |
443 * |
452 * @param status status byte value, which must represent a short MIDI message |
444 * @param status status byte value, which must represent a short MIDI |
|
445 * message |
453 * @return data length in bytes (0, 1, or 2) |
446 * @return data length in bytes (0, 1, or 2) |
454 * @throws InvalidMidiDataException if the |
447 * @throws InvalidMidiDataException if the {@code status} argument does not |
455 * <code>status</code> argument does not represent the status byte for any |
448 * represent the status byte for any short message |
456 * short message |
|
457 */ |
449 */ |
458 protected final int getDataLength(int status) throws InvalidMidiDataException { |
450 protected final int getDataLength(int status) throws InvalidMidiDataException { |
459 // system common and system real-time messages |
451 // system common and system real-time messages |
460 switch(status) { |
452 switch(status) { |
461 case 0xF6: // Tune Request |
453 case 0xF6: // Tune Request |