Max has a wide variety of objects for storing and managing data. Objects such as
table,
funbuff,
coll, and
umenu all store information that you can set manually or via a mechanism within a patch itself. The
preset object, which also stores data, is useful for capturing and recalling the ‘states’ of user-interface objects within a patcher, giving you the ability to rapidly restore settings to multiple parts of your patch in one step.
Often a project in Max will require a more sophisticated state management system than the basic data structures objects allow for. The
pattr family of objects (
pattr,
pattrhub,
autopattr, and
pattrstorage) provides the functionality of the
preset object and adds a more extensive set of state management features:
- We can maintain sets of data from objects throughout a Max patch hierarchy. For example, with pattr you can control the state of objects inside of patcher and bpatcher objects all from the top level of the patch.
- We can store any type of data used by any type of object (including data simply stored inside a pattr itself, without any other objects involved).
- We can use pattr objects to remotely set and query the state of objects controlled by the pattr system from anywhere within the patch.
- The pattr objects store groups of settings as XML files, allowing us to easily read and edit saved data outside of Max.
- The pattr objects can recall the state of objects in a specific order, avoiding difficulties with, for example, the recalling of a toggle object that starts a process before all the variables are in place for the process to function correctly.
- Not only can we store the states of many objects under a single address, we can also interpolate between these states, allowing for a seamless crossfade between multiple settings.
- The pattr objects feature a high-level interface for viewing and managing the current state of controlled objects and the states that have been saved.
In this tutorial, we’ll look at some of the basic features of
pattr and
pattrhub, showing how the objects can be used to communicate remotely with objects anywhere in a Max patch.
Take a look at the tutorial patcher. Turn on the
metro object with the
toggle object box labeled ‘start’. You should hear some music if you double-click the
noteout object and select a valid output synthesizer. The number box attached to the
metro object controls the speed of the generated pattern. Click on the colored
message boxes to the right of the patch and note that they change the value of that
number box even though there are no patch cords or
send,
forward, or
receive objects in the patch.
Clicking in a colored
message box changes the
metro object’s time value.
The
pattr object to the right of the
metro object is controlling the value in the
number box above it. In the language of patcher storage, we say that our
pattr object is
bound to the
number box. When we send messages to that
pattr object, it will at all times refer to the data stored in the
number box, allowing us to ask the
pattr object what the number is currently set to, as well as tell the
pattr object to set the number to a specific value remotely.
Our
pattr object has a
name -
speed - which is set by the object’s argument and allows other
pattr-family objects to communicate with it. The
pattrhub object at the bottom of the patch can receive messages and forward them to any
pattr objects in the patch. By sending the message
speed 125 to the
pattrhub, we are telling the object to find the
pattr with the name
speed. If it finds the relevant
pattr object, it will instruct the object to send the message
125 to whatever object it is bound to (in this case, our
number box).
Unlock the patch and click on the
number box attached to the
metro object. Select
Name… from the
Object menu.
Our
pattr object is bound to our
number box because the
bindto attribute of our
pattr object is set to the name of our
number box (
temponum). The act of
naming Max objects allows us easier access to them via the
pattr system. Note that the
pattrhub object controls our
number box via the name of the
pattr object to which it is bound (
speed), not the name of the
number box itself (
temponum).
Rename the
number box to something else and close the Inspector. Try changing settings for the patch by clicking on the message boxes again.
Note that if we rename our referred object, our
pattr object can no longer bind to it. In order to rebind it, we need to tell
pattr to bind to our
number box again.
Open the Inspector for the
number box and name it back to
temponum. Close the inspector and recreate the
pattr object binding to
temponum (either delete the object and undo the deletion, or create a new
pattr object). Verify that it is receiving updates from the
pattrhub object by clicking on the
message boxes again.
Instead of recreating the
pattr object, we could have sent our newly ‘unbound’
pattr object a
bindto message with the name of the
number box, setting the
bindto attribute to a valid object.
Naming a Max object and explicitly binding a
pattr to it with its
bindto attribute is only one way to get a
pattr to refer to an object in our patch. It has the advantage of requiring no connecting patchcords between the two objects, allowing them to communicate from spatially disparate parts of the patcher.
Open the subpatch
notes by double-clicking the
patcher object containing it. This subpatch contains eight
pattr object-bound
number box objects that define the four pitches in our pattern generator, as well as the number of beats between each trigger of the pitch. This is the part of the patch that allows us to construct a polyrhythmic pattern off of a single
counter object (driven by the
metro object in the main patcher).
Click on the
message boxes back in the main patcher with this window open and notice that the
number box objects in the subpatch update correctly when you click on the different patterns. Clicking on the
message box updates the subpatch values, too!
In addition to binding objects to
pattr through explicit naming and the bindto attribute,
pattr objects can control other Max objects through patchcord connections.
The notes subpatch shows two possible ways to do this:
1. Using the
pattr object itself to store the data
2. Automatically
binding a
pattr object to an object using the
pattr object’s middle outlet.
If a
pattr object is unbound, it will store any messages sent in its left inlet and recall them from its left outlet. Messages sent to an unbound
pattr object from a
pattrhub object will echo out of the left outlet as well.
Unlock the notes subpatch and attach an
slider object to the left outlet of one of the
pattr objects named
val_a,
val_b,
val_c, or
val_d. Recall the
pattr objects’ states by clicking on the
message boxes in the main patch. Scroll the
number box attached to the
pattr object. The
slider object should move as well.
The
pattr objects controlling our pitches are not bound to any single object, and are maintaining the values of the
number box objects attached to them not by referring to the objects directly, but by receiving their values as messages. As a result, the
number box objects attached to these
pattr objects can be deleted and replaced with other objects (or more than one object). Because the
pattr object outputs its values when changed (either directly or remotely) we can easily attach multiple objects to the
pattr object to set and display values stored in the object.
The use of the
prepend object with ‘set’ argument in
pattr connections is to prevent the triggering of MIDI events when we recall the
pattr object’s state. Unlike most Max objects,
pattr objects can be connected to other objects that are directly connected to them in turn without causing a stack overflow.
In the same subpatch, try to connect a
slider object to the middle outlet of one of the
pattr objects labeled
mod_a,
mod_b,
mod_c, or
mod_d. The Max window should print an error message and the program should prevent you from making the connection.
The middle outlet of
pattr allows for the automatic binding of the
pattr to a single object in the same patcher. The
number box objects controlling the
% objects are communicating with their respective
pattr objects just as if we had named them and bound the
pattr objects to them manually.
Look at the names for the
number box objects by selecting
Name… from the
Object menu.
The
bindto (middle) outlet of
pattr objects automatically gives the referring object a name if it doesn’t have one already. The name is based on the class of object attached, and multiple objects of the same class in a patch will be given incrementing notation to uniquely identify them (e.g.
number,
number[1],
number[2], etc.).
Back in the main patch, open the
durs subpatch of the main patch by double-clicking the
patcher object containing it. Observe that the two
pattr objects in there (
min and
max) have been bound to two
number box objects through their middle outlets.
Close the subpatchers and go back to the main tutorial patch. Look at the
message boxes again and notice the notation used in them to refer to
pattr objects inside subpatchers.
Because most of our
pattr objects are inside subpatchers, the
pattrhub object refers to them using a
colon-separated notation that takes the form
subpatcher:pattr_name
We can communicate to
pattr objects in nested subpatchers by the same convention, e.g. a
pattr named
yikes in a patcher called
stuff in a bpatcher called
things would be accessed through
pattrhub with the name:
things:stuff:yikes
Using the
umenu object in the main tutorial patch, select one of the
pattr objects in the patch.
In addition to setting the state of
pattr objects through
pattrhub, we can also
query the state of
pattr objects, which will then tell
pattrhub their internal state or the value of the object to which they’re bound. We do this by sending
pattrhub the message
get followed by the name of the
pattr object we want to query, with no space in the message, e.g.
getspeed will poll the state of the
pattr named
speed.
The
number box to the right of the
umenu reflects the current value of the selected
pattr, output by the second outlet of
pattrhub as a message beginning with the name of the queried
pattr.
Change the value of the selected
pattr by changing the
number box next to the
umenu. Check to see that the value changed by looking at the
number box controlled by that
pattr. Select some other
pattr objects and change their values, familiarizing yourself with how the system allows you to query and set the states of objects anywhere in the patch.
The
pattr objects provide a powerful way to manage data from multiple objects in a Max patch. The
pattr object can maintain its own internal information (sent and returned through its leftmost inlet and outlet), or it can bind to a Max user interface object either by naming that object and using the
pattr object’s bindto attribute, or by using the middle outlet of the
pattr object to automatically name and bind to an object. Each
pattr object can only bind to one object at a time. The
pattrhub object allows you to control the state of all
pattr objects within a patch, including those within subpatchers, which can be accessed through a hierarchical notation system of successive patcher names separated by colons (
:) followed by the name of the appropriate
pattr object. By sending a
get message (followed by the name of a
pattr with no intervening space) you can query the state of any
pattr object within a patch from a
pattrhub.
See Also
Name |
Description |
pattr |
Patcher-specific, named data wrapper
|
pattrhub |
Access all of the pattr objects in a patcher
|
patcher |
Create a subpatch within a patch
|
preset |
Store and recall the settings of other objects
|