001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package javax.sound.midi;
019:
020: import org.apache.harmony.sound.internal.nls.Messages;
021:
022: public class ShortMessage extends MidiMessage {
023:
024: public static final int ACTIVE_SENSING = 254;
025:
026: public static final int CHANNEL_PRESSURE = 208;
027:
028: public static final int CONTINUE = 251;
029:
030: public static final int CONTROL_CHANGE = 176;
031:
032: public static final int END_OF_EXCLUSIVE = 247;
033:
034: public static final int MIDI_TIME_CODE = 241;
035:
036: public static final int NOTE_OFF = 128;
037:
038: public static final int NOTE_ON = 144;
039:
040: public static final int PITCH_BEND = 224;
041:
042: public static final int POLY_PRESSURE = 160;
043:
044: public static final int PROGRAM_CHANGE = 192;
045:
046: public static final int SONG_POSITION_POINTER = 242;
047:
048: public static final int SONG_SELECT = 243;
049:
050: public static final int START = 250;
051:
052: public static final int STOP = 252;
053:
054: public static final int SYSTEM_RESET = 255;
055:
056: public static final int TIMING_CLOCK = 248;
057:
058: public static final int TUNE_REQUEST = 246;
059:
060: public ShortMessage() {
061: super (new byte[] { -112, 64, 127 });
062: }
063:
064: protected ShortMessage(byte[] data) {
065: super (data);
066: }
067:
068: @Override
069: public Object clone() {
070: return new ShortMessage(this .getMessage());
071: }
072:
073: public int getChannel() {
074: /*
075: * channel change from 0 up to 15
076: */
077: if ((data == null) || (data.length == 0)) {
078: return 0;
079: }
080: return data[0] & 0x0F;
081: }
082:
083: public int getCommand() {
084: /*
085: * command should be divisible by 16 without rest
086: */
087: if ((data == null) || (data.length == 0)) {
088: return 0;
089: }
090: return (data[0] & 0xFF) - getChannel();
091: }
092:
093: public int getData1() {
094: if ((data == null) || (data.length == 0)) {
095: return 0;
096: } else if (data.length < 2) {
097: return 0;
098: } else {
099: return data[1] & 0xFF;
100: }
101: }
102:
103: public int getData2() {
104: if ((data == null) || (data.length == 0)) {
105: return 0;
106: } else if (data.length < 3) {
107: return 0;
108: } else {
109: return data[2] & 0xFF;
110: }
111: }
112:
113: protected final int getDataLength(int status)
114: throws InvalidMidiDataException {
115: // FIXME
116: /*
117: * I have some question about this method. I didn't understand how
118: * should to work this method, but some results I get by experimental
119: * method. From 0 up to 127, from 256 up to 383 and so on this method
120: * throw out exception, i.e. after 256 begin cycle with some small
121: * differences in the first lap, from 0 up to 255. From the second lap
122: * and so on this method, getDataLength(int), throw out exception with
123: * value of status from 496 up to 511, from 752 up to 767 and so on,
124: * i.e. on the last 16 number of 256-lap. And now differences in the
125: * first lap. This method don't throw out exception with value of status
126: * from 240 up to 255. It has next behavior:
127: * - value of status equals 240 -- throw out exception;
128: * - 241 -- return 1;
129: * - 242 -- return 2;
130: * - 243 -- return 1;
131: * - from 244 up to 245 -- throw out exception;
132: * - from 246 up to 255 -- return 0;
133: */
134: if (status < 0) {
135: // sound.04=Invalid status byte: {0}
136: throw new InvalidMidiDataException(Messages.getString(
137: "sound.04", status)); //$NON-NLS-1$
138: }
139: if (((status % 256) >= 0) && ((status % 256) <= 127)) {
140: // sound.04=Invalid status byte: {0}
141: throw new InvalidMidiDataException(Messages.getString(
142: "sound.04", status)); //$NON-NLS-1$
143: }
144: if (((status / 256) == 0)
145: && ((status == 240) || (status == 244) || (status == 245))) {
146: // sound.04=Invalid status byte: {0}
147: throw new InvalidMidiDataException(Messages.getString(
148: "sound.04", status)); //$NON-NLS-1$
149: }
150: if (((status / 256) != 0) && ((status % 256) >= 244)
151: && ((status % 256) <= 255)) {
152: // sound.04=Invalid status byte: {0}
153: throw new InvalidMidiDataException(Messages.getString(
154: "sound.04", status)); //$NON-NLS-1$
155: }
156:
157: if ((status / 256) == 0) {
158: if ((status == 241) || (status == 243)) {
159: return 1;
160: } else if (status == 242) {
161: return 2;
162: } else if ((status >= 246) && (status <= 255)) {
163: return 0;
164: }
165: }
166: if (((status % 256) >= 128) && ((status % 256) <= 191)) {
167: return 2;
168: } else if (((status % 256) >= 192) && ((status % 256) <= 223)) {
169: return 1;
170: } else {
171: return 2;
172: }
173: }
174:
175: public void setMessage(int status) throws InvalidMidiDataException {
176: /*
177: * value of variable status is more or equals 246 and less or equals 255
178: */
179: if ((status < 246) || (status > 255)) {
180: // sound.04=Invalid status byte: {0}
181: throw new InvalidMidiDataException(Messages.getString(
182: "sound.04", status)); //$NON-NLS-1$
183: }
184: super .setMessage(new byte[] { (byte) status }, 1);
185: }
186:
187: public void setMessage(int status, int data1, int data2)
188: throws InvalidMidiDataException {
189: // FIXME
190: /*
191: * In the Sun's implementation variables data1 and data2 don't use; I
192: * don't find situation when this variables influence on result of
193: * functions getData1() and getData2(). But function getDataLength(int)
194: * return 0 when I modify status byte from 246 up to 255, and so I think
195: * it's true.
196: */
197: if ((status < 246) || (status > 255)) {
198: // sound.04=Invalid status byte: {0}
199: throw new InvalidMidiDataException(Messages.getString(
200: "sound.04", status)); //$NON-NLS-1$
201: }
202: super .setMessage(new byte[] { (byte) status }, 1);
203: }
204:
205: public void setMessage(int command, int channel, int data1,
206: int data2) throws InvalidMidiDataException {
207: // FIXME
208: /*
209: * value of variable command is more or equals 128 and less or equals
210: * 239
211: */
212: if ((command < 128) || (command > 239)) {
213: /*
214: * when this exception throw out, the value of variable command
215: * should be the hexadecimal number
216: */
217: // sound.05=command out of range: {0}
218: throw new InvalidMidiDataException(Messages.getString(
219: "sound.05", command)); //$NON-NLS-1$
220: }
221: /*
222: * value of variable channel is more or equals 0 and less or equals 15
223: */
224: if ((channel < 0) || (channel > 15)) {
225: // sound.06=channel out of range: {0}
226: throw new InvalidMidiDataException(Messages.getString(
227: "sound.06", channel)); //$NON-NLS-1$
228: }
229: /*
230: * value of data1 and data2 is more or equals 0 and less or equals 127,
231: * but when command more or equals 192 and less or equals 223 the second
232: * data, data2, is unused, because getDataLength(int) return 1 in this
233: * case, and in other cases it return 2
234: */
235: if ((getDataLength(command) >= 1)
236: && ((data1 < 0) || (data1 > 127))) {
237: // sound.07=data1 out of range: {0}
238: throw new InvalidMidiDataException(Messages.getString(
239: "sound.07", data1)); //$NON-NLS-1$
240: }
241: if ((getDataLength(command) == 2)
242: && ((data2 < 0) || (data2 > 127))) {
243: // sound.08=data2 out of range: {0}
244: throw new InvalidMidiDataException(Messages.getString(
245: "sound.08", data2)); //$NON-NLS-1$
246: }
247:
248: int tcom = command - (command % 16);
249: if (getDataLength(command) == 1) {
250: super .setMessage(new byte[] { (byte) (tcom + channel),
251: (byte) data1 }, 2);
252: } else {
253: super .setMessage(new byte[] { (byte) (tcom + channel),
254: (byte) data1, (byte) data2 }, 3);
255: }
256: }
257:
258: }
|