{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"$id": "https://audx.site/schemas/theme.schema.json",
	"title": "@litlab/audx Sound Theme",
	"description": "Schema for @litlab/audx sound theme JSON files",
	"type": "object",
	"required": ["name", "sounds"],
	"properties": {
		"$schema": {
			"type": "string"
		},
		"name": {
			"type": "string",
			"description": "Display name of the theme"
		},
		"author": {
			"type": "string"
		},
		"version": {
			"type": "string"
		},
		"description": {
			"type": "string"
		},
		"tags": {
			"type": "array",
			"items": {
				"type": "string"
			}
		},
		"license": {
			"type": "string",
			"description": "SPDX license identifier (e.g. MIT, Apache-2.0)"
		},
		"compatibility": {
			"type": "string",
			"description": "Semver range for @litlab/audx compatibility (e.g. >=1.0.0)"
		},
		"sounds": {
			"type": "object",
			"description": "Map of sound names to their definitions",
			"additionalProperties": {
				"$ref": "#/$defs/SoundDefinition"
			}
		}
	},
	"additionalProperties": false,
	"$defs": {
		"SoundDefinition": {
			"oneOf": [
				{
					"$ref": "#/$defs/Layer"
				},
				{
					"$ref": "#/$defs/MultiLayerSound"
				}
			]
		},
		"MultiLayerSound": {
			"type": "object",
			"required": ["layers"],
			"properties": {
				"layers": {
					"type": "array",
					"items": {
						"$ref": "#/$defs/Layer"
					}
				},
				"effects": {
					"type": "array",
					"items": {
						"$ref": "#/$defs/Effect"
					}
				}
			},
			"additionalProperties": false
		},
		"Layer": {
			"type": "object",
			"required": ["source"],
			"properties": {
				"source": {
					"$ref": "#/$defs/Source"
				},
				"filter": {
					"oneOf": [
						{
							"$ref": "#/$defs/Filter"
						},
						{
							"type": "array",
							"items": {
								"$ref": "#/$defs/Filter"
							}
						}
					]
				},
				"envelope": {
					"$ref": "#/$defs/Envelope"
				},
				"gain": {
					"type": "number"
				},
				"pan": {
					"type": "number",
					"minimum": -1,
					"maximum": 1
				},
				"panner": {
					"$ref": "#/$defs/Panner3D"
				},
				"delay": {
					"type": "number",
					"minimum": 0
				},
				"lfo": {
					"oneOf": [
						{
							"$ref": "#/$defs/LFO"
						},
						{
							"type": "array",
							"items": {
								"$ref": "#/$defs/LFO"
							}
						}
					]
				},
				"effects": {
					"type": "array",
					"items": {
						"$ref": "#/$defs/Effect"
					}
				}
			},
			"additionalProperties": false
		},
		"Source": {
			"oneOf": [
				{
					"$ref": "#/$defs/OscillatorSource"
				},
				{
					"$ref": "#/$defs/NoiseSource"
				},
				{
					"$ref": "#/$defs/WavetableSource"
				},
				{
					"$ref": "#/$defs/SampleSource"
				},
				{
					"$ref": "#/$defs/ConstantSource"
				}
			]
		},
		"OscillatorSource": {
			"type": "object",
			"required": ["type", "frequency"],
			"properties": {
				"type": {
					"enum": ["sine", "triangle", "square", "sawtooth"]
				},
				"frequency": {
					"oneOf": [
						{
							"type": "number"
						},
						{
							"type": "object",
							"required": ["start", "end"],
							"properties": {
								"start": {
									"type": "number"
								},
								"end": {
									"type": "number"
								}
							},
							"additionalProperties": false
						}
					]
				},
				"detune": {
					"type": "number"
				},
				"fm": {
					"type": "object",
					"required": ["ratio", "depth"],
					"properties": {
						"ratio": {
							"type": "number"
						},
						"depth": {
							"type": "number"
						}
					},
					"additionalProperties": false
				}
			},
			"additionalProperties": false
		},
		"NoiseSource": {
			"type": "object",
			"required": ["type"],
			"properties": {
				"type": {
					"const": "noise"
				},
				"color": {
					"enum": ["white", "pink", "brown"]
				}
			},
			"additionalProperties": false
		},
		"WavetableSource": {
			"type": "object",
			"required": ["type", "harmonics", "frequency"],
			"properties": {
				"type": {
					"const": "wavetable"
				},
				"harmonics": {
					"type": "array",
					"items": {
						"type": "number"
					}
				},
				"frequency": {
					"oneOf": [
						{
							"type": "number"
						},
						{
							"type": "object",
							"required": ["start", "end"],
							"properties": {
								"start": {
									"type": "number"
								},
								"end": {
									"type": "number"
								}
							},
							"additionalProperties": false
						}
					]
				}
			},
			"additionalProperties": false
		},
		"SampleSource": {
			"type": "object",
			"required": ["type"],
			"properties": {
				"type": {
					"const": "sample"
				},
				"url": {
					"type": "string"
				},
				"playbackRate": {
					"type": "number"
				},
				"detune": {
					"type": "number"
				},
				"loop": {
					"type": "boolean"
				},
				"loopStart": {
					"type": "number"
				},
				"loopEnd": {
					"type": "number"
				}
			},
			"additionalProperties": false
		},
		"ConstantSource": {
			"type": "object",
			"required": ["type"],
			"properties": {
				"type": {
					"const": "constant"
				},
				"offset": {
					"type": "number"
				}
			},
			"additionalProperties": false
		},
		"Filter": {
			"oneOf": [
				{
					"$ref": "#/$defs/BiquadFilter"
				},
				{
					"$ref": "#/$defs/IIRFilter"
				}
			]
		},
		"BiquadFilter": {
			"type": "object",
			"required": ["type", "frequency"],
			"properties": {
				"type": {
					"enum": [
						"lowpass",
						"highpass",
						"bandpass",
						"notch",
						"allpass",
						"peaking",
						"lowshelf",
						"highshelf"
					]
				},
				"frequency": {
					"type": "number"
				},
				"resonance": {
					"type": "number"
				},
				"gain": {
					"type": "number"
				},
				"envelope": {
					"$ref": "#/$defs/FilterEnvelope"
				}
			},
			"additionalProperties": false
		},
		"FilterEnvelope": {
			"type": "object",
			"required": ["peak", "decay"],
			"properties": {
				"attack": {
					"type": "number",
					"minimum": 0
				},
				"peak": {
					"type": "number"
				},
				"decay": {
					"type": "number",
					"minimum": 0
				}
			},
			"additionalProperties": false
		},
		"IIRFilter": {
			"type": "object",
			"required": ["type", "feedforward", "feedback"],
			"properties": {
				"type": {
					"const": "iir"
				},
				"feedforward": {
					"type": "array",
					"items": {
						"type": "number"
					}
				},
				"feedback": {
					"type": "array",
					"items": {
						"type": "number"
					}
				}
			},
			"additionalProperties": false
		},
		"Envelope": {
			"type": "object",
			"required": ["decay"],
			"properties": {
				"attack": {
					"type": "number",
					"minimum": 0
				},
				"decay": {
					"type": "number",
					"minimum": 0
				},
				"sustain": {
					"type": "number",
					"minimum": 0,
					"maximum": 1
				},
				"release": {
					"type": "number",
					"minimum": 0
				}
			},
			"additionalProperties": false
		},
		"LFO": {
			"type": "object",
			"required": ["type", "frequency", "depth", "target"],
			"properties": {
				"type": {
					"enum": ["sine", "triangle", "square", "sawtooth"]
				},
				"frequency": {
					"type": "number"
				},
				"depth": {
					"type": "number"
				},
				"target": {
					"enum": [
						"frequency",
						"detune",
						"gain",
						"pan",
						"filter.frequency",
						"filter.detune",
						"filter.Q",
						"filter.gain",
						"playbackRate"
					]
				}
			},
			"additionalProperties": false
		},
		"Panner3D": {
			"type": "object",
			"required": ["positionX", "positionY", "positionZ"],
			"properties": {
				"positionX": {
					"type": "number"
				},
				"positionY": {
					"type": "number"
				},
				"positionZ": {
					"type": "number"
				},
				"orientationX": {
					"type": "number"
				},
				"orientationY": {
					"type": "number"
				},
				"orientationZ": {
					"type": "number"
				},
				"panningModel": {
					"enum": ["equalpower", "HRTF"]
				},
				"distanceModel": {
					"enum": ["linear", "inverse", "exponential"]
				},
				"maxDistance": {
					"type": "number"
				},
				"refDistance": {
					"type": "number"
				},
				"rolloffFactor": {
					"type": "number"
				},
				"coneInnerAngle": {
					"type": "number"
				},
				"coneOuterAngle": {
					"type": "number"
				},
				"coneOuterGain": {
					"type": "number"
				}
			},
			"additionalProperties": false
		},
		"Effect": {
			"oneOf": [
				{
					"$ref": "#/$defs/ReverbEffect"
				},
				{
					"$ref": "#/$defs/ConvolverEffect"
				},
				{
					"$ref": "#/$defs/DelayEffect"
				},
				{
					"$ref": "#/$defs/DistortionEffect"
				},
				{
					"$ref": "#/$defs/ChorusEffect"
				},
				{
					"$ref": "#/$defs/FlangerEffect"
				},
				{
					"$ref": "#/$defs/PhaserEffect"
				},
				{
					"$ref": "#/$defs/TremoloEffect"
				},
				{
					"$ref": "#/$defs/VibratoEffect"
				},
				{
					"$ref": "#/$defs/BitcrusherEffect"
				},
				{
					"$ref": "#/$defs/CompressorEffect"
				},
				{
					"$ref": "#/$defs/EQEffect"
				},
				{
					"$ref": "#/$defs/GainEffect"
				},
				{
					"$ref": "#/$defs/StereoPanEffect"
				}
			]
		},
		"ReverbEffect": {
			"type": "object",
			"required": ["type"],
			"properties": {
				"type": {
					"const": "reverb"
				},
				"decay": {
					"type": "number",
					"minimum": 0
				},
				"preDelay": {
					"type": "number",
					"minimum": 0
				},
				"damping": {
					"type": "number",
					"minimum": 0,
					"maximum": 1
				},
				"roomSize": {
					"type": "number",
					"minimum": 0
				},
				"mix": {
					"type": "number",
					"minimum": 0,
					"maximum": 1
				}
			},
			"additionalProperties": false
		},
		"ConvolverEffect": {
			"type": "object",
			"required": ["type"],
			"properties": {
				"type": {
					"const": "convolver"
				},
				"url": {
					"type": "string"
				},
				"mix": {
					"type": "number",
					"minimum": 0,
					"maximum": 1
				}
			},
			"additionalProperties": false
		},
		"DelayEffect": {
			"type": "object",
			"required": ["type"],
			"properties": {
				"type": {
					"const": "delay"
				},
				"time": {
					"type": "number",
					"minimum": 0
				},
				"feedback": {
					"type": "number",
					"minimum": 0,
					"maximum": 1
				},
				"feedbackFilter": {
					"type": "object",
					"required": ["type", "frequency"],
					"properties": {
						"type": {
							"enum": [
								"lowpass",
								"highpass",
								"bandpass",
								"notch",
								"allpass",
								"peaking",
								"lowshelf",
								"highshelf"
							]
						},
						"frequency": {
							"type": "number"
						},
						"Q": {
							"type": "number"
						}
					},
					"additionalProperties": false
				},
				"mix": {
					"type": "number",
					"minimum": 0,
					"maximum": 1
				}
			},
			"additionalProperties": false
		},
		"DistortionEffect": {
			"type": "object",
			"required": ["type"],
			"properties": {
				"type": {
					"const": "distortion"
				},
				"amount": {
					"type": "number"
				},
				"mix": {
					"type": "number",
					"minimum": 0,
					"maximum": 1
				}
			},
			"additionalProperties": false
		},
		"ChorusEffect": {
			"type": "object",
			"required": ["type"],
			"properties": {
				"type": {
					"const": "chorus"
				},
				"rate": {
					"type": "number"
				},
				"depth": {
					"type": "number"
				},
				"mix": {
					"type": "number",
					"minimum": 0,
					"maximum": 1
				}
			},
			"additionalProperties": false
		},
		"FlangerEffect": {
			"type": "object",
			"required": ["type"],
			"properties": {
				"type": {
					"const": "flanger"
				},
				"rate": {
					"type": "number"
				},
				"depth": {
					"type": "number"
				},
				"feedback": {
					"type": "number"
				},
				"mix": {
					"type": "number",
					"minimum": 0,
					"maximum": 1
				}
			},
			"additionalProperties": false
		},
		"PhaserEffect": {
			"type": "object",
			"required": ["type"],
			"properties": {
				"type": {
					"const": "phaser"
				},
				"rate": {
					"type": "number"
				},
				"depth": {
					"type": "number"
				},
				"stages": {
					"type": "integer",
					"minimum": 1
				},
				"feedback": {
					"type": "number"
				},
				"mix": {
					"type": "number",
					"minimum": 0,
					"maximum": 1
				}
			},
			"additionalProperties": false
		},
		"TremoloEffect": {
			"type": "object",
			"required": ["type"],
			"properties": {
				"type": {
					"const": "tremolo"
				},
				"rate": {
					"type": "number"
				},
				"depth": {
					"type": "number"
				}
			},
			"additionalProperties": false
		},
		"VibratoEffect": {
			"type": "object",
			"required": ["type"],
			"properties": {
				"type": {
					"const": "vibrato"
				},
				"rate": {
					"type": "number"
				},
				"depth": {
					"type": "number"
				}
			},
			"additionalProperties": false
		},
		"BitcrusherEffect": {
			"type": "object",
			"required": ["type"],
			"properties": {
				"type": {
					"const": "bitcrusher"
				},
				"bits": {
					"type": "integer",
					"minimum": 1,
					"maximum": 16
				},
				"sampleRateReduction": {
					"type": "number",
					"minimum": 1
				},
				"mix": {
					"type": "number",
					"minimum": 0,
					"maximum": 1
				}
			},
			"additionalProperties": false
		},
		"CompressorEffect": {
			"type": "object",
			"required": ["type"],
			"properties": {
				"type": {
					"const": "compressor"
				},
				"threshold": {
					"type": "number"
				},
				"knee": {
					"type": "number"
				},
				"ratio": {
					"type": "number"
				},
				"attack": {
					"type": "number"
				},
				"release": {
					"type": "number"
				}
			},
			"additionalProperties": false
		},
		"EQEffect": {
			"type": "object",
			"required": ["type", "bands"],
			"properties": {
				"type": {
					"const": "eq"
				},
				"bands": {
					"type": "array",
					"items": {
						"$ref": "#/$defs/EQBand"
					}
				}
			},
			"additionalProperties": false
		},
		"EQBand": {
			"type": "object",
			"required": ["type", "frequency", "gain"],
			"properties": {
				"type": {
					"enum": ["lowshelf", "highshelf", "peaking"]
				},
				"frequency": {
					"type": "number"
				},
				"gain": {
					"type": "number"
				},
				"Q": {
					"type": "number"
				}
			},
			"additionalProperties": false
		},
		"GainEffect": {
			"type": "object",
			"required": ["type", "value"],
			"properties": {
				"type": {
					"const": "gain"
				},
				"value": {
					"type": "number"
				}
			},
			"additionalProperties": false
		},
		"StereoPanEffect": {
			"type": "object",
			"required": ["type", "value"],
			"properties": {
				"type": {
					"const": "pan"
				},
				"value": {
					"type": "number",
					"minimum": -1,
					"maximum": 1
				}
			},
			"additionalProperties": false
		}
	}
}
