diff options
-rw-r--r-- | src/main/java/com/jsyn/midi/MessageParser.java | 45 | ||||
-rw-r--r-- | src/main/java/com/jsyn/midi/MidiSynthesizer.java | 4 |
2 files changed, 37 insertions, 12 deletions
diff --git a/src/main/java/com/jsyn/midi/MessageParser.java b/src/main/java/com/jsyn/midi/MessageParser.java index d0f5d4d..4ef119a 100644 --- a/src/main/java/com/jsyn/midi/MessageParser.java +++ b/src/main/java/com/jsyn/midi/MessageParser.java @@ -28,44 +28,58 @@ public class MessageParser { private int MASK_14BIT = (1 << 14) - 1; public void parse(byte[] message) { - int status = message[0]; + parse(message, /* offset= */ 0, message.length); + } + + public void parse(byte[] message, int offset, int length) { + checkMessageLength(/* expectedLength= */ 1, length); + int status = message[offset]; int command = status & 0xF0; int channel = status & 0x0F; switch (command) { case MidiConstants.NOTE_ON: - int velocity = message[2]; + checkMessageLength(/* expectedLength= */ 3, length); + int velocity = message[offset + 2]; if (velocity == 0) { - noteOff(channel, message[1], velocity); + noteOff(channel, message[offset + 1], velocity); } else { - noteOn(channel, message[1], velocity); + noteOn(channel, message[offset + 1], velocity); } break; case MidiConstants.NOTE_OFF: - noteOff(channel, message[1], message[2]); + checkMessageLength(/* expectedLength= */ 3, length); + noteOff(channel, message[offset + 1], message[offset + 2]); break; case MidiConstants.POLYPHONIC_AFTERTOUCH: - polyphonicAftertouch(channel, message[1], message[2]); + checkMessageLength(/* expectedLength= */ 3, length); + polyphonicAftertouch(channel, message[offset + 1], message[offset + 2]); break; case MidiConstants.CHANNEL_PRESSURE: - channelPressure(channel, message[1]); + checkMessageLength(/* expectedLength= */ 2, length); + channelPressure(channel, message[offset + 1]); break; case MidiConstants.CONTROL_CHANGE: - rawControlChange(channel, message[1], message[2]); + checkMessageLength(/* expectedLength= */ 3, length); + rawControlChange(channel, message[offset + 1], message[offset + 2]); break; case MidiConstants.PROGRAM_CHANGE: - programChange(channel, message[1]); + checkMessageLength(/* expectedLength= */ 2, length); + programChange(channel, message[offset + 1]); break; case MidiConstants.PITCH_BEND: - int bend = (message[2] << 7) + message[1]; + checkMessageLength(/* expectedLength= */ 3, length); + int bend = (message[offset + 2] << 7) + message[offset + 1]; pitchBend(channel, bend); break; + default: + break; // We ignore unsupported commands. } } @@ -117,6 +131,17 @@ public class MessageParser { } } + private void checkMessageLength(int expectedLength, int actualLength) { + if (actualLength < expectedLength) { + throw new IllegalArgumentException( + "Expected message of at least " + + expectedLength + + " bytes but got " + + actualLength + + " bytes."); + } + } + public void nonRegisteredParameter(int channel, int index14, int value14) { } diff --git a/src/main/java/com/jsyn/midi/MidiSynthesizer.java b/src/main/java/com/jsyn/midi/MidiSynthesizer.java index 1f5485c..86834d7 100644 --- a/src/main/java/com/jsyn/midi/MidiSynthesizer.java +++ b/src/main/java/com/jsyn/midi/MidiSynthesizer.java @@ -110,8 +110,8 @@ public class MidiSynthesizer extends MessageParser { multiSynth.setPitchBend(channel, offset); } - public void onReceive(byte[] bytes, int i, int length) { - parse(bytes); // TODO + public void onReceive(byte[] bytes, int offset, int length) { + parse(bytes, offset, length); } } |