Index: modules/sound/src/main/java/javax/sound/midi/ShortMessage.java =================================================================== --- modules/sound/src/main/java/javax/sound/midi/ShortMessage.java (revision 424670) +++ modules/sound/src/main/java/javax/sound/midi/ShortMessage.java (working copy) @@ -14,6 +14,10 @@ * limitations under the License. */ +/** + * @author Evgeny S. Sidorenko + */ + package javax.sound.midi; public class ShortMessage extends MidiMessage { @@ -53,57 +57,219 @@ public static final int TUNE_REQUEST = 246; + private int m_data1; + + private int m_data2; + + private int m_channel; + + private int m_command; + public ShortMessage() { - //TODO - super(null); + super(new byte[] {-112, 64, 127}); + m_data1 = 64; + m_data2 = 127; + m_channel = 0; + m_command = 144; } protected ShortMessage(byte[] data) { - //TODO - super(data); + super(data); + if ((data == null) || (data.length == 0)) { + m_data1 = 0; + m_data2 = 0; + m_channel = 0; + m_command = 0; + } else if (data.length >= 3) { + m_data1 = (int) (data[1] & 0xFF); + m_data2 = (int) (data[2] & 0xFF); + m_channel = ((int) (data[0] & 0xFF)) % 16; + m_command = ((int) (data[0] & 0xFF)) - m_channel; + } else if (data.length == 2) { + m_data1 = (int) (data[1] & 0xFF); + m_data2 = 0; + m_channel = ((int) (data[0] & 0xFF)) % 16; + m_command = ((int) (data[0] & 0xFF)) - m_channel; + } else { + m_data1 = 0; + m_data2 = 0; + m_channel = ((int) (data[0] & 0xFF)) % 16; + m_command = ((int) (data[0] & 0xFF)) - m_channel; + } } public Object clone() { - //TODO - return null; + return new ShortMessage(this.getMessage()); } public int getChannel() { - //TODO - return 1; + return m_channel; } public int getCommand() { - //TODO - return 1; + return m_command; } public int getData1() { - //TODO - return 1; + return m_data1; } public int getData2() { - //TODO - return 1; + return m_data2; } protected final int getDataLength(int status) throws InvalidMidiDataException { - //TODO - return 1; +// FIXME + /* + * I have some question about this method. I didn't understand how + * should to work this method, but some results I get by + * experimental method. + * From 0 up to 127, from 256 up to 383 and so on this method throw + * out exception, i.e. after 256 begin cycle with some small + * differences in the first lap, from 0 up to 255. From the second + * lap and so on this method, getDataLenght(int), throw out + * exception with value of status from 496 up to 511, from 752 up to + * 767 and so on, i.e. on the last 16 number of 256-lap. + * And now differences in the first lap. This method don't throw out + * exception with value of status from 240 up to 255. It has next + * behavior: + * - value of status equals 240 -- throw out exception; + * - 241 -- return 1; + * - 242 -- return 2; + * - 243 -- return 1; + * - from 244 up to 245 -- throw out exception; + * - from 246 up to 255 -- return 0; + */ + if (status < 0) { + throw new InvalidMidiDataException("Invalid status byte: " + status); + } + if (((status % 256) >= 0) && ((status % 256) <= 127)) { + throw new InvalidMidiDataException("Invalid status byte: " + status); + } + if (((status / 256) == 0) && ((status == 240) || (status == 244) || (status == 245))) { + throw new InvalidMidiDataException("Invalid status byte: " + status); + } + if (((status / 256) != 0) && ((status % 256) >= 244) && ((status % 256) <= 255)) { + throw new InvalidMidiDataException("Invalid status byte: " + status); + } + + if ((status / 256) == 0) { + if ((status == 241) || (status == 243)) { + return 1; + } else if (status == 242) { + return 2; + } else if ((status >= 246) && (status <= 255)) { + return 0; + } + } + if (((status % 256) >= 128) && ((status % 256) <= 191)) { + return 2; + } else if (((status % 256) >= 192) && ((status % 256) <= 223)) { + return 1; + } else { + return 2; + } } public void setMessage(int status) throws InvalidMidiDataException { - //TODO + /** + * value of variable status is more or equals 246 and + * less or equals 255 + */ + if ((status < 246) || (status > 255)) { + throw new InvalidMidiDataException("Invalid status byte: " + status); + } + super.setMessage(new byte[] {(byte) status}, 1); + /** + * channel change from 0 up to 15, and + * channel + command == status + */ + m_data1 = 0; + m_data2 = 0; + m_channel = status % 16; + m_command = status - m_channel; } public void setMessage(int status, int data1, int data2) throws InvalidMidiDataException { - //TODO +// FIXME + /* + * In the Sun's implementation variables data1 and data2 + * don't use; I don't find situation when this variables + * influence on result of functions getData1() and getData2(). + * But function getDataLength(int) return 0 when I modify status + * byte from 246 up to 255, and so I think it's true. + */ + /** + * value of variable status is more or equals 246 and + * less or equals 255 + */ + if ((status < 246) || (status > 255)) { + throw new InvalidMidiDataException("Invalid status byte: " + status); + } + super.setMessage(new byte[] {(byte) status}, 1); + /** + * channel change from 0 up to 15, and + * channel + command == status + */ + m_data1 = 0; + m_data2 = 0; + m_channel = status % 16; + m_command = status - m_channel; } public void setMessage(int command, int channel, int data1, int data2) throws InvalidMidiDataException { - //TODO +// FIXME + /** + * value of variable command is more or equals 128 and + * less or equals 239 + */ + if ((command < 128) || (command > 239)) { + /* + * when this exception throw out, the value of variable command + * should be the hexadecimal number + */ + throw new InvalidMidiDataException("command out of range: " + command); + } + /** + * value of variable channel is more or equals 0 and + * less or equals 15 + */ + if ((channel < 0) || (channel > 15)) { + throw new InvalidMidiDataException("channel out of range: " + channel); + } + /** + * value of data1 and data2 is more or equals 0 and + * less or equals 127, but when command more or + * equals 192 and less or equals 223 the second data, + * data2, is unused, because getDataLength(int) return 1 + * in this case, and in other cases it return 2 + */ + if ((data1 < 0) || (data1 > 127)) { + throw new InvalidMidiDataException("data1 out of range: " + data1); + } + if ((getDataLength(command) == 2) && ((data2 < 0) || (data2 > 127))) { + throw new InvalidMidiDataException("data2 out of range: " + data2); + } + + /** + * channel change from 0 up to 15, and + * channel + command == status + */ + m_command = command - (command % 16); + m_channel = channel; + m_data1 = data1; + /** + * status in this case equals getCommand() + getChannel() + */ + if (getDataLength(command) == 1) { + super.setMessage(new byte[] {(byte) (m_command + m_channel), (byte) data1}, 2); + m_data2 = 0; + } else { + super.setMessage(new byte[] {(byte) (m_command + m_channel), (byte) data1, + (byte) data2}, 3); + m_data2 = data2; + } } }