Review Phase 3a before building on it, then implement Phase 3b. The Phase 3a draft had four blocking defects: nodes were described as a keyed map while every documented example carried an inline `id` field, so under the strict unknown-field policy each minimal example would have failed its own acceptance trace; no section said where a node lives; the `audioMaxFrequency` ceiling was declared a semantic-stage error while depending on a live AudioContext sample rate; and the sample-hold PRNG child key that section 9.3 requires was undocumented. Close all four, plus nine further gaps in noise seeding, spectral definitions, impulse decay math, Nyquist handling, missing-field codes, LFO phase origin, the units table, node-type staging, and a duplicated diagnostics table. Add Format Specification section 15 for Phase 3b: nine processing and routing node contracts, the component instance node, audio routing and modulation with an explicit modulatable-property registry, twelve graph legality rules, authoring limits, components with a component-scoped `inputs.*` namespace, sound definitions and recipes, and buses. Implement the subsystem in three modules. audio-contract.js holds the declarative node, limit, and modulation tables every consumer reads. audio-graph.js validates, expands components, and checks legality without ever opening an AudioContext. audio-engine.js resolves node fields once from the seeded stream, clamps frequencies to the live device ceiling, realizes the graph through Web Audio, and owns the runtime AudioSubsystem. Extend the schema, delegate the standalone validator's audio checks to the shared module rather than carrying a second implementation, and add a generic audio fixture. Phase 3 is not accepted. Automation precedence, the lifecycle state machine, unlock behavior, voice ceilings, and master protection are Phase 3c. No sound has been heard from any build, so the audio acceptance challenge, peak and finite-sample capture, and listening observations remain open. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_011FWPdCqKaaDnP9NC3JAwh6
1754 lines
43 KiB
JSON
1754 lines
43 KiB
JSON
{
|
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
"$id": "https://xzbt.org/schemas/0.1/exhibit.json",
|
|
"title": "XZBT Exhibit Schema 0.1",
|
|
"description": "Authoritative structural schema for XZBT 0.1 declarative exhibits.",
|
|
"type": "object",
|
|
"required": [
|
|
"xzbt",
|
|
"meta"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"xzbt": {
|
|
"type": "string",
|
|
"const": "0.1",
|
|
"description": "XZBT format specification version. Must be '0.1'."
|
|
},
|
|
"meta": {
|
|
"type": "object",
|
|
"description": "Exhibit metadata and descriptive properties.",
|
|
"required": [
|
|
"id",
|
|
"name"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"pattern": "^[a-z][a-z0-9_-]*$",
|
|
"maxLength": 64,
|
|
"description": "Unique exhibit identifier."
|
|
},
|
|
"name": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"maxLength": 128,
|
|
"description": "Human-readable exhibit title."
|
|
},
|
|
"version": {
|
|
"type": "string",
|
|
"description": "Exhibit author semantic version string."
|
|
},
|
|
"author": {
|
|
"type": "string",
|
|
"maxLength": 128,
|
|
"description": "Author or entity attribution."
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"maxLength": 1024,
|
|
"description": "Short description of exhibit behavior and theme."
|
|
},
|
|
"license": {
|
|
"type": "string",
|
|
"description": "License or rights attribution."
|
|
},
|
|
"tags": {
|
|
"type": "array",
|
|
"maxItems": 16,
|
|
"items": {
|
|
"type": "string",
|
|
"maxLength": 32
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"runtime": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"seed": {
|
|
"oneOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "string",
|
|
"const": "random"
|
|
}
|
|
],
|
|
"description": "PRNG seed: integer for deterministic reproduction, or 'random'."
|
|
}
|
|
}
|
|
},
|
|
"parameters": {
|
|
"type": "object",
|
|
"description": "User-tunable exhibit parameters.",
|
|
"patternProperties": {
|
|
"^[a-z][a-z0-9_-]*$": {
|
|
"$ref": "#/definitions/ParameterSpec"
|
|
}
|
|
},
|
|
"additionalProperties": false
|
|
},
|
|
"state": {
|
|
"type": "object",
|
|
"description": "Simulation-owned runtime state variables.",
|
|
"patternProperties": {
|
|
"^[a-z][a-z0-9_-]*$": {
|
|
"$ref": "#/definitions/StateSpec"
|
|
}
|
|
},
|
|
"additionalProperties": false
|
|
},
|
|
"signals": {
|
|
"type": "object",
|
|
"description": "Read-only environmental and input signals.",
|
|
"patternProperties": {
|
|
"^[a-z][a-z0-9_-]*$": {
|
|
"type": "object"
|
|
}
|
|
},
|
|
"additionalProperties": false
|
|
},
|
|
"ui": {
|
|
"type": "object",
|
|
"description": "Generated UI grouping and presentation preferences.",
|
|
"additionalProperties": true
|
|
},
|
|
"components": {
|
|
"type": "object",
|
|
"description": "Modular audio and visual reusable components.",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"audio": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"pattern": "^[a-z][a-z0-9_-]*$"
|
|
},
|
|
"additionalProperties": {
|
|
"$ref": "#/definitions/AudioComponent"
|
|
}
|
|
},
|
|
"visual": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
},
|
|
"visuals": {
|
|
"type": "object",
|
|
"description": "Procedural rendering systems, canvas, and cameras.",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"camera": {
|
|
"type": "object"
|
|
},
|
|
"systems": {
|
|
"type": "object"
|
|
},
|
|
"passes": {
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"audio": {
|
|
"type": "object",
|
|
"description": "Synthesizer graphs, buses, and routing.",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"buses": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"pattern": "^[a-z][a-z0-9_-]*$",
|
|
"not": {
|
|
"const": "master"
|
|
}
|
|
},
|
|
"additionalProperties": {
|
|
"$ref": "#/definitions/AudioBus"
|
|
}
|
|
},
|
|
"recipes": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"pattern": "^[a-z][a-z0-9_-]*$"
|
|
},
|
|
"additionalProperties": {
|
|
"$ref": "#/definitions/AudioRecipe"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"sounds": {
|
|
"type": "object",
|
|
"description": "Sound definitions separating metadata from synthesis.",
|
|
"propertyNames": {
|
|
"pattern": "^[a-z][a-z0-9_-]*$"
|
|
},
|
|
"additionalProperties": {
|
|
"$ref": "#/definitions/Sound"
|
|
}
|
|
},
|
|
"cadence": {
|
|
"type": "object",
|
|
"description": "Procedural rhythm clocks and pulse pools.",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"clocks": {
|
|
"type": "object"
|
|
},
|
|
"pools": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
},
|
|
"modulators": {
|
|
"type": "object",
|
|
"description": "Continuous LFOs, noise generators, and sample-and-hold signals.",
|
|
"patternProperties": {
|
|
"^[a-z][a-z0-9_-]*$": {
|
|
"type": "object"
|
|
}
|
|
},
|
|
"additionalProperties": false
|
|
},
|
|
"bindings": {
|
|
"type": "array",
|
|
"description": "Directed value propagation links.",
|
|
"items": {
|
|
"$ref": "#/definitions/BindingSpec"
|
|
}
|
|
},
|
|
"events": {
|
|
"type": "object",
|
|
"description": "Discrete lifecycle and state change event triggers.",
|
|
"patternProperties": {
|
|
"^[a-z][a-z0-9_-]*$": {
|
|
"type": "object"
|
|
}
|
|
},
|
|
"additionalProperties": false
|
|
},
|
|
"scenarios": {
|
|
"type": "object",
|
|
"description": "Autonomous orchestrated scenarios and timelines.",
|
|
"patternProperties": {
|
|
"^[a-z][a-z0-9_-]*$": {
|
|
"type": "object"
|
|
}
|
|
},
|
|
"additionalProperties": false
|
|
}
|
|
},
|
|
"definitions": {
|
|
"ParameterSpec": {
|
|
"type": "object",
|
|
"required": [
|
|
"type",
|
|
"default"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"number",
|
|
"integer",
|
|
"boolean",
|
|
"string",
|
|
"color",
|
|
"enum"
|
|
]
|
|
},
|
|
"default": {},
|
|
"min": {
|
|
"type": "number"
|
|
},
|
|
"max": {
|
|
"type": "number"
|
|
},
|
|
"step": {
|
|
"type": "number",
|
|
"exclusiveMinimum": 0
|
|
},
|
|
"values": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"label": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
},
|
|
"unit": {
|
|
"type": "string",
|
|
"maxLength": 16
|
|
}
|
|
}
|
|
},
|
|
"StateSpec": {
|
|
"type": "object",
|
|
"required": [
|
|
"type",
|
|
"initial"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"number",
|
|
"integer",
|
|
"boolean",
|
|
"string"
|
|
]
|
|
},
|
|
"initial": {},
|
|
"min": {
|
|
"type": "number"
|
|
},
|
|
"max": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"BindingSpec": {
|
|
"type": "object",
|
|
"required": [
|
|
"source",
|
|
"target"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"source": {
|
|
"type": "string",
|
|
"description": "Source reference path (e.g. 'parameters.activity')."
|
|
},
|
|
"target": {
|
|
"type": "string",
|
|
"description": "Target reference path (e.g. 'audio.buses.ambient.gain')."
|
|
},
|
|
"scale": {
|
|
"type": "number",
|
|
"description": "Numeric source multiplier. Defaults to 1."
|
|
},
|
|
"offset": {
|
|
"type": "number",
|
|
"description": "Numeric offset applied after scaling. Defaults to 0."
|
|
},
|
|
"clamp": {
|
|
"type": "array",
|
|
"minItems": 2,
|
|
"maxItems": 2,
|
|
"items": {
|
|
"type": "number"
|
|
},
|
|
"description": "Inclusive [minimum, maximum] clamp applied to the transformed binding value."
|
|
},
|
|
"smoothing": {
|
|
"$ref": "#/definitions/DurationSpec",
|
|
"description": "Optional smoothing low-pass duration."
|
|
},
|
|
"when": {
|
|
"$ref": "#/definitions/ConditionSpec",
|
|
"description": "Optional condition; defaults to true."
|
|
}
|
|
}
|
|
},
|
|
"ValueSpec": {
|
|
"description": "Universal value expression (literal, reference, random, weighted choice, or operation).",
|
|
"oneOf": [
|
|
{
|
|
"type": "number",
|
|
"description": "Literal numeric constant."
|
|
},
|
|
{
|
|
"type": "boolean",
|
|
"description": "Literal boolean constant."
|
|
},
|
|
{
|
|
"type": "string",
|
|
"description": "Literal string or color constant."
|
|
},
|
|
{
|
|
"type": "object",
|
|
"required": [
|
|
"ref"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"ref": {
|
|
"type": "string",
|
|
"pattern": "^[a-z][a-z0-9_-]*(\\.[a-z][a-z0-9_-]*)+$",
|
|
"description": "Dot-separated reference path."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"type": "object",
|
|
"required": [
|
|
"random"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"random": {
|
|
"type": "object",
|
|
"required": [
|
|
"min",
|
|
"max"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"min": {
|
|
"type": "number"
|
|
},
|
|
"max": {
|
|
"type": "number"
|
|
},
|
|
"integer": {
|
|
"type": "boolean"
|
|
},
|
|
"distribution": {
|
|
"type": "string",
|
|
"enum": [
|
|
"uniform",
|
|
"gaussian"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"type": "object",
|
|
"required": [
|
|
"choose"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"choose": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"items": {
|
|
"type": "object",
|
|
"required": [
|
|
"value",
|
|
"weight"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"value": {},
|
|
"weight": {
|
|
"type": "number",
|
|
"exclusiveMinimum": 0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"type": "object",
|
|
"required": [
|
|
"op",
|
|
"args"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"enum": [
|
|
"abs",
|
|
"negate",
|
|
"round",
|
|
"floor",
|
|
"ceil",
|
|
"add",
|
|
"subtract",
|
|
"multiply",
|
|
"divide",
|
|
"min",
|
|
"max",
|
|
"clamp",
|
|
"lerp"
|
|
]
|
|
},
|
|
"args": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/ValueSpec"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"ConditionSpec": {
|
|
"description": "Boolean condition expression (comparison, and, or, not).",
|
|
"oneOf": [
|
|
{
|
|
"type": "object",
|
|
"required": [
|
|
"op",
|
|
"left",
|
|
"right"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"enum": [
|
|
"eq",
|
|
"ne",
|
|
"gt",
|
|
"gte",
|
|
"lt",
|
|
"lte"
|
|
]
|
|
},
|
|
"left": {
|
|
"$ref": "#/definitions/ValueSpec"
|
|
},
|
|
"right": {
|
|
"$ref": "#/definitions/ValueSpec"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"type": "object",
|
|
"required": [
|
|
"and"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"and": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"items": {
|
|
"$ref": "#/definitions/ConditionSpec"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"type": "object",
|
|
"required": [
|
|
"or"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"or": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"items": {
|
|
"$ref": "#/definitions/ConditionSpec"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"type": "object",
|
|
"required": [
|
|
"not"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"not": {
|
|
"$ref": "#/definitions/ConditionSpec"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"DurationSpec": {
|
|
"type": "string",
|
|
"pattern": "^([0-9]+(\\.[0-9]+)?)(ms|s|m|h)$",
|
|
"description": "Normalized duration literal string (e.g. '250ms', '4s', '1.5m', '1h')."
|
|
},
|
|
"AudioPartial": {
|
|
"type": "object",
|
|
"description": "One custom-waveform partial (Format Specification 14.7).",
|
|
"required": [
|
|
"ratio",
|
|
"gain"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"ratio": {
|
|
"description": "Partial frequency as a multiple of the node frequency.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0.001,
|
|
"maximum": 256
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"gain": {
|
|
"description": "Linear amplitude relative to the fundamental.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"phase": {
|
|
"description": "Starting phase offset in degrees.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"exclusiveMaximum": 360
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"AudioResonatorMode": {
|
|
"type": "object",
|
|
"description": "One resonator mode (Format Specification 15.10).",
|
|
"additionalProperties": false,
|
|
"oneOf": [
|
|
{
|
|
"required": [
|
|
"ratio"
|
|
]
|
|
},
|
|
{
|
|
"required": [
|
|
"frequency"
|
|
]
|
|
}
|
|
],
|
|
"properties": {
|
|
"ratio": {
|
|
"description": "Mode frequency as a multiple of the fundamental.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0.001,
|
|
"maximum": 256
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"frequency": {
|
|
"description": "Absolute mode frequency in Hz.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0.1,
|
|
"maximum": 24000
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"gain": {
|
|
"description": "Linear amplitude of the mode.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"decay": {
|
|
"$ref": "#/definitions/DurationSpec"
|
|
}
|
|
}
|
|
},
|
|
"AudioNode": {
|
|
"type": "object",
|
|
"description": "One audio graph node, keyed by node ID (Format Specification 14.3).",
|
|
"required": [
|
|
"type"
|
|
],
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"oscillator",
|
|
"noise",
|
|
"impulse",
|
|
"constant",
|
|
"lfo",
|
|
"sample-hold",
|
|
"gain",
|
|
"filter",
|
|
"compressor",
|
|
"waveshaper",
|
|
"delay",
|
|
"reverb",
|
|
"stereo-pan",
|
|
"mixer",
|
|
"resonator",
|
|
"component"
|
|
]
|
|
}
|
|
},
|
|
"allOf": [
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "oscillator"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Oscillator (14.7).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"waveform": {
|
|
"type": "string",
|
|
"enum": [
|
|
"sine",
|
|
"triangle",
|
|
"square",
|
|
"sawtooth",
|
|
"custom"
|
|
]
|
|
},
|
|
"frequency": {
|
|
"description": "Frequency in Hz.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0.1,
|
|
"maximum": 24000
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"detune": {
|
|
"description": "Detune in cents.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": -4800,
|
|
"maximum": 4800
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"harmonics": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"maxItems": 64,
|
|
"items": {
|
|
"$ref": "#/definitions/AudioPartial"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "noise"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Noise (14.8).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"color": {
|
|
"type": "string",
|
|
"enum": [
|
|
"white",
|
|
"pink",
|
|
"brown"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "impulse"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Impulse (14.9).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"color": {
|
|
"type": "string",
|
|
"enum": [
|
|
"white",
|
|
"pink",
|
|
"brown"
|
|
]
|
|
},
|
|
"duration": {
|
|
"$ref": "#/definitions/DurationSpec"
|
|
},
|
|
"amplitude": {
|
|
"description": "Peak amplitude.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"decay": {
|
|
"type": "string",
|
|
"enum": [
|
|
"flat",
|
|
"linear",
|
|
"exponential"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "constant"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Constant control source (14.10).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"value": {
|
|
"description": "Constant control value.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": -1000,
|
|
"maximum": 1000
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "lfo"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "LFO control source (14.11).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"waveform": {
|
|
"type": "string",
|
|
"enum": [
|
|
"sine",
|
|
"triangle",
|
|
"square",
|
|
"sawtooth"
|
|
]
|
|
},
|
|
"frequency": {
|
|
"description": "LFO rate in Hz.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0.001,
|
|
"maximum": 40
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"amplitude": {
|
|
"description": "Output amplitude.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1000
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"polarity": {
|
|
"type": "string",
|
|
"enum": [
|
|
"bipolar",
|
|
"unipolar"
|
|
]
|
|
},
|
|
"phase": {
|
|
"description": "Starting phase in degrees.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"exclusiveMaximum": 360
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "sample-hold"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Sample-and-hold control source (14.12).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"rate": {
|
|
"description": "Tick rate in Hz.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0.01,
|
|
"maximum": 100
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"min": {
|
|
"description": "Lower draw bound.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": -1000,
|
|
"maximum": 1000
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"max": {
|
|
"description": "Upper draw bound.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": -1000,
|
|
"maximum": 1000
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"slew": {
|
|
"$ref": "#/definitions/DurationSpec"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "gain"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Gain (15.2).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"gain": {
|
|
"description": "Linear gain.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 4
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "filter"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Filter (15.3).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"mode": {
|
|
"type": "string",
|
|
"enum": [
|
|
"lowpass",
|
|
"highpass",
|
|
"bandpass",
|
|
"notch",
|
|
"peaking",
|
|
"lowshelf",
|
|
"highshelf",
|
|
"allpass"
|
|
]
|
|
},
|
|
"frequency": {
|
|
"description": "Cutoff or center frequency in Hz.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 10,
|
|
"maximum": 24000
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"q": {
|
|
"description": "Filter Q.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0.0001,
|
|
"maximum": 100
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"gain": {
|
|
"description": "Shelf or peak gain in dB.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": -40,
|
|
"maximum": 40
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"detune": {
|
|
"description": "Detune in cents.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": -4800,
|
|
"maximum": 4800
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "compressor"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Compressor (15.4).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"threshold": {
|
|
"description": "Threshold in dB.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": -100,
|
|
"maximum": 0
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"knee": {
|
|
"description": "Knee width in dB.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 40
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"ratio": {
|
|
"description": "Compression ratio.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 1,
|
|
"maximum": 20
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"attack": {
|
|
"$ref": "#/definitions/DurationSpec"
|
|
},
|
|
"release": {
|
|
"$ref": "#/definitions/DurationSpec"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "waveshaper"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Waveshaper (15.5).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"shape": {
|
|
"type": "string",
|
|
"enum": [
|
|
"soft-clip",
|
|
"hard-clip",
|
|
"saturation"
|
|
]
|
|
},
|
|
"amount": {
|
|
"description": "Shaping amount.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"oversample": {
|
|
"type": "string",
|
|
"enum": [
|
|
"none",
|
|
"2x",
|
|
"4x"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "delay"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Delay (15.6).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"time": {
|
|
"$ref": "#/definitions/DurationSpec"
|
|
},
|
|
"feedback": {
|
|
"description": "Internal feedback amount.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 0.95
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"mix": {
|
|
"description": "Dry/wet blend.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "reverb"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Reverb (15.7).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"size": {
|
|
"description": "Perceived space size.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"decay": {
|
|
"$ref": "#/definitions/DurationSpec"
|
|
},
|
|
"damping": {
|
|
"description": "High-frequency damping.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"predelay": {
|
|
"$ref": "#/definitions/DurationSpec"
|
|
},
|
|
"mix": {
|
|
"description": "Dry/wet blend.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "stereo-pan"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Stereo pan (15.8).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"pan": {
|
|
"description": "Stereo position.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": -1,
|
|
"maximum": 1
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "mixer"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Mixer (15.9).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "resonator"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Resonator (15.10).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"fundamental": {
|
|
"description": "Fundamental frequency in Hz.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0.1,
|
|
"maximum": 24000
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"modes": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"maxItems": 16,
|
|
"items": {
|
|
"$ref": "#/definitions/AudioResonatorMode"
|
|
}
|
|
},
|
|
"mix": {
|
|
"description": "Dry/wet blend.",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"required": [
|
|
"type",
|
|
"modes"
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"type": {
|
|
"const": "component"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
]
|
|
},
|
|
"then": {
|
|
"type": "object",
|
|
"description": "Component instance (15.11).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"use": {
|
|
"type": "string",
|
|
"pattern": "^[a-z][a-z0-9_-]*$"
|
|
},
|
|
"values": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"pattern": "^[a-z][a-z0-9_-]*$"
|
|
},
|
|
"additionalProperties": {
|
|
"$ref": "#/definitions/ValueSpec"
|
|
}
|
|
}
|
|
},
|
|
"required": [
|
|
"type",
|
|
"use"
|
|
]
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"AudioRoute": {
|
|
"type": "object",
|
|
"description": "An audio or modulation route (Format Specification 15.12).",
|
|
"required": [
|
|
"from",
|
|
"to"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"from": {
|
|
"type": "string",
|
|
"pattern": "^[a-z][a-z0-9_-]*$"
|
|
},
|
|
"to": {
|
|
"type": "string",
|
|
"pattern": "^[a-z][a-z0-9_-]*(\\.[a-z][a-z0-9_-]*)?$"
|
|
},
|
|
"depth": {
|
|
"$ref": "#/definitions/ValueSpec"
|
|
}
|
|
}
|
|
},
|
|
"AudioNodeMap": {
|
|
"type": "object",
|
|
"minProperties": 1,
|
|
"propertyNames": {
|
|
"pattern": "^[a-z][a-z0-9_-]*$",
|
|
"not": {
|
|
"enum": [
|
|
"output",
|
|
"input"
|
|
]
|
|
}
|
|
},
|
|
"additionalProperties": {
|
|
"$ref": "#/definitions/AudioNode"
|
|
}
|
|
},
|
|
"AudioRouteList": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/AudioRoute"
|
|
}
|
|
},
|
|
"AudioRecipe": {
|
|
"type": "object",
|
|
"description": "A recipe graph, or a reference to a shared recipe (15.16).",
|
|
"oneOf": [
|
|
{
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"nodes"
|
|
],
|
|
"properties": {
|
|
"nodes": {
|
|
"$ref": "#/definitions/AudioNodeMap"
|
|
},
|
|
"routes": {
|
|
"$ref": "#/definitions/AudioRouteList"
|
|
},
|
|
"mode": {
|
|
"type": "string",
|
|
"enum": [
|
|
"oneshot",
|
|
"continuous"
|
|
]
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"use"
|
|
],
|
|
"properties": {
|
|
"use": {
|
|
"type": "string",
|
|
"pattern": "^[a-z][a-z0-9_-]*$"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"AudioComponent": {
|
|
"type": "object",
|
|
"description": "A reusable audio component graph (15.15).",
|
|
"required": [
|
|
"nodes"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"nodes": {
|
|
"$ref": "#/definitions/AudioNodeMap"
|
|
},
|
|
"routes": {
|
|
"$ref": "#/definitions/AudioRouteList"
|
|
},
|
|
"input": {
|
|
"type": "boolean"
|
|
},
|
|
"parameters": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"pattern": "^[a-z][a-z0-9_-]*$"
|
|
},
|
|
"additionalProperties": {
|
|
"type": "object",
|
|
"required": [
|
|
"type"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"const": "number"
|
|
},
|
|
"default": {
|
|
"type": "number"
|
|
},
|
|
"min": {
|
|
"type": "number"
|
|
},
|
|
"max": {
|
|
"type": "number"
|
|
},
|
|
"unit": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"AudioBus": {
|
|
"type": "object",
|
|
"description": "A declared bus (15.17).",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"gain": {
|
|
"description": "Bus gain in [0, 4].",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 4
|
|
},
|
|
{
|
|
"type": "object"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"Sound": {
|
|
"type": "object",
|
|
"description": "A sound definition (15.16).",
|
|
"required": [
|
|
"name",
|
|
"recipe"
|
|
],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"name": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"maxLength": 128
|
|
},
|
|
"tags": {
|
|
"type": "array",
|
|
"maxItems": 16,
|
|
"items": {
|
|
"type": "string",
|
|
"maxLength": 32
|
|
}
|
|
},
|
|
"usage": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"items": {
|
|
"type": "string",
|
|
"enum": [
|
|
"automatic",
|
|
"manual",
|
|
"scenario"
|
|
]
|
|
}
|
|
},
|
|
"cadence": {
|
|
"type": "object"
|
|
},
|
|
"bus": {
|
|
"type": "string",
|
|
"pattern": "^[a-z][a-z0-9_-]*$"
|
|
},
|
|
"recipe": {
|
|
"$ref": "#/definitions/AudioRecipe"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|