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