@SuppressWarnings({"rawtypes", "unchecked"}) private static void noteOn( int phrIndex, Note[] curNote, SMFTools smf, int i, double[] currentLength, double startTime, Vector phrVct, short midiChannel, short pitch, int dynamic, Vector evtList) { phrIndex = -1; // work out what phrase is ready to accept a note for (int p = 0; p < phrVct.size(); p++) { // Warning 0.02 should really be fixed if (currentLength[p] <= (startTime + 0.08)) { phrIndex = p; break; } } // need to create new phrase for a new voice? if (phrIndex == -1) { phrIndex = phrVct.size(); phrVct.addElement(new Phrase(startTime)); currentLength[phrIndex] = startTime; } // Do we need to add a rest ? if ((startTime > currentLength[phrIndex]) && (curNote[phrIndex] != null)) { double newTime = startTime - currentLength[phrIndex]; // perform a level of quantisation first if (newTime < 0.25) { double length = curNote[phrIndex].getRhythmValue(); curNote[phrIndex].setRhythmValue(length + newTime); } else { Note restNote = new Note(REST, newTime, 0); restNote.setPan(midiChannel); restNote.setDuration(newTime); restNote.setOffset(0.0); ((Phrase) phrVct.elementAt(phrIndex)).addNote(restNote); } currentLength[phrIndex] += newTime; } // get end time double time = MidiUtil.getEndEvt(pitch, evtList, i) / (double) smf.getPPQN(); // create the new note Note tempNote = new Note(pitch, time, dynamic); tempNote.setDuration(time); curNote[phrIndex] = tempNote; ((Phrase) phrVct.elementAt(phrIndex)).addNote(curNote[phrIndex]); currentLength[phrIndex] += curNote[phrIndex].getRhythmValue(); }
/** * 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; // 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 = jm.midi.MidiUtil.createMetaEvent(type); } else if (status >= 0xF0) { // System Exclusive --- NOT // SUPPORTED 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); if (evt == null) { throw new IOException("MIDI file read error: invalid voice event type!"); } evt.setMidiChannel(midiChannel); event = evt; } oldStatus = status; } catch (EOFException ex) { logger.warn("EOFException (" + ex.getMessage() + ") encountered in SMFTools"); } catch (Exception e) { throw new IllegalStateException(e); } if (event != null) { // read data into the new event and // add the new event to the Track object event.setTime(deltaTime); event.read(dis); track.addEvent(event); // event.print(); if (event instanceof EndTrack) break; } else { // skip the stream ahead to next valid event dis.skipBytes(eventLength); } } }