Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/sound/midi/Sequence.java
38830 views
/*1* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.sound.midi;2627import java.util.Vector;28import com.sun.media.sound.MidiUtils;293031/**32* A <code>Sequence</code> is a data structure containing musical33* information (often an entire song or composition) that can be played34* back by a <code>{@link Sequencer}</code> object. Specifically, the35* <code>Sequence</code> contains timing36* information and one or more tracks. Each <code>{@link Track track}</code> consists of a37* series of MIDI events (such as note-ons, note-offs, program changes, and meta-events).38* The sequence's timing information specifies the type of unit that is used39* to time-stamp the events in the sequence.40* <p>41* A <code>Sequence</code> can be created from a MIDI file by reading the file42* into an input stream and invoking one of the <code>getSequence</code> methods of43* {@link MidiSystem}. A sequence can also be built from scratch by adding new44* <code>Tracks</code> to an empty <code>Sequence</code>, and adding45* <code>{@link MidiEvent}</code> objects to these <code>Tracks</code>.46*47* @see Sequencer#setSequence(java.io.InputStream stream)48* @see Sequencer#setSequence(Sequence sequence)49* @see Track#add(MidiEvent)50* @see MidiFileFormat51*52* @author Kara Kytle53*/54public class Sequence {555657// Timing types5859/**60* The tempo-based timing type, for which the resolution is expressed in pulses (ticks) per quarter note.61* @see #Sequence(float, int)62*/63public static final float PPQ = 0.0f;6465/**66* The SMPTE-based timing type with 24 frames per second (resolution is expressed in ticks per frame).67* @see #Sequence(float, int)68*/69public static final float SMPTE_24 = 24.0f;7071/**72* The SMPTE-based timing type with 25 frames per second (resolution is expressed in ticks per frame).73* @see #Sequence(float, int)74*/75public static final float SMPTE_25 = 25.0f;7677/**78* The SMPTE-based timing type with 29.97 frames per second (resolution is expressed in ticks per frame).79* @see #Sequence(float, int)80*/81public static final float SMPTE_30DROP = 29.97f;8283/**84* The SMPTE-based timing type with 30 frames per second (resolution is expressed in ticks per frame).85* @see #Sequence(float, int)86*/87public static final float SMPTE_30 = 30.0f;888990// Variables9192/**93* The timing division type of the sequence.94* @see #PPQ95* @see #SMPTE_2496* @see #SMPTE_2597* @see #SMPTE_30DROP98* @see #SMPTE_3099* @see #getDivisionType100*/101protected float divisionType;102103/**104* The timing resolution of the sequence.105* @see #getResolution106*/107protected int resolution;108109/**110* The MIDI tracks in this sequence.111* @see #getTracks112*/113protected Vector<Track> tracks = new Vector<Track>();114115116/**117* Constructs a new MIDI sequence with the specified timing division118* type and timing resolution. The division type must be one of the119* recognized MIDI timing types. For tempo-based timing,120* <code>divisionType</code> is PPQ (pulses per quarter note) and121* the resolution is specified in ticks per beat. For SMTPE timing,122* <code>divisionType</code> specifies the number of frames per123* second and the resolution is specified in ticks per frame.124* The sequence will contain no initial tracks. Tracks may be125* added to or removed from the sequence using <code>{@link #createTrack}</code>126* and <code>{@link #deleteTrack}</code>.127*128* @param divisionType the timing division type (PPQ or one of the SMPTE types)129* @param resolution the timing resolution130* @throws InvalidMidiDataException if <code>divisionType</code> is not valid131*132* @see #PPQ133* @see #SMPTE_24134* @see #SMPTE_25135* @see #SMPTE_30DROP136* @see #SMPTE_30137* @see #getDivisionType138* @see #getResolution139* @see #getTracks140*/141public Sequence(float divisionType, int resolution) throws InvalidMidiDataException {142143if (divisionType == PPQ)144this.divisionType = PPQ;145else if (divisionType == SMPTE_24)146this.divisionType = SMPTE_24;147else if (divisionType == SMPTE_25)148this.divisionType = SMPTE_25;149else if (divisionType == SMPTE_30DROP)150this.divisionType = SMPTE_30DROP;151else if (divisionType == SMPTE_30)152this.divisionType = SMPTE_30;153else throw new InvalidMidiDataException("Unsupported division type: " + divisionType);154155this.resolution = resolution;156}157158159/**160* Constructs a new MIDI sequence with the specified timing division161* type, timing resolution, and number of tracks. The division type must be one of the162* recognized MIDI timing types. For tempo-based timing,163* <code>divisionType</code> is PPQ (pulses per quarter note) and164* the resolution is specified in ticks per beat. For SMTPE timing,165* <code>divisionType</code> specifies the number of frames per166* second and the resolution is specified in ticks per frame.167* The sequence will be initialized with the number of tracks specified by168* <code>numTracks</code>. These tracks are initially empty (i.e.169* they contain only the meta-event End of Track).170* The tracks may be retrieved for editing using the <code>{@link #getTracks}</code>171* method. Additional tracks may be added, or existing tracks removed,172* using <code>{@link #createTrack}</code> and <code>{@link #deleteTrack}</code>.173*174* @param divisionType the timing division type (PPQ or one of the SMPTE types)175* @param resolution the timing resolution176* @param numTracks the initial number of tracks in the sequence.177* @throws InvalidMidiDataException if <code>divisionType</code> is not valid178*179* @see #PPQ180* @see #SMPTE_24181* @see #SMPTE_25182* @see #SMPTE_30DROP183* @see #SMPTE_30184* @see #getDivisionType185* @see #getResolution186*/187public Sequence(float divisionType, int resolution, int numTracks) throws InvalidMidiDataException {188189if (divisionType == PPQ)190this.divisionType = PPQ;191else if (divisionType == SMPTE_24)192this.divisionType = SMPTE_24;193else if (divisionType == SMPTE_25)194this.divisionType = SMPTE_25;195else if (divisionType == SMPTE_30DROP)196this.divisionType = SMPTE_30DROP;197else if (divisionType == SMPTE_30)198this.divisionType = SMPTE_30;199else throw new InvalidMidiDataException("Unsupported division type: " + divisionType);200201this.resolution = resolution;202203for (int i = 0; i < numTracks; i++) {204tracks.addElement(new Track());205}206}207208209/**210* Obtains the timing division type for this sequence.211* @return the division type (PPQ or one of the SMPTE types)212*213* @see #PPQ214* @see #SMPTE_24215* @see #SMPTE_25216* @see #SMPTE_30DROP217* @see #SMPTE_30218* @see #Sequence(float, int)219* @see MidiFileFormat#getDivisionType()220*/221public float getDivisionType() {222return divisionType;223}224225226/**227* Obtains the timing resolution for this sequence.228* If the sequence's division type is PPQ, the resolution is specified in ticks per beat.229* For SMTPE timing, the resolution is specified in ticks per frame.230*231* @return the number of ticks per beat (PPQ) or per frame (SMPTE)232* @see #getDivisionType233* @see #Sequence(float, int)234* @see MidiFileFormat#getResolution()235*/236public int getResolution() {237return resolution;238}239240241/**242* Creates a new, initially empty track as part of this sequence.243* The track initially contains the meta-event End of Track.244* The newly created track is returned. All tracks in the sequence245* may be retrieved using <code>{@link #getTracks}</code>. Tracks may be246* removed from the sequence using <code>{@link #deleteTrack}</code>.247* @return the newly created track248*/249public Track createTrack() {250251Track track = new Track();252tracks.addElement(track);253254return track;255}256257258/**259* Removes the specified track from the sequence.260* @param track the track to remove261* @return <code>true</code> if the track existed in the track and was removed,262* otherwise <code>false</code>.263*264* @see #createTrack265* @see #getTracks266*/267public boolean deleteTrack(Track track) {268return tracks.removeElement(track);269}270271272/**273* Obtains an array containing all the tracks in this sequence.274* If the sequence contains no tracks, an array of length 0 is returned.275* @return the array of tracks276*277* @see #createTrack278* @see #deleteTrack279*/280public Track[] getTracks() {281// Creation of the non-empty array will be synchronized inside toArray()282return tracks.toArray(new Track[0]);283}284285286/**287* Obtains the duration of this sequence, expressed in microseconds.288* @return this sequence's duration in microseconds.289*/290public long getMicrosecondLength() {291292return com.sun.media.sound.MidiUtils.tick2microsecond(this, getTickLength(), null);293}294295296/**297* Obtains the duration of this sequence, expressed in MIDI ticks.298*299* @return this sequence's length in ticks300*301* @see #getMicrosecondLength302*/303public long getTickLength() {304305long length = 0;306307synchronized(tracks) {308309for(int i=0; i<tracks.size(); i++ ) {310long temp = ((Track)tracks.elementAt(i)).ticks();311if( temp>length ) {312length = temp;313}314}315return length;316}317}318319320/**321* Obtains a list of patches referenced in this sequence.322* This patch list may be used to load the required323* <code>{@link Instrument}</code> objects324* into a <code>{@link Synthesizer}</code>.325*326* @return an array of <code>{@link Patch}</code> objects used in this sequence327*328* @see Synthesizer#loadInstruments(Soundbank, Patch[])329*/330public Patch[] getPatchList() {331332// $$kk: 04.09.99: need to implement!!333return new Patch[0];334}335}336337338