f02. FTM Basics — ftm.mess


ftm.mess Does More than Send Messages


The ftm.mess object f02-01.jpg is the FTM version of the Max message box. It looks similar to it, and it does send messages, but it can do many more things besides. It incorporates capabilities similar to those of the expr object (but with access to even more operations and functions than expr provides), and is a sort of send/receive object in the sense that it can remotely access and modify data that is stored in FTM data structures. The combination of all these capabilities in one object is so powerful that you can actually write pretty involved portions of a program in a single ftm.mess.


This tutorial patch shows a few of the most basic of these capabilities. All of the message boxes in this patch are ftm.mess objects rather than Max message boxes; in these tutorials we'll always use ftm.mess objects when communicating with FTM objects. In the upper left corner of the patch are two examples that demonstrate that for ordinary Max messages, the ftm.mess object works pretty much the same as a message box.


• Click on the first two messages and you'll see that the messages that come out are just as you would expect from a message box. All the rest of the ftm.mess objects in this patch show some special capabilities that the message box does not have.


Evaluation of Expressions and Functions


The most important feature of ftm.mess is that parentheses instruct the object to evaluate the operations or functions contained within them, and then send out the returned result. For example, when you click on the message (4 + 5.99) ftm.mess treats the + sign not just as a symbol, as would be the case with a message box, but rather as a math operator. It performs the operation in question and returns the result, and sends it out the outlet.


Another feature of ftm.mess is that it can have multiple inlets for providing $ arguments to the object, and those inlets can optionally be set to all trigger output, rather than the default case of only the left inlet triggering output. The number of inlets and the triggering of the inlets are set in the object's Inspector.


• Use the number boxes to enter numbers for the two operands of the expression ($1 * $2). You'll notice that the expression is evaluated and the result is sent out whenever a number comes in either inlet; that's because the object has been set to be triggered by all its inlets.


It's worth noting that the white space around the math operators is important for separating the operator from its arguments. (This is different from the Max expr object, in which white space is ignored.) In general each argument, operator, or function name in an ftm.mess should be separated from others by a white space.


ftm.mess provides all the operators one would expect in any programming language, with a format similar to the Max expr object, including math operators, logical operators, and bitwise operators.


The next example shows that in addition to those operators ftm.mess provides access to a large number of functions for more advanced math operations, complex math, trigonmetric functions, and various conversion functions. (See the ftm.mess help file for a complete listing.) It also demonstrates some of the other features that can be set in the Inspector, such as initial values for the inlet arguments, and variables that are local (and persistent) within that object. In this object, for example, an initial value is provided for t, A, and f (that is, for the arguments $1, $2, and $3) before any number comes in those inlets, and an internal private variable is created named twopi, set to the value of 2π, 6.283185. (It actually acts as a constant value rather than a variable in this case, since it will never be changed, but it serves to make the expression in the message a bit clearer.) Because the initial value for $3 is 0.25, when time values are supplied in the left inlet the evaluated result will output floats that describe a sinusoid with a frequency of 1/4 Hz.


• Click on the toggle to turn on the clocker object. You can alter the behavior by changing the values for A and f. (Note that because the clocker is outputting at a rate of 20 Hz, the Nyquist frequency of this example is 10 Hz.)


The ftm.mess object below that scales the result by 64, adds 64 to it, and trunctates it (removes the fractional part) so that the simple harmonic motion can be displayed by an ordinary Max slider.


Accessing Objects and their Methods


In addition to accessing mathematical operators and functions, ftm.mess can in fact access any functions or methods of FTM objects.


• Click on the message ($array128 fill $mtof). Now double-click on the fmat object named array128 to open its display window. You will see a list of 128 numbers; these are the frequencies, in Hertz, associated with each of the 128 MIDI note numbers 0 to 127.


Let's analyze this message. You will note that the entire message is enclosed in parentheses, and thus will ultimately be evaluated and will output the returned result. However, the outlet of this ftm.mess is not connected to anything, so the message doesn't go anywhere. Nevertheless, the message gets evaluated. Within the parentheses are three items. Those items are a reference to the name of a fmat (a matrix of  floats), a method understood by fmat, and a reference to the name of an expr (an expression to be evaluated). The first and last are classes of ftm.object. (We introduced fmat in the previous chapter.) The middle one, fill, is a method of the fmat class—a task that it knows how to perform. So the message just says, in effect, "Find the matrix and fill it with this." (However, the "this" is not just a single number in this case, but instead is an expression.)


You can see that the patch contains two ftm.objects—an fmat named array128 (that has 128 rows and 1 column) and an expr named mtof. A ftm.mess can access the contents of those objects by using a $ reference to their names. The fill method to a fmat causes that fmat to be filled with whatever is specified by the following argument. That might be a number, or it might be a $ argument referring to a number that came in an inlet of the ftm.mess, or it might be a $ variable referring to a private variable of the ftm.mess; in those cases all the cells of the matrix would be filled with the same value. However, the argument to fill might also be a $ reference to any FTM object, including an expression to be evaluated. In this case it is a reference to the expr mtof—the expression (midi2hz $row). (It's contained within single quotes so that it will be treated as a single thing by other objects.) That expression uses the FTM midi2hz function with a $ argument that refers to the number of each row of the fmat that is being filled.) The expression says, in effect, "Take the row number and treat it as if it were a MIDI number and convert that number to the corresponding frequency." Since the expression is being evaluated by the fill method of an fmat, the $row reference is understood to mean the row number of that fmat; fill evaluates the expression for each cell of the matrix and puts the returned result into that cell.


The above description may seem a bit complicated, but that's only because each of the items in the message refers to a moderately complicated thing (a matrix, a method, and an expression). Within parentheses, each item might be a reference to a matrix or an expression or a function or a method (or any of a variety of other FTM objects), and it might even be another pair of parentheses that needs to be evaluated before the outer pair of parentheses can be evaluated. This use of parentheses within parentheses is referred to as "nested parentheses", a concept common in mathematics and object-oriented programming. To understand such an expression, you have to evaluate each level of parentheses in turn. For a programmer, this is a powerful tool, because it allows the nesting of one procedure within another, thus enabling the construction of arbitrarily elaborate commands.


It might also help to remember that every function or method "returns" (sends back) something to the object that called it. When the fmat is done running its fill method is done, fill returns a reference to the object. You can think of that returned reference as being the evaluated value of what is contained within the parentheses. That is what the what the ftm.mess sends out its outlet (if the outlet is connected to another object).


The next message in the patch is much simpler. ($array128 zero) just means "Find the array128 object and run its zero method.) Since array128 is the name of a fmat, and fmat's zero method fills all cells of the fmat with the number 0, the result is straightforward.


• Click on the message ($array128 zero) and observe the result in the array128 display window.


Note that each of these last two messages involved methods that alter the contents of the called object. This remote in-place modification of data results in the loss of whatever data was there previously. (It's comparable to two different Jitter objects writing into the same named matrix.)


The fmat and the expr in these two preceding examples are what is called "statically created" FTM objects. They will continue to exist in memory as long as the patch is open (although they can be altered in all sorts of ways). However, we may occasion want to create an object on the fly just long enough to use its information, and then free its space in memory. That's called "dynamic creation". The ftm.mess object can, if need be, create new internal FTM objects, because those object classes have a "new" method that creates a new instance of their class.


• Click on the ftm.mess in the lower-left corner of the patch, and observe what is printed in the Max console window. The result that comes out of the outlet is a reference to a dynamically-created matrix, and its contents are the same as we produced earlier in the array128 fmat. In this case, though, the message created a new expression and a new matrix on the fly and returned the result of the fill method (a reference to the filled matrix). The reference is what the ftm.mess sends out, and ftm.print looks at that place in memory and prints the contents of the matrix.


Further Examples, Interfacing with Max Obects


The two examples on the right side of the patch show some more methods and show some ways that ftm.mess might be useful in the context of a Max patch.


The upper example has several levels of nested parentheses. We can understand how it works by starting to evaluate the lowest level of parentheses. The part that reads '($row / 127.)' states an expression that will divide each row number by 127. That expression gets contained in an instance of the expr class that is created on the fly by a new method: (new expr '($row / 127.)'). That expression is used in a fill method by the fmat named array128: ($array128 fill (new expr '($row / 127.)')). The fill method returns a reference to the fmat array128, and that matrix is used as the left operand in a pow function, which takes the value of its left operand to the power of its right operand. Since its left operand is a matrix and its right operand is the $1 argument (the number that comes in the left inlet), it will raise the value of every cell of the matrix to the power of whatever exponent comes in the inlet. In addition to filling the fmat—which you can verify by looking in its display window—the fill method returns a reference to that matrix. That reference is used as the argument to a list function, which returns a list consisting of the contents of its argument (the matrix). Since that list is the thing that is returned by the outermost set of parentheses in the message, that is what ftm.mess sends out, and we use that list message to set the contents of a Max multislider object.


• Enter a number in the number box labeled "exponent" to trigger the ftm.mess. In effect, the message creates an expression, uses that expression to fill the array128 matrix with a linear progression of 128 values going from 0 to 1, raises those values to the power of whatever exponent came in its inlet, and then sends those values out as a list. After all that, the matrix will contain 128 values describing an exponential curve from 0 to 1, and identical values will be contained and displayed in the multislider. Try different numbers from 0 to 1 and from 1 to 10 to see various curves.


The Comma, the Semicolon, and Private Variables


The last example uses a well-known chaos formula to generate MIDI notes. It's an example of an iterative formula, one in which the result is repeatedly put back into the formula in place of one of the variables. We use a metro object to trigger calculation of the formula repeatedly ten times per second. The chaos formula itself generates a number between 0 and 1, and we map that number into the range of integers from  36 to 96 for use as MIDI pitch values.


The ftm.mess actually contains two separate messages. The first message uses a private variable x (initialized to a value of 0.1 in the Inspector) to calculate an integer value from 36 to 96, and sends it out. The second message uses the formula (1-x)xr, where r is actually the $2 argument (initialized to 3.58 in the Inspector) to calculate a new value, and assigns that value to the private x variable. The two messages are separated by a comma, and the second message is followed by a semicolon. As you'll recall from the previous tutorial, this means that the ftm.mess will send out its output after evaluating the first message, but not after evaluating the second one.


• Click on the toggle above the metro to start triggering messages. Changing the number that goes in the right inlet will change the $2 argument and thus change the chaotic behavior of the iterative formula. For example, an r value of 3.43 will cause extreme attraction to two particular x values. An r value of 3.50 will cause a regular pattern of four x values. An r value of 3.55 will cause a regular pattern of eight x values. An r value of 3.60 creates a pattern of high and low values that varies in details of its length and actual x values. And an r value of 3.7 will cause a variable longer pattern with occasional surprise repetitions of a single x value.


This patch uses four methods of displaying the output of the iterative formula—a keyboard kslider, a number box, a multislider in Point Scroll mode, and MIDI notes played on a synthesizer with noteout.


Summary


In the ftm.mess object one uses parentheses to access math operators and functions. The object evaluates the result of the operation or function and sends out the returned result. Parentheses can be nested. The object can have multiple inlets, and can have initialized values and private variables, set in the Inspector. The $ can be used to access inlets and private variables as well as to reference ay other FTM object. By using parentheses and $ references, one can access any of the methods of other FTM objects and include the returned results of those methods in the message. Messages can be concatenated in a single ftm.mess, separated by a comma or a semicolon; messages separated by a semicolon will be evaluated but will not cause output. By combining multiple messages, nested parentheses, and references to other FTM objects, one can construct fairly elaborate processes within a single ftm.mess.