Chaining Notes with Dependencies
Learn how to create musical relationships between notes using expressions that reference other notes.
Understanding Dependencies
In RMT Compose, notes can reference other notes' properties. When you write an expression like:
module.getNoteById(1).getVariable('frequency')You create a dependency - Note 2 depends on Note 1's frequency. When Note 1 changes, Note 2 automatically updates.
Why Use Dependencies?
Traditional Approach (Absolute Values)
Note 1: frequency = 440 Hz
Note 2: frequency = 660 Hz (manually calculated 440 × 3/2)
Note 3: frequency = 880 Hz (manually calculated 440 × 2)Problem: If you want to transpose everything up, you must edit every note.
RMT Approach (Relative Values)
Note 1: frequency = 440 Hz
Note 2: frequency = Note1.frequency × 3/2
Note 3: frequency = Note1.frequency × 2Benefit: Change Note 1 to 330 Hz, and Notes 2 and 3 update automatically to 495 Hz and 660 Hz.
Creating Your First Dependency Chain
Step 1: Create the Root Note
- Double-click the workspace to create a note
- In the frequency field, enter:javascript
module.baseNote.getVariable('frequency') - Set startTime:
new Fraction(0) - Set duration:
new Fraction(1)
This note inherits from BaseNote (440 Hz by default).
Step 2: Create a Dependent Note
- Create a second note
- For frequency, reference Note 1 (assuming ID is 1):javascript
module.getNoteById(1).getVariable('frequency').mul(new Fraction(3, 2)) - For startTime, chain to Note 1's end:javascript
module.getNoteById(1).getVariable('startTime').add(module.getNoteById(1).getVariable('duration')) - Duration:
new Fraction(1)
Now Note 2 plays a perfect fifth above Note 1, starting right after it ends.
Step 3: Extend the Chain
Create Note 3 that depends on Note 2:
// Frequency: Perfect fourth above Note 2
module.getNoteById(2).getVariable('frequency').mul(new Fraction(4, 3))
// StartTime: After Note 2
module.getNoteById(2).getVariable('startTime').add(module.getNoteById(2).getVariable('duration'))Viewing Dependencies
Visual Feedback
- Select a note by clicking on it
- Blue lines show notes this note depends on (parents)
- Red lines show notes that depend on this note (children)
Understanding the Flow
BaseNote (440 Hz)
↓ (blue line)
Note 1 (440 Hz) - inherits from BaseNote
↓ (blue line)
Note 2 (660 Hz) - depends on Note 1
↓ (blue line)
Note 3 (880 Hz) - depends on Note 2Practical Example: Ascending Scale
Build a major scale where each note depends on the previous:
// Note 1 (Root)
frequency: module.baseNote.getVariable('frequency')
startTime: new Fraction(0)
duration: new Fraction(1)
// Note 2 (Major Second - 9:8 ratio)
frequency: module.getNoteById(1).getVariable('frequency').mul(new Fraction(9, 8))
startTime: module.getNoteById(1).getVariable('startTime').add(module.getNoteById(1).getVariable('duration'))
// Note 3 (Major Third - 5:4 ratio from root, or 10:9 from Note 2)
frequency: module.getNoteById(1).getVariable('frequency').mul(new Fraction(5, 4))
startTime: module.getNoteById(2).getVariable('startTime').add(module.getNoteById(2).getVariable('duration'))
// Continue the pattern...Timing Dependencies
Sequential Notes
Each note starts when the previous ends:
module.getNoteById(PREV_ID).getVariable('startTime')
.add(module.getNoteById(PREV_ID).getVariable('duration'))Simultaneous Notes (Chords)
Multiple notes share the same start time:
// All chord notes reference the same start time
module.getNoteById(ROOT_ID).getVariable('startTime')Offset Timing
Add a delay from a reference:
module.getNoteById(1).getVariable('startTime')
.add(new Fraction(1, 2)) // Half-second offsetComplex Dependencies
Multi-Property Dependencies
A note can depend on different notes for different properties:
// Frequency from Note 1
frequency: module.getNoteById(1).getVariable('frequency').mul(new Fraction(5, 4))
// Timing from Note 3
startTime: module.getNoteById(3).getVariable('startTime')
duration: module.getNoteById(3).getVariable('duration')Inherited Duration
Make all notes share a duration:
// All notes reference BaseNote's duration
duration: module.baseNote.getVariable('duration')Now changing BaseNote's duration affects all notes.
Avoiding Circular Dependencies
RMT Compose prevents circular references:
Note 1 → depends on → Note 2
Note 2 → depends on → Note 1 // ERROR!If you try to create a circular dependency, you'll see an error message.
How to Fix Circular Dependencies
- Identify the loop in your dependency chain
- Break the cycle by referencing a common ancestor
- Use BaseNote as the ultimate root for shared properties
Best Practices
1. Plan Your Hierarchy
Sketch out your dependency structure before building:
BaseNote (tempo, base frequency)
├── Melody Root
│ ├── Melody Note 2
│ └── Melody Note 3
└── Bass Root
├── Bass Note 2
└── Bass Note 32. Use Meaningful Chains
- Frequency chains: Keep related pitches connected
- Timing chains: Sequential notes should link their timing
- Duration chains: Notes that share duration should reference a common source
3. Test by Changing Root Values
After building your dependencies:
- Select the root note
- Change its frequency or timing
- Verify all dependent notes update correctly
Troubleshooting
Note Not Updating
- Check that the dependency expression is correct
- Verify the referenced note ID exists
- Look for typos in
getVariable()property names
Unexpected Values
- Click the note to see both Raw and Evaluated values
- Trace the dependency chain to find where values diverge
- Check for conflicting dependencies
Next Steps
- Working with Octaves - Octave manipulation techniques
- Measure-Based Timing - Tempo and beat dependencies
- Expression Syntax Reference - Full expression guide