Reference

Runtime values and conversions

Sample rate, sample period, explicit casts, vector constructors and the properties of an external buffer.

Anyone looking up units, types or the values supplied by a host.

A DSP expression often needs information about the world around it: the sample rate, the size of a loaded sample, or the difference between a floating-point position and an integer index. This page puts those small interfaces in one place. Maths functions have their own reference.

processor.frequency#

processor.frequency → float, in Hz

The processor's sample rate: how many frames it computes per second. It is supplied by the host and is available in main() and init. It takes no arguments and is a property, so do not append parentheses.

Playground
let frequencyHz = 440.0f;
let cyclesPerFrame = frequencyHz / processor.frequency;
out <- cyclesPerFrame;

At 48 kHz, a 440 Hz oscillator advances by about 0.00917 cycles per frame. Using the supplied rate keeps its pitch correct when the host uses 44.1 or 96 kHz instead. A divided graph node receives its own effective rate.

processor.period#

processor.period → float, in seconds

The reciprocal of the sample rate: 1.0f / processor.frequency. Multiplying hertz by the period gives cycles per frame; dividing seconds by the period gives a duration in frames.

Playground
let cyclesPerFrame = 440.0f * processor.period;
let samplesInTenMs = int(0.010f / processor.period);
out <- cyclesPerFrame;

int(value)#

int(float value) → int

Parameter: value, a finite float within the signed 32-bit integer range. Returns: the value with its fractional part discarded toward zero. int(2.9f) is 2 and int(-2.9f) is -2. This is different from rounding down with floor, especially for negative positions.

Playground
let delaySeconds = 0.25f;
let delaySamples = int(delaySeconds * processor.frequency);
out <- float(delaySamples);

A cast changes the type, not the unit. The multiplication changes seconds to samples; the cast then makes that sample count usable as an index.

float(value)#

float(int value) → float

Parameter: value, an integer to use in floating-point arithmetic. Returns: its 32-bit floating-point representation. Large integers may lose precision: a float cannot represent every integer beyond 16,777,216 exactly.

Playground
let index = 7;
let tablePosition = float(index) / 1024.0f;
out <- tablePosition;

Pole does not insert numeric conversions for you. Keep both operands the same numeric kind, and write the conversion where the meaning changes from an index to a continuous value.

float<2>(left, right)#

float<2>(float left, float right) → float<2>

Parameters: left and right, one float for each lane. Returns: a stereo pair in that order. This constructs a value; it does not create a state array.

Playground
output stream float<2> out;
let mono = in * 0.5f;
out <- float<2>(mono, mono);

Use pair[0] and pair[1] to read individual lanes. The types chapter covers wider vectors and the rules for broadcasting.

External-buffer properties#

Declare an external to read data supplied by the host:

Playground
external float sample[];
let sampleCount = sample.length;
let sourceRate = sample.rate;
let channelCount = sample.channels;
out <- 0.0f;
PropertyTypeMeaning
sample.lengthintNumber of elements in the bound buffer. For interleaved scalar audio, this counts all channels' samples.
sample.ratefloatSource sample rate in Hz. Zero means the host supplied no rate, as can happen for a wavetable.
sample.channelsintSource channel count; at least 1. For interleaved stereo data this is 2.

For scalar interleaved audio, sample.length / sample.channels gives the number of audio frames. A 100-frame stereo file has 200 scalar elements, not 200 stereo frames. These properties belong to externals; an ordinary state array has a size declared in the source.

A fixed-size external uses wrapped indexing; a sizeless external uses its runtime length and clamps reads to the available range. See arrays and external state before building a sample player.

advance()#

advance() → frame boundary

Takes no arguments and produces no value to assign. Place it at the end of the frame loop, after writing outputs and updating state. It is a language operation, not a maths helper; helpers, event handlers and init cannot use it.

See program structure for a complete processor and the rules for unwritten outputs.