1 /* 2 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.sound.midi; 27 28 /** 29 * A <code>ShortMessage</code> contains a MIDI message that has at most 30 * two data bytes following its status byte. The types of MIDI message 31 * that satisfy this criterion are channel voice, channel mode, system common, 32 * and system real-time--in other words, everything except system exclusive 33 * and meta-events. The <code>ShortMessage</code> class provides methods 34 * for getting and setting the contents of the MIDI message. 35 * <p> 36 * A number of <code>ShortMessage</code> methods have integer parameters by which 37 * you specify a MIDI status or data byte. If you know the numeric value, you 38 * can express it directly. For system common and system real-time messages, 39 * you can often use the corresponding fields of <code>ShortMessage</code>, such as 40 * {@link #SYSTEM_RESET SYSTEM_RESET}. For channel messages, 41 * the upper four bits of the status byte are specified by a command value and 42 * the lower four bits are specified by a MIDI channel number. To 43 * convert incoming MIDI data bytes that are in the form of Java's signed bytes, 44 * you can use the <A HREF="MidiMessage.html#integersVsBytes">conversion code</A> 45 * given in the <code>{@link MidiMessage}</code> class description. 46 * 47 * @see SysexMessage 48 * @see MetaMessage 49 * 50 * @author David Rivas 51 * @author Kara Kytle 52 * @author Florian Bomers 53 */ 54 55 public class ShortMessage extends MidiMessage { 56 57 58 // Status byte defines 59 60 61 // System common messages 62 63 /** 64 * Status byte for MIDI Time Code Quarter Frame message (0xF1, or 241). 65 * @see MidiMessage#getStatus 66 */ 67 public static final int MIDI_TIME_CODE = 0xF1; // 241 68 69 /** 70 * Status byte for Song Position Pointer message (0xF2, or 242). 71 * @see MidiMessage#getStatus 72 */ 73 public static final int SONG_POSITION_POINTER = 0xF2; // 242 74 75 /** 76 * Status byte for MIDI Song Select message (0xF3, or 243). 77 * @see MidiMessage#getStatus 78 */ 79 public static final int SONG_SELECT = 0xF3; // 243 80 81 /** 82 * Status byte for Tune Request message (0xF6, or 246). 83 * @see MidiMessage#getStatus 84 */ 85 public static final int TUNE_REQUEST = 0xF6; // 246 86 87 /** 88 * Status byte for End of System Exclusive message (0xF7, or 247). 89 * @see MidiMessage#getStatus 90 */ 91 public static final int END_OF_EXCLUSIVE = 0xF7; // 247 92 93 94 // System real-time messages 95 96 /** 97 * Status byte for Timing Clock message (0xF8, or 248). 98 * @see MidiMessage#getStatus 99 */ 100 public static final int TIMING_CLOCK = 0xF8; // 248 101 102 /** 103 * Status byte for Start message (0xFA, or 250). 104 * @see MidiMessage#getStatus 105 */ 106 public static final int START = 0xFA; // 250 107 108 /** 109 * Status byte for Continue message (0xFB, or 251). 110 * @see MidiMessage#getStatus 111 */ 112 public static final int CONTINUE = 0xFB; // 251 113 114 /** 115 * Status byte for Stop message (0xFC, or 252). 116 * @see MidiMessage#getStatus 117 */ 118 public static final int STOP = 0xFC; //252 119 120 /** 121 * Status byte for Active Sensing message (0xFE, or 254). 122 * @see MidiMessage#getStatus 123 */ 124 public static final int ACTIVE_SENSING = 0xFE; // 254 125 126 /** 127 * Status byte for System Reset message (0xFF, or 255). 128 * @see MidiMessage#getStatus 129 */ 130 public static final int SYSTEM_RESET = 0xFF; // 255 131 132 133 // Channel voice message upper nibble defines 134 135 /** 136 * Command value for Note Off message (0x80, or 128) 137 */ 138 public static final int NOTE_OFF = 0x80; // 128 139 140 /** 141 * Command value for Note On message (0x90, or 144) 142 */ 143 public static final int NOTE_ON = 0x90; // 144 144 145 /** 146 * Command value for Polyphonic Key Pressure (Aftertouch) message (0xA0, or 160) 147 */ 148 public static final int POLY_PRESSURE = 0xA0; // 160 149 150 /** 151 * Command value for Control Change message (0xB0, or 176) 152 */ 153 public static final int CONTROL_CHANGE = 0xB0; // 176 154 155 /** 156 * Command value for Program Change message (0xC0, or 192) 157 */ 158 public static final int PROGRAM_CHANGE = 0xC0; // 192 159 160 /** 161 * Command value for Channel Pressure (Aftertouch) message (0xD0, or 208) 162 */ 163 public static final int CHANNEL_PRESSURE = 0xD0; // 208 164 165 /** 166 * Command value for Pitch Bend message (0xE0, or 224) 167 */ 168 public static final int PITCH_BEND = 0xE0; // 224 169 170 171 // Instance variables 172 173 /** 174 * Constructs a new <code>ShortMessage</code>. The 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 180 */ 181 public ShortMessage() { 182 this(new byte[3]); 183 // Default message data: NOTE_ON on Channel 0 with max volume 184 data[0] = (byte) (NOTE_ON & 0xFF); 185 data[1] = (byte) 64; 186 data[2] = (byte) 127; 187 length = 3; 188 } 189 190 /** 191 * Constructs a new {@code ShortMessage} which represents a MIDI 192 * message that takes no data bytes. 193 * The contents of the message can be changed by using one of 194 * the {@code setMessage} methods. 195 * 196 * @param status the MIDI status byte 197 * @throws InvalidMidiDataException if {@code status} does not specify 198 * a valid MIDI status byte for a message that requires no data bytes 199 * @see #setMessage(int) 200 * @see #setMessage(int, int, int) 201 * @see #setMessage(int, int, int, int) 202 * @see #getStatus() 203 * @since 1.7 204 */ 205 public ShortMessage(int status) throws InvalidMidiDataException { 206 super(null); 207 setMessage(status); // can throw InvalidMidiDataException 208 } 209 210 /** 211 * Constructs a new {@code ShortMessage} which represents a MIDI message 212 * that takes up to two data bytes. If the message only takes one data byte, 213 * the second data byte is ignored. If the message does not take 214 * any data bytes, both data bytes are ignored. 215 * The contents of the message can be changed by using one of 216 * the {@code setMessage} methods. 217 * 218 * @param status the MIDI status byte 219 * @param data1 the first data byte 220 * @param data2 the second data byte 221 * @throws InvalidMidiDataException if the status byte or all data bytes 222 * belonging to the message do not specify a valid MIDI message 223 * @see #setMessage(int) 224 * @see #setMessage(int, int, int) 225 * @see #setMessage(int, int, int, int) 226 * @see #getStatus() 227 * @see #getData1() 228 * @see #getData2() 229 * @since 1.7 230 */ 231 public ShortMessage(int status, int data1, int data2) 232 throws InvalidMidiDataException { 233 super(null); 234 setMessage(status, data1, data2); // can throw InvalidMidiDataException 235 } 236 237 /** 238 * Constructs a new {@code ShortMessage} which represents a channel 239 * MIDI message that takes up to two data bytes. If the message only takes 240 * one data byte, the second data byte is ignored. If the message does not 241 * take any data bytes, both data bytes are ignored. 242 * The contents of the message can be changed by using one of 243 * the {@code setMessage} methods. 244 * 245 * @param command the MIDI command represented by this message 246 * @param channel the channel associated with the message 247 * @param data1 the first data byte 248 * @param data2 the second data byte 249 * @throws InvalidMidiDataException if the command value, channel value 250 * or all data bytes belonging to the message do not specify 251 * a valid MIDI message 252 * @see #setMessage(int) 253 * @see #setMessage(int, int, int) 254 * @see #setMessage(int, int, int, int) 255 * @see #getCommand() 256 * @see #getChannel() 257 * @see #getData1() 258 * @see #getData2() 259 * @since 1.7 260 */ 261 public ShortMessage(int command, int channel, int data1, int data2) 262 throws InvalidMidiDataException { 263 super(null); 264 setMessage(command, channel, data1, data2); 265 } 266 267 268 /** 269 * Constructs a new <code>ShortMessage</code>. 270 * @param data an array of bytes containing the complete message. 271 * The message data may be changed using the <code>setMessage</code> 272 * method. 273 * @see #setMessage 274 */ 275 // $$fb this should throw an Exception in case of an illegal message! 276 protected ShortMessage(byte[] data) { 277 // $$fb this may set an invalid message. 278 // Can't correct without compromising compatibility 279 super(data); 280 } 281 282 283 /** 284 * Sets the parameters for a MIDI message that takes no data bytes. 285 * @param status the MIDI status byte 286 * @throws InvalidMidiDataException if <code>status</code> does not 287 * specify a valid MIDI status byte for a message that requires no data bytes. 288 * @see #setMessage(int, int, int) 289 * @see #setMessage(int, int, int, int) 290 */ 291 public void setMessage(int status) throws InvalidMidiDataException { 292 // check for valid values 293 int dataLength = getDataLength(status); // can throw InvalidMidiDataException 294 if (dataLength != 0) { 295 throw new InvalidMidiDataException("Status byte; " + status + " requires " + dataLength + " data bytes"); 296 } 297 setMessage(status, 0, 0); 298 } 299 300 301 /** 302 * Sets the parameters for a MIDI message that takes one or two data 303 * bytes. If the message takes only one data byte, the second data 304 * byte is ignored; if the message does not take any data bytes, both 305 * data bytes are ignored. 306 * 307 * @param status the MIDI status byte 308 * @param data1 the first data byte 309 * @param data2 the second data byte 310 * @throws InvalidMidiDataException if the 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) 314 * @see #setMessage(int) 315 */ 316 public void setMessage(int status, int data1, int data2) throws InvalidMidiDataException { 317 // check for valid values 318 int dataLength = getDataLength(status); // can throw InvalidMidiDataException 319 if (dataLength > 0) { 320 if (data1 < 0 || data1 > 127) { 321 throw new InvalidMidiDataException("data1 out of range: " + data1); 322 } 323 if (dataLength > 1) { 324 if (data2 < 0 || data2 > 127) { 325 throw new InvalidMidiDataException("data2 out of range: " + data2); 326 } 327 } 328 } 329 330 331 // set the length 332 length = dataLength + 1; 333 // re-allocate array if ShortMessage(byte[]) constructor gave array with fewer elements 334 if (data == null || data.length < length) { 335 data = new byte[3]; 336 } 337 338 // set the data 339 data[0] = (byte) (status & 0xFF); 340 if (length > 1) { 341 data[1] = (byte) (data1 & 0xFF); 342 if (length > 2) { 343 data[2] = (byte) (data2 & 0xFF); 344 } 345 } 346 } 347 348 349 /** 350 * Sets the short message parameters for a channel message 351 * which takes up to two data bytes. If the message only 352 * takes one data byte, the second data byte is ignored; if 353 * the message does not take any data bytes, both data bytes 354 * are ignored. 355 * 356 * @param command the MIDI command represented by this message 357 * @param channel the channel associated with the message 358 * @param data1 the first data byte 359 * @param data2 the second data byte 360 * @throws InvalidMidiDataException if the 361 * status byte or all data bytes belonging to the message, do 362 * not specify a valid MIDI message 363 * 364 * @see #setMessage(int, int, int) 365 * @see #setMessage(int) 366 * @see #getCommand 367 * @see #getChannel 368 * @see #getData1 369 * @see #getData2 370 */ 371 public void setMessage(int command, int channel, int data1, int data2) throws InvalidMidiDataException { 372 // check for valid values 373 if (command >= 0xF0 || command < 0x80) { 374 throw new InvalidMidiDataException("command out of range: 0x" + Integer.toHexString(command)); 375 } 376 if ((channel & 0xFFFFFFF0) != 0) { // <=> (channel<0 || channel>15) 377 throw new InvalidMidiDataException("channel out of range: " + channel); 378 } 379 setMessage((command & 0xF0) | (channel & 0x0F), data1, data2); 380 } 381 382 383 /** 384 * Obtains the MIDI channel associated with this event. This method 385 * assumes that the event is a MIDI channel message; if not, the return 386 * value will not be meaningful. 387 * @return MIDI channel associated with the message. 388 * @see #setMessage(int, int, int, int) 389 */ 390 public int getChannel() { 391 // this returns 0 if an invalid message is set 392 return (getStatus() & 0x0F); 393 } 394 395 396 /** 397 * Obtains the MIDI command associated with this event. This method 398 * assumes that the event is a MIDI channel message; if not, the return 399 * value will not be meaningful. 400 * @return the MIDI command associated with this event 401 * @see #setMessage(int, int, int, int) 402 */ 403 public int getCommand() { 404 // this returns 0 if an invalid message is set 405 return (getStatus() & 0xF0); 406 } 407 408 409 /** 410 * Obtains the first data byte in the message. 411 * @return the value of the <code>data1</code> field 412 * @see #setMessage(int, int, int) 413 */ 414 public int getData1() { 415 if (length > 1) { 416 return (data[1] & 0xFF); 417 } 418 return 0; 419 } 420 421 422 /** 423 * Obtains the second data byte in the message. 424 * @return the value of the <code>data2</code> field 425 * @see #setMessage(int, int, int) 426 */ 427 public int getData2() { 428 if (length > 2) { 429 return (data[2] & 0xFF); 430 } 431 return 0; 432 } 433 434 435 /** 436 * Creates a new object of the same class and with the same contents 437 * as this object. 438 * @return a clone of this instance. 439 */ 440 public Object clone() { 441 byte[] newData = new byte[length]; 442 System.arraycopy(data, 0, newData, 0, newData.length); 443 444 ShortMessage msg = new ShortMessage(newData); 445 return msg; 446 } 447 448 449 /** 450 * Retrieves the number of data bytes associated with a particular 451 * status byte value. 452 * @param status status byte value, which must represent a short MIDI message 453 * @return data length in bytes (0, 1, or 2) 454 * @throws InvalidMidiDataException if the 455 * <code>status</code> argument does not represent the status byte for any 456 * short message 457 */ 458 protected final int getDataLength(int status) throws InvalidMidiDataException { 459 // system common and system real-time messages 460 switch(status) { 461 case 0xF6: // Tune Request 462 case 0xF7: // EOX 463 // System real-time messages 464 case 0xF8: // Timing Clock 465 case 0xF9: // Undefined 466 case 0xFA: // Start 467 case 0xFB: // Continue 468 case 0xFC: // Stop 469 case 0xFD: // Undefined 470 case 0xFE: // Active Sensing 471 case 0xFF: // System Reset 472 return 0; 473 case 0xF1: // MTC Quarter Frame 474 case 0xF3: // Song Select 475 return 1; 476 case 0xF2: // Song Position Pointer 477 return 2; 478 default: 479 } 480 481 // channel voice and mode messages 482 switch(status & 0xF0) { 483 case 0x80: 484 case 0x90: 485 case 0xA0: 486 case 0xB0: 487 case 0xE0: 488 return 2; 489 case 0xC0: 490 case 0xD0: 491 return 1; 492 default: 493 throw new InvalidMidiDataException("Invalid status byte: " + status); 494 } 495 } 496 }