Link Search Menu Expand Document

ExprTK support

Several processes allow to write simple math expressions. Such processes include:

  • Micromap: for very simple math expressions, e.g. x * 100.
  • Expression Audio Generator: generates multi-channel audio.
  • Expression Audio Filter: filters multi-channel audio.
  • Expression Value Generator: generates values suitable for the device explorer.
  • Expression Value Filter: filters values suitable for the device explorer.

ExprTK

These expressions are evaluated within score using the ExprTK library.

The expression can be written in the process built-in editor on multiple lines.

Numerous math functions are available: sin, cos, abs, log, as well as the usual pi, etc. constants.

Audio handling

For audio processes, the processing is done per-frame. The input x is an array, where x[0] is the first channel, x[1] the second channel, etc.

Note that ExprTK has powerful array processing features; the following two codes implement the same distortion:

// This is the syntax to get the size of the array
// e.g. the number of channels here:
var n := x[];

for (var i := 0; i < n; i += 1) {
  var dist := tan(x[i]*log(1 + 200 * a));
  out[i] := clamp(-1, dist, 1);
}
out := clamp(-1, tan(x * log(1 + 200 * a)), 1);

Array handling

For value processes, the same expression syntax cannot be used for single-value or array input:

  • Use x, px, po to write an expression that processes single values, e.g. a float input.
  • Use xv, pxv, pov to write an expression that processes arrays.

For instance:

tanh(x + 1)

will process a single float as input, while:

return [ xv[0] cos(xv[1]), xv[0] sin(xv[1]) ];

will take a vec2 that contains polar coordinates [r, theta] and convert it into cartesian coordinates [x, y].

Available variables

Everywhere

  • t: the current time
  • pos: the position in the interval
  • a, b, c: three provided controls
  • pa, pb, pc: previous value of a, b, c
  • m1, m2, m3: three provided variables (which will keep their value across a tick)
    • In the audio cases they are arrays.

Value mapping

  • x: the value of the current input if it’s a single value
  • px: the value of the previous input if it was a single value
  • po: the value of the previous output if it was a single value
  • xv: the value of the current input if it’s an array
  • pxv: the value of the previous input if it was an array
  • pov: the value of the previous output if it was an array
  • dt: the time delta

Audio mapping

  • x: the value of the current sample
  • out: where to write the output
  • px: the value of the previous sample
  • fs: the sampling rate

Value generator

  • dt: the time delta

Audio generator

  • out: where to write the output
  • fs: the sampling rate

Available functions

ExprTK-provided functions:

  • Basic math: min, max, avg, sum, abs, ceil, floor, round, roundn, exp, log, log10, logn, pow, root, sqrt, clamp, inrange, swap
  • Trigonometry: sin, cos, tan, acos, asin, atan, atan2, cosh, cot, csc, sec, sinh, tanh, d2r, r2d, d2g, g2d, hyp
  • Numeric integration and differentiation
  • Vector Processing: BLAS-L1 (axpy, axpby, axpb), all/any-true/false, count, rotate-left/right, shift-left/right, sort, nth_element, iota, sum, kahan-sum, dot-product, copy

score-provided functions

  • random(min, max): returns a random real number in the given interval.
    • random(0, 1) can be 0., 0.3, 0.23455436, 1.
    • round(random(1, 20)) is a 20-sided dice with lower probabilities for 1, 20.
    • floor(random(1, 21)) is a 20-sided dice with same probabilities for everyone.
  • noise(t, octaves, persistence): Perlin noise.
    • t should be something that increases ; pos is generally a good candidate.
    • octaves: the higher this is, the more detailed the noise is. 2 would be smooth, 7 very detailed but more computationally intensive. Between 1 and 10.
    • persistence: how much each octave fades. 1: no fade, very noisy. 0: very smooth.
    • 5 * (noise(pos * 100, 4, 0.5) - 0.5) gives a convincing fairly dynamic noise between -1 and 1.
    • noise(pos * 10, 3, 0.1) gives a very smooth evolution between 0 and 1.

ExprTK

Examples

The user library comes with a few utility functions, be sure to check them in the preset pane !

Contributing useful functions to the library is also very welcome.

Value generator

Logistic function

Implemented as a preset (Logistic):

if(m1 == 0) {
  m2 := 0.8;
  m1 := 1;
}

var r := 4 * a;
m2 := r * m2 * (1 - m2)

Value mapper

Add noise

Implemented as a preset (Noisify):

var rnd_m := pow(2, 31);
var rnd_a := 1103515245;
var rnd_c := 12345;

if(m2 == 0) {
  m2 := 1;
  m1 := 12345678;
}

var r := (rnd_a * m1 + rnd_c) % rnd_m;
m1 := r;
x + a * r / (2^33);

Audio generator

Sine wave

Implemented as a preset (Sine):

var phi := 2 * pi * (20 + a * 500) / fs;

m1[0] += phi;

out[0] := b * cos(m1[0]);
out[1] := b * cos(m1[0]);

Square wave

Implemented as a preset (Square):

var phi := 2 * pi * (20 + a * 500) / fs;

m1[0] += phi;

var f := cos(m1[0]) > 0 ? b : -b;
out[0] := f;
out[1] := f;

Wobbly synth

Implemented as a preset (Wobbly):

var freq_l := 225 +  cos(t/(100*(a+0.1)));
freq_l := 2 * pi * m1[0] *  freq_l * b / fs;

var freq_r := 215 +  sin(t/(100*(a+0.1)));
freq_r := 2 * pi * m1[0] *  freq_l * b / fs;

m1[0] += 1;

out[0] := b * cos( freq_l );
out[1] := b * cos( freq_r );

Audio filter

Crude distortion

2-channel version:

out[0] := clamp(0,  tan(x[0]*log(1 + 200 * a)), 1);
out[1] := clamp(0,  tan(x[1]*log(1 + 200 * a)), 1);

Any number of channel version:

var n := x[];

for (var i := 0; i < n; i += 1) {
  var dist := tan(x[i]*log(1 + 200 * a));
  out[i] := clamp(-1, dist, 1);
}