KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > sound > midi > MetaMessage


1 /*
2  * @(#)MetaMessage.java 1.24 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.sound.midi;
9
10 import java.io.ByteArrayOutputStream JavaDoc;
11 import java.io.DataOutputStream JavaDoc;
12 import java.io.IOException JavaDoc;
13
14
15 /**
16  * A <code>MetaMessage</code> is a <code>{@link MidiMessage}</code> that is not meaningful to synthesizers, but
17  * that can be stored in a MIDI file and interpreted by a sequencer program.
18  * (See the discussion in the <code>MidiMessage</code>
19  * class description.) The Standard MIDI Files specification defines
20  * various types of meta-events, such as sequence number, lyric, cue point,
21  * and set tempo. There are also meta-events
22  * for such information as lyrics, copyrights, tempo indications, time and key
23  * signatures, markers, etc. For more information, see the Standard MIDI Files 1.0
24  * specification, which is part of the Complete MIDI 1.0 Detailed Specification
25  * published by the MIDI Manufacturer's Association
26  * (<a href = http://www.midi.org>http://www.midi.org</a>).
27  *
28  * <p>
29  * When data is being transported using MIDI wire protocol,
30  * a <code>{@link ShortMessage}</code> with the status value <code>0xFF</code> represents
31  * a system reset message. In MIDI files, this same status value denotes a <code>MetaMessage</code>.
32  * The types of meta-message are distinguished from each other by the first byte
33  * that follows the status byte <code>0xFF</code>. The subsequent bytes are data
34  * bytes. As with system exclusive messages, there are an arbitrary number of
35  * data bytes, depending on the type of <code>MetaMessage</code>.
36  *
37  * @see MetaEventListener
38  *
39  * @version 1.24, 03/12/19
40  * @author David Rivas
41  * @author Kara Kytle
42  */

43
44 public class MetaMessage extends MidiMessage JavaDoc {
45
46
47     // Status byte defines
48

49     /**
50      * Status byte for <code>MetaMessage</code> (0xFF, or 255), which is used
51      * in MIDI files. It has the same value as SYSTEM_RESET, which
52      * is used in the real-time "MIDI wire" protocol.
53      * @see MidiMessage#getStatus
54      */

55     public static final int META = 0xFF; // 255
56

57
58     // Default meta message data: just the META status byte value
59
// $$kk: 09.09.99: need a real event here!!
60

61     private static byte[] defaultMessage = { (byte)META, 0 };
62
63
64
65     // Instance variables
66

67     /**
68      * The length of the actual message in the data array.
69      * This is used to determine how many bytes of the data array
70      * is the message, and how many are the status byte, the
71      * type byte, and the variable-length-int describing the
72      * length of the message.
73      */

74     private int dataLength = 0;
75
76
77     /**
78      * Constructs a new <code>MetaMessage</code>. The contents of
79      * the message are not set here; use
80      * {@link #setMessage(int, byte[], int) setMessage}
81      * to set them subsequently.
82      */

83     public MetaMessage() {
84     //super(defaultMessage);
85
this(defaultMessage);
86     }
87
88
89     /**
90      * Constructs a new <code>MetaMessage</code>.
91      * @param data an array of bytes containing the complete message.
92      * The message data may be changed using the <code>setMessage</code>
93      * method.
94      * @see #setMessage
95      */

96     protected MetaMessage(byte[] data) {
97     super(data);
98     //$$fb 2001-10-06: need to calculate dataLength. Fix for bug #4511796
99
if (data.length>=3) {
100         dataLength=data.length-3;
101         int pos=2;
102         while (pos<data.length && (data[pos] & 0x80)!=0) {
103         dataLength--; pos++;
104         }
105     }
106     }
107
108
109     /**
110      * Sets the message parameters for a <code>MetaMessage</code>.
111      * Since only one status byte value, <code>0xFF</code>, is allowed for meta-messages,
112      * it does not need to be specified here. Calls to <code>{@link MidiMessage#getStatus getStatus}</code> return
113      * <code>0xFF</code> for all meta-messages.
114      * <p>
115      * The <code>type</code> argument should be a valid value for the byte that
116      * follows the status byte in the <code>MetaMessage</code>. The <code>data</code> argument
117      * should contain all the subsequent bytes of the <code>MetaMessage</code>. In other words,
118      * the byte that specifies the type of <code>MetaMessage</code> is not considered a data byte.
119      *
120      * @param type meta-message type (must be less than 128)
121      * @param data the data bytes in the MIDI message
122      * @param length the number of bytes in the <code>data</code>
123      * byte array
124      * @throws <code>InvalidMidiDataException</code> if the
125      * parameter values do not specify a valid MIDI meta message
126      */

127     public void setMessage(int type, byte[] data, int length) throws InvalidMidiDataException JavaDoc {
128
129     if (type >= 128 || type < 0) {
130         throw new InvalidMidiDataException JavaDoc("Invalid meta event with type " + type);
131     }
132     if ((length > 0 && length > data.length) || length < 0) {
133         throw new InvalidMidiDataException JavaDoc("length out of bounds: "+length);
134     }
135     
136     this.length = 2 + getVarIntLength(length) + length;
137     this.dataLength = length;
138     this.data = new byte[this.length];
139     this.data[0] = (byte) META; // status value for MetaMessages (meta events)
140
this.data[1] = (byte) type; // MetaMessage type
141
writeVarInt(this.data, 2, length); // write the length as a variable int
142
if (length > 0) {
143         System.arraycopy(data, 0, this.data, this.length - this.dataLength, this.dataLength);
144     }
145     }
146
147
148     /**
149      * Obtains the type of the <code>MetaMessage</code>.
150      * @return an integer representing the <code>MetaMessage</code> type
151      */

152     public int getType() {
153     if (length>=2) {
154         return data[1] & 0xFF;
155     }
156     return 0;
157     }
158
159
160
161     /**
162      * Obtains a copy of the data for the meta message. The returned
163      * array of bytes does not include the status byte or the message
164      * length data. The length of the data for the meta message is
165      * the length of the array. Note that the length of the entire
166      * message includes the status byte and the meta message type
167      * byte, and therefore may be longer than the returned array.
168      * @return array containing the meta message data.
169      * @see MidiMessage#getLength
170      */

171     public byte[] getData() {
172     byte[] returnedArray = new byte[dataLength];
173     System.arraycopy(data, (length - dataLength), returnedArray, 0, dataLength);
174     return returnedArray;
175     }
176
177
178     /**
179      * Creates a new object of the same class and with the same contents
180      * as this object.
181      * @return a clone of this instance
182      */

183     public Object JavaDoc clone() {
184     byte[] newData = new byte[length];
185     System.arraycopy(data, 0, newData, 0, newData.length);
186
187     MetaMessage JavaDoc event = new MetaMessage JavaDoc(newData);
188     return event;
189     }
190
191     // HELPER METHODS
192

193     private int getVarIntLength(long value) {
194     int length = 0;
195     do {
196         value = value >> 7;
197         length++;
198     } while (value > 0);
199     return length;
200     }
201     
202     private final static long mask = 0x7F;
203
204     private void writeVarInt(byte[] data, int off, long value) {
205         int shift=63; // number of bitwise left-shifts of mask
206
// first screen out leading zeros
207
while ((shift > 0) && ((value & (mask << shift)) == 0)) shift-=7;
208         // then write actual values
209
while (shift > 0) {
210         data[off++]=(byte) (((value & (mask << shift)) >> shift) | 0x80);
211         shift-=7;
212         }
213         data[off] = (byte) (value & mask);
214     }
215
216 }
217
Popular Tags