KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)Sequence.java 1.27 04/05/05
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.util.Vector JavaDoc;
11 import com.sun.media.sound.MidiUtils;
12
13
14 /**
15  * A <code>Sequence</code> is a data structure containing musical
16  * information (often an entire song or composition) that can be played
17  * back by a <code>{@link Sequencer}</code> object. Specifically, the
18  * <code>Sequence</code> contains timing
19  * information and one or more tracks. Each <code>{@link Track track}</code> consists of a
20  * series of MIDI events (such as note-ons, note-offs, program changes, and meta-events).
21  * The sequence's timing information specifies the type of unit that is used
22  * to time-stamp the events in the sequence.
23  * <p>
24  * A <code>Sequence</code> can be created from a MIDI file by reading the file
25  * into an input stream and invoking one of the <code>getSequence</code> methods of
26  * {@link MidiSystem}. A sequence can also be built from scratch by adding new
27  * <code>Tracks</code> to an empty <code>Sequence</code>, and adding
28  * <code>{@link MidiEvent}</code> objects to these <code>Tracks</code>.
29  *
30  * @see Sequencer#setSequence(java.io.InputStream stream)
31  * @see Sequencer#setSequence(Sequence sequence)
32  * @see Track#add(MidiEvent)
33  * @see MidiFileFormat
34  *
35  * @version 1.27, 04/05/05
36  * @author Kara Kytle
37  */

38 public class Sequence {
39
40
41     // Timing types
42

43     /**
44      * The tempo-based timing type, for which the resolution is expressed in pulses (ticks) per quarter note.
45      * @see #Sequence(float, int)
46      */

47     public static final float PPQ = 0.0f;
48
49     /**
50      * The SMPTE-based timing type with 24 frames per second (resolution is expressed in ticks per frame).
51      * @see #Sequence(float, int)
52      */

53     public static final float SMPTE_24 = 24.0f;
54
55     /**
56      * The SMPTE-based timing type with 25 frames per second (resolution is expressed in ticks per frame).
57      * @see #Sequence(float, int)
58      */

59     public static final float SMPTE_25 = 25.0f;
60
61     /**
62      * The SMPTE-based timing type with 29.97 frames per second (resolution is expressed in ticks per frame).
63      * @see #Sequence(float, int)
64      */

65     public static final float SMPTE_30DROP = 29.97f;
66
67     /**
68      * The SMPTE-based timing type with 30 frames per second (resolution is expressed in ticks per frame).
69      * @see #Sequence(float, int)
70      */

71     public static final float SMPTE_30 = 30.0f;
72
73
74     // Variables
75

76     /**
77      * The timing division type of the sequence.
78      * @see #PPQ
79      * @see #SMPTE_24
80      * @see #SMPTE_25
81      * @see #SMPTE_30DROP
82      * @see #SMPTE_30
83      * @see #getDivisionType
84      */

85     protected float divisionType;
86
87     /**
88      * The timing resolution of the sequence.
89      * @see #getResolution
90      */

91     protected int resolution;
92
93     /**
94      * The MIDI tracks in this sequence.
95      * @see #getTracks
96      */

97     protected Vector JavaDoc<Track JavaDoc> tracks = new Vector JavaDoc<Track JavaDoc>();
98
99
100     /**
101      * Constructs a new MIDI sequence with the specified timing division
102      * type and timing resolution. The division type must be one of the
103      * recognized MIDI timing types. For tempo-based timing,
104      * <code>divisionType</code> is PPQ (pulses per quarter note) and
105      * the resolution is specified in ticks per beat. For SMTPE timing,
106      * <code>divisionType</code> specifies the number of frames per
107      * second and the resolution is specified in ticks per frame.
108      * The sequence will contain no initial tracks. Tracks may be
109      * added to or removed from the sequence using <code>{@link #createTrack}</code>
110      * and <code>{@link #deleteTrack}</code>.
111      *
112      * @param divisionType the timing division type (PPQ or one of the SMPTE types)
113      * @param resolution the timing resolution
114      * @throws InvalidMidiDataException if <code>divisionType</code> is not valid
115      *
116      * @see #PPQ
117      * @see #SMPTE_24
118      * @see #SMPTE_25
119      * @see #SMPTE_30DROP
120      * @see #SMPTE_30
121      * @see #getDivisionType
122      * @see #getResolution
123      * @see #getTracks
124      */

125     public Sequence(float divisionType, int resolution) throws InvalidMidiDataException JavaDoc {
126
127     if (divisionType == PPQ)
128         this.divisionType = PPQ;
129     else if (divisionType == SMPTE_24)
130         this.divisionType = SMPTE_24;
131     else if (divisionType == SMPTE_25)
132         this.divisionType = SMPTE_25;
133     else if (divisionType == SMPTE_30DROP)
134         this.divisionType = SMPTE_30DROP;
135     else if (divisionType == SMPTE_30)
136         this.divisionType = SMPTE_30;
137     else throw new InvalidMidiDataException JavaDoc("Unsupported division type: " + divisionType);
138
139     this.resolution = resolution;
140     }
141
142
143     /**
144      * Constructs a new MIDI sequence with the specified timing division
145      * type, timing resolution, and number of tracks. The division type must be one of the
146      * recognized MIDI timing types. For tempo-based timing,
147      * <code>divisionType</code> is PPQ (pulses per quarter note) and
148      * the resolution is specified in ticks per beat. For SMTPE timing,
149      * <code>divisionType</code> specifies the number of frames per
150      * second and the resolution is specified in ticks per frame.
151      * The sequence will be initialized with the number of tracks specified by
152      * <code>numTracks</code>. These tracks are initially empty (i.e.
153      * they contain only the meta-event End of Track).
154      * The tracks may be retrieved for editing using the <code>{@link #getTracks}</code>
155      * method. Additional tracks may be added, or existing tracks removed,
156      * using <code>{@link #createTrack}</code> and <code>{@link #deleteTrack}</code>.
157      *
158      * @param divisionType the timing division type (PPQ or one of the SMPTE types)
159      * @param resolution the timing resolution
160      * @param numTracks the initial number of tracks in the sequence.
161      * @throws InvalidMidiDataException if <code>divisionType</code> is not valid
162      *
163      * @see #PPQ
164      * @see #SMPTE_24
165      * @see #SMPTE_25
166      * @see #SMPTE_30DROP
167      * @see #SMPTE_30
168      * @see #getDivisionType
169      * @see #getResolution
170      */

171     public Sequence(float divisionType, int resolution, int numTracks) throws InvalidMidiDataException JavaDoc {
172
173     if (divisionType == PPQ)
174         this.divisionType = PPQ;
175     else if (divisionType == SMPTE_24)
176         this.divisionType = SMPTE_24;
177     else if (divisionType == SMPTE_25)
178         this.divisionType = SMPTE_25;
179     else if (divisionType == SMPTE_30DROP)
180         this.divisionType = SMPTE_30DROP;
181     else if (divisionType == SMPTE_30)
182         this.divisionType = SMPTE_30;
183     else throw new InvalidMidiDataException JavaDoc("Unsupported division type: " + divisionType);
184
185     this.resolution = resolution;
186
187     for (int i = 0; i < numTracks; i++) {
188         tracks.addElement(new Track JavaDoc());
189     }
190     }
191
192
193     /**
194      * Obtains the timing division type for this sequence.
195      * @return the division type (PPQ or one of the SMPTE types)
196      *
197      * @see #PPQ
198      * @see #SMPTE_24
199      * @see #SMPTE_25
200      * @see #SMPTE_30DROP
201      * @see #SMPTE_30
202      * @see #Sequence(float, int)
203      * @see MidiFileFormat#getDivisionType()
204      */

205     public float getDivisionType() {
206     return divisionType;
207     }
208
209
210     /**
211      * Obtains the timing resolution for this sequence.
212      * If the sequence's division type is PPQ, the resolution is specified in ticks per beat.
213      * For SMTPE timing, the resolution is specified in ticks per frame.
214      *
215      * @return the number of ticks per beat (PPQ) or per frame (SMPTE)
216      * @see #getDivisionType
217      * @see #Sequence(float, int)
218      * @see MidiFileFormat#getResolution()
219      */

220     public int getResolution() {
221     return resolution;
222     }
223
224
225     /**
226      * Creates a new, initially empty track as part of this sequence.
227      * The track initially contains the meta-event End of Track.
228      * The newly created track is returned. All tracks in the sequence
229      * may be retrieved using <code>{@link #getTracks}</code>. Tracks may be
230      * removed from the sequence using <code>{@link #deleteTrack}</code>.
231      * @return the newly created track
232      */

233     public Track JavaDoc createTrack() {
234
235     Track JavaDoc track = new Track JavaDoc();
236     tracks.addElement(track);
237
238     return track;
239     }
240
241
242     /**
243      * Removes the specified track from the sequence.
244      * @param track the track to remove
245      * @return <code>true</code> if the track existed in the track and was removed,
246      * otherwise <code>false</code>.
247      *
248      * @see #createTrack
249      * @see #getTracks
250      */

251     public boolean deleteTrack(Track JavaDoc track) {
252
253     synchronized(tracks) {
254
255         return tracks.removeElement(track);
256     }
257     }
258
259
260     /**
261      * Obtains an array containing all the tracks in this sequence.
262      * If the sequence contains no tracks, an array of length 0 is returned.
263      * @return the array of tracks
264      *
265      * @see #createTrack
266      * @see #deleteTrack
267      */

268     public Track JavaDoc[] getTracks() {
269
270     return (Track JavaDoc[]) tracks.toArray(new Track JavaDoc[tracks.size()]);
271     }
272
273
274     /**
275      * Obtains the duration of this sequence, expressed in microseconds.
276      * @return this sequence's duration in microseconds.
277      */

278     public long getMicrosecondLength() {
279
280         return com.sun.media.sound.MidiUtils.tick2microsecond(this, getTickLength(), null);
281     }
282
283
284     /**
285      * Obtains the duration of this sequence, expressed in MIDI ticks.
286      *
287      * @return this sequence's length in ticks
288      *
289      * @see #getMicrosecondLength
290      */

291     public long getTickLength() {
292
293     long length = 0;
294
295     synchronized(tracks) {
296
297         for(int i=0; i<tracks.size(); i++ ) {
298         long temp = ((Track JavaDoc)tracks.elementAt(i)).ticks();
299         if( temp>length ) {
300             length = temp;
301         }
302         }
303         return length;
304     }
305     }
306
307
308     /**
309      * Obtains a list of patches referenced in this sequence.
310      * This patch list may be used to load the required
311      * <code>{@link Instrument}</code> objects
312      * into a <code>{@link Synthesizer}</code>.
313      *
314      * @return an array of <code>{@link Patch}</code> objects used in this sequence
315      *
316      * @see Synthesizer#loadInstruments(Soundbank, Patch[])
317      */

318     public Patch JavaDoc[] getPatchList() {
319
320     // $$kk: 04.09.99: need to implement!!
321
return new Patch JavaDoc[0];
322     }
323 }
324
Popular Tags