(max) midi learn and encapsulation

I’m using an example of how to program a MIDI CC learn function to illustrate patcher encapsulation in Max.

CC Learning

MIDI CC learn is a common function in most software synthesizers, whereby you want to assign an external MIDI CC to some software parameter by moving the desired external control (and not having to know or type in the CC number). It’s a handy feature, and one that we can recreate in Max.

Download ccListen.maxpat. The basic idea of the patcher is that you use one ctlin object without an argument in order to get input from all external CC’s. The CC # (sent from second outlet) flows to a ‘set $1’ message, that changes a second ctlin object to only listen to that CC #.

The programming issue is one of automation. You want to specify when to learn a CC # — when to listen — and automatically stop listening once an input has been received. That automation requires a gate, obviously, to turn listening on. To turn listening off, you use the first message through the gate to trigger a bang (any incoming message to a bang causes a ‘bang’ message to be sent). The bang is sent to the toggle, reversing its state and closing the gate. By order of operation, triggering the bang first and sending it to the toggle will close the gate after only one message (the integer representing the CC #) has passed through. After closing the gate, the one message that passed through will be sent to the set message, and on to the second ctlin object.

For additional functionality, I have an integer number object to allow for typing in a CC #. You could use this number object receiving a message from loadmess to initialize the setting. The rest of the patch just allows for some documentation, via the print window, and output of CC value and CC #.


Encapsulation is the process of creating patchers within patchers. It can help to organize your overall patcher layout and function, and create shortcuts that you can reuse in multiple patchers. Download encapsulation.maxpat and ccAssignDemo14.maxpat to follow the presentation below.

The patcher object

Inserting a patcher (p) object creates a new patcher window. The new patcher window functions like any other patcher window, but it is part of the parent patcher. In a locked patcher, double-click the p contlassign object. The window that opens is very similar to the ccLearn patcher from the previous post. The difference is that contlassign has new objects: two inlet and two outlet objects.

Inlet objects within a patcher create object inlets. You use these to pass messages from the parent patcher to the subpatcher. Be sure to open the inlet inspector and add a helpful comment. Comments show up as popup help when you mouse over an inlet. The first inlet of contlassign is to send a bang to turn on the toggle and open the gate to set the CC number to the currently changing CC. The second inlet allows you to just send a number to set the CC #.

Outlets send messages from the subpatcher to the parent patcher. Be sure to comment them as well. The two outlets send the set CC value (the position or value of the controller) and the CC number.

Patcher objects are useful if you think you might want to edit the subpatcher from within the parent patcher. But the contents of the patcher object are only usable within the single parent patcher that the object is in.

Subpatchers as objects

You can save any patcher and then use it as an object within another patcher. Look at the bottom part of encapsulation. ccAssignDemo14 has the exact same contents as contlassign, and functions in the exact same way. But since ccAssignNew is a saved patcher, it can be used repeatedly in any patcher without having to type anything each time it is inserted.

The only small difference is that the inlets and outlets are not numbered. Their relative position is still important, and corresponds to their placement on the object.

Object subpatchers have to be stored in either the same folder as the parent patcher (the parent patchers has to be saved first for this to work), or in a folder that Max searches. If I plan on using an object in many patchers, I store the object patcher in Max/Cycling ’74/max-externals with the other Max objects.


Leave a Reply