API Overview API Index Package Overview Direct link to this page
JDK 1.6
  javax.sound.midi. MetaMessage View Javadoc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

/*
 * @(#)MetaMessage.java	1.25 05/11/17
 *
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package javax.sound.midi;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;


/**
 * A <code>MetaMessage</code> is a <code>{@link MidiMessage}</code> that is not meaningful to synthesizers, but
 * that can be stored in a MIDI file and interpreted by a sequencer program.
 * (See the discussion in the <code>MidiMessage</code>
 * class description.)  The Standard MIDI Files specification defines
 * various types of meta-events, such as sequence number, lyric, cue point,
 * and set tempo.  There are also meta-events
 * for such information as lyrics, copyrights, tempo indications, time and key
 * signatures, markers, etc.  For more information, see the Standard MIDI Files 1.0
 * specification, which is part of the Complete MIDI 1.0 Detailed Specification
 * published by the MIDI Manufacturer's Association
 * (<a href = http://www.midi.org>http://www.midi.org</a>).
 *
 * <p>
 * When data is being transported using MIDI wire protocol,
 * a <code>{@link ShortMessage}</code> with the status value <code>0xFF</code> represents
 * a system reset message.  In MIDI files, this same status value denotes a <code>MetaMessage</code>.
 * The types of meta-message are distinguished from each other by the first byte
 * that follows the status byte <code>0xFF</code>.  The subsequent bytes are data
 * bytes.  As with system exclusive messages, there are an arbitrary number of
 * data bytes, depending on the type of <code>MetaMessage</code>.
 *
 * @see MetaEventListener
 *
 * @version 1.25, 05/11/17
 * @author David Rivas
 * @author Kara Kytle
 */

public class MetaMessage extends MidiMessage {


    // Status byte defines

    /**
     * Status byte for <code>MetaMessage</code> (0xFF, or 255), which is used
     * in MIDI files.  It has the same value as SYSTEM_RESET, which
     * is used in the real-time "MIDI wire" protocol.
     * @see MidiMessage#getStatus
     */
    public static final int META						= 0xFF; // 255


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

    private static byte[] defaultMessage				= { (byte)META, 0 };



    // Instance variables

    /**
     * The length of the actual message in the data array.
     * This is used to determine how many bytes of the data array
     * is the message, and how many are the status byte, the
     * type byte, and the variable-length-int describing the
     * length of the message.
     */
    private int dataLength = 0;


    /**
     * Constructs a new <code>MetaMessage</code>. The contents of
     * the message are not set here; use
     * {@link #setMessage(int, byte[], int) setMessage}
     * to set them subsequently.
     */
    public MetaMessage() {
	//super(defaultMessage);
	this(defaultMessage);
    }


    /**
     * Constructs a new <code>MetaMessage</code>.
     * @param data an array of bytes containing the complete message.
     * The message data may be changed using the <code>setMessage</code>
     * method.
     * @see #setMessage
     */
    protected MetaMessage(byte[] data) {
	super(data);
	//$$fb 2001-10-06: need to calculate dataLength. Fix for bug #4511796
	if (data.length>=3) {
	    dataLength=data.length-3;
	    int pos=2;
	    while (pos<data.length && (data[pos] & 0x80)!=0) {
		dataLength--; pos++;
	    }
	}
    }


    /**
     * Sets the message parameters for a <code>MetaMessage</code>.
     * Since only one status byte value, <code>0xFF</code>, is allowed for meta-messages,
     * it does not need to be specified here.  Calls to <code>{@link MidiMessage#getStatus getStatus}</code> return
     * <code>0xFF</code> for all meta-messages.
     * <p>
     * The <code>type</code> argument should be a valid value for the byte that
     * follows the status byte in the <code>MetaMessage</code>.  The <code>data</code> argument
     * should contain all the subsequent bytes of the <code>MetaMessage</code>.  In other words,
     * the byte that specifies the type of <code>MetaMessage</code> is not considered a data byte.
     *
     * @param type		meta-message type (must be less than 128)
     * @param data		the data bytes in the MIDI message
     * @param length	the number of bytes in the <code>data</code>
     * byte array
     * @throws			<code>InvalidMidiDataException</code>  if the
     * parameter values do not specify a valid MIDI meta message
     */
    public void setMessage(int type, byte[] data, int length) throws InvalidMidiDataException {

	if (type >= 128 || type < 0) {
	    throw new InvalidMidiDataException("Invalid meta event with type " + type);
	}
	if ((length > 0 && length > data.length) || length < 0) {
	    throw new InvalidMidiDataException("length out of bounds: "+length);
	}
	
	this.length = 2 + getVarIntLength(length) + length;
	this.dataLength = length;
	this.data = new byte[this.length];
	this.data[0] = (byte) META;        // status value for MetaMessages (meta events)
	this.data[1] = (byte) type;        // MetaMessage type
	writeVarInt(this.data, 2, length); // write the length as a variable int
	if (length > 0) {
	    System.arraycopy(data, 0, this.data, this.length - this.dataLength, this.dataLength);
	}
    }


    /**
     * Obtains the type of the <code>MetaMessage</code>.
     * @return an integer representing the <code>MetaMessage</code> type
     */
    public int getType() {
	if (length>=2) {
	    return data[1] & 0xFF;
	}
	return 0;
    }



    /**
     * Obtains a copy of the data for the meta message.  The returned
     * array of bytes does not include the status byte or the message
     * length data.  The length of the data for the meta message is
     * the length of the array.  Note that the length of the entire
     * message includes the status byte and the meta message type
     * byte, and therefore may be longer than the returned array.
     * @return array containing the meta message data.
     * @see MidiMessage#getLength
     */
    public byte[] getData() {
	byte[] returnedArray = new byte[dataLength];
	System.arraycopy(data, (length - dataLength), returnedArray, 0, dataLength);
	return returnedArray;
    }


    /**
     * Creates a new object of the same class and with the same contents
     * as this object.
     * @return a clone of this instance
     */
    public Object clone() {
	byte[] newData = new byte[length];
	System.arraycopy(data, 0, newData, 0, newData.length);

	MetaMessage event = new MetaMessage(newData);
	return event;
    }

    // HELPER METHODS

    private int getVarIntLength(long value) {
	int length = 0;
	do {
	    value = value >> 7;
	    length++;
	} while (value > 0);
	return length;
    }
    
    private final static long mask = 0x7F;

    private void writeVarInt(byte[] data, int off, long value) {
    	int shift=63; // number of bitwise left-shifts of mask
    	// first screen out leading zeros
    	while ((shift > 0) && ((value & (mask << shift)) == 0)) shift-=7;
    	// then write actual values
    	while (shift > 0) {
	    data[off++]=(byte) (((value & (mask << shift)) >> shift) | 0x80);
	    shift-=7;
    	}
    	data[off] = (byte) (value & mask);
    }

}

Generated By: JavaOnTracks Doclet 0.1.4     ©Thibaut Colar