private void readTrack(DataInputStream dataInputStream, Track track)
     throws InvalidMidiDataException, IOException {
   // search for a "MTrk" chunk
   while (true) {
     int nMagic = dataInputStream.readInt();
     if (nMagic == MidiConstants.TRACK_MAGIC) {
       break;
     }
     int nChunkLength = dataInputStream.readInt();
     if (nChunkLength % 2 != 0) {
       nChunkLength++;
     }
     dataInputStream.skip(nChunkLength);
   }
   int nTrackChunkLength = dataInputStream.readInt();
   long lTicks = 0;
   long[] alRemainingBytes = new long[1];
   alRemainingBytes[0] = nTrackChunkLength;
   int[] anRunningStatusByte = new int[1];
   // indicates no running status in effect
   anRunningStatusByte[0] = -1;
   while (alRemainingBytes[0] > 0) {
     long lDeltaTicks = readVariableLengthQuantity(dataInputStream, alRemainingBytes);
     // TDebug.out("delta ticks: " + lDeltaTicks);
     lTicks += lDeltaTicks;
     MidiEvent event = readEvent(dataInputStream, alRemainingBytes, anRunningStatusByte, lTicks);
     track.add(event);
   }
 }
  public MidiFileFormat getMidiFileFormat(InputStream inputStream)
      throws InvalidMidiDataException, IOException {
    DataInputStream dataInputStream = new DataInputStream(inputStream);
    int nHeaderMagic = dataInputStream.readInt();
    if (nHeaderMagic != MidiConstants.HEADER_MAGIC) {
      throw new InvalidMidiDataException("not a MIDI file: wrong header magic");
    }
    int nHeaderLength = dataInputStream.readInt();
    if (nHeaderLength < 6) {
      throw new InvalidMidiDataException("corrupt MIDI file: wrong header length");
    }
    int nType = dataInputStream.readShort();
    if (nType < 0 || nType > 2) {
      throw new InvalidMidiDataException("corrupt MIDI file: illegal type");
    }
    if (nType == 2) {
      throw new InvalidMidiDataException("this implementation doesn't support type 2 MIDI files");
    }
    int nNumTracks = dataInputStream.readShort();
    if (nNumTracks <= 0) {
      throw new InvalidMidiDataException("corrupt MIDI file: number of tracks must be positive");
    }
    if (nType == 0 && nNumTracks != 1) {
      throw new InvalidMidiDataException(
          "corrupt MIDI file:  type 0 files must contain exactely one track");
    }
    int nDivision = dataInputStream.readUnsignedShort();
    float fDivisionType = -1.0F;
    int nResolution = -1;
    if ((nDivision & 0x8000) != 0) // frame division
    {
      int nFrameType = -((nDivision >>> 8) & 0xFF);
      switch (nFrameType) {
        case 24:
          fDivisionType = Sequence.SMPTE_24;
          break;

        case 25:
          fDivisionType = Sequence.SMPTE_25;
          break;

        case 29:
          fDivisionType = Sequence.SMPTE_30DROP;
          break;

        case 30:
          fDivisionType = Sequence.SMPTE_30;
          break;

        default:
          throw new InvalidMidiDataException("corrupt MIDI file: illegal frame division type");
      }
      nResolution = nDivision & 0xff;
    } else // BPM division
    {
      fDivisionType = Sequence.PPQ;
      nResolution = nDivision & 0x7fff;
    }
    // skip additional bytes in the header
    dataInputStream.skip(nHeaderLength - 6);
    MidiFileFormat midiFileFormat =
        new TMidiFileFormat(
            nType,
            fDivisionType,
            nResolution,
            MidiFileFormat.UNKNOWN_LENGTH,
            MidiFileFormat.UNKNOWN_LENGTH,
            nNumTracks);
    return midiFileFormat;
  }