This tutorial will cover some of the basics of using the MIDI (Musical Instrument Digital Interface) communications protocol. We will see how to receive MIDI information from input devices, send it to other hardware or software and select the device that will get the sent information.
While the prevalence of software-only music systems have reduced the need for MIDI devices, the MIDI protocol is still necessary for working with both hardware and software synthesizers and samplers. MIDI is also becoming more widely used by artists working with physical interfaces, since it provides a compact and easy-to-use communications protocol for receiving sensor information and producing control messages for motors and other controllable devices.
The tutorial patcher contains a number of small MIDI-specific patches. The left-most patch changes a
number box anytime information is received from a MIDI input device (via the
midiin object), then sends that information out to another MIDI device (through the
midiout object). However, you need to select which device will be used for MIDI input and output. A simple way select a MIDI device is to double-click on the MIDI object you want to assign. Double-clicking on the
midiin object produces a menu of available MIDI
inputs, while double-clicking on the
midiout object will display a menu of MIDI
outputs.
In addition to the physical MIDI devices that are connected to your computer, you will also see some virtual MIDI ports, depending on your operating system and how it's configured. One of the most useful virtual ports is the built-in synthesizer output – it allows you to generate sounds from MIDI messages without having to connect a physical synthesizer or sampler.
If you select a MIDI input keyboard for the
midiin object, and the built-in synthesizer for output, you have a simple MIDI
thru application with very little patching. The
midiin and
midiout objects pass out and expect unformatted
raw MIDI messages – if you route the output of the
midiin object to a print object, you will see that you have a serial stream of numbers that can be difficult to interpret. Max contains a number of objects that give us a little more control how we use MIDI data inside out program by selecting which
types of MIDI events (notes, continuous controllers, etc.) we want to work with.
The
notein and
noteout objects are an example of
message-specific MIDI objects. They accept the input of a MIDI stream, and ignore all message types other than
note messages - those traditionally caused by playing keys on a MIDI keyboard or pads on a drum trigger. As with the
midiin and
midiout objects, we can select the MIDI port by double-clicking on the object.
The second patch shows a basic note display; we can select a MIDI port, then view the notes that are received on that port. The
notein object displays three pieces of information for each incoming note message: the note
number (or
pitch), the note
velocity and the MIDI channel it was transmitted on. Play a MIDI keyboard or other controller that creates MIDI note messages, and see how the note information is displayed by the
number boxes.
You will notice that there is no “on or off” display to differentiate keys being played (a "note-on") and keys being released (a "note-off") – rather, a note-off message is displayed as a note with a velocity of zero (
0). This is a common MIDI convention, and it is used by many Max objects as the preferred way of displaying a note-off message. We have also used a
number box with the
Display Format attribute set to
MIDI. This provides us with an easily-read cue as to the pitch of the note that is being played.
The next patch is a simple example of the reverse process:
generating note messages to be played by a MIDI device. The
noteout object expects
pitch,
velocity, and
channel numbers to be received in its left, center, and right inlets, respectively. The left inlet (
pitch) is
hot, while the others are cold. In this case, we use Max’s ability to decode a
list of messages as the input to all of the inlets of an object. Thus, the
message box labeled
64 100 0 is treated like three separate messages to each inlet: they are “channel 0”, “velocity 100” and “note 64”. This will send a note-on message for pitch
64 (
E3) at a velocity of
100 to channel
0. The second
message box is almost the same, but uses a velocity of
0 – which is the equivalent of a note-off message. Double-click on the
noteout object, and select a valid MIDI output device. Then click on the first
message box. You should hear the device sound the note. It should sustain until you hit the second
message box, which will turn it off. This is a basic MIDI note event structure, and can be used as the basis for generating MIDI messages that play music.
The right-most patch is a simple version of an application that
remaps MIDI controller data: it changes any modulation wheel control value (by convention, MIDI controller
1) into a pan control value (controller
10). In this case, the
ctlin and
ctlout objects are used for receiving and sending MIDI continuous controller messages. These objects are message-specific MIDI object dedicated to MIDI controller values which are often sent by MIDI fader boxes and knob/rotary controllers, as well as more music-centric interfaces such as keyboard sustain pedals. As with the other objects, you can double-click them to set a MIDI port for use.
The incoming values are used to set up the control system. The patch uses the incoming controller number (the middle outlet of
ctlin) to determine the routing of a graphical gate (
gswitch2) object. When controller
1 is seen, the
== object outputs a
1, which sets the the switch to allow the controller value (the
left outlet) to go into the subsequent
message box. This value is then assembled into a valid message for
ctlout, which will send the value (assigned to MIDI controller
10 on channel
0) to the selected MIDI output.
There is a little extra programming attached to the
ctlout object: a
button is connected to a
midiinfo object, which loads a
umenu object with some data when it receives a
bang message. This data is fed into the
ctlout object. What is this about?
Sometimes, you don’t want the end user of your patch to have to double-click the MIDI objects to set a port, or you may want to set the port on many objects simultaneously. The
midiinfo object provides a lot of information on your current MIDI setup, which you can use to set the port information on your MIDI objects. In this case, when the
midiinfo object receives a
bang message in its
left inlet, it produces the names of the available MIDI
output ports currently defined on your system. This is used to load the
umenu object with your current MIDI setup. When you select an item from the menu, it is sent to the
ctlout object as an identifier of the port you want to use.
This is just one of the uses of the
midiinfo object; we will see other uses in upcoming tutorials. If you want to query your computer for information about available MIDI ports and available controllers, review the
midiinfo help files and reference pages.
In order to exercise the MIDI message tools, let’s create a basic MIDI monitoring application. We can start by creating a version of the
midiinfo/
umenu combination that will show available MIDI
inputs. In order to see the inputs, we need to send a
bang message into the
right inlet of the
midiinfo object. You can do this with a
button object, or use a
loadbang object so the menu will be loaded each time the patch is loaded.
In order to track both note and controller information, we can send the output of the
umenu to both a
notein and
ctlin object. This sets up the two objects to receive MIDI information from the same MIDI port. Now, connect
number boxes to each of the outlets of the
notein and
ctlin objects. We can probably have a single
number box share the “channel” messages, since we won’t have notes and controllers being generated at the same time. Finally, changing the note
number box to use a
Display Format of MIDI will allow us to easily see the key of the depressed note.
While this is a fairly simple MIDI monitor application, it is the sort of application that can help you debug a complex MIDI setup. You can expand this patch by using other MIDI message-specific objects, such as
pgmin (MIDI program changes) and
bendin (MIDI pitch bend messages), to see even more of the received MIDI data stream.
The basic contents of an incoming MIDI stream can be retrieved using the
midiin object, and a MIDI stream can be sent using the
midiout object. However, in most cases, it is easier to deal with individual message types using their message-specific objects. The
notein/
noteout and
ctlin/
ctlout objects provide an easy way to deal with messages without having to decode the raw MIDI input or create raw MIDI output.
The
midiinfo object, is a powerful tool for examining the current state of your MIDI setup. Using it to load a menu of available MIDI ports can help make your patch easier to use and is also the best way to set a number of objects simultaneously.
See Also
Name |
Description |
midiin |
Output received raw MIDI data
|
midiout |
Transmit raw MIDI data
|
notein |
Output received MIDI note messages
|
noteout |
Transmit MIDI note messages
|
ctlin |
Output received MIDI control values
|
ctlout |
Transmit MIDI control messages
|
midiinfo |
Set a pop-up menu with names of MIDI devices
|
gswitch2 |
Pass the input out one of two outlets
|