Save This Page
Home » openjdk-7 » javax.sound » midi » [javadoc | source]
    1   /*
    2    * Copyright 1999-2003 Sun Microsystems, Inc.  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.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.sound.midi;
   27   
   28   import java.io.ByteArrayOutputStream;
   29   import java.io.DataOutputStream;
   30   import java.io.IOException;
   31   
   32   
   33   /**
   34    * A <code>MetaMessage</code> is a <code>{@link MidiMessage}</code> that is not meaningful to synthesizers, but
   35    * that can be stored in a MIDI file and interpreted by a sequencer program.
   36    * (See the discussion in the <code>MidiMessage</code>
   37    * class description.)  The Standard MIDI Files specification defines
   38    * various types of meta-events, such as sequence number, lyric, cue point,
   39    * and set tempo.  There are also meta-events
   40    * for such information as lyrics, copyrights, tempo indications, time and key
   41    * signatures, markers, etc.  For more information, see the Standard MIDI Files 1.0
   42    * specification, which is part of the Complete MIDI 1.0 Detailed Specification
   43    * published by the MIDI Manufacturer's Association
   44    * (<a href = http://www.midi.org>http://www.midi.org</a>).
   45    *
   46    * <p>
   47    * When data is being transported using MIDI wire protocol,
   48    * a <code>{@link ShortMessage}</code> with the status value <code>0xFF</code> represents
   49    * a system reset message.  In MIDI files, this same status value denotes a <code>MetaMessage</code>.
   50    * The types of meta-message are distinguished from each other by the first byte
   51    * that follows the status byte <code>0xFF</code>.  The subsequent bytes are data
   52    * bytes.  As with system exclusive messages, there are an arbitrary number of
   53    * data bytes, depending on the type of <code>MetaMessage</code>.
   54    *
   55    * @see MetaEventListener
   56    *
   57    * @author David Rivas
   58    * @author Kara Kytle
   59    */
   60   
   61   public class MetaMessage extends MidiMessage {
   62   
   63   
   64       // Status byte defines
   65   
   66       /**
   67        * Status byte for <code>MetaMessage</code> (0xFF, or 255), which is used
   68        * in MIDI files.  It has the same value as SYSTEM_RESET, which
   69        * is used in the real-time "MIDI wire" protocol.
   70        * @see MidiMessage#getStatus
   71        */
   72       public static final int META                                                = 0xFF; // 255
   73   
   74   
   75       // Default meta message data: just the META status byte value
   76       // $$kk: 09.09.99: need a real event here!!
   77   
   78       private static byte[] defaultMessage                                = { (byte)META, 0 };
   79   
   80   
   81   
   82       // Instance variables
   83   
   84       /**
   85        * The length of the actual message in the data array.
   86        * This is used to determine how many bytes of the data array
   87        * is the message, and how many are the status byte, the
   88        * type byte, and the variable-length-int describing the
   89        * length of the message.
   90        */
   91       private int dataLength = 0;
   92   
   93   
   94       /**
   95        * Constructs a new <code>MetaMessage</code>. The contents of
   96        * the message are not set here; use
   97        * {@link #setMessage(int, byte[], int) setMessage}
   98        * to set them subsequently.
   99        */
  100       public MetaMessage() {
  101           //super(defaultMessage);
  102           this(defaultMessage);
  103       }
  104   
  105   
  106       /**
  107        * Constructs a new <code>MetaMessage</code>.
  108        * @param data an array of bytes containing the complete message.
  109        * The message data may be changed using the <code>setMessage</code>
  110        * method.
  111        * @see #setMessage
  112        */
  113       protected MetaMessage(byte[] data) {
  114           super(data);
  115           //$$fb 2001-10-06: need to calculate dataLength. Fix for bug #4511796
  116           if (data.length>=3) {
  117               dataLength=data.length-3;
  118               int pos=2;
  119               while (pos<data.length && (data[pos] & 0x80)!=0) {
  120                   dataLength--; pos++;
  121               }
  122           }
  123       }
  124   
  125   
  126       /**
  127        * Sets the message parameters for a <code>MetaMessage</code>.
  128        * Since only one status byte value, <code>0xFF</code>, is allowed for meta-messages,
  129        * it does not need to be specified here.  Calls to <code>{@link MidiMessage#getStatus getStatus}</code> return
  130        * <code>0xFF</code> for all meta-messages.
  131        * <p>
  132        * The <code>type</code> argument should be a valid value for the byte that
  133        * follows the status byte in the <code>MetaMessage</code>.  The <code>data</code> argument
  134        * should contain all the subsequent bytes of the <code>MetaMessage</code>.  In other words,
  135        * the byte that specifies the type of <code>MetaMessage</code> is not considered a data byte.
  136        *
  137        * @param type              meta-message type (must be less than 128)
  138        * @param data              the data bytes in the MIDI message
  139        * @param length    the number of bytes in the <code>data</code>
  140        * byte array
  141        * @throws                  <code>InvalidMidiDataException</code>  if the
  142        * parameter values do not specify a valid MIDI meta message
  143        */
  144       public void setMessage(int type, byte[] data, int length) throws InvalidMidiDataException {
  145   
  146           if (type >= 128 || type < 0) {
  147               throw new InvalidMidiDataException("Invalid meta event with type " + type);
  148           }
  149           if ((length > 0 && length > data.length) || length < 0) {
  150               throw new InvalidMidiDataException("length out of bounds: "+length);
  151           }
  152   
  153           this.length = 2 + getVarIntLength(length) + length;
  154           this.dataLength = length;
  155           this.data = new byte[this.length];
  156           this.data[0] = (byte) META;        // status value for MetaMessages (meta events)
  157           this.data[1] = (byte) type;        // MetaMessage type
  158           writeVarInt(this.data, 2, length); // write the length as a variable int
  159           if (length > 0) {
  160               System.arraycopy(data, 0, this.data, this.length - this.dataLength, this.dataLength);
  161           }
  162       }
  163   
  164   
  165       /**
  166        * Obtains the type of the <code>MetaMessage</code>.
  167        * @return an integer representing the <code>MetaMessage</code> type
  168        */
  169       public int getType() {
  170           if (length>=2) {
  171               return data[1] & 0xFF;
  172           }
  173           return 0;
  174       }
  175   
  176   
  177   
  178       /**
  179        * Obtains a copy of the data for the meta message.  The returned
  180        * array of bytes does not include the status byte or the message
  181        * length data.  The length of the data for the meta message is
  182        * the length of the array.  Note that the length of the entire
  183        * message includes the status byte and the meta message type
  184        * byte, and therefore may be longer than the returned array.
  185        * @return array containing the meta message data.
  186        * @see MidiMessage#getLength
  187        */
  188       public byte[] getData() {
  189           byte[] returnedArray = new byte[dataLength];
  190           System.arraycopy(data, (length - dataLength), returnedArray, 0, dataLength);
  191           return returnedArray;
  192       }
  193   
  194   
  195       /**
  196        * Creates a new object of the same class and with the same contents
  197        * as this object.
  198        * @return a clone of this instance
  199        */
  200       public Object clone() {
  201           byte[] newData = new byte[length];
  202           System.arraycopy(data, 0, newData, 0, newData.length);
  203   
  204           MetaMessage event = new MetaMessage(newData);
  205           return event;
  206       }
  207   
  208       // HELPER METHODS
  209   
  210       private int getVarIntLength(long value) {
  211           int length = 0;
  212           do {
  213               value = value >> 7;
  214               length++;
  215           } while (value > 0);
  216           return length;
  217       }
  218   
  219       private final static long mask = 0x7F;
  220   
  221       private void writeVarInt(byte[] data, int off, long value) {
  222           int shift=63; // number of bitwise left-shifts of mask
  223           // first screen out leading zeros
  224           while ((shift > 0) && ((value & (mask << shift)) == 0)) shift-=7;
  225           // then write actual values
  226           while (shift > 0) {
  227               data[off++]=(byte) (((value & (mask << shift)) >> shift) | 0x80);
  228               shift-=7;
  229           }
  230           data[off] = (byte) (value & mask);
  231       }
  232   
  233   }

Save This Page
Home » openjdk-7 » javax.sound » midi » [javadoc | source]