Skip to content

Expression Controller

Description

A controller whose output combines one or more input controllers using a simple C-language-like expression provided as a string.

⚠️ The Expression controller is no longer available since Modalys 3.6. In Lisp, use the Foreign Call controller and in Max context use the mlys.lua object.

(make-controller 'expression ... )

Syntax and Default Values

The 'expression controller can be created using the following Lisp syntax:

(make-controller 'expression dimension period expression_string controller1 controller2 ... )
or:

(make-controller 'expression dimension period expression_string (list controller1 controller2 ... ))

Parameters

The 'expression controller takes the following arguments:

  • dimension: number of dimensions for the output controller.
  • period: the time between controller updates (in synthesis seconds).
  • expression_string: a text string representing the expression to be evaluated. see details, below.
  • controller1, controller2, etc...: controllers to "plug-in" to the math expression.

The output controller can be optionally re-sampled using the period argument. A period of 0, as always, indicates the controller will be updated every sample.

The C-like expression string syntax is described in detail, below.

A variable number of controllers may be provided as a series of arguments, or as a list.

Discussion

The expression controller is similar to the arithmetic controller, but with a richer syntax for mathematical expressions, and support for multi-dimensional controllers. It is available outside the Lisp environment, so it should be used, when and where possible, instead of a 'foreign-call controller, which is not only painfully slow, but also specific just to Modalys in the Lisp environment.

Note that the expression controller is now available in the Max/MSP Windows environment.

Here is a simple example of the 'expression controller's use to multiply two controllers (my-ctl1 and my-ctl2):

(make-controller 'expression 1 0 "in(1,1)*in(2,1)" my-ctl1 my-ctl2)
In this case, in(1,1) refers to the first dimension of the first controller (my-ctl1, in this example), and in(2,1) refers to the first dimension of the second controller.

The expression also lets you use variables and separate an expression into multiple subsequent statements using a semicolon. The above example could be rewritten as:

(make-controller 'expression 1 0 "a=in(1,1); b=in(2,1); a*b" my-ctl1 my-ctl2)
Of course the main advantage to the expression controller is it is well-suited to more complicated mathematical expressions, such as the following example which creates a Hanning window from a one-second ramp (a graph of the original ramp and window resulting from the expression controller is shown, above):

(setq my-ramp (make-controller 'envelope 1 '((0 0) (1 1))))
(setq my-window (make-controller 'expression 1 0 "0.5+(0.5*cos((in(1,1)+0.5)*pi*2))" my-ramp))
You can even get information about things in the Modalys workspace within the expression string. The following shows an example of using the expression controller to get info about the first mode of a mono-string object:

(setq my-string (make-object 'mono-string))
(setq my-ctl (make-controller 'expression 1 0 "get_info('mode-frequency', in(1), 0)" my-string))
Note that the input controllers and their dimensions are numbered starting from 1 in the expression, not from 0 as they are in many other Modalys functions (such as 'dimension-mapping and 'foreign-call).

Options

Operations

The operations in the expression string can be any of the following:

  • the four standard arithmetic operators:
    • /
  • exponential functions:
    • sqrt(x)
    • power(x,n)
    • exp(x)
    • log(x,n)
    • log10(x)
  • trigonometric functions:
    • cos(x)
    • sin(x)
    • tan(x)
    • acos(x)
    • asin(x)
    • atan(x)
    • sinh(x)
    • cosh(x)
    • tanh(x)
  • other functions:
    • abs(x)
    • min(x,y)
    • max(x,y)
    • sign(x)
  • comparison:
    • <
    • <=
    • =

  • logical operators:
    • and
    • or
  • conditional statements:
    • if (condition, if-true, if-false)
  • constants
    • pi
  • local variables (statements separated by a semicolon):
    • a = 1; b = a+1;
  • controllers are indexed by (numbering starts from 1):
    • in(1,1)
  • objects are indexed by (no dimension index! and numbering starts from 1)
    • in(1)
  • the Modalys (get-info ... ) command can be accessed using get_info():
    • get_info('sample-rate')
    • get_info('mode-frequency', in(1), 0)
  • multi-dimensional outputs are possible by separating multiple items with commas inside square brackets - each corresponds to a different dimension of the output controller
    • [ expression_1 , expression_2 ]

Some practical examples to demonstrate the syntax in a complete expression string:

  • cosine of an input-controller:
    • "cos(in(1,1))"
  • masking = maximum between 2 dimensions of two input-controllers:
    • "max(in(1,1),in(1,2))"
  • clipping a controller to lie between -1,1:
    • "max(-1,min(1,in(1,1)))"

Also, within the Lisp environment, you could also use the Lisp (format ...) function to generate expressions for the expression controller:

(format nil "~{~[~; + ~]~cos~;sin~~}" (list-of-groups-of-4-numbers))