The language

Control flow

if, for, while, break, every — all of them bounded, on purpose.

Anyone whose patch has to decide something.

Playground
if (x > 0.0f) { ... } else if (x > -1.0f) { ... } else { ... }

for (wrap<64> i) { ... }        // constant trip count, i is int
while (cond) { ... }            // capped at 1024 iterations
loop { ...; advance(); }        // one frame
every (64) { ... }              // once every 64 frames

Choose a loop for the job#

The outer loop says “produce the next audio frame.” A for inside it says “do a known number of operations while producing that frame.” They describe different scales of time. An eight-voice sum needs eight calculations before one output sample is ready; it does not need eight calls to advance().

FormUse it forImportant detail
if / elseChoose behaviour from the current valuesThe condition is a boolean expression, such as gate > 0.5f.
for (wrap<N> i)Visit a fixed number of entriesi runs from 0 through N−1 and is an int.
while (condition)Search until a condition changesThe safety cap can end it; design for a bounded result.
every (N)Update occasional work inside the frame loopPut values that must hold between updates in state.
breakStop a bounded search earlyExits the innermost bounded loop, not the audio frame.

Try it: in the search below, change target from 0.5 to 0.9. The loop examines more entries before it finds a match. At 1.0 there is no match because the table ends at 63/64, so the initialized fallback value remains. This is a control-value example, not a tone generator.

Every loop is bounded#

for takes a constant trip count: for (wrap<64> i) runs 64 times and i is an int. A non-constant bound is POLE0209.

while is allowed and is capped by the safety pass at 1024 iterations. It cannot run forever, whatever its condition does.

This is not a restriction that gets in the way in practice — a DSP loop is over a table, a partial count or a voice count, all of which are known — and it buys something large: a patch cannot hang the thing running it. That is what lets the playground compile and run code from strangers.

break#

break; exits the nearest enclosing for or capped while, and execution continues after that loop. It works inside conditionals and inside pure helper functions; nested loops each have their own exit.

It does not exit a frame's loop, cross a function boundary, or jump out of an every body (POLE0362).

A bounded search, with an early exitPlayground
processor Search
{
    output stream float out;
    param  float target = 0.5f [0.0f, 1.0f];

    float table[64];

    init
    {
        for (wrap<64> i) { table[i] = float (i) * (1.0f / 64.0f); }
    }

    void main()
    {
        loop
        {
            var found = 0.0f;
            for (wrap<64> i)
            {
                if (table[i] >= target) { found = float (i) * (1.0f / 64.0f); break; }
            }
            out <- found * 0.2f;
            advance();
        }
    }
}

The safety pass still charges the full trip count even when a break looks inevitable. An early exit saves work at run time without weakening the worst-case bound, which is the number the guarantee is made of.

every#

every (N) { … } runs its body once every N frames. It is how you do something at a slower rate than the audio without leaving the frame loop — refill a slice of a table, recompute a coefficient set, advance a sequencer step.

A bounded loop inside an every body can use break normally.