Attributes are a new way to specify the behavior of Max objects. Most Jitter objects use attributes for the different variables that make up their current internal state.
The good old Max counter object
Many Max objects, such as the counter
object shown above, take a number of arguments
to determine how they behave. The order of these arguments after the object's name determines how the object interprets them. In the example above, the first argument to counter
sets the direction in which the object counts; the second and third arguments determine the minimum and maximum values that the object counts between. Since these values are simply given to the object as numbers, their ordering is important. With some Max objects (counter
is one of them) the number of arguments you give has some effect on the way in which they are interpreted. If you supply counter
with only two arguments, they will be understood by the object as the minimum and maximum count, not
the direction and minimum count. Because the position and number of arguments are crucial, there is no way, for example, to create a counter
object with a predefined direction and maximum count using only two arguments.
The arguments to an object are often seen as initial
values, and Max objects typically have ways to modify those values through additional inlets to the object or special messages you send the object. You can change the direction and maximum count of a counter
object by sending integers into its second and fifth inlets, respectively. These will override the default values supplied by the arguments. Similarly, you can change the minimum count of the object by sending the message min followed by an integer into the left inlet.
While this system works well when a Max object only has two or three variables that define its behavior, Jitter objects often have many, many more variables (sometimes dozens). If all of these variables depended on the order of inlets and object arguments, you would spend all day searching the reference manual and never have time to do any work with Jitter!
Jitter objects, unlike Max objects, can be told how to behave by using attributes. You can type attributes into an object box along with the Jitter object's name, or you can set (and retrieve) attributes through Max messages after the object is created.
A Jitter object with attributes after the object name
The Jitter object shown above, called jit.brcosa
, has three typed-in attributes. Typed-in attributes are set in object boxes by using the symbol followed by the name of the attribute and one or more arguments (which could be any kind of Max data: ints, floats, symbols, or lists). You can enter as many attributes as the object recognizes, in any order
, after the object's name. While you may not know what the jit.brcosa
object does yet, you can infer a little bit about the object based on the names of the attributes and what type of data they have assigned to them.
Important: There is no space between the sign and the name of the typed-in attribute you want to set. The character tells the Jitter object to interpret the word attached to it as an attribute name instead of an argument value for a previous attribute.
Also Important: Jitter objects can have both typed-in attributes and typed-in arguments. See the Jitter Object Arguments section below for details.
As with Max objects, the information you give a Jitter object to set its initial behavior is generally something you can change after the object is created. Attributes can be changed at any time by sending messages to the object as shown below.
Attributes can be changed with Max messages
object has its attribute set to . initially, but we've changed it to by sending the message into the object's left inlet. You can change virtually any attribute by sending a message with the attribute's name, followed by the relevant arguments, into a Jitter object's left inlet.
As with Max objects, Jitter objects have default values for their parameters. The jit.brcosa
object above only has typed-in attributes initializing its value, but other attributes are set to their default values. We’ll show you how to find out what attributes an object uses below. In the example above, we can change the values of the object's and attributes using messages, overriding whatever default values the object has supplied.
There are four pieces of information that most Jitter objects use that can be entered either as typed-in attributes or typed-in arguments. In fact, they are always attributes, but Jitter objects automatically handle them correctly when they are used as arguments.
Jitter objects can have arguments, too!
object, shown above, clearly has one attribute initialized: . But what does the other stuff mean?
If you supply arguments for a Jitter object that processes Jitter matrix data (and most Jitter objects do), the arguments are interpreted as:
1. The of the output matrix.
2. The of the output matrix.
3. The size, or 'dimension list' ( ), of the output matrix.
Now that we know this, we can determine that the jit.rota
object above will output a matrix that is made up of planes of (8-bit integer) data with two dimensions of by cells.
Important: Jitter object arguments, if used, must appear before any attributes are set. Otherwise the Jitter object will misinterpret the arguments as values for the attribute, not arguments to the object.
These arguments can also be set by attributes that are consistent for all Jitter objects that output matrix data:
, , and . They can be set as unordered typed-in attributes or changed with messages. The three objects below, for example, are identical.
Arguments or attributes? You decide.
The first object has its output matrix attributes set using typed-in arguments. The second object has the
and set using typed-in arguments, but uses a typed-in attribute for the dimension list. The third object uses a typed-in attributes to set everything.
If you prefer, you can initialize an object’s attributes using messages triggered from a loadbang object as shown below.
Yet another way to initialize your attributes
An additional (and very useful) feature of attributes is that you can ask a Jitter object to tell you what value it currently has stored for any given attribute. You do this by querying the attribute with the Max message followed (with no space) by the name of the attribute you want to know about. The resulting value is output by the Jitter object as a message (beginning with the attribute's name), sent out the object's right outlet.
Querying an attribute for a Jitter object
object. The Max route
object lets you easily separate the values for each of the attributes.
to find the values of attributes lets you discover the current value of an attribute, even if you never set the attribute in the first place. For example, the patch below discovers some of the default values of the
Finding out the default values of object attributes
Two messages you can send to any Jitter object,
and , output all the attributes used by the object.
Finding out your options…
object) will have special meaning for the object that uses them.
message causes the Jitter object to output the message followed by a list of all the attribute symbols that Jitter object understands. Experimenting with a few Jitter objects will quickly show you that many of these, such as , and , are fairly standard. Others (such as mask in the
message dumps out all the attributes for the Jitter object as if every conceivable attribute query had been performed all at once.
Finding an object's state
You can then use route
, and other Max objects to extract the attributes as you need them. Later in the tutorials, you will encounter several Jitter objects where the attributes change based on calculations performed on the input matrix (or a file that has just been opened by the object). Querying the relevant attributes is how you can find out the result of the object's calculation.
Jitter attributes are a powerful tool for managing the parameters of complex objects. You can use attributes to initialize, change, and find out the current values stored in Jitter objects, and the attachment of each value to a fixed attribute name eliminates the need to remember typed-in argument ordering or the role of each inlet in a complex object.