////////////////////////////////////////////////////////////////////////////// // Copyright 2011 Alex Leffelman // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. ////////////////////////////////////////////////////////////////////////////// package com.leff.midi.event; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import com.leff.midi.event.meta.MetaEvent; import com.leff.midi.util.VariableLengthInt; public abstract class MidiEvent implements Comparable<MidiEvent> { protected long mTick; protected VariableLengthInt mDelta; public MidiEvent(long tick, long delta) { mTick = tick; mDelta = new VariableLengthInt((int) delta); } public long getTick() { return mTick; } public long getDelta() { return mDelta.getValue(); } public void setDelta(long d) { mDelta.setValue((int) d); } protected abstract int getEventSize(); public int getSize() { return getEventSize() + mDelta.getByteCount(); } public boolean requiresStatusByte(MidiEvent prevEvent) { if(prevEvent == null) { return true; } if(this instanceof MetaEvent) { return true; } if(this.getClass().equals(prevEvent.getClass())) { return false; } return true; } public void writeToFile(OutputStream out, boolean writeType) throws IOException { out.write(mDelta.getBytes()); } private static int sId = -1; private static int sType = -1; private static int sChannel = -1; public static final MidiEvent parseEvent(long tick, long delta, InputStream in) throws IOException { in.mark(1); boolean reset = false; int id = in.read(); if(!verifyIdentifier(id)) { in.reset(); reset = true; } if(sType >= 0x8 && sType <= 0xE) { return ChannelEvent.parseChannelEvent(tick, delta, sType, sChannel, in); } else if(sId == 0xFF) { return MetaEvent.parseMetaEvent(tick, delta, in); } else if(sId == 0xF0 || sId == 0xF7) { VariableLengthInt size = new VariableLengthInt(in); byte[] data = new byte[size.getValue()]; in.read(data); return new SystemExclusiveEvent(sId, tick, delta, data); } else { System.out.println("Unable to handle status byte, skipping: " + sId); if(reset) { in.read(); } } return null; } private static boolean verifyIdentifier(int id) { sId = id; int type = id >> 4; int channel = id & 0x0F; if(type >= 0x8 && type <= 0xE) { sId = id; sType = type; sChannel = channel; } else if(id == 0xFF) { sId = id; sType = -1; sChannel = -1; } else if(type == 0xF) { sId = id; sType = type; sChannel = -1; } else { return false; } return true; } @Override public String toString() { return "" + mTick + " (" + mDelta.getValue() + "): " + this.getClass().getSimpleName(); } }