This tutorial covers two of the most useful objects in the Max world: coll
. The coll
object allows for the indexed collection of data; you can think of it as a small and fast database for message data. The route
object is also tied to the concept of indexing – it will send data out of a specific outlet based on the index (first entry) of a list.
data is very useful for complex routing of information. Often data is already indexed for you: MIDI controllers normally index the value with the controller number, while note information is often indexed by the MIDI channel. Using indexing for data can also help when sending messages throughout a complex patch – by creating an indexing system, you can send data around indiscriminately, and have the route
object find and decode the data as necessary.
There are several small- to medium-sized patches scattered throughout the interface for this tutorial. We will be starting with the patch at the top-left side.
The first patch (labeled 1
) introduces the coll
object. Three message
boxes are connected to it. If you click all three, you will load the coll
object with three value sets. The easiest way to see what is stored in the coll
is to double-click on it; it will open an editing window that will show you that the first number was stored as an index
, and the second number was stored as a value
. To programmatically retrieve a value, you send an index value into the inlet – the output will be the value (or values) stored at that index location. If you use the number
box to send a to the coll
object, it will output (the value at index location 0); and will output and respectively. This is the most basic, and most common, use of the coll
object – as a storage mechanism for indexed value sets.
The patch labeled 2
is slightly different in that it uses symbols
, rather than numbers, as the index value. Click on the three message
boxes, and again double-click on the coll
to see the stored data. The data is similar to the first coll
, but the indexes are symbols (words) rather than numbers. Now, if you click on the message
boxes to the left ( , , ), the coll
object will output the correct value for each of the symbols.
The third patch (labeled 3
) has already-stored data in it. If you select any number between and , the coll
will output the data for that index. In this case, rather than a single number, the coll
is storing a string of symbols (in this case, the opening soliloquy of Shakespeare's Richard III
); all of the symbols are output as a list. Prepending a message to the list allows us to display the value string in a message
In order to store the data within the patcher (as we’ve done with this example), you have to set an attribute in the coll
object's Inspector. Unlock the patcher, and open the Inspector for the coll
in patch 3. You will notice that the attribute labeled “Save Data With Patcher” is selected. When this attribute is set, any information stored in the coll
will be written to the patcher file when it is saved, and is immediately accessible when the patch is opened again.
The center section of our patch (section 4
) uses a coll
to control both a drawing and a MIDI playback function. In this case, the coll
is loaded with some pre-defined data; however, instead of having been stored in the patcher, this data is loaded from an external file containing data from an EEG readout. The filename is “eeg.txt”, and that filename is used as the argument for the coll
, so the data is read into the coll
when it is first initialized.
At the top of the patch is a simple little “self-incrementing” counter system. Each time a number is generated, it increments itself by an amount determined by the upper-right number
box. By default, the increment is one, since that is what the +
object contains. Playing through the data set at this speed, however, can take quite a while, as our data file contains many thousands of lines. If you change the number
box to (meaning that you increment the steps by at each generated by the metro
), you will see the EEG pattern much more clearly. The output of this number generator is used to retrieve the indexed data from the coll
, and is sent to both the drawit
subpatcher and a simple MIDI player (makenote
). The MIDI player just uses the number (scaled to the range of MIDI) as the MIDI note, while the drawit
subpatcher uses the incoming value as the vertical offset of a scrolling drawn circle. Start the metro
(with the toggle
) and notice how different "increment" values for the counting change the way the EEG data unfolds. If you need to restart the file at the beginning, the message
box labeled will reset the int
box to again.
Storing data into a coll
for later use is the best way to deal with large datasets. This EEG capture, which represents over 18,000 data points, would cause your patcher to be very large if it was stored in the patcher's file. Instead, the data can be captured into a coll
, saved in a text file (using the message), and read into the coll
at runtime (used either as an argument, or using the message).
The next patch segment, labeled 5
, shows a few more tricks that coll
has up its sleeve. This coll
has a name – – that manages 8 different cues handled by the rest of the patch (double-click the coll
object to look at what's stored inside). You can use the connected number
box to fire off the messages, but you can also use the three message
boxes to walk through the cues. The message moves you to the beginning of the coll
contents, while the and messages move forward and backward through the cues. This allows you to step through the coll
in sequence, even if the entries are not numbered sequentially, and will automatically loop back to the start when the end is reached. This is the easiest way to implement a sequential step-through of a coll
’s contents. Without worrying about the route
object just yet, step through the sequence using the , and messages and observe how different actions are triggered by the output of the coll
There is also a small patch just to the right, where another coll
is also named “cues”. If you double-click on this coll
, you will see that it has the same contents. In fact, because it is named
the same as the previously viewed coll
, it is actually sharing the contents of the coll
– much like the value
object shared data through a naming convention. Using named colls that share their information allows you to have easy access to a dataset in different places in your patch, or even within subpatchers.
The small patch in the lower-right shows the functionality of the route
object: as you click on the message
boxes, the messages are matched based on their identifier (the first item in their list); if the identifier matches one of the arguments to the route
object, the message is stripped of its identifier and the remaining data (in this case, an integer) is sent out the outlet. The route
object has one outlet for each argument, as well as a final outlet for items that don't match. This patch shows what happens if an unrecognized message is received: the message is not enumerated in the route
object, and therefore cannot be routed. Rather than ignoring the message, it sends the entire message out the right outlet – possibly to be used by another route
object, or perhaps to be sent (as we have in this case) to the Max window with the print
Patch segment 5
also uses the route
object to take messages from the coll
and parse them to perform actions on different objects in the patch. As we saw inside the coll
, the data contains a symbol ( , , and ) and a data item ( for , and for the symbol). When this message is received by the route
object, it uses the first
element (the symbol) to determine the output routing, and sends the rest of the message through that outlet. Hence, a message that begins with will be routed through the first outlet, while a message that begins with will be routed through the fourth.
If we use the start and next messages to walk through the cues coll
, we will see that a sequence of actions is performed based on the first segment of the message. The metro
objects are started and stopped, and the random
object is triggered twice. You can see that the route
object is useful for taking undifferentiated message contents and routing them where they might be useful.
object is a powerful way to work with indexed messages and data; the object provides way to get specific messages or to step sequentially through the contents. You can share the contents between named coll
objects – letting you have access to this data throughout your patch; coll
can also read its data from external files. We also saw how the route
object allows you to track and move messages based on the contents of the message, helping you to route the data that you need to different objects based on an index.
Store and edit a collection of different messages
Selectively pass the output out a specific outlet