Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/sound/midi/Sequence.java
38830 views
1
/*
2
* Copyright (c) 1999, 2016, 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
import java.util.Vector;
29
import com.sun.media.sound.MidiUtils;
30
31
32
/**
33
* A <code>Sequence</code> is a data structure containing musical
34
* information (often an entire song or composition) that can be played
35
* back by a <code>{@link Sequencer}</code> object. Specifically, the
36
* <code>Sequence</code> contains timing
37
* information and one or more tracks. Each <code>{@link Track track}</code> consists of a
38
* series of MIDI events (such as note-ons, note-offs, program changes, and meta-events).
39
* The sequence's timing information specifies the type of unit that is used
40
* to time-stamp the events in the sequence.
41
* <p>
42
* A <code>Sequence</code> can be created from a MIDI file by reading the file
43
* into an input stream and invoking one of the <code>getSequence</code> methods of
44
* {@link MidiSystem}. A sequence can also be built from scratch by adding new
45
* <code>Tracks</code> to an empty <code>Sequence</code>, and adding
46
* <code>{@link MidiEvent}</code> objects to these <code>Tracks</code>.
47
*
48
* @see Sequencer#setSequence(java.io.InputStream stream)
49
* @see Sequencer#setSequence(Sequence sequence)
50
* @see Track#add(MidiEvent)
51
* @see MidiFileFormat
52
*
53
* @author Kara Kytle
54
*/
55
public class Sequence {
56
57
58
// Timing types
59
60
/**
61
* The tempo-based timing type, for which the resolution is expressed in pulses (ticks) per quarter note.
62
* @see #Sequence(float, int)
63
*/
64
public static final float PPQ = 0.0f;
65
66
/**
67
* The SMPTE-based timing type with 24 frames per second (resolution is expressed in ticks per frame).
68
* @see #Sequence(float, int)
69
*/
70
public static final float SMPTE_24 = 24.0f;
71
72
/**
73
* The SMPTE-based timing type with 25 frames per second (resolution is expressed in ticks per frame).
74
* @see #Sequence(float, int)
75
*/
76
public static final float SMPTE_25 = 25.0f;
77
78
/**
79
* The SMPTE-based timing type with 29.97 frames per second (resolution is expressed in ticks per frame).
80
* @see #Sequence(float, int)
81
*/
82
public static final float SMPTE_30DROP = 29.97f;
83
84
/**
85
* The SMPTE-based timing type with 30 frames per second (resolution is expressed in ticks per frame).
86
* @see #Sequence(float, int)
87
*/
88
public static final float SMPTE_30 = 30.0f;
89
90
91
// Variables
92
93
/**
94
* The timing division type of the sequence.
95
* @see #PPQ
96
* @see #SMPTE_24
97
* @see #SMPTE_25
98
* @see #SMPTE_30DROP
99
* @see #SMPTE_30
100
* @see #getDivisionType
101
*/
102
protected float divisionType;
103
104
/**
105
* The timing resolution of the sequence.
106
* @see #getResolution
107
*/
108
protected int resolution;
109
110
/**
111
* The MIDI tracks in this sequence.
112
* @see #getTracks
113
*/
114
protected Vector<Track> tracks = new Vector<Track>();
115
116
117
/**
118
* Constructs a new MIDI sequence with the specified timing division
119
* type and timing resolution. The division type must be one of the
120
* recognized MIDI timing types. For tempo-based timing,
121
* <code>divisionType</code> is PPQ (pulses per quarter note) and
122
* the resolution is specified in ticks per beat. For SMTPE timing,
123
* <code>divisionType</code> specifies the number of frames per
124
* second and the resolution is specified in ticks per frame.
125
* The sequence will contain no initial tracks. Tracks may be
126
* added to or removed from the sequence using <code>{@link #createTrack}</code>
127
* and <code>{@link #deleteTrack}</code>.
128
*
129
* @param divisionType the timing division type (PPQ or one of the SMPTE types)
130
* @param resolution the timing resolution
131
* @throws InvalidMidiDataException if <code>divisionType</code> is not valid
132
*
133
* @see #PPQ
134
* @see #SMPTE_24
135
* @see #SMPTE_25
136
* @see #SMPTE_30DROP
137
* @see #SMPTE_30
138
* @see #getDivisionType
139
* @see #getResolution
140
* @see #getTracks
141
*/
142
public Sequence(float divisionType, int resolution) throws InvalidMidiDataException {
143
144
if (divisionType == PPQ)
145
this.divisionType = PPQ;
146
else if (divisionType == SMPTE_24)
147
this.divisionType = SMPTE_24;
148
else if (divisionType == SMPTE_25)
149
this.divisionType = SMPTE_25;
150
else if (divisionType == SMPTE_30DROP)
151
this.divisionType = SMPTE_30DROP;
152
else if (divisionType == SMPTE_30)
153
this.divisionType = SMPTE_30;
154
else throw new InvalidMidiDataException("Unsupported division type: " + divisionType);
155
156
this.resolution = resolution;
157
}
158
159
160
/**
161
* Constructs a new MIDI sequence with the specified timing division
162
* type, timing resolution, and number of tracks. The division type must be one of the
163
* recognized MIDI timing types. For tempo-based timing,
164
* <code>divisionType</code> is PPQ (pulses per quarter note) and
165
* the resolution is specified in ticks per beat. For SMTPE timing,
166
* <code>divisionType</code> specifies the number of frames per
167
* second and the resolution is specified in ticks per frame.
168
* The sequence will be initialized with the number of tracks specified by
169
* <code>numTracks</code>. These tracks are initially empty (i.e.
170
* they contain only the meta-event End of Track).
171
* The tracks may be retrieved for editing using the <code>{@link #getTracks}</code>
172
* method. Additional tracks may be added, or existing tracks removed,
173
* using <code>{@link #createTrack}</code> and <code>{@link #deleteTrack}</code>.
174
*
175
* @param divisionType the timing division type (PPQ or one of the SMPTE types)
176
* @param resolution the timing resolution
177
* @param numTracks the initial number of tracks in the sequence.
178
* @throws InvalidMidiDataException if <code>divisionType</code> is not valid
179
*
180
* @see #PPQ
181
* @see #SMPTE_24
182
* @see #SMPTE_25
183
* @see #SMPTE_30DROP
184
* @see #SMPTE_30
185
* @see #getDivisionType
186
* @see #getResolution
187
*/
188
public Sequence(float divisionType, int resolution, int numTracks) throws InvalidMidiDataException {
189
190
if (divisionType == PPQ)
191
this.divisionType = PPQ;
192
else if (divisionType == SMPTE_24)
193
this.divisionType = SMPTE_24;
194
else if (divisionType == SMPTE_25)
195
this.divisionType = SMPTE_25;
196
else if (divisionType == SMPTE_30DROP)
197
this.divisionType = SMPTE_30DROP;
198
else if (divisionType == SMPTE_30)
199
this.divisionType = SMPTE_30;
200
else throw new InvalidMidiDataException("Unsupported division type: " + divisionType);
201
202
this.resolution = resolution;
203
204
for (int i = 0; i < numTracks; i++) {
205
tracks.addElement(new Track());
206
}
207
}
208
209
210
/**
211
* Obtains the timing division type for this sequence.
212
* @return the division type (PPQ or one of the SMPTE types)
213
*
214
* @see #PPQ
215
* @see #SMPTE_24
216
* @see #SMPTE_25
217
* @see #SMPTE_30DROP
218
* @see #SMPTE_30
219
* @see #Sequence(float, int)
220
* @see MidiFileFormat#getDivisionType()
221
*/
222
public float getDivisionType() {
223
return divisionType;
224
}
225
226
227
/**
228
* Obtains the timing resolution for this sequence.
229
* If the sequence's division type is PPQ, the resolution is specified in ticks per beat.
230
* For SMTPE timing, the resolution is specified in ticks per frame.
231
*
232
* @return the number of ticks per beat (PPQ) or per frame (SMPTE)
233
* @see #getDivisionType
234
* @see #Sequence(float, int)
235
* @see MidiFileFormat#getResolution()
236
*/
237
public int getResolution() {
238
return resolution;
239
}
240
241
242
/**
243
* Creates a new, initially empty track as part of this sequence.
244
* The track initially contains the meta-event End of Track.
245
* The newly created track is returned. All tracks in the sequence
246
* may be retrieved using <code>{@link #getTracks}</code>. Tracks may be
247
* removed from the sequence using <code>{@link #deleteTrack}</code>.
248
* @return the newly created track
249
*/
250
public Track createTrack() {
251
252
Track track = new Track();
253
tracks.addElement(track);
254
255
return track;
256
}
257
258
259
/**
260
* Removes the specified track from the sequence.
261
* @param track the track to remove
262
* @return <code>true</code> if the track existed in the track and was removed,
263
* otherwise <code>false</code>.
264
*
265
* @see #createTrack
266
* @see #getTracks
267
*/
268
public boolean deleteTrack(Track track) {
269
return tracks.removeElement(track);
270
}
271
272
273
/**
274
* Obtains an array containing all the tracks in this sequence.
275
* If the sequence contains no tracks, an array of length 0 is returned.
276
* @return the array of tracks
277
*
278
* @see #createTrack
279
* @see #deleteTrack
280
*/
281
public Track[] getTracks() {
282
// Creation of the non-empty array will be synchronized inside toArray()
283
return tracks.toArray(new Track[0]);
284
}
285
286
287
/**
288
* Obtains the duration of this sequence, expressed in microseconds.
289
* @return this sequence's duration in microseconds.
290
*/
291
public long getMicrosecondLength() {
292
293
return com.sun.media.sound.MidiUtils.tick2microsecond(this, getTickLength(), null);
294
}
295
296
297
/**
298
* Obtains the duration of this sequence, expressed in MIDI ticks.
299
*
300
* @return this sequence's length in ticks
301
*
302
* @see #getMicrosecondLength
303
*/
304
public long getTickLength() {
305
306
long length = 0;
307
308
synchronized(tracks) {
309
310
for(int i=0; i<tracks.size(); i++ ) {
311
long temp = ((Track)tracks.elementAt(i)).ticks();
312
if( temp>length ) {
313
length = temp;
314
}
315
}
316
return length;
317
}
318
}
319
320
321
/**
322
* Obtains a list of patches referenced in this sequence.
323
* This patch list may be used to load the required
324
* <code>{@link Instrument}</code> objects
325
* into a <code>{@link Synthesizer}</code>.
326
*
327
* @return an array of <code>{@link Patch}</code> objects used in this sequence
328
*
329
* @see Synthesizer#loadInstruments(Soundbank, Patch[])
330
*/
331
public Patch[] getPatchList() {
332
333
// $$kk: 04.09.99: need to implement!!
334
return new Patch[0];
335
}
336
}
337
338