Tutorial 22: Designing Equations
This tutorial covers the creation of equations: mathematical statements that evaluate an expression based on input values. The key to equations in Max is the expr object, which provides a wealth of mathematical functions and a “write your own” mechanism for developing complex statements.
To this point, we have created somewhat complex mathematical processes using individual math objects (+, *, etc.). However, in many cases, we can collapse a number of objects into a single mathematical equation, eliminating a lot of unnecessary complexity in our patches. The tool used for this simplification is the expr object, which uses a specific syntax for creating an equation that accepts multiple inputs and can produce very complex results.
To open the tutorial patch, click on the green Open Tutorial button in the upper right-hand corner of the documentation window.
Overview of the drawing patch
Take a look at the tutorial patch to see the work we have ahead of us. This patch is broken into two encapsulated portions of patcher logic and a drawing routine foran lcd object, also encapsulated. Communication between the parts is accomplished using value objects and pairs of send and receive objects. To see the patch in action, turn on the metro at the left of the patcher using the green toggle box, then hit the space bar to trigger the events at the top of the patch. The result will vary from small scribbles to large-format abstract line-and-circle drawings. Each time you hit the space bar, the lcd will clear and a new, related drawing will begin to appear.
The comment box at the top of the patch shows three lines of mathematical equations:
These expressions compute three values ( , , and ) based on applying some simple trigonometric functions to their previous states as well as five fixed values ( , , , , and ). When plotted onto the lcd object (with visualized as a circle of variable size), we can see that a wide variety of patterns can be created. This equation generates something called a strange attractor - in essence an iterated function where the previous outputs of the equation combine with five variables (called coefficients) to generate a variety of shapes that exhibit chaotic behavior.
Let’s examine each section of this patch. The lower-left corner of the main patch is obviously the key to making things draw – it generates metro that are sent to the and receive objects, as well as into a subpatch that slowly varies the color of the drawing (more on this later). After the subpatch is evaluated, the subpatch receives a via its receive object. This updates the equation for the next round of drawing by triggering a number of value objects, sending their output through equations encoded in the expr objects. These then update the , , and values for drawing. We'll examine how these expr objects work in a moment.messages from a
The send object named sends messages to the drawing routine in the subpatch. This triggers the newly calculated , and values which are scaled, packed into command messages, and then put through a send object to the receive object attached to the lcd, which performs the drawing commands that were generated.
Look at the upper left of the main patch. When the key object outputs a (meaning that the space bar has been depressed), a button is used to generate a message that is sent to the subpatch This, in turn, performs seven actions in order from right to left: the generation of 5 random values ( to ) that are scaled from to , the transmission of a message to the lcd object, and a reset of the value contained in the , and value objects. In essence, the space bar is the overall reset key for this patch, in that virtually every segment of the patch is affected when that key is hit.
Using expr for equation creation
Now let’s look into the expr objects themselves. While they look complicated, the argument for each of the expr objects is a relatively simple equation. The important thing to realize is that the references simply refer to an incoming message, along with its message type and inlet number. So, for instance, using a reference named means that the equation should use an incoming message ( ) that is a floating-point number ( ) retrieved from inlet number 1 ( ). Once you realize that the apparent complexity of the equation is simply its reference to incoming messages, the format of the expr statement is a little more comprehensible.
The operations used in our expr statements are limited to the sin (sine function), cos (cosine) and * (multiply) functions; however, there are dozens of operations available. You can use the common math operators (+, -, * and /), logic (&&, ||), bitwise comparison (&, |) and other C language math functions such as abs, sin, cos, and pow. The documentation provides a complete list of the available functions.
In the case of our tutorial patch, the three expr objects use eight different variables ( , , , , , , , ) to create the three target values ( , , ). There is an interesting bit of feedback here: the target variables are not only used for the drawing routine, but are also used for the next round of computation. The five variables through only change when the space bar is hit, so they provide an anchor to the drawing routine while the ever-changing , and variables determine the individual line and circle drawings for each round of computation.
Adding your own equation
In order to make the drawing a little more interesting, let’s do some creative equation-making and use it to generate a constantly shifting foreground color. We are going to tap into the value objects that are updated on each of the metro., and
Double-click the patcher object labeled at the bottom of the patch. We can see that the foreground color of the lcd is being altered by a trio of drunk objects that are packed into an message sent to the lcd. In here, we are going to use an expr object compute the (e to the power of x) mathematical function. If you aren’t familiar with the properties of e, that’s OK – it’s sufficient to know that it is exponential in nature, and that the value will rapidly increase as the input value increases.
Delete the drunk objects, or disconnect them from the inlet and pack objects and move them out of the way. Create three new value objects with , , and as their respective arguments and connect the inlet object to their inlets.
Now create a new object and type in the following:
Examining the argument/equation from the inside-out, we see that we are taking an incoming floating-point value ( ), using the function to create a new value ( ), multiplying it by 5.0 ( ) then turning it into an integer ( ). The result will be a number that is approximately in the range of color values (0-255), but is predominantly low in that number range. Copy this expr object two times, then connect the output of the three value objects ( , and ) to each of the expr objects. Connect the outlets of the expr objects into the pack, and see what happens.
When we start the metro and the lcd, we will see that the drawing is colored, but tends toward the darker colors. Since the coloring is influenced by the calculated , and coordinates, the colors will tend to be brighter toward the extreme edges of the drawing window. This is an example of calculating drawing commands that might be difficult using traditional object-based programming, but is made quite easy using expr.
Using the expr object gives us the opportunity to create complex mathematical and logical equations without having to resort to large object programming segments. The huge number of operations that can be performed, in combination with the ability to define and use multiple inputs, allows for interesting results that might otherwise be cumbersome to create.