// Is called by Java MIDI libraries for each MIDI message encountered. public void send(MidiMessage message, long timeStamp) { if (message.getStatus() > 127 && message.getStatus() < 144) { // Note OFF // Convert the MIDI channel being used to the controller pin on the // Arduino by multipying by 2. byte pin = (byte) (2 * (message.getStatus() - 127)); System.out.println("Got note OFF on pin: " + (pin & 0xFF)); mb.sendEvent(pin, 0); currentPeriod[message.getStatus() - 128] = 0; } else if (message.getStatus() > 143 && message.getStatus() < 160) { // Note ON // Convert the MIDI channel being used to the controller pin on the // Arduino by multipying by 2. byte pin = (byte) (2 * (message.getStatus() - 143)); // Get note number from MIDI message, and look up the period. // NOTE: Java bytes range from -128 to 127, but we need to make them // 0-255 to use for lookups. & 0xFF does the trick. // After looking up the period, devide by (the Arduino resolution * 2). // The Arduino's timer will only tick once per X microseconds based on the // resolution. And each tick will only turn the pin on or off. So a full // on-off cycle (one step on the floppy) is two periods. int period = microPeriods[(message.getMessage()[1] & 0xff)] / (ARDUINO_RESOLUTION * 2); System.out.println("Got note ON on pin: " + (pin & 0xFF) + " with period " + period); System.out.println(message.getLength() + " " + message.getMessage()[message.getLength() - 1]); // Zero velocity events turn off the pin. if (message.getMessage()[2] == 0) { mb.sendEvent(pin, 0); currentPeriod[message.getStatus() - 144] = 0; } else { mb.sendEvent(pin, period); currentPeriod[message.getStatus() - 144] = period; } } else if (message.getStatus() > 223 && message.getStatus() < 240) { // Pitch bends // Only proceed if the note is on (otherwise, no pitch bending) if (currentPeriod[message.getStatus() - 224] != 0) { // Convert the MIDI channel being used to the controller pin on the // Arduino by multipying by 2. byte pin = (byte) (2 * (message.getStatus() - 223)); double pitchBend = ((message.getMessage()[2] & 0xff) << 8) + (message.getMessage()[1] & 0xff); int period = (int) (currentPeriod[message.getStatus() - 224] / Math.pow(2.0, (pitchBend - 8192) / 8192)); System.out.println(currentPeriod[message.getStatus() - 224] + "-" + period); mb.sendEvent(pin, period); } } }
/** return true if the passed message is Meta End Of Track */ public static boolean isMetaEndOfTrack(MidiMessage midiMsg) { // first check if it is a META message at all if (midiMsg.getLength() != 3 || midiMsg.getStatus() != MetaMessage.META) { return false; } // now get message and check for end of track byte[] msg = midiMsg.getMessage(); return ((msg[1] & 0xFF) == META_END_OF_TRACK_TYPE) && (msg[2] == 0); }
/** return if the given message is a meta tempo message */ public static boolean isMetaTempo(MidiMessage midiMsg) { // first check if it is a META message at all if (midiMsg.getLength() != 6 || midiMsg.getStatus() != MetaMessage.META) { return false; } // now get message and check for tempo byte[] msg = midiMsg.getMessage(); // meta type must be 0x51, and data length must be 3 return ((msg[1] & 0xFF) == META_TEMPO_TYPE) && (msg[2] == 3); }
/** * parses this message for a META tempo message and returns the tempo in MPQ, or -1 if this isn't * a tempo message */ public static int getTempoMPQ(MidiMessage midiMsg) { // first check if it is a META message at all if (midiMsg.getLength() != 6 || midiMsg.getStatus() != MetaMessage.META) { return -1; } byte[] msg = midiMsg.getMessage(); if (((msg[1] & 0xFF) != META_TEMPO_TYPE) || (msg[2] != 3)) { return -1; } int tempo = (msg[5] & 0xFF) | ((msg[4] & 0xFF) << 8) | ((msg[3] & 0xFF) << 16); return tempo; }
/** {@inheritDoc} */ public void send(MidiMessage midi, long time) { byte[] msg = midi.getMessage(); int len = midi.getLength(); if (len <= 1) { return; } StringBuilder out = new StringBuilder("Status: "); out.append(msg[0]); out.append(" Data: ["); for (int i = 1; i < len; i++) { out.append(msg[i]); if (i == len - 1) { out.append(""); } else { out.append(','); } } out.append(']'); log.debug(out.toString()); }