How to read incoming MIDI messages

First, you must create an object related to the MidiInPort class, such as the classes: MidiInput, MidiIO, Synthesizer, or RadioBaton.

For example, the following line of code creates an object of type MidiInput:

      MidiInput incoming;
The above line of code (probably placed with the global variables) creates an object called "incoming" of the type "MidiInput". The variable name "incoming" is completely arbitrary. You can use any valid variable name in its place.

Secondly, if you are not using the MIDI interfaces in one of the Improv environments, then you should set the MIDI input port. The default port is 0, but you can find out how many MIDI input ports are available by the calling the following function which returns the total number of MIDI inputs available:

      incoming.getNumPorts();
You can then select any one of the ports in the range from 0 to one minus the value returned above. For example if there were two MIDI input ports available, then you can access port 0, or port 1. Here is how you would set the port to port 1 for the "incoming" object:
      incoming.setPort(1);
There is one more step and you will be ready to read MIDI input: By default, the port is not opened automatically, so you will have to specifically tell the "incoming" object to start reading the MIDI input on port 1:
      incoming.open();
Now you are ready to read incoming MIDI messages from the "incoming" object. There is one more useful low-level function which you should know about, however. There is a pause() and unpause() set of functions for MidiInPort objects which is sometime useful. The pause() function will keep the particular port open, but it will no add any incoming messages into the input buffer. This is handy if you want to ignore messages for a short period of time to prevent old MIDI messages in the buffer to be overwritten, as in the following case of a user input:
      incoming.pause();
      cout << "Enter a number for some reason: ";
      cin  >> aUserEnteredNumber;
      incoming.unpause();
So while the user of the program is typing in a number, all MIDI messages coming in are ignored.

Finally, now that you have a working MIDI input object which is actively waiting for MIDI input messages, you can ask the object for a count of how many MIDI messages are waiting in the input buffer with the following command:

      incoming.getCount();
This function call will return the number of messages currently waiting for you in the input buffer. The default size of the buffer is 1024 messages (which should be MORE than enought), but you can change that size with the following command:
      incoming.setBufferSize(47);
which would set the maximum number of input stored messages to 47.

Now suppose that incoming.getCount() returns a non-zero number. That means that there is at least 1 messages waiting in the buffer. To get the message out of the buffer, you use the incoming.extract() command, but first I should explain what form the incoming message is stored in.

MIDI messages are stored in MidiInPort-related classes with the type "MidiMessage" which is a class containing two primary data fields:

  1. a time stamp (a 4-byte integer)
  2. a MIDI data field (a 4-byte integer)
The MIDI data field is further subdivided into 4 separate bytes. The bytes are:
  1. the MIDI command byte
  2. the first parameter byte (if any)
  3. the second parameter byte (if any)
  4. the third parameter byte (if any, although never happens in MIDI protocol -- just empty space (used for incoming sysex buffer location to be written later)

Suppose that I create a MidiMessage object called "aMessage":

      MidiMessage aMessage;
The initial contents of "aMessage" are undefined. but the data can be accessed with the following commands:
aMessage.time returns the time stamp of the message
aMessage.command() returns the MIDI command byte which is a hexadecimal number in the range from 0x80 to 0xFF.
aMessage.p0() Same as the aMessage.command() function call
aMessage.p1() The first parameter byte
aMessage.p2() The second parameter byte
aMessage.p3() The third parameter byte, (used for sysex messages).
aMessage.data a 4-byte number which contains the entire MIDI message.


Anyway, back to the incoming.extract(); command.

If there is a MIDI message in the buffer, then you can get it out of the MIDI input buffer, with the following code:

      aMessage = incoming.extract();
aMessage now contain the extrated Message. Which Message is extracted if there are more than one message in the buffer? The oldest message is extracted.

Suppose that you overflow the input buffer? That is OK in most cases, since the buffer is circular. The most oldest message will be forgotten by the buffer, and the total number of messages will remain constant at the size of the buffer (1024 by default).

Suppose that there are a lot of messages in the input bufferr that you want to skip over. Then you can use the command:

      incoming.clear();
but I haven't added that command yet. For now you can change the size of the buffer and it will remove all of the current messages as a side effect.


Input spoofing


Multiple MIDI input objected connected to a single port



Once you extract a message from the buffer, it is not erased. There is another way to access MIDI messages. This other method is not particularly appropriate in most cases however. You can look at the last written midi message with the index operator:

      incoming[0].time;
The above code for example, would return the time of the most recent midi Message in the buffer.
      incoming[-1].command();
      incoming[1].command();
would return the MIDI command of the second most recent MIDI message in the buffer. This operator[] is not fully implemented yet however.


Higher-level MIDI input interpretation











This How to was last updated: Wed Nov 4 16:43:44 PST 1998
craig@ccrma.stanford.edu