Expressions
Expressions are the mathematical formulas that define note properties. Understanding expressions is key to mastering RMT Compose.
What Are Expressions?
Every note property (frequency, startTime, duration) is computed from an expression. Expressions can be:
- Constants: Fixed values like
440or3/4 - References: Values from other notes like
[1].forbase.f - Computations: Arithmetic on values like
* (3/2)
Basic Syntax
Creating Fractions
Fractions represent exact rational numbers:
// Integer (440/1)
440
// Fraction (3/2)
3/2
// Negative
-1/4Legacy JavaScript syntax
new Fraction(440)
new Fraction(3, 2)
new Fraction(-1, 4)Referencing Notes
Access other notes' properties:
// BaseNote's frequency
base.f
// Note 5's start time
[5].t
// Note 3's duration
[3].dLegacy JavaScript syntax
module.baseNote.getVariable('frequency')
module.getNoteById(5).getVariable('startTime')
module.getNoteById(3).getVariable('duration')Arithmetic Operations
Perform math on values:
// Addition
a + b
// Subtraction
a - b
// Multiplication
a * b
// Division
a / b
// Negation
-a
// Power (for TET systems)
a ^ bLegacy JavaScript syntax
a.add(b)
a.sub(b)
a.mul(b)
a.div(b)
a.neg()
a.pow(b)Common Patterns
Frequency Expressions
// Exact frequency in Hz
440
// Relative to BaseNote (perfect fifth)
base.f * (3/2)
// Relative to another note (major third above)
[1].f * (5/4)
// 12-TET semitone (irrational)
base.f * 2 ^ (1/12)Legacy JavaScript syntax
new Fraction(440)
module.baseNote.getVariable('frequency').mul(new Fraction(3, 2))
module.getNoteById(1).getVariable('frequency').mul(new Fraction(5, 4))
module.baseNote.getVariable('frequency').mul(new Fraction(2).pow(new Fraction(1, 12)))Start Time Expressions
// At the beginning
0
// Same time as BaseNote
base.t
// After Note 3 ends
[3].t + [3].d
// 2 beats after BaseNote
base.t + 2Legacy JavaScript syntax
new Fraction(0)
module.baseNote.getVariable('startTime')
module.getNoteById(3).getVariable('startTime').add(module.getNoteById(3).getVariable('duration'))
module.baseNote.getVariable('startTime').add(new Fraction(2))Duration Expressions
// Fixed: 1 beat
1
// Tempo-relative: Quarter note
60 / tempo(base)
// Tempo-relative: Half note
60 / tempo(base) * 2
// Same as another note
[1].dLegacy JavaScript syntax
new Fraction(1)
new Fraction(60).div(module.findTempo(module.baseNote))
new Fraction(60).div(module.findTempo(module.baseNote)).mul(new Fraction(2))
module.getNoteById(1).getVariable('duration')Module Lookup Functions
Special functions for finding inherited values:
// Find tempo (walks up dependency chain to BaseNote)
tempo(base)
// Find measure length
measure(base)Legacy JavaScript syntax
module.findTempo(module.baseNote)
module.findMeasureLength(module.baseNote)Expression Evaluation
Expressions are:
- Compiled to binary bytecode at load time
- Evaluated by a stack-based virtual machine
- Cached for performance
- Re-evaluated when dependencies change
Evaluation Order
The dependency graph determines evaluation order:
- BaseNote is evaluated first
- Notes are evaluated in topological order (dependencies before dependents)
- If Note B depends on Note A, Note A is always evaluated first
Error Handling
Syntax Errors
Invalid expressions prevent saving:
// Missing parenthesis - ERROR
(3/2 * (5/4)
// Correct
(3/2) * (5/4)Circular Dependencies
Notes cannot depend on each other in a cycle:
// Note A depends on Note B
[B].f * (3/2)
// Note B depends on Note A - ERROR!
[A].f * (5/4)Invalid References
Referencing a non-existent note causes an error:
// Note 999 doesn't exist - ERROR
[999].fIrrational Values (TET)
Power expressions can produce irrational results:
// 2^(1/12) is irrational
2 ^ (1/12)Legacy JavaScript syntax
new Fraction(2).pow(new Fraction(1, 12))These are stored as SymbolicPower objects, not floats:
- Preserves algebraic structure
- Combines like bases:
2^(1/12) × 2^(1/12) = 2^(1/6) - Displayed with ≈ prefix
Expression vs. Value
| Concept | Description |
|---|---|
| Expression | The formula (e.g., base.f * (3/2)) |
| Value | The computed result (e.g., 660 Hz) |
| Raw | The expression text in the Variable Widget |
| Evaluated | The value shown in the Variable Widget |
Changing the BaseNote frequency updates all evaluated values, but expressions stay the same.
Tips
- Start simple: Use constants first, add references as needed
- Test incrementally: Check the evaluated value after each change
- Copy working expressions: Use existing expressions as templates
- Mind the parentheses: Every
.and()must be correct - Use Ctrl+Z: Undo if an expression breaks something