/** * Read from a standard MIDI file * * @params InputStream - the datasource to read from * @params Score score - the score to place jMusic data translation into * @exception IOException - any IO problems */ public void read(InputStream is) throws IOException { // Given the small size of MIDI files read all // data into a ByteArrayStream for further processing byte[] fileData = new byte[is.available()]; is.read(fileData); ByteArrayInputStream bais = new ByteArrayInputStream(fileData); DataInputStream dis = new DataInputStream(bais); // clear any SMF data if (!this.trackList.isEmpty()) { this.trackList.removeAllElements(); // remove any previous tracks } // check header for MIDIfile validity if (dis.readInt() != 0x4D546864) { // Check for MIDI track validity throw new IOException("This is NOT a MIDI file !!!"); } else { // If MIDI file passes skip length bytes dis.readInt(); // skip over Length info } // get SMF Class data try { fileType = dis.readShort(); if (VERBOSE) System.out.println("MIDI file type = " + fileType); this.numOfTracks = dis.readShort(); if (VERBOSE) System.out.println("Number of tracks = " + numOfTracks); this.ppqn = dis.readShort(); if (VERBOSE) System.out.println("ppqn = " + ppqn); } catch (IOException e) { System.out.println(e); e.printStackTrace(); } // skip the tempo track fro type 1 files /* if(fileType == 1) { skipATrack(dis); numOfTracks--; } */ // Read all track chunks for (int i = 0; i < numOfTracks; i++) { readTrackChunk(dis); } is.close(); dis.close(); }
/** * Reads a MIDI track chunk * * @param DataInputStream dis - the input stream to read from * @exception IOException */ private void readTrackChunk(DataInputStream dis) throws IOException { // local variables for Track class Track track = new Track(); // Insert new Track into a list of tracks this.trackList.addElement(track); int deltaTime = 0; if (VERBOSE) System.out.println("Reading Track .........."); // Read track header if (dis.readInt() != 0x4D54726B) { // If MTrk read is wrong throw new IOException("Track started in wrong place!!!! ABORTING"); } else { // If MTrk read ok get bytesRemaining dis.readInt(); } // loop variables int status, oldStatus = 0, eventLength = 0; // Start gathering event data Event event = null; while (true) { try { // get variable length timestamp deltaTime = MidiUtil.readVarLength(dis); // mark stream so we can return if we need running status dis.mark(2); status = dis.readUnsignedByte(); // decide on running status if (status < 0x80) { // set running status status = oldStatus; // return stream to before status read dis.reset(); } // create default event of correct type if (status >= 0xFF) { // Meta Event int type = dis.readUnsignedByte(); eventLength = MidiUtil.readVarLength(dis); event = MidiUtil.createMetaEvent(type); } else if (status >= 0xF0) { // System Exclusive --- NOT SUPPORTED System.out.println("SysEX---"); eventLength = MidiUtil.readVarLength(dis); } else if (status >= 0x80) { // MIDI voice event short selection = (short) (status / 0x10); short midiChannel = (short) (status - (selection * 0x10)); VoiceEvt evt = (VoiceEvt) MidiUtil.createVoiceEvent(selection); evt.setMidiChannel(midiChannel); event = evt; if (event == null) { throw new IOException("MIDI file read error: invalid voice event type!"); } } oldStatus = status; } catch (Exception e) { e.printStackTrace(); System.exit(1); } if (event != null) { // read data into the new event and // add the new event to the Track object event.setTime(deltaTime); event.read(dis); // if (VERBOSE) event.print(); track.addEvent(event); // event.print(); if (event instanceof EndTrack) break; } else { // skip the stream ahead to next valid event dis.skipBytes(eventLength); } } }