Skip to content

Operators

Resonon is strict: outside the cross-type rules in Type compatibility, mixing types is a type error rather than a silent coercion.

OperatorMeaningExample
+Add; concatenate strings; transpose a Note or Event up10 + 3 → 13
-Subtract; transpose down; interval between two pitches10 - 3 → 7
*Multiply; scale a pitch’s frequency10 * 3 → 30
/Divide; scale a pitch’s frequency; ratio of two pitches10 / 4 → 2.5
%Remainder10 % 3 → 1
- (unary)Negate-10
+ (unary)Identity+10

On a Note or an Event, + and - move by semitones and * and / scale the frequency (a Note is stored as MIDI, the log of frequency, so a frequency ratio is the harmonic-series operation). An Event keeps its velocity, channel and timing. Results are unclamped until output, where they are pinned to MIDI 0–127.

assert C4 + 2 == D4; // up 2 semitones
assert C4 - 12 == C3; // down an octave
assert C5 - C4 == 12; // semitone interval, a Number
assert C4 * 2 == C5; // double the frequency: an octave up
assert C4 / 2 == C3; // half the frequency: an octave down
assert C5 / C4 == 2; // frequency ratio, a Number
assert "value: " + 42 == "value: 42";
print(C4 * 3 / 2); // a just perfect fifth above C4

== equal, != not equal, < less, > greater, <= less or equal, >= greater or equal. Every comparison returns a Boolean.

OperatorMeaning
&&AND; stops at the first false
||OR; stops at the first true
!NOT

Operands must be Booleans. There is no truthy coercion (true && 0 is a type error).

OperatorEquivalent
=Assign
+=x = x + value
-=x = x - value
*=x = x * value
/=x = x / value
%=x = x % value

The target is a variable, a field (p.x += 1) or an index (d["k"] += 1).

target << value; sends a value to a target: a pattern or script pattern to a track, or a value or signal to a parameter. It is a statement, written once per statement, and each side is a whole expression.

lead << [C4 E4 G4].fast(2); // play a pattern on a track
echo.parameter("Feedback") << 0.6; // set a parameter
filter.parameter("Cutoff") << Sine(2).range_exp(400, 4000); // modulate a parameter

a >> b sets the single audio output of track a to b — another track, master, hardware channels (Output(2, 3)), or nowhere (Live’s Sends Only: only the track’s sends are heard) — and evaluates to b, so routes chain: drums >> bus >> master. Every track has exactly one output, master by default; >> is the only way to set it. Sends are a separate mechanism, track.set_send(); see Share an Effect with a Send.

On a MIDI track, a >> b sets its output to a port and channel, MidiOutput("synth", 2), or to nowhere (Live’s No Output, where a new MIDI track starts): bass >> MidiOutput("synth", 2). A MIDI track is no one’s destination, so its chain is one hop. Between visual operators, >> fills the primary input.

An audio routing chain is applied as one change. Every source and destination is checked first; if any link is invalid, none of the chain’s outputs change. Operand expressions still evaluate in order before routing is checked.

From tightest to loosest. Operators on one row bind equally and associate left to right.

BindsOperatorsKind
1 (tightest)f(x), a[i], a.bPostfix: call, index, member access
2-, +, !Prefix: negation, identity, logical NOT
3*, /, %Multiplicative
4+, -Additive
5<, >, <=, >=Comparison
6==, !=Equality
7&&Logical AND
8||Logical OR
9 (loosest)>>Routing
let xs = #[1, 2, 3];
assert 2 + 3 * 4 == 14; // * before +
assert (2 + 3) * 4 == 20; // parentheses first
assert -xs[2] == -3; // index before negation
assert !false && false == false; // == before &&
assert true || false && false; // && before ||
print("precedence holds");

>> binds loosest, so each side is a whole expression and a >> b >> c chains left to right: gfx.Noise("field") >> gfx.Blur("soft") >> screen.

<< is not an expression operator. It is written once per statement, target << value, and each side is a whole expression: lead << [C4 E4 G4].fast(2);.

The result of each operator for each pair of operand types.

OperatorNumber↔NumberString↔StringNote↔NumberNote↔NoteEvent↔NumberNUL as operand
+NumberStringNoteerrorEventerror
-NumbererrorNoteNumber (interval)Eventerror
*NumbererrorNoteerrorerrorerror
/NumbererrorNoteNumber (ratio)errorerror
%Numbererrorerrorerrorerrorerror
== !=BooleanBooleanBooleanBooleanerrorBoolean
< > <= >=BooleanerrorBooleanBooleanBooleanerror
&& || !errorerrorerrorerrorerrorerror
  • + with a String on either side coerces the other side to a String, NUL included ("got: " + NUL is "got: NUL").
  • For - and / the Note must be on the left (C4 - 2, C4 / 2); 2 - C4 and 2 / C4 are errors. + and * are commutative.
  • The frequency ratio in * and / must be positive.
  • Logical operators accept Boolean ↔ Boolean only.
  • << takes a Track or Parameter on the left and a Pattern, Signal or value on the right.
  • >> routes an AudioTrack to an AudioTrack, master, Output(…) or nowhere (Sends Only), master to Output(…), and a MidiTrack to MidiOutput(…) or nowhere (No Output). Output(…), MidiOutput(…) and nowhere only end a chain. It is the one way to set an output. Between visual operators it fills the primary input; see The Visual Graph.