{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://signalsandsorcery.com/contract/arrangement-export/v1/schema.json",
  "title": "Signals & Sorcery arrangement export 1.x (latest: 1.2.0)",
  "description": "The export.json written beside an arrangement export's audio. Semantics: SPEC.md. Readers ignore properties they don't know, accept a higher minor version and refuse an unknown major.",
  "type": "object",
  "required": [
    "schema",
    "renderedAt",
    "project",
    "arrangement",
    "contractVersion",
    "engine",
    "sampleRate",
    "lengthSeconds",
    "options",
    "name",
    "tail",
    "files",
    "master",
    "nullTest",
    "monoContent",
    "buses",
    "abletonBundle",
    "staleStemsRendered",
    "warnings"
  ],
  "properties": {
    "$schema": {
      "type": "string",
      "format": "uri",
      "description": "The exact schema version's URL."
    },
    "exportVersion": {
      "type": "string",
      "pattern": "^1\\.[0-9]+\\.[0-9]+$",
      "description": "The format version; absent = 1.0.0."
    },
    "exportId": {
      "type": "string",
      "format": "uuid",
      "description": "New for every export."
    },
    "timingHash": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$",
      "description": "SPEC.md \"Change detection\"."
    },
    "arrangementHash": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$",
      "description": "SPEC.md \"Change detection\"."
    },
    "scoreHash": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$",
      "description": "SPEC.md \"Change detection\"; present with score."
    },
    "score": {
      "type": "object",
      "description": "The resolved score (SPEC.md \"Score\"): the timing maps, the bar grid, the sections and every layer as it plays.",
      "required": [
        "v",
        "tempoMap",
        "meterMap",
        "bars",
        "sections",
        "layers"
      ],
      "properties": {
        "v": {
          "const": 1
        },
        "noteFields": {
          "const": [
            "frame",
            "pitch",
            "velocity",
            "durationFrames"
          ],
          "description": "Present when the score includes notes: the order of a note tuple."
        },
        "tempoMap": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "required": [
              "bar",
              "beat",
              "frame",
              "bpm"
            ],
            "properties": {
              "bar": {
                "type": "integer",
                "minimum": 1
              },
              "beat": {
                "type": "number",
                "minimum": 0
              },
              "frame": {
                "type": "integer",
                "minimum": 0
              },
              "bpm": {
                "type": "number",
                "exclusiveMinimum": 0
              }
            }
          }
        },
        "meterMap": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "bar",
              "beat",
              "frame",
              "numerator",
              "denominator"
            ],
            "properties": {
              "bar": {
                "type": "integer",
                "minimum": 1
              },
              "beat": {
                "type": "number",
                "minimum": 0
              },
              "frame": {
                "type": "integer",
                "minimum": 0
              },
              "numerator": {
                "type": "integer",
                "minimum": 1
              },
              "denominator": {
                "type": "integer",
                "minimum": 1
              }
            }
          }
        },
        "bars": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "index",
              "startFrame",
              "lengthFrames"
            ],
            "properties": {
              "index": {
                "type": "integer",
                "minimum": 1
              },
              "startFrame": {
                "type": "integer",
                "minimum": 0
              },
              "lengthFrames": {
                "type": "integer",
                "minimum": 0
              }
            }
          }
        },
        "sections": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "instanceId",
              "sourceSceneId",
              "firstBar",
              "lengthBars"
            ],
            "properties": {
              "instanceId": {
                "type": "string",
                "minLength": 1,
                "description": "= arrangement.instances[].instanceId."
              },
              "sourceSceneId": {
                "type": "string",
                "minLength": 1
              },
              "firstBar": {
                "type": "integer",
                "minimum": 1
              },
              "lengthBars": {
                "type": "integer",
                "minimum": 1
              },
              "role": {
                "type": "string",
                "description": "The section's role in the song form; absent until the arrangement carries one."
              }
            }
          }
        },
        "layers": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "layerId",
              "name",
              "role",
              "bucket",
              "spans",
              "treatments"
            ],
            "properties": {
              "layerId": {
                "type": "string",
                "minLength": 1,
                "description": "The catalog track id (= files[].layerIds)."
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "role": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "bucket": {
                "enum": [
                  "drums",
                  "bass",
                  "harmony",
                  "top",
                  null
                ]
              },
              "drumClass": {
                "enum": [
                  "kick",
                  "snare",
                  "hat",
                  "perc",
                  "cymbal",
                  "unknown",
                  "kit"
                ]
              },
              "drumMap": {
                "type": "object",
                "propertyNames": {
                  "pattern": "^[0-9]{1,3}$"
                },
                "additionalProperties": {
                  "enum": [
                    "kick",
                    "snare",
                    "hat",
                    "perc",
                    "cymbal",
                    "unknown"
                  ]
                }
              },
              "silent": {
                "const": true
              },
              "spans": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "section",
                    "startBar",
                    "endBar",
                    "startFrame",
                    "endFrame",
                    "gainDb",
                    "gainPoints"
                  ],
                  "properties": {
                    "section": {
                      "type": "string",
                      "minLength": 1
                    },
                    "startBar": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "endBar": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "startFrame": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "endFrame": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "continues": {
                      "const": true
                    },
                    "gainDb": {
                      "type": "number"
                    },
                    "gainPoints": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "frame",
                          "db"
                        ],
                        "properties": {
                          "frame": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "db": {
                            "type": "number"
                          }
                        }
                      }
                    },
                    "fadeIn": {
                      "type": "object",
                      "required": [
                        "frames",
                        "curve"
                      ],
                      "properties": {
                        "frames": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "curve": {
                          "type": "string",
                          "description": "SPEC.md \"Fades\": equalPower (default; also any unknown name), linear, exponential, sCurve."
                        }
                      }
                    },
                    "fadeOut": {
                      "type": "object",
                      "required": [
                        "frames",
                        "curve"
                      ],
                      "properties": {
                        "frames": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "curve": {
                          "type": "string",
                          "description": "SPEC.md \"Fades\": equalPower (default; also any unknown name), linear, exponential, sCurve."
                        }
                      }
                    }
                  }
                }
              },
              "treatments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "section",
                    "type",
                    "bar",
                    "bars",
                    "mode",
                    "startFrame",
                    "endFrame",
                    "params",
                    "gainDb"
                  ],
                  "properties": {
                    "section": {
                      "type": "string",
                      "minLength": 1
                    },
                    "type": {
                      "type": "string",
                      "minLength": 1
                    },
                    "bar": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "bars": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "mode": {
                      "enum": [
                        "replace",
                        "add"
                      ]
                    },
                    "startFrame": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "endFrame": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "params": {
                      "type": "object",
                      "additionalProperties": {
                        "anyOf": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "string"
                          }
                        ]
                      }
                    },
                    "gainDb": {
                      "type": "number"
                    }
                  }
                }
              },
              "notes": {
                "type": "array",
                "items": {
                  "type": "array",
                  "prefixItems": [
                    {
                      "type": "integer",
                      "minimum": 0
                    },
                    {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 127
                    },
                    {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 127
                    },
                    {
                      "type": "integer",
                      "minimum": 1
                    }
                  ],
                  "minItems": 4,
                  "maxItems": 4,
                  "description": "[frame, pitch, velocity, durationFrames] (noteFields)."
                }
              }
            }
          }
        }
      }
    },
    "schema": {
      "const": "sas-arrangement-export/1"
    },
    "renderedAt": {
      "type": "string",
      "format": "date-time",
      "description": "When the export started (UTC)."
    },
    "project": {
      "type": "object",
      "required": [
        "id",
        "name",
        "bpm"
      ],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1,
          "description": "Local to the machine: a project imported elsewhere gets a new id."
        },
        "name": {
          "type": "string"
        },
        "bpm": {
          "type": "number",
          "exclusiveMinimum": 0,
          "description": "Quarter notes per minute; constant over the song."
        }
      }
    },
    "arrangement": {
      "type": "object",
      "required": [
        "id",
        "name",
        "planId",
        "instances"
      ],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1
        },
        "name": {
          "type": "string"
        },
        "planId": {
          "type": "string",
          "description": "A new id per render plan: never stable."
        },
        "instances": {
          "type": "array",
          "items": {
            "type": "object",
            "description": "A section: one instance on the timeline, in the export's `sampleRate` frames (SPEC.md \"Sections\").",
            "required": [
              "instanceId",
              "label",
              "startFrame",
              "lengthFrames"
            ],
            "properties": {
              "instanceId": {
                "type": "string",
                "minLength": 1,
                "description": "Stable across saves and re-exports (and across a project import)."
              },
              "label": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The instance label, or \"<scene name> <ordinal>\" (e.g. \"Chorus 2\")."
              },
              "startFrame": {
                "type": "integer",
                "minimum": 0
              },
              "lengthFrames": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "description": "In timeline order: by (orderKey, id) in the arrangement."
        },
        "revision": {
          "type": "object",
          "required": [
            "seq",
            "docHash"
          ],
          "properties": {
            "seq": {
              "type": "integer",
              "minimum": 0,
              "description": "The arrangement's latest applied edit batch: grows with every edit, not dense, local to the machine."
            },
            "docHash": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$",
              "description": "SHA-256 of the arrangement document's canonical JSON."
            }
          }
        },
        "endFrame": {
          "type": "integer",
          "minimum": 0,
          "description": "The last bar's end, in `sampleRate` frames."
        }
      }
    },
    "contractVersion": {
      "type": "string",
      "description": "The arranger semantics the export was made under. Informational: it moves for changes that never touch the export."
    },
    "engine": {
      "type": "object",
      "required": [
        "sha256"
      ],
      "properties": {
        "sha256": {
          "oneOf": [
            {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$"
            },
            {
              "type": "null"
            }
          ]
        }
      }
    },
    "sampleRate": {
      "type": "integer",
      "minimum": 1,
      "description": "The rate of every frame number in this file except files[].frames."
    },
    "lengthSeconds": {
      "type": "number",
      "minimum": 0,
      "description": "The rendered length, tail included (the last bar ends earlier)."
    },
    "options": {
      "type": "object",
      "description": "The export request, as made.",
      "required": [
        "mix",
        "master",
        "stems",
        "editableStems",
        "ableton",
        "preset",
        "masterBitDepth",
        "stemBitDepth",
        "renderStale"
      ],
      "properties": {
        "destination": {
          "type": "string",
          "description": "Absolute folder the export was written into; absent with pathFree."
        },
        "name": {
          "type": "string"
        },
        "tail": {
          "oneOf": [
            {
              "type": "object",
              "required": [
                "mode"
              ],
              "properties": {
                "mode": {
                  "const": "auto"
                }
              }
            },
            {
              "type": "object",
              "required": [
                "mode",
                "seconds"
              ],
              "properties": {
                "mode": {
                  "const": "fixed"
                },
                "seconds": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 30
                }
              }
            }
          ]
        },
        "mix": {
          "type": "boolean"
        },
        "master": {
          "type": "boolean"
        },
        "stems": {
          "type": "boolean"
        },
        "editableStems": {
          "type": "boolean"
        },
        "ableton": {
          "type": "boolean"
        },
        "preset": {
          "enum": [
            "streaming",
            "loud",
            "custom"
          ]
        },
        "targetLufs": {
          "type": "number"
        },
        "ceilingDbtp": {
          "type": "number"
        },
        "masterBitDepth": {
          "enum": [
            16,
            24,
            32
          ]
        },
        "stemBitDepth": {
          "enum": [
            24,
            32
          ]
        },
        "sampleRate": {
          "enum": [
            44100,
            48000,
            96000
          ],
          "description": "The master's delivery rate (the other files stay at the export's sampleRate)."
        },
        "renderStale": {
          "type": "boolean"
        },
        "pathFree": {
          "type": "boolean",
          "description": "Absolute paths were left out (SPEC.md \"Privacy\")."
        },
        "score": {
          "type": "boolean",
          "description": "The resolved `score` was asked for (SPEC.md \"Score\"). Absent = false."
        },
        "scoreNotes": {
          "type": "boolean",
          "description": "The score includes the notes. Absent = false."
        }
      }
    },
    "name": {
      "type": "string"
    },
    "tail": {
      "description": "How far the audio runs past the last bar (SPEC.md \"Tail\").",
      "oneOf": [
        {
          "type": "object",
          "required": [
            "mode",
            "capSeconds",
            "floorDbfs"
          ],
          "properties": {
            "mode": {
              "const": "auto"
            },
            "capSeconds": {
              "type": "number"
            },
            "floorDbfs": {
              "type": "number"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "mode",
            "seconds"
          ],
          "properties": {
            "mode": {
              "const": "fixed"
            },
            "seconds": {
              "type": "number",
              "minimum": 0
            }
          }
        }
      ]
    },
    "files": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "kind",
          "label",
          "file",
          "sha256",
          "frames",
          "sampleRate",
          "bitDepth",
          "peakDbfs"
        ],
        "properties": {
          "kind": {
            "enum": [
              "mix",
              "master",
              "stem",
              "editable"
            ]
          },
          "label": {
            "type": "string"
          },
          "file": {
            "type": "string",
            "minLength": 1,
            "description": "Bundle-relative path, \"/\" separators."
          },
          "sha256": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$",
            "description": "Of the whole file (header included): the audio hash."
          },
          "frames": {
            "type": "integer",
            "minimum": 0,
            "description": "In the file's OWN sample rate."
          },
          "sampleRate": {
            "type": "integer",
            "minimum": 1
          },
          "bitDepth": {
            "type": "integer",
            "minimum": 1
          },
          "peakDbfs": {
            "type": [
              "number",
              "null"
            ],
            "description": "Null when the file is silent."
          },
          "layerIds": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1
            },
            "uniqueItems": true,
            "description": "The layers (catalog track ids) a stem carries. Absent on the mix and master (every audible layer)."
          },
          "startFrame": {
            "const": 0,
            "description": "The song frame of the file's first sample: always 0 (no pre-roll)."
          },
          "latencyMs": {
            "type": "number",
            "minimum": 0,
            "description": "Known UNcompensated latency, ms: 0 (SPEC.md \"Alignment\")."
          }
        }
      }
    },
    "master": {
      "oneOf": [
        {
          "type": "null"
        },
        {
          "type": "object",
          "required": [
            "elapsedMs",
            "input",
            "output",
            "applied",
            "warnings",
            "preset",
            "resampled"
          ],
          "properties": {
            "elapsedMs": {
              "type": "number",
              "minimum": 0
            },
            "input": {
              "type": "object",
              "required": [
                "integratedLufs",
                "lra",
                "truePeakDbtp",
                "samplePeakDbfs",
                "plrDb",
                "durationS",
                "sampleRate",
                "channels",
                "bitDepth",
                "sampleFormat"
              ],
              "properties": {
                "path": {
                  "type": "string",
                  "description": "Absolute path of the measured file; absent with pathFree."
                },
                "integratedLufs": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "lra": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "truePeakDbtp": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "samplePeakDbfs": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "plrDb": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "durationS": {
                  "type": "number",
                  "minimum": 0
                },
                "sampleRate": {
                  "type": "integer",
                  "minimum": 1
                },
                "channels": {
                  "type": "integer",
                  "minimum": 1
                },
                "bitDepth": {
                  "type": "integer",
                  "minimum": 1
                },
                "sampleFormat": {
                  "enum": [
                    "pcm",
                    "float"
                  ]
                }
              }
            },
            "output": {
              "type": "object",
              "required": [
                "integratedLufs",
                "lra",
                "truePeakDbtp",
                "samplePeakDbfs",
                "plrDb",
                "durationS",
                "sampleRate",
                "channels",
                "bitDepth",
                "sampleFormat"
              ],
              "properties": {
                "path": {
                  "type": "string",
                  "description": "Absolute path of the measured file; absent with pathFree."
                },
                "integratedLufs": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "lra": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "truePeakDbtp": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "samplePeakDbfs": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "plrDb": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "durationS": {
                  "type": "number",
                  "minimum": 0
                },
                "sampleRate": {
                  "type": "integer",
                  "minimum": 1
                },
                "channels": {
                  "type": "integer",
                  "minimum": 1
                },
                "bitDepth": {
                  "type": "integer",
                  "minimum": 1
                },
                "sampleFormat": {
                  "enum": [
                    "pcm",
                    "float"
                  ]
                }
              },
              "description": "The master file's loudness: integratedLufs and truePeakDbtp are the output's."
            },
            "applied": {
              "type": "object",
              "required": [
                "targetLufs",
                "ceilingDbtp",
                "iterations",
                "oversampling",
                "dither",
                "seed",
                "releaseMode"
              ],
              "properties": {
                "targetLufs": {
                  "type": "number"
                },
                "ceilingDbtp": {
                  "type": "number"
                },
                "preGainDb": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "trimDb": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "maxGainReductionDb": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "meanGainReductionDb": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "limitingTimePct": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "iterations": {
                  "type": "integer",
                  "minimum": 0
                },
                "oversampling": {
                  "type": "integer",
                  "minimum": 1
                },
                "dither": {
                  "enum": [
                    "tpdf",
                    "none"
                  ]
                },
                "seed": {
                  "type": "integer"
                },
                "releaseMode": {
                  "type": "string"
                },
                "releaseMs": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "lookaheadMs": {
                  "type": [
                    "number",
                    "null"
                  ]
                }
              }
            },
            "warnings": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "code",
                  "message"
                ],
                "properties": {
                  "code": {
                    "type": "string"
                  },
                  "message": {
                    "type": "string"
                  }
                }
              }
            },
            "preset": {
              "type": "string"
            },
            "resampled": {
              "oneOf": [
                {
                  "type": "null"
                },
                {
                  "type": "object",
                  "required": [
                    "fromRate",
                    "toRate",
                    "resampler"
                  ],
                  "properties": {
                    "fromRate": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "toRate": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "resampler": {
                      "type": "string"
                    }
                  }
                }
              ]
            }
          }
        }
      ]
    },
    "nullTest": {
      "oneOf": [
        {
          "type": "null"
        },
        {
          "type": "object",
          "description": "Σ stems − mix, when stems were rendered.",
          "required": [
            "frames",
            "residualPeakDbfs",
            "residualRelativeDb",
            "mixPeakDbfs",
            "pass",
            "thresholdDb",
            "mismatches"
          ],
          "properties": {
            "frames": {
              "type": "integer",
              "minimum": 0
            },
            "residualPeakDbfs": {
              "type": [
                "number",
                "null"
              ]
            },
            "residualRelativeDb": {
              "type": [
                "number",
                "null"
              ]
            },
            "mixPeakDbfs": {
              "type": [
                "number",
                "null"
              ]
            },
            "pass": {
              "type": "boolean"
            },
            "thresholdDb": {
              "type": "number"
            },
            "mismatches": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        }
      ]
    },
    "monoContent": {
      "type": "boolean"
    },
    "buses": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "busKey",
          "fx"
        ],
        "properties": {
          "busKey": {
            "type": "string"
          },
          "fx": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "name",
                "pluginId",
                "enabled",
                "version"
              ],
              "properties": {
                "name": {
                  "type": "string"
                },
                "pluginId": {
                  "type": "string"
                },
                "enabled": {
                  "type": "boolean"
                },
                "version": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "abletonBundle": {
      "type": [
        "string",
        "null"
      ]
    },
    "staleStemsRendered": {
      "type": "integer",
      "minimum": 0
    },
    "warnings": {
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  }
}
