Skip to content

Operators

Operators are how you combine values. Most of them — +, -, *, ==, && — behave exactly as you’d expect from any language. Two of them are special to Resonon and worth dwelling on: the output operator <<, which sends patterns and values into your live session, and the routing operator >>, which wires a track’s audio to its destination.

A quick tour of the everyday ones:

PRINT 10 + 3; // 13
PRINT 10 % 3; // 1 (remainder)
PRINT "Hello, " + 42; // "Hello, 42" (Number coerced to String)
PRINT 5 > 3 && 2 < 4; // true
PRINT C4 == 60; // true (Note compared to Number by MIDI value)

Resonon is strict: outside the handful of cross-type rules below, mixing types is a type error rather than a silent coercion.

OperatorDescriptionExample
+Addition / string concatenation10 + 313
-Subtraction10 - 37
*Multiplication10 * 330
/Division10 / 33.333…
%Modulo (remainder)10 % 31
- (unary)Negation-10
+ (unary)Identity+10
PRINT 5.5 / 2.0; // 2.75
PRINT 2 % 2; // 0

The + operator also concatenates strings. When one side is a String, the other side is coerced to a String:

PRINT "Hello" + ", " + "World!"; // "Hello, World!"
PRINT "value: " + 42; // "value: 42"
PRINT true + " story"; // "true story"
  • + adds two Numbers, concatenates two Strings, transposes an Event or a Note by a Number (semitones). When one side is a String, the other is coerced to a String.
  • - subtracts two Numbers, or transposes an Event/Note down.
  • *, / multiply and divide Numbers.
  • % works on Numbers only.
// Event transposition happens inside pattern callbacks, where you hold an Event:
event + 7; // transpose up a fifth
event - 12; // transpose down an octave

A bare Note takes part in arithmetic in two complementary ways. + / - move by semitone steps; * / / scale the note’s frequency (a Note is stored as MIDI, i.e. log₂ of frequency, so multiplying frequency by a ratio is the harmonic-series / just-intonation operation). Combining a Note with a Number yields a Note; combining two Notes yields the distance between them — a semitone interval for -, a frequency ratio for /.

PRINT C4 + 2; // Note: D4 (62) — up 2 semitones
PRINT C4 - 12; // Note: C3 (48) — down an octave (12 semitones)
PRINT C5 - C4; // 12 — semitone interval (a Number)
PRINT C4 * 2; // Note: C5 (72) — double the frequency = octave up
PRINT C4 / 2; // Note: C3 (48) — half the frequency = octave down
PRINT C5 / C4; // 2 — frequency ratio (a Number)

Non-power-of-2 ratios are microtonal — C4 * 3 is the third harmonic (≈ G5 +2¢), and root * 3 / 2 is a just perfect fifth. The frequency ratio in * / / must be positive. Combining two Notes with + or * (adding or multiplying two absolute pitches) is a type error. Results are unclamped and only pinned to the 0–127 MIDI range at output, so transposing out of range is fine mid-expression.

NUL does not propagate through arithmetic; using it as an operand is a type error — except with + when the other side is a String, where it coerces to "NUL":

PRINT "got: " + NUL; // "got: NUL"

All comparison operators return a Boolean.

OperatorDescriptionExample
==Equal5 == 5true
!=Not equal5 != 3true
<Less than3 < 5true
>Greater than5 > 3true
<=Less than or equal5 <= 5true
>=Greater than or equal5 >= 3true

Equality (==, !=) crosses types in two cases:

  • Note ↔ Number — compared by MIDI value
  • NUL ↔ anythingNUL == NUL is true; NUL equals nothing else
PRINT C4 == 60; // true — Note by MIDI value
PRINT D4 != 62; // false
PRINT NUL == NUL; // true
PRINT NUL == 0; // false — NUL is not zero
PRINT NUL == false; // false — NUL is not false

Ordering operators (<, >, <=, >=) compare Numbers and Notes, coercing notes to their MIDI value. NUL can be tested for equality but not ordered — NUL < 1 is a type error.

PRINT D4 > C4; // true — 62 > 60
PRINT A4 >= 69; // true
OperatorDescriptionExample
&&Logical AND (short-circuit)true && falsefalse
||Logical OR (short-circuit)true || falsetrue
!Logical NOT!truefalse

Short-circuiting means && stops at the first false and || stops at the first true:

let val = 7;
PRINT val > 5 && val < 10; // true

Logical operators require Boolean operands — there is no truthy coercion here (that only applies to higher-order callbacks; see Truthiness).

true && 0; // type error — 0 is a Number, not a Boolean
!NUL; // type error — NUL is not a Boolean

These combine an arithmetic operation with assignment, following the same type rules as their arithmetic counterparts.

OperatorEquivalent
+=x = x + value
-=x = x - value
*=x = x * value
/=x = x / value
%=x = x % value
let count = 1;
count += 1; // 2
count *= 3; // 6
PRINT count; // 6

<< sends something to a target — most often a pattern to a track, or a value to an effect parameter. It is the verb of live-coding: “play this here.”

let lead = MidiTrack(1);
lead << [C4 E4 G4 E4]; // send a pattern to a track
PRINT "playing";

It also feeds effect parameters, including signals that modulate them over time:

echo.param("Feedback") << 0.6; // set a parameter
filter.param("Cutoff") << Sine(2).range_exp(400, 4000); // modulate with a signal

For the details, see MIDI Out, Effects, and Signals & Automation.

>> sets a track’s single audio output destination. Every track has exactly one output, which defaults to master; >> replaces that destination. You can chain it to route through an aux track and on to the master output:

let drums = AudioTrack("drums");
let bus = AudioTrack("bus");
drums >> bus >> master; // drums → bus → master
PRINT "routed";

From highest to lowest:

  1. Unary (-, +, !)
  2. Multiplicative (*, /, %)
  3. Additive (+, -)
  4. Comparison (<, >, <=, >=)
  5. Equality (==, !=)
  6. Logical AND (&&)
  7. Logical OR (||)
PRINT 2 + 3 * 4; // 14 (multiplication first)
PRINT (2 + 3) * 4; // 20 (parentheses first)

<< and >> are statement-level operators, not part of expression precedence: each binds an entire right-hand expression to a target.

A quick map of which types each operator accepts.

OperatorNumber↔NumberString↔StringNote↔NumberNote↔NoteEvent↔NumberNUL as operand
+NumberStringNoteerrorEventerror
-NumbererrorNoteNumber (interval)Eventerror
*NumbererrorNoteerrorerrorerror
/NumbererrorNoteNumber (ratio)errorerror
%Numbererrorerrorerrorerrorerror
== !=BooleanBooleanBooleanBooleanerrorBoolean
< > <= >=BooleanerrorBooleanBooleanBooleanerror
&& || !errorerrorerrorerrorerrorerror

For - and / the Note must be on the left (C4 - 2, C4 / 2); 2 - C4 and 2 / C4 are errors. + and * are commutative.

  • Logical operators accept Boolean ↔ Boolean only.
  • << takes a Track or Parameter on the left and a Pattern, Signal, or Value on the right.
  • >> takes an AudioTrack on the left and an AudioTrack or master on the right.