Tutorial 3: Numbers and Lists
Numeric Data in Max
A lot of what goes into programming in Max involves being able to manipulate different types of data. In this tutorial, we'll look at how max deals with some new types of messages: numbers and lists. We will spend some time with user interface elements that allow us to manipulate numbers, and learn how to use arguments to insert list elements into a message.
While messages made of text are useful for communicating with humans (and sending commands to a lot of Max objects which we'll look at later on), much of the media world is dependent on numbers, whether they are MIDI note data, video pixel colors or robotic motion control. Having a command of numeric messages is critical to makes Max patches useful in most real-world applications.
Numeric messages in Max are not always singular entities; they are often combined with command text or other information to create a list of data that is useful to other objects, the user of your patch, or the outside world. Hence, combining messages into lists provides the formatting necessary to create useful data structures.
Number boxes
Take a look at the 03mNumbersAndLists tutorial. The patch window contains several small patches that feature number and list manipulations. The left-most patch looks at a new object (in green) called the number box. It deals with integer (often called whole) numbers, and accepts many different messages. Click on some of the connected message boxes, and notice their effect on the number box (as well as any messages that might appear in the Max window via the print object).
The most noticeable effect comes when numeric data is sent to the number box: it responds by displaying the data as well as sending the number from its outlet. When a floating-point number (such as 3.5) is sent to the object, it takes the integer portion of the number and truncates the decimal portion. If a non-numeric message is sent (such as the Hey! message), the Max window displays a complaint by the object, stating that it doesn’t understand that type of message.
Two other special messages are accepted by the number box. First, sending a number box a bang forces the current value to be output without any change to the data. Secondly, preceding a number with the set message will change the data without any output – in essence, providing a way to "silently" change the contents of a number box. The set method is fairly common in Max objects as a way to manipulate the state of the object without triggering any additional messages.
The patch just to the right is similar, but uses a floating-point number box that allows for decimal values to be displayed and output. Many of the messages produce similar results to the integer number box. However, when a floating point value is received, the entire value is saved (and displayed) in this number box. The bang and set messages behave as we’d expect, and the Hey! message is not valid.
The user interface of the number box
In addition to sending them messages, we can also directly enter and manipulate the values stored in number boxes. For example, we can click-drag within the box to manually change the number box contents. This is useful for performance situations where we may want a change a number in real-time while the patch is running. Rather than having to set up message boxes for every possible value we might need, we can manipulate the number box to change a setting. If we click-drag on the integer number box, we see that the Max window displays a stream of data – the number box generates output for each of the values that we scroll through.
With integer data, it is easy to support a scrolling value area – moving up adds 1 to the value, while scrolling down subtracts 1. But what do we add/subtract when we have floating point values? In the case of the floating-point number box, the answer is based on where we place the mouse before we click-drag. If the mouse is on the integer portion of the data (to the left of the decimal point), click-dragging will produce changes similar to the integer number box. However, if we position the mouse of the fractional portion of the data, we can change any of the displayed digits. This allows we to manipulate the data stored in the number box at both a "coarse" and "fine" grain.
Sometimes we will encounter situations where scrolling around in number boxes will trigger too many events or be too inaccurate. Alternately, we might simply know exactly what number we want. We can also change the data for both integer and floating-point number boxes by clicking on them (when the patch is locked), typing in that number, and then either pressing the return key or clicking elsewhere in the patcher. This is a convenient way to enter numbers accurately without having to resort to a message box (or having to scroll for days). Notice that the new data is displayed in the number box, and the object outputs its value as well.
The third patch has three number boxes hooked up to each other. Here, you can see the visible difference between integer and floating-point number boxes – the floating-point versions have a displayed decimal point. If you change the top-most (floating-point) number box, you will see its data being used to update an integer number box, which subsequently updates the next (floating-point) number box. You can also directly manipulate the integer one to see how its messages affect the floating-point variant.
Enter a large number into the top-most number box – something like 60000. You will see that the integer number boxes can’t display this number, since it is too large for the provided display area. Unlock the patch and move your mouse to the right-hand side of the object. You will see a small "handle" appear, and the cursor will change to a left/right arrow; this is called a grow box, and can be used to re-size most user interface objects in Max. Click-drag on the handle to change the width of the number box, then click on a blank area of the patch to deselect the object. You will see an immediate change in the integer display.
Finally, enter a ridiculously high number, like 7245569558. The integer number box changed to -2147483648. How did that happen? While floating-point numbers have a very high threshold of recognized value, the 32-bit integers have a limit – in this case, the maximum value of an integer is 2147483520. Any numbers greater than that cause the integer value to "overflow", and become the greatest negative number. Other very high values might provide other values, depending on how far over this limit the number is.
Looking at lists and replaceable arguments
The right-most patch is a little different – it is just a group of message boxes with contents that are groups of number and text. When we click on the message box with 60 30, we see the two numbers displayed together on the Max window. A combination of numbers and text is called a list; the list is a mechanism for keeping data together into a single message that can be send via patchcords to other objects. The numbers can be either integer, floating-point, or a combination, as you can see in the second example (22 33.9 -5 -44.2).
The next example message is a number box connected to a message box. Use the mouse to change the value of the number box; the result is that the Max window displays the fleas message, but replaces the \$1 text with the incoming number. The \$1 text is called a replaceable argument, and allows you to substitute message content variably using a message box.
The last example accepts two values (as noted by the \$1 and \$2 replaceable arguments), and uses the incoming list values to create the fleas and ticks message. You can have up to 9 replaceable arguments, numbered \$1 through \$9, and the arguments can be in any order. Let’s try an experiment with the arguments:
Unlock the patch window, and select the text in that last message box. At the end of the existing text, add the following text:
\$2 ticks are worse the \$1 fleas.
Lock the patch, and click on one of the two connected lists. You should see the new statement displayed in the Max window, with the proper list content replacing the arguments in the message. This demonstrates that replaceable arguments can be re-used (i.e. you can have multiple \$1 arguments in a message) and can be invoked in any order (i.e. \$2 can follow \$1 in a message).
Conclusion
Max can send numeric data as messages, just like text. There are a few user-interface objects that help us construct and process numeric data, such as the integer and floating-point number boxes. Max can also keep groups of numbers linked in a single message using lists; message boxes can be used to construct lists and other more complex messages with replaceable arguments.