Skip to content

Module JSON Schema

RMT Compose modules are saved as JSON files. This document describes the complete schema.

Top-Level Structure

json
{
  "baseNote": { ... },
  "notes": [ ... ]
}
FieldTypeDescription
baseNoteobjectReference note with default values
notesarrayArray of note objects

BaseNote Object

json
{
  "baseNote": {
    "frequency": "new Fraction(440)",
    "startTime": "new Fraction(0)",
    "duration": "new Fraction(1)",
    "tempo": "new Fraction(120)",
    "beatsPerMeasure": "new Fraction(4)"
  }
}
PropertyTypeDefaultDescription
frequencystring"new Fraction(440)"Base frequency in Hz
startTimestring"new Fraction(0)"Start time reference
durationstring"new Fraction(1)"Default duration
tempostring"new Fraction(60)"Tempo in BPM
beatsPerMeasurestring"new Fraction(4)"Time signature numerator

Note Object

json
{
  "id": 1,
  "frequency": "module.baseNote.getVariable('frequency').mul(new Fraction(3, 2))",
  "startTime": "module.baseNote.getVariable('startTime')",
  "duration": "new Fraction(60).div(module.findTempo(module.baseNote))",
  "color": "#4a90d9",
  "instrument": "sine-wave"
}
PropertyTypeRequiredDescription
idnumberYesUnique note identifier (positive integer)
frequencystringNoFrequency expression
startTimestringNoStart time expression
durationstringNoDuration expression
tempostringNoTempo override (rare)
beatsPerMeasurestringNoTime signature override (rare)
colorstringNoCSS color for visualization
instrumentstringNoInstrument name

Expression Strings

All expression properties are stored as strings that will be compiled at load time:

json
// Constant value
"new Fraction(440)"

// Reference to BaseNote
"module.baseNote.getVariable('frequency')"

// Reference to another note
"module.getNoteById(1).getVariable('frequency').mul(new Fraction(3, 2))"

// Complex expression
"module.getNoteById(2).getVariable('startTime').add(module.getNoteById(2).getVariable('duration'))"

Complete Example

json
{
  "baseNote": {
    "frequency": "new Fraction(440)",
    "startTime": "new Fraction(0)",
    "duration": "new Fraction(1)",
    "tempo": "new Fraction(120)",
    "beatsPerMeasure": "new Fraction(4)"
  },
  "notes": [
    {
      "id": 1,
      "frequency": "module.baseNote.getVariable('frequency')",
      "startTime": "module.baseNote.getVariable('startTime')",
      "duration": "new Fraction(60).div(module.findTempo(module.baseNote))",
      "color": "#4a90d9"
    },
    {
      "id": 2,
      "frequency": "module.baseNote.getVariable('frequency').mul(new Fraction(5, 4))",
      "startTime": "module.getNoteById(1).getVariable('startTime').add(module.getNoteById(1).getVariable('duration'))",
      "duration": "new Fraction(60).div(module.findTempo(module.baseNote))",
      "color": "#e74c3c"
    },
    {
      "id": 3,
      "frequency": "module.baseNote.getVariable('frequency').mul(new Fraction(3, 2))",
      "startTime": "module.getNoteById(2).getVariable('startTime').add(module.getNoteById(2).getVariable('duration'))",
      "duration": "new Fraction(60).div(module.findTempo(module.baseNote))",
      "color": "#2ecc71"
    }
  ]
}

This creates a simple C-E-G arpeggio using just intonation ratios.

Instruments

Built-in instrument names:

NameTypeDescription
sine-waveSynthPure sine wave
square-waveSynthSquare wave
sawtooth-waveSynthSawtooth wave
triangle-waveSynthTriangle wave
organSynthOrgan with harmonics
vibraphoneSynthVibraphone with vibrato
pianoSamplePiano samples
violinSampleViolin samples

File Extension

RMT Compose modules use the .json extension. When saving, the suggested filename is module.json.

Validation

When loading a module:

  1. ID uniqueness: All note IDs must be unique
  2. ID validity: Referenced note IDs must exist
  3. No circular dependencies: Expressions cannot form dependency cycles
  4. Valid expressions: All expression strings must be syntactically valid

Binary Format (Internal)

Internally, expressions are compiled to binary bytecode for efficient evaluation. The JSON format stores the human-readable source; bytecode is generated at load time.

See Also

Released under the RMT Personal Non-Commercial License