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; }