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); // 13print(10 % 3); // 1 (remainder)print("Hello, " + 42); // "Hello, 42" (Number coerced to String)print(5 > 3 && 2 < 4); // trueprint(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.
Arithmetic
Section titled “Arithmetic”| Operator | Description | Example |
|---|---|---|
+ | Addition / string concatenation | 10 + 3 → 13 |
- | Subtraction | 10 - 3 → 7 |
* | Multiplication | 10 * 3 → 30 |
/ | Division | 10 / 3 → 3.333… |
% | Modulo (remainder) | 10 % 3 → 1 |
- (unary) | Negation | -10 |
+ (unary) | Identity | +10 |
print(5.5 / 2.0); // 2.75print(2 % 2); // 0The + 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"Cross-type behaviour
Section titled “Cross-type behaviour”+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. Commutative for pitches:5 + C4andC4 + 5are the same.-subtracts two Numbers, or transposes an Event/Note down (or gives the interval between two pitches).*,/multiply and divide Numbers, or scale the frequency of an Event/Note (see below).%works on Numbers only.
An Event is a Note carrying velocity, channel, and timing. It takes part in arithmetic exactly like a Note — the same semitone/frequency algebra applies to its pitch — and the velocity, channel, and timing are carried through unchanged:
// Event arithmetic happens inside pattern callbacks, where you hold an Event:event + 7; // transpose up a fifthevent - 12; // transpose down an octaveevent * 2; // up an octave (frequency ratio), velocity/timing preservedNote arithmetic
Section titled “Note arithmetic”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 /. An Event follows the same rules on its pitch.
print(C4 + 2); // Note: D4 (62) — up 2 semitonesprint(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 upprint(C4 / 2); // Note: C3 (48) — half the frequency = octave downprint(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"Comparison
Section titled “Comparison”All comparison operators return a Boolean.
| Operator | Description | Example |
|---|---|---|
== | Equal | 5 == 5 → true |
!= | Not equal | 5 != 3 → true |
< | Less than | 3 < 5 → true |
> | Greater than | 5 > 3 → true |
<= | Less than or equal | 5 <= 5 → true |
>= | Greater than or equal | 5 >= 3 → true |
Cross-type behaviour
Section titled “Cross-type behaviour”Equality (==, !=) crosses types in two cases:
- Note ↔ Number — compared by MIDI value
- NUL ↔ anything —
NUL == NUListrue;NULequals nothing else
print(C4 == 60); // true — Note by MIDI valueprint(D4 != 62); // falseprint(NUL == NUL); // trueprint(NUL == 0); // false — NUL is not zeroprint(NUL == false); // false — NUL is not falseOrdering 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 > 60print(A4 >= 69); // trueLogical
Section titled “Logical”| Operator | Description | Example |
|---|---|---|
&& | Logical AND (short-circuit) | true && false → false |
|| | Logical OR (short-circuit) | true || false → true |
! | Logical NOT | !true → false |
Short-circuiting means && stops at the first false and || stops at the first true:
let val = 7;print(val > 5 && val < 10); // trueLogical 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 BooleanCompound assignment
Section titled “Compound assignment”These combine an arithmetic operation with assignment, following the same type rules as their arithmetic counterparts.
| Operator | Equivalent |
|---|---|
+= | x = x + value |
-= | x = x - value |
*= | x = x * value |
/= | x = x / value |
%= | x = x % value |
let count = 1;count += 1; // 2count *= 3; // 6print(count); // 6The output operator <<
Section titled “The output operator <<”<< 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 trackprint("playing");It also feeds effect parameters, including signals that modulate them over time:
echo.param("Feedback") << 0.6; // set a parameterfilter.param("Cutoff") << Sine(2).range_exp(400, 4000); // modulate with a signalFor the details, see MIDI Out, Effects, and Signals & Automation.
The routing operator >>
Section titled “The routing operator >>”>> 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 → masterprint("routed");Precedence
Section titled “Precedence”From highest to lowest:
- Unary (
-,+,!) - Multiplicative (
*,/,%) - Additive (
+,-) - Comparison (
<,>,<=,>=) - Equality (
==,!=) - Logical AND (
&&) - 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.
Type compatibility
Section titled “Type compatibility”A quick map of which types each operator accepts.
| Operator | Number↔Number | String↔String | Note↔Number | Note↔Note | Event↔Number | NUL as operand |
|---|---|---|---|---|---|---|
+ | Number | String | Note | error | Event | error |
- | Number | error | Note | Number (interval) | Event | error |
* | Number | error | Note | error | error | error |
/ | Number | error | Note | Number (ratio) | error | error |
% | Number | error | error | error | error | error |
== != | Boolean | Boolean | Boolean | Boolean | error | Boolean |
< > <= >= | Boolean | error | Boolean | Boolean | Boolean | error |
&& || ! | error | error | error | error | error | error |
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 ormasteron the right.
Next Steps
Section titled “Next Steps”- Control Flow & Match — branch and loop on these comparisons
- Values & Variables — the types these operators act on
- Routing, Buses & Sends —
>>and sends in full