Expression Syntax
Complete reference for the RMT Compose expression language.
Overview
Expressions are JavaScript-like formulas that define note properties. They compile to binary bytecode for efficient evaluation.
Constants
Integer
javascript
new Fraction(440) // 440/1
new Fraction(0) // 0/1
new Fraction(-5) // -5/1Fraction
javascript
new Fraction(3, 2) // 3/2
new Fraction(5, 4) // 5/4
new Fraction(-1, 4) // -1/4Large Numbers
For very large or precise values:
javascript
new Fraction(123456789, 987654321)Arbitrary precision is supported via BigInt internally.
References
BaseNote Reference
javascript
module.baseNote.getVariable('frequency')
module.baseNote.getVariable('startTime')
module.baseNote.getVariable('duration')
module.baseNote.getVariable('tempo')
module.baseNote.getVariable('beatsPerMeasure')Note Reference
javascript
module.getNoteById(1).getVariable('frequency')
module.getNoteById(5).getVariable('startTime')
module.getNoteById(10).getVariable('duration')The note ID must be a positive integer matching an existing note.
Arithmetic Operations
Addition
javascript
a.add(b)
// Examples
new Fraction(1).add(new Fraction(2)) // 3
module.baseNote.getVariable('startTime').add(new Fraction(1))Subtraction
javascript
a.sub(b)
// Examples
new Fraction(5).sub(new Fraction(2)) // 3
module.getNoteById(3).getVariable('startTime').sub(new Fraction(0.5))Multiplication
javascript
a.mul(b)
// Examples
new Fraction(3).mul(new Fraction(2)) // 6
module.baseNote.getVariable('frequency').mul(new Fraction(3, 2)) // FifthDivision
javascript
a.div(b)
// Examples
new Fraction(6).div(new Fraction(2)) // 3
new Fraction(60).div(module.findTempo(module.baseNote)) // Beat durationNegation
javascript
a.neg()
// Examples
new Fraction(5).neg() // -5Power
javascript
a.pow(b)
// Examples
new Fraction(2).pow(new Fraction(3)) // 8 (2³)
new Fraction(2).pow(new Fraction(1, 2)) // √2 ≈ 1.414
new Fraction(2).pow(new Fraction(1, 12)) // 12-TET semitoneWARNING
Non-integer exponents produce irrational results (SymbolicPower). These display with the ≈ prefix.
Lookup Functions
Find Tempo
javascript
module.findTempo(module.baseNote)Walks the inheritance chain to find the tempo value. Usually returns BaseNote's tempo.
Find Measure Length
javascript
module.findMeasureLength(module.baseNote)Computes measure duration based on tempo and beatsPerMeasure.
Chaining Operations
Operations can be chained:
javascript
module.baseNote.getVariable('frequency')
.mul(new Fraction(3, 2))
.mul(new Fraction(5, 4))
// Equivalent to: baseFreq × 3/2 × 5/4 = baseFreq × 15/8Precedence
Standard mathematical precedence applies:
- Parentheses (implicit in method chaining)
- Power (
.pow()) - Negation (
.neg()) - Multiplication/Division (
.mul(),.div()) - Addition/Subtraction (
.add(),.sub())
Common Patterns
Relative Frequency
javascript
// Perfect fifth above BaseNote
module.baseNote.getVariable('frequency').mul(new Fraction(3, 2))
// Major third above another note
module.getNoteById(1).getVariable('frequency').mul(new Fraction(5, 4))
// Octave below
module.baseNote.getVariable('frequency').div(new Fraction(2))Sequential Timing
javascript
// Start when previous note ends
module.getNoteById(prev).getVariable('startTime')
.add(module.getNoteById(prev).getVariable('duration'))Beat-Relative Duration
javascript
// One beat
new Fraction(60).div(module.findTempo(module.baseNote))
// Two beats
new Fraction(60).div(module.findTempo(module.baseNote)).mul(new Fraction(2))
// Half beat
new Fraction(60).div(module.findTempo(module.baseNote)).mul(new Fraction(1, 2))TET Intervals
javascript
// 12-TET semitone
new Fraction(2).pow(new Fraction(1, 12))
// 12-TET major third (4 semitones)
new Fraction(2).pow(new Fraction(4, 12))
// Simplified: 4/12 = 1/3
new Fraction(2).pow(new Fraction(1, 3))Error Conditions
Syntax Errors
javascript
// Missing parenthesis
new Fraction(3, 2.mul() // Error
// Unknown method
new Fraction(3).multiply(2) // Error (should be .mul())
// Invalid fraction
new Fraction(3.5, 2) // Error (must be integers)Reference Errors
javascript
// Non-existent note
module.getNoteById(999).getVariable('frequency') // Error
// Invalid variable name
module.baseNote.getVariable('pitch') // Error (should be 'frequency')Circular Dependencies
javascript
// Note 1 references Note 2
note1.frequency = module.getNoteById(2).getVariable('frequency')
// Note 2 references Note 1 - Error!
note2.frequency = module.getNoteById(1).getVariable('frequency')Best Practices
- Use meaningful references: Reference notes by their role, not arbitrary IDs
- Keep expressions readable: Break complex expressions into multiple notes
- Simplify fractions: Use
new Fraction(1, 2)notnew Fraction(2, 4) - Test incrementally: Verify each expression before building on it
- Use BaseNote for transposition: Reference BaseNote for root-relative notes
See Also
- Fraction API - Complete Fraction.js reference
- Module API - Module methods
- Operators - Arithmetic details