Reference

Built-in maths

Function signatures, argument descriptions, return values and practical DSP examples for every supported maths builtin.

Anyone looking up a function while writing a patch.

A function call is easiest to use when you can see what goes in and what comes out. Start with the table to find a function, then open its entry for argument order, units, return values and a small example.

The available names and argument counts below are checked against the local compiler. The explanations and examples are maintained alongside that check, and every Pole example is compiled by the documentation verifier.

Quick lookup#

CallUseScalar types
sin(x)Trigonometryfloat
cos(x)Trigonometryfloat
tan(x)Trigonometryfloat
tanh(x)Shaping and roundingfloat
exp(x)Powers and logarithmsfloat
log(x)Powers and logarithmsfloat
log10(x)Powers and logarithmsfloat
sqrt(x)Powers and logarithmsfloat
abs(x)Shaping and roundingfloat
floor(x)Shaping and roundingfloat
ceil(x)Shaping and roundingfloat
pow(base, exponent)Powers and logarithmsfloat
min(a, b)Bounds and comparisonsfloat or int
max(a, b)Bounds and comparisonsfloat or int
clamp(x, low, high)Bounds and comparisonsfloat or int

Reading a signature#

float pow(float base, float exponent) means that the function takes two float arguments in that order and returns a float. You call it as pow(2.0f, 3.0f), without writing the types at the call site. The signatures are reference notation; the examples below are actual Pole statements.

All arguments are required and positional. Builtins accept vectors of the same numeric kind and operate separately on each lane. Scalar arguments broadcast to the vector width; two vector arguments must have matching widths. A call on a float<2> therefore returns a float<2>, not a mono value.

Only min, max and clamp accept integers. Within one call, use all int or all float arguments: clamp(3, 0, 7) works; clamp(3, 0.0f, 7.0f) does not. A whole-number float result from floor or ceil is still a float.

The examples that output a coefficient, frequency or decibel value demonstrate arithmetic; they are not complete audio effects. See the cookbook to use these values in a signal path, and Functions to write your own helpers.

sin#

float sin(float x)

Use a phase accumulator for an oscillator. Multiply a phase measured in cycles by 2π before calling sin; passing a frequency in Hz directly does not create a tone.

Parameters

NameMeaning
xAngle in radians, not degrees or cycles.

Returns

The sine of x, between -1 and 1 for finite inputs.

Example

Playground
let phaseCycles = 0.25f;
let sample = sin(6.2831853f * phaseCycles); // approximately 1.0
out <- sample;

cos#

float cos(float x)

cos starts at 1 when its angle is zero. It is a quarter cycle ahead of sin, useful when the left and right channels need offset modulation from one phase accumulator.

Parameters

NameMeaning
xAngle in radians.

Returns

The cosine of x, between -1 and 1 for finite inputs.

Example

Playground
let sample = cos(0.0f); // 1.0
out <- sample;

tan#

float tan(float x)

Useful in filter coefficient calculations. Near its poles the magnitude becomes very large, so constrain a cutoff before converting it to an angle.

Parameters

NameMeaning
xAngle in radians; keep away from π/2 plus integer multiples of π.

Returns

The tangent of x. Unlike sin and cos, the result is not bounded to -1…1.

Example

Playground
let cutoffHz = 1000.0f;
let coefficient = tan(3.14159265f * cutoffHz / processor.frequency);
out <- coefficient;

tanh#

float tanh(float x)

A convenient soft clipper: near zero it is almost linear; larger inputs are compressed smoothly. Increasing drive changes both tone and loudness, so add output trim. Nonlinear shaping can still alias.

Parameters

NameMeaning
xInput value after any desired drive gain.

Returns

The hyperbolic tangent of x, approaching -1 and 1 as the input magnitude grows.

Example

Playground
let drive = 3.0f;
let trim = 0.5f;
out <- tanh(in * drive) * trim;

exp#

float exp(float x)

An exponential envelope multiplies its previous level by a coefficient just below 1 each sample. Large positive arguments can overflow; envelope coefficients normally use a negative exponent.

Parameters

NameMeaning
xExponent of Euler's number e; dimensionless.

Returns

e raised to x. exp(0.0f) is 1.0f; negative inputs produce values between 0 and 1.

Example

Playground
let seconds = 0.1f;
let coefficient = exp(-1.0f / (seconds * processor.frequency));
out <- coefficient;

log#

float log(float x)

This is the inverse of exp. Zero produces negative infinity and negative inputs are outside the real-valued domain; protect values derived from audio with a positive floor.

Parameters

NameMeaning
xPositive value, strictly greater than zero.

Returns

The natural logarithm of x (base e). log(1.0f) is 0.0f.

Example

Playground
let magnitude = max(abs(in), 0.000001f);
out <- log(magnitude);

log10#

float log10(float x)

For an amplitude ratio, decibels are 20 * log10(ratio). For a power ratio the multiplier is 10. A meter needs a positive floor so silence has a finite display value.

Parameters

NameMeaning
xPositive value, strictly greater than zero.

Returns

The base-10 logarithm of x. log10(10.0f) is 1.0f.

Example

Playground
let amplitude = max(abs(in), 0.000001f);
let decibels = 20.0f * log10(amplitude); // floor: -120 dB
out <- decibels;

sqrt#

float sqrt(float x)

Used in RMS metering and equal-power gains. Negative values are outside the real-valued domain. sqrt is not an integer conversion, even when the input is a whole number.

Parameters

NameMeaning
xNon-negative value, including zero.

Returns

The non-negative square root of x, as a float.

Example

Playground
let mix = 0.5f;
let dryGain = sqrt(1.0f - mix);
let wetGain = sqrt(mix);
out <- in * dryGain;

abs#

float abs(float x)

Rectification is the first step in an envelope follower: abs turns both halves of the waveform positive. It does not smooth the result; that needs a filter and state.

Parameters

NameMeaning
xA float value; convert an int explicitly before calling.

Returns

The magnitude of x, with its sign removed. abs(-0.5f) is 0.5f.

Example

Playground
let rectified = abs(in);
out <- rectified;

floor#

float floor(float x)

floor(-1.7f) is -2.0f. int(-1.7f) is -1, because the cast truncates toward zero. Use x - floor(x) for a fractional phase that stays in [0, 1) even when x is negative.

Parameters

NameMeaning
xValue to round downward.

Returns

The greatest whole-number value less than or equal to x, still typed float.

Example

Playground
let phase = -0.25f;
let wrapped = phase - floor(phase); // 0.75
out <- wrapped;

ceil#

float ceil(float x)

ceil(1.2f) is 2.0f, and ceil(-1.2f) is -1.0f. If the result becomes an array index, use an explicit int conversion after rounding.

Parameters

NameMeaning
xValue to round upward.

Returns

The smallest whole-number value greater than or equal to x, still typed float.

Example

Playground
let index = int(ceil(1.2f)); // int value 2
out <- float(index);

pow#

float pow(float base, float exponent)

Pitch intervals are ratios: an octave multiplies frequency by 2, and a semitone by 2^(1/12). Negative bases require integer-valued exponents for a real result; avoid zero with a negative exponent.

Parameters

NameMeaning
baseBase value; use a positive base for arbitrary fractional exponents.
exponentPower to raise the base to. Both arguments must be float values.

Returns

base raised to exponent. pow(2.0f, 3.0f) is 8.0f.

Example

Playground
let semitones = 12.0f;
let frequency = 440.0f * pow(2.0f, semitones / 12.0f); // 880 Hz
out <- frequency;

min#

float min(float a, float b)
int min(int a, int b)

Use min to impose a ceiling, for example on a feedback amount. It does not impose a lower bound; use clamp when both limits matter.

Parameters

NameMeaning
aFirst value.
bSecond value, with the same numeric kind as a.

Returns

The smaller of a and b, keeping the numeric kind of the arguments.

Example

Playground
let ceiling = min(1.2f, 0.9f); // 0.9
let count = min(12, 8);       // int value 8
out <- ceiling;

max#

float max(float a, float b)
int max(int a, int b)

Use max to impose a floor. A positive floor on a duration prevents division by zero; a positive floor on a magnitude makes logarithms usable at silence.

Parameters

NameMeaning
aFirst value.
bSecond value, with the same numeric kind as a.

Returns

The larger of a and b, keeping the numeric kind of the arguments.

Example

Playground
let seconds = max(0.0f, 0.001f); // 1 ms minimum
let count = max(-2, 0);          // int value 0
out <- seconds;

clamp#

float clamp(float x, float low, float high)
int clamp(int x, int low, int high)

The order is value, minimum, maximum. Bounds are not automatically sorted. On stereo input a pair of scalar bounds applies to both channels. Use this for hard clipping or for keeping a computed control in its intended range.

Parameters

NameMeaning
xValue to constrain.
lowInclusive lower bound; must be no greater than high.
highInclusive upper bound.

Returns

x when it is inside the bounds, low below them, or high above them. The result keeps the arguments' numeric kind.

Example

Playground
let sample = clamp(in, -1.0f, 1.0f);
let index = clamp(12, 0, 7); // int value 7
out <- sample;

Common mistakes#

SymptomCheck
Unknown function (POLE0325)Pole's builtins are the ones above. Write helpers such as lerp yourself.
Wrong argument count (POLE0326)Compare the call with its signature; clamp needs three arguments.
Wrong argument type (POLE0327)Use 1.0f for a float literal or convert explicitly with float(value).
Unexpected oscillator pitchsin takes an angle in radians. Advance phase using frequency divided by sample rate.
Non-finite outputCheck the input domain of log, sqrt and pow, and divisions used to form their arguments.

For vector examples and the optional approximation mode, continue to maths in a patch.