{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://tune.toys/schemas/platform/media-analysis.schema.json",
  "title": "SoundAnalysis",
  "description": "One engine run over a media version: its state, the facet summary the index reads and the full report. A newer engine version appends a row; the resolved view takes the newest ready one.",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "versionId": {
      "$ref": "common.schema.json#/$defs/EntityId"
    },
    "engine": {
      "type": "string",
      "minLength": 1,
      "maxLength": 64
    },
    "engineVersion": {
      "$ref": "common.schema.json#/$defs/SemVer"
    },
    "state": {
      "$ref": "enums.schema.json#/$defs/AnalysisState"
    },
    "summary": {
      "anyOf": [
        {
          "$ref": "#/$defs/AnalysisSummary"
        },
        {
          "type": "null"
        }
      ]
    },
    "report": {
      "anyOf": [
        {
          "$ref": "#/$defs/AnalysisReport"
        },
        {
          "type": "null"
        }
      ]
    },
    "error": {
      "anyOf": [
        {
          "type": "string",
          "minLength": 1,
          "maxLength": 512,
          "description": "Failure or unsupported reason, plain text."
        },
        {
          "type": "null"
        }
      ]
    },
    "startedAt": {
      "anyOf": [
        {
          "$ref": "common.schema.json#/$defs/Timestamp"
        },
        {
          "type": "null"
        }
      ]
    },
    "finishedAt": {
      "anyOf": [
        {
          "$ref": "common.schema.json#/$defs/Timestamp"
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "versionId",
    "engine",
    "engineVersion",
    "state",
    "summary",
    "report",
    "error",
    "startedAt",
    "finishedAt"
  ],
  "$defs": {
    "TagScore": {
      "title": "TagScore",
      "description": "A vocabulary id with its zero-shot score.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 64
        },
        "score": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "0 (a guess) to 1 (certain)."
        }
      },
      "required": ["id", "score"]
    },
    "TagScores": {
      "title": "TagScores",
      "description": "Optional stage-3 tag scores, present only when the embedding model ran.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "instruments": {
          "type": "array",
          "maxItems": 16,
          "uniqueItems": true,
          "items": {
            "$ref": "#/$defs/TagScore"
          }
        },
        "genres": {
          "type": "array",
          "maxItems": 16,
          "uniqueItems": true,
          "items": {
            "$ref": "#/$defs/TagScore"
          }
        },
        "moods": {
          "type": "array",
          "maxItems": 16,
          "uniqueItems": true,
          "items": {
            "$ref": "#/$defs/TagScore"
          }
        },
        "vocals": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "present": {
              "type": "boolean"
            },
            "confidence": {
              "type": "number",
              "minimum": 0,
              "maximum": 1,
              "description": "0 (a guess) to 1 (certain)."
            }
          },
          "required": ["present", "confidence"]
        }
      },
      "required": ["instruments", "genres", "moods"]
    },
    "AnalysisSummary": {
      "title": "AnalysisSummary",
      "description": "The subset the media index needs, each estimate with its confidence; null where the engine reported nothing.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "durationMs": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "tempo": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "bpm": {
                  "type": "number",
                  "minimum": 1,
                  "maximum": 1000
                },
                "confidence": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1,
                  "description": "0 (a guess) to 1 (certain)."
                }
              },
              "required": ["bpm", "confidence"]
            },
            {
              "type": "null"
            }
          ]
        },
        "key": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "root": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 11,
                  "description": "Pitch class of the key root: 0 = C … 11 = B."
                },
                "mode": {
                  "$ref": "enums.schema.json#/$defs/MusicalMode"
                },
                "tonality": {
                  "$ref": "enums.schema.json#/$defs/Tonality"
                },
                "camelot": {
                  "type": "string",
                  "pattern": "^(1[0-2]|[1-9])[AB]$",
                  "description": "Camelot wheel code: 1A–12A minor, 1B–12B major."
                },
                "confidence": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1,
                  "description": "0 (a guess) to 1 (certain)."
                }
              },
              "required": ["root", "mode", "tonality", "camelot", "confidence"]
            },
            {
              "type": "null"
            }
          ]
        },
        "meter": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "numerator": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 32
                },
                "denominator": {
                  "type": "integer",
                  "enum": [1, 2, 4, 8, 16]
                },
                "confidence": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1,
                  "description": "0 (a guess) to 1 (certain)."
                }
              },
              "required": ["numerator", "denominator", "confidence"]
            },
            {
              "type": "null"
            }
          ]
        },
        "loudnessLufs": {
          "anyOf": [
            {
              "type": "number",
              "minimum": -100,
              "maximum": 10
            },
            {
              "type": "null"
            }
          ]
        },
        "rootMidi": {
          "anyOf": [
            {
              "type": "integer",
              "minimum": 0,
              "maximum": 127
            },
            {
              "type": "null"
            }
          ]
        },
        "soundType": {
          "anyOf": [
            {
              "$ref": "enums.schema.json#/$defs/SoundType"
            },
            {
              "type": "null"
            }
          ]
        },
        "tags": {
          "anyOf": [
            {
              "$ref": "#/$defs/TagScores"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "required": [
        "durationMs",
        "tempo",
        "key",
        "meter",
        "loudnessLufs",
        "rootMidi",
        "soundType",
        "tags"
      ]
    },
    "AnalysisEngine": {
      "title": "AnalysisEngine",
      "description": "The engine build that produced a report.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 64
        },
        "version": {
          "$ref": "common.schema.json#/$defs/SemVer"
        },
        "target": {
          "type": "string",
          "enum": ["native", "wasm"]
        }
      },
      "required": ["name", "version", "target"]
    },
    "AnalysisInput": {
      "title": "AnalysisInput",
      "description": "What was decoded.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "sha256": {
          "$ref": "common.schema.json#/$defs/Sha256Hex"
        },
        "mediaType": {
          "type": "string",
          "minLength": 3,
          "maxLength": 128,
          "pattern": "^[a-z]+/[A-Za-z0-9!#$&^_.+-]+$",
          "description": "Admitted media type without parameters."
        },
        "sampleRate": {
          "type": "integer",
          "minimum": 1,
          "maximum": 1000000
        },
        "channels": {
          "type": "integer",
          "minimum": 1,
          "maximum": 64
        },
        "bitDepth": {
          "anyOf": [
            {
              "type": "integer",
              "minimum": 1,
              "maximum": 64
            },
            {
              "type": "null"
            }
          ]
        },
        "durationMs": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "decoded": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "sampleRate": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000000
            },
            "frames": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          },
          "required": ["sampleRate", "frames"]
        }
      },
      "required": [
        "sha256",
        "mediaType",
        "sampleRate",
        "channels",
        "bitDepth",
        "durationMs",
        "decoded"
      ]
    },
    "Loudness": {
      "title": "Loudness",
      "description": "EBU R128 loudness and level facts.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "integratedLufs": {
          "type": "number",
          "minimum": -100,
          "maximum": 10
        },
        "rangeLu": {
          "type": "number",
          "minimum": 0,
          "maximum": 100
        },
        "truePeakDbtp": {
          "type": "number",
          "minimum": -100,
          "maximum": 20
        },
        "samplePeakDbfs": {
          "type": "number",
          "minimum": -100,
          "maximum": 20
        },
        "rmsDbfs": {
          "type": "number",
          "minimum": -100,
          "maximum": 20
        },
        "dcOffset": {
          "type": "number",
          "minimum": -1,
          "maximum": 1
        },
        "clippedSamples": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "integratedLufs",
        "rangeLu",
        "truePeakDbtp",
        "samplePeakDbfs",
        "rmsDbfs",
        "dcOffset",
        "clippedSamples"
      ]
    },
    "TempoCandidate": {
      "title": "TempoCandidate",
      "description": "A tempo hypothesis and its score.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "bpm": {
          "type": "number",
          "minimum": 1,
          "maximum": 1000
        },
        "score": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "0 (a guess) to 1 (certain)."
        }
      },
      "required": ["bpm", "score"]
    },
    "Tempo": {
      "title": "Tempo",
      "description": "Tempo estimate from onset autocorrelation.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "bpm": {
          "type": "number",
          "minimum": 1,
          "maximum": 1000
        },
        "confidence": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "0 (a guess) to 1 (certain)."
        },
        "candidates": {
          "type": "array",
          "maxItems": 8,
          "uniqueItems": false,
          "items": {
            "$ref": "#/$defs/TempoCandidate"
          }
        },
        "beatsMs": {
          "type": "array",
          "maxItems": 100000,
          "items": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          }
        },
        "barAligned": {
          "type": "boolean"
        },
        "bars": {
          "anyOf": [
            {
              "type": "number",
              "minimum": 0,
              "maximum": 1000000
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "required": [
        "bpm",
        "confidence",
        "candidates",
        "beatsMs",
        "barAligned",
        "bars"
      ]
    },
    "MeterEstimate": {
      "title": "MeterEstimate",
      "description": "Meter estimate from beat grouping.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "numerator": {
          "type": "integer",
          "minimum": 1,
          "maximum": 32
        },
        "denominator": {
          "type": "integer",
          "enum": [1, 2, 4, 8, 16]
        },
        "confidence": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "0 (a guess) to 1 (certain)."
        }
      },
      "required": ["numerator", "denominator", "confidence"]
    },
    "KeyAlternative": {
      "title": "KeyAlternative",
      "description": "A lower-scoring key hypothesis.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "root": {
          "type": "integer",
          "minimum": 0,
          "maximum": 11,
          "description": "Pitch class of the key root: 0 = C … 11 = B."
        },
        "mode": {
          "$ref": "enums.schema.json#/$defs/MusicalMode"
        },
        "score": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "0 (a guess) to 1 (certain)."
        }
      },
      "required": ["root", "mode", "score"]
    },
    "KeyEstimate": {
      "title": "KeyEstimate",
      "description": "Key estimate from profile correlation.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "root": {
          "type": "integer",
          "minimum": 0,
          "maximum": 11,
          "description": "Pitch class of the key root: 0 = C … 11 = B."
        },
        "mode": {
          "$ref": "enums.schema.json#/$defs/MusicalMode"
        },
        "tonality": {
          "$ref": "enums.schema.json#/$defs/Tonality"
        },
        "camelot": {
          "type": "string",
          "pattern": "^(1[0-2]|[1-9])[AB]$",
          "description": "Camelot wheel code: 1A–12A minor, 1B–12B major."
        },
        "confidence": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "0 (a guess) to 1 (certain)."
        },
        "tuningCents": {
          "type": "number",
          "minimum": -50,
          "maximum": 50
        },
        "alternatives": {
          "type": "array",
          "maxItems": 8,
          "uniqueItems": false,
          "items": {
            "$ref": "#/$defs/KeyAlternative"
          }
        },
        "chroma": {
          "type": "array",
          "minItems": 12,
          "maxItems": 12,
          "items": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        }
      },
      "required": [
        "root",
        "mode",
        "tonality",
        "camelot",
        "confidence",
        "tuningCents",
        "alternatives",
        "chroma"
      ]
    },
    "Pitch": {
      "title": "Pitch",
      "description": "Root pitch of a tuned sound (pYIN on the attack).",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "midi": {
          "type": "integer",
          "minimum": 0,
          "maximum": 127
        },
        "note": {
          "type": "string",
          "minLength": 2,
          "maxLength": 4,
          "pattern": "^[A-G][#b]?-?[0-9]$"
        },
        "cents": {
          "type": "number",
          "minimum": -50,
          "maximum": 50
        },
        "confidence": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "0 (a guess) to 1 (certain)."
        }
      },
      "required": ["midi", "note", "cents", "confidence"]
    },
    "Structure": {
      "title": "Structure",
      "description": "Temporal structure and quality flags.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "soundType": {
          "$ref": "enums.schema.json#/$defs/SoundType"
        },
        "oneShot": {
          "type": "boolean"
        },
        "silenceHeadMs": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "silenceTailMs": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "onsetCount": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "transientsPerSecond": {
          "type": "number",
          "minimum": 0,
          "maximum": 100000
        }
      },
      "required": [
        "soundType",
        "oneShot",
        "silenceHeadMs",
        "silenceTailMs",
        "onsetCount",
        "transientsPerSecond"
      ]
    },
    "Spectral": {
      "title": "Spectral",
      "description": "Spectral descriptors averaged over the file.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "centroidHz": {
          "type": "number",
          "minimum": 0,
          "maximum": 1000000
        },
        "rolloffHz": {
          "type": "number",
          "minimum": 0,
          "maximum": 1000000
        },
        "flatness": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "bandwidthHz": {
          "type": "number",
          "minimum": 0,
          "maximum": 1000000
        },
        "zcr": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        }
      },
      "required": ["centroidHz", "rolloffHz", "flatness", "bandwidthHz", "zcr"]
    },
    "AnalysisReport": {
      "title": "AnalysisReport",
      "description": "The full `tt-analysis` report: stable field order, every number finite, at most 256 KiB. Sections the engine could not compute are null.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "engine": {
          "$ref": "#/$defs/AnalysisEngine"
        },
        "input": {
          "$ref": "#/$defs/AnalysisInput"
        },
        "loudness": {
          "anyOf": [
            {
              "$ref": "#/$defs/Loudness"
            },
            {
              "type": "null"
            }
          ]
        },
        "tempo": {
          "anyOf": [
            {
              "$ref": "#/$defs/Tempo"
            },
            {
              "type": "null"
            }
          ]
        },
        "meter": {
          "anyOf": [
            {
              "$ref": "#/$defs/MeterEstimate"
            },
            {
              "type": "null"
            }
          ]
        },
        "key": {
          "anyOf": [
            {
              "$ref": "#/$defs/KeyEstimate"
            },
            {
              "type": "null"
            }
          ]
        },
        "pitch": {
          "anyOf": [
            {
              "$ref": "#/$defs/Pitch"
            },
            {
              "type": "null"
            }
          ]
        },
        "structure": {
          "anyOf": [
            {
              "$ref": "#/$defs/Structure"
            },
            {
              "type": "null"
            }
          ]
        },
        "spectral": {
          "anyOf": [
            {
              "$ref": "#/$defs/Spectral"
            },
            {
              "type": "null"
            }
          ]
        },
        "tags": {
          "anyOf": [
            {
              "$ref": "#/$defs/TagScores"
            },
            {
              "type": "null"
            }
          ]
        },
        "renditions": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "peaks": {
              "anyOf": [
                {
                  "$ref": "common.schema.json#/$defs/EntityId"
                },
                {
                  "type": "null"
                }
              ]
            },
            "beats": {
              "anyOf": [
                {
                  "$ref": "common.schema.json#/$defs/EntityId"
                },
                {
                  "type": "null"
                }
              ]
            }
          },
          "required": ["peaks", "beats"]
        },
        "timing": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "decodeMs": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            },
            "analyzeMs": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          },
          "required": ["decodeMs", "analyzeMs"]
        }
      },
      "required": [
        "engine",
        "input",
        "loudness",
        "tempo",
        "meter",
        "key",
        "pitch",
        "structure",
        "spectral",
        "tags",
        "renditions",
        "timing"
      ]
    }
  }
}
