{
  "$id": "https://raw.githubusercontent.com/spectral-discord/TSON/main/schema/tson.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "TSON Schema",
  "type": "object",
  "properties": {
    "tunings": {
      "type": "array",
      "description": "List of tuning objects",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The tuning's name"
          },
          "description": {
            "type": "string",
            "description": "A description of the tuning"
          },
          "id": {
            "type": "string",
            "description": "A unique identifier for the tuning"
          },
          "scales": {
            "type": "array",
            "description": "List of scale objects",
            "minItems": 1,
            "items": {
              "type": "object",
              "properties": {
                "notes": {
                  "type": "array",
                  "description": "A list of the scale's notes",
                  "minItems": 1,
                  "uniqueItems": true,
                  "items": {
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "frequency ratio": {
                            "description": "The note's frequency ratio",
                            "oneOf": [
                              {
                                "type": "string",
                                "pattern": "^([1234567890.,+\\-*/^%()e ]|(pi)|(tau)|(abs)|(log))+$"
                              },
                              {
                                "type": "number"
                              }
                            ]
                          },
                          "ratio": {
                            "description": "The note's frequency ratio",
                            "oneOf": [
                              {
                                "type": "string",
                                "pattern": "^([1234567890.,+\\-*/^%()e ]|(pi)|(tau)|(abs)|(log))+$"
                              },
                              {
                                "type": "number"
                              }
                            ]
                          },
                          "name": {
                            "type": "string",
                            "description": "The note's name"
                          }
                        },
                        "additionalProperties": true
                      },
                      {
                        "description": "The note's frequency ratio",
                        "oneOf": [
                          {
                            "type": "string",
                            "pattern": "^([1234567890.,+\\-*/^%()e ]|(pi)|(tau)|(abs)|(log))+$"
                          },
                          {
                            "type": "number"
                          }
                        ]
                      }
                    ]
                  }
                },
                "reference": {
                  "type": "object",
                  "description": "A reference frequency that is used to map the note's frequency ratios to real frequencies values (ie., in Hz).\nCan be either a number (optionally appended with \" Hz\") or an object containing a frequency and an optional note that references one of the note names from the scale's notes list.\nIf no note name is provided, the reference frequency will be mapped to the frequency ratio \"1\".",
                  "properties": {
                    "frequency": {
                      "description": "The reference frequency - a number, optionally with \" Hz\" appended",
                      "oneOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "string",
                          "pattern": "^(0*[1-9][0-9]*(\\.[0-9]+)?|0+\\.[0-9]*[1-9][0-9]*)( Hz)?$"
                        }
                      ]
                    },
                    "note": {
                      "type": "string",
                      "description": "The name of the note that should be mapped onto the reference frequency"
                    }
                  },
                  "required": [
                    "frequency"
                  ],
                  "additionalProperties": true
                },
                "repeat ratio": {
                  "description": "The frequency ratio at which the scale's notes will repeat",
                  "oneOf": [
                    {
                      "type": "string",
                      "pattern": "^([1234567890.,+\\-*/^%()e ]|(pi)|(tau)|(abs)|(log))+$"
                    },
                    {
                      "type": "number"
                    }
                  ]
                },
                "repeat": {
                  "description": "The frequency ratio at which the scale's notes will repeat",
                  "oneOf": [
                    {
                      "type": "string",
                      "pattern": "^([1234567890.,+\\-*/^%()e ]|(pi)|(tau)|(abs)|(log))+$"
                    },
                    {
                      "type": "number"
                    }
                  ]
                },
                "max frequency": {
                  "description": "A maximum frequency for the scale.\nWhen mapping the scale's notes onto actual frequencies, notes from this scale will not be mapped above the provided frequency.",
                  "oneOf": [
                    {
                      "type": "number"
                    },
                    {
                      "type": "string",
                      "pattern": "^(0*[1-9][0-9]*(\\.[0-9]+)?|0+\\.[0-9]*[1-9][0-9]*)( Hz)?$"
                    }
                  ]
                },
                "max": {
                  "description": "A maximum frequency for the scale.\nWhen mapping the scale's notes onto actual frequencies, notes from this scale will not be mapped above the provided frequency.",
                  "oneOf": [
                    {
                      "type": "number"
                    },
                    {
                      "type": "string",
                      "pattern": "^(0*[1-9][0-9]*(\\.[0-9]+)?|0+\\.[0-9]*[1-9][0-9]*)( Hz)?$"
                    }
                  ]
                },
                "maximum": {
                  "description": "A maximum frequency for the scale.\nWhen mapping the scale's notes onto actual frequencies, notes from this scale will not be mapped above the provided frequency.",
                  "oneOf": [
                    {
                      "type": "number"
                    },
                    {
                      "type": "string",
                      "pattern": "^(0*[1-9][0-9]*(\\.[0-9]+)?|0+\\.[0-9]*[1-9][0-9]*)( Hz)?$"
                    }
                  ]
                },
                "min frequency": {
                  "description": "A minimum frequency for the scale.\nWhen mapping the scale's notes onto actual frequencies, notes from this scale will not be mapped below the provided frequency.",
                  "oneOf": [
                    {
                      "type": "number"
                    },
                    {
                      "type": "string",
                      "pattern": "^(0*[1-9][0-9]*(\\.[0-9]+)?|0+\\.[0-9]*[1-9][0-9]*)( Hz)?$"
                    }
                  ]
                },
                "minimum": {
                  "description": "A minimum frequency for the scale.\nWhen mapping the scale's notes onto actual frequencies, notes from this scale will not be mapped below the provided frequency.",
                  "oneOf": [
                    {
                      "type": "number"
                    },
                    {
                      "type": "string",
                      "pattern": "^(0*[1-9][0-9]*(\\.[0-9]+)?|0+\\.[0-9]*[1-9][0-9]*)( Hz)?$"
                    }
                  ]
                },
                "min": {
                  "description": "A minimum frequency for the scale.\nWhen mapping the scale's notes onto actual frequencies, notes from this scale will not be mapped below the provided frequency.",
                  "oneOf": [
                    {
                      "type": "number"
                    },
                    {
                      "type": "string",
                      "pattern": "^(0*[1-9][0-9]*(\\.[0-9]+)?|0+\\.[0-9]*[1-9][0-9]*)( Hz)?$"
                    }
                  ]
                },
                "spectrum": {
                  "type": "string",
                  "description": "The spectrum of the tones that should be used for this tuning.\nThis enables multiple, scale-dependent spectra to be used within a single tuning."
                }
              },
              "required": [
                "notes",
                "reference"
              ],
              "additionalProperties": true,
              "allOf": [
                {
                  "not": {
                    "required": [
                      "repeat",
                      "repeat ratio"
                    ]
                  }
                },
                {
                  "oneOf": [
                    {
                      "required": [
                        "min"
                      ]
                    },
                    {
                      "required": [
                        "minimum"
                      ]
                    },
                    {
                      "required": [
                        "min frequency"
                      ]
                    },
                    {
                      "not": {
                        "oneOf": [
                          {
                            "required": [
                              "min"
                            ]
                          },
                          {
                            "required": [
                              "minimum"
                            ]
                          },
                          {
                            "required": [
                              "min frequency"
                            ]
                          },
                          {
                            "required": [
                              "min",
                              "minimum"
                            ]
                          },
                          {
                            "required": [
                              "min",
                              "min frequency"
                            ]
                          },
                          {
                            "required": [
                              "minimum",
                              "min frequency"
                            ]
                          }
                        ]
                      }
                    }
                  ]
                },
                {
                  "oneOf": [
                    {
                      "required": [
                        "max"
                      ]
                    },
                    {
                      "required": [
                        "maximum"
                      ]
                    },
                    {
                      "required": [
                        "max frequency"
                      ]
                    },
                    {
                      "not": {
                        "oneOf": [
                          {
                            "required": [
                              "max"
                            ]
                          },
                          {
                            "required": [
                              "maximum"
                            ]
                          },
                          {
                            "required": [
                              "max frequency"
                            ]
                          },
                          {
                            "required": [
                              "max",
                              "maximum"
                            ]
                          },
                          {
                            "required": [
                              "max",
                              "max frequency"
                            ]
                          },
                          {
                            "required": [
                              "maximum",
                              "max frequency"
                            ]
                          }
                        ]
                      }
                    }
                  ]
                }
              ]
            }
          }
        },
        "required": [
          "id",
          "scales"
        ],
        "additionalProperties": true
      }
    },
    "spectra": {
      "type": "array",
      "description": "A list of spectrum objects",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The spectrum's name"
          },
          "description": {
            "type": "string",
            "description": "A description of the spectrum"
          },
          "id": {
            "type": "string",
            "description": "A unique identifier for the spectrum"
          },
          "partial distribution": {
            "type": "array",
            "description": "A list of partials that should be used to reconstruct the spectrum",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "type": "object",
              "properties": {
                "frequency ratio": {
                  "description": "The partial's frequency ratio",
                  "oneOf": [
                    {
                      "type": "string",
                      "pattern": "^([1234567890.,+\\-*/^%()e ]|(pi)|(tau)|(abs)|(log))+$"
                    },
                    {
                      "type": "number"
                    }
                  ]
                },
                "ratio": {
                  "description": "The partial's frequency ratio",
                  "oneOf": [
                    {
                      "type": "string",
                      "pattern": "^([1234567890.,+\\-*/^%()e ]|(pi)|(tau)|(abs)|(log))+$"
                    },
                    {
                      "type": "number"
                    }
                  ]
                },
                "amplitude weight": {
                  "description": "The partial's amplitude weight.\nThis determines how much the partial contributes to the overall power (ie., loudness) of the reconstructed spectrum.",
                  "oneOf": [
                    {
                      "type": "string",
                      "pattern": "^([1234567890.,+\\-*/^%()e ]|(pi)|(tau)|(abs)|(log))+$"
                    },
                    {
                      "type": "number"
                    }
                  ]
                },
                "weight": {
                  "description": "The partial's amplitude weight.\nThis determines how much the partial contributes to the overall power (ie., loudness) of the reconstructed spectrum.",
                  "oneOf": [
                    {
                      "type": "string",
                      "pattern": "^([1234567890.,+\\-*/^%()e ]|(pi)|(tau)|(abs)|(log))+$"
                    },
                    {
                      "type": "number"
                    }
                  ]
                }
              },
              "additionalProperties": true,
              "allOf": [
                {
                  "if": {
                    "propertyNames": {
                      "enum": [
                        "frequency ratio",
                        "ratio"
                      ]
                    },
                    "minProperties": 2
                  },
                  "then": false,
                  "else": {
                    "oneOf": [
                      {
                        "required": [
                          "frequency ratio"
                        ]
                      },
                      {
                        "required": [
                          "ratio"
                        ]
                      }
                    ]
                  }
                },
                {
                  "if": {
                    "propertyNames": {
                      "enum": [
                        "amplitude weight",
                        "weight"
                      ]
                    },
                    "minProperties": 2
                  },
                  "then": false,
                  "else": {
                    "oneOf": [
                      {
                        "required": [
                          "amplitude weight"
                        ]
                      },
                      {
                        "required": [
                          "weight"
                        ]
                      }
                    ]
                  }
                }
              ]
            }
          },
          "partials": {
            "type": "array",
            "description": "A list of partials that should be used to reconstruct the spectrum",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "type": "object",
              "properties": {
                "frequency ratio": {
                  "description": "The partial's frequency ratio",
                  "oneOf": [
                    {
                      "type": "string",
                      "pattern": "^([1234567890.,+\\-*/^%()e ]|(pi)|(tau)|(abs)|(log))+$"
                    },
                    {
                      "type": "number"
                    }
                  ]
                },
                "ratio": {
                  "description": "The partial's frequency ratio",
                  "oneOf": [
                    {
                      "type": "string",
                      "pattern": "^([1234567890.,+\\-*/^%()e ]|(pi)|(tau)|(abs)|(log))+$"
                    },
                    {
                      "type": "number"
                    }
                  ]
                },
                "amplitude weight": {
                  "description": "The partial's amplitude weight.\nThis determines how much the partial contributes to the overall power (ie., loudness) of the reconstructed spectrum.",
                  "oneOf": [
                    {
                      "type": "string",
                      "pattern": "^([1234567890.,+\\-*/^%()e ]|(pi)|(tau)|(abs)|(log))+$"
                    },
                    {
                      "type": "number"
                    }
                  ]
                },
                "weight": {
                  "description": "The partial's amplitude weight.\nThis determines how much the partial contributes to the overall power (ie., loudness) of the reconstructed spectrum.",
                  "oneOf": [
                    {
                      "type": "string",
                      "pattern": "^([1234567890.,+\\-*/^%()e ]|(pi)|(tau)|(abs)|(log))+$"
                    },
                    {
                      "type": "number"
                    }
                  ]
                }
              },
              "additionalProperties": true,
              "allOf": [
                {
                  "if": {
                    "propertyNames": {
                      "enum": [
                        "frequency ratio",
                        "ratio"
                      ]
                    },
                    "minProperties": 2
                  },
                  "then": false,
                  "else": {
                    "oneOf": [
                      {
                        "required": [
                          "frequency ratio"
                        ]
                      },
                      {
                        "required": [
                          "ratio"
                        ]
                      }
                    ]
                  }
                },
                {
                  "if": {
                    "propertyNames": {
                      "enum": [
                        "amplitude weight",
                        "weight"
                      ]
                    },
                    "minProperties": 2
                  },
                  "then": false,
                  "else": {
                    "oneOf": [
                      {
                        "required": [
                          "amplitude weight"
                        ]
                      },
                      {
                        "required": [
                          "weight"
                        ]
                      }
                    ]
                  }
                }
              ]
            }
          }
        },
        "required": [
          "id"
        ],
        "additionalProperties": true,
        "if": {
          "propertyNames": {
            "enum": [
              "partials",
              "partial distribution"
            ]
          },
          "minProperties": 2
        },
        "then": false,
        "else": {
          "oneOf": [
            {
              "required": [
                "partials"
              ]
            },
            {
              "required": [
                "partial distribution"
              ]
            }
          ]
        }
      }
    },
    "sets": {
      "type": "array",
      "description": "A list of set objects",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "A unique identifier for the set"
          },
          "name": {
            "type": "string",
            "description": "The set's name"
          },
          "description": {
            "type": "string",
            "description": "A description of the set"
          },
          "members": {
            "type": "array",
            "description": "A list of set member objects",
            "minItems": 1,
            "items": {
              "type": "object",
              "properties": {
                "tuning": {
                  "type": "string",
                  "description": "A reference of a tuning's ID"
                },
                "spectrum": {
                  "type": "string",
                  "description": "A reference of a spectrum's ID"
                },
                "override scale spectra": {
                  "type": "boolean",
                  "description": "If true, the set's spectrum should be applied to all scales in the set's tuning, overriding any spectra that are references by the scales."
                }
              },
              "additionalProperties": true
            }
          }
        },
        "required": [
          "id",
          "members"
        ],
        "additionalProperties": true
      }
    }
  },
  "additionalProperties": true,
  "anyOf": [
    {
      "required": [
        "tunings"
      ]
    },
    {
      "required": [
        "spectra"
      ]
    },
    {
      "required": [
        "sets"
      ]
    }
  ]
}