{
"id": "at.atmosynth.patch",
"defs": {
"main": {
"key": "tid",
"type": "record",
"record": {
"type": "object",
"required": [
"descriptionVersion",
"name",
"description",
"moduleInstances",
"createdAt"
],
"properties": {
"name": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"tags": {
"type": "array",
"items": {
"type": "string",
"maxLength": 128
},
"description": "Freely created tags, lower-cased on write so one hashtag matches one set of patches."
},
"types": {
"type": "array",
"items": {
"type": "string",
"knownValues": [
"Lead",
"Pad",
"Bass",
"Plucked",
"Percussion",
"Keys",
"Brass",
"Strings",
"Vocal",
"SFX"
]
},
"description": "Zero or more of the ten fixed types. A patch may carry several."
},
"output": {
"ref": "#outputRef",
"type": "ref",
"description": "Which instance reaches the audio output."
},
"createdAt": {
"type": "string",
"format": "datetime"
},
"forkedFrom": {
"ref": "#lineage",
"type": "ref"
},
"connections": {
"type": "array",
"items": {
"ref": "#connection",
"type": "ref"
}
},
"description": {
"type": "string",
"maxLength": 3000
},
"midiRouting": {
"type": "array",
"items": {
"ref": "#midiRoute",
"type": "ref"
},
"description": "Which module instances receive MIDI input."
},
"moduleInstances": {
"type": "array",
"items": {
"ref": "#moduleInstance",
"type": "ref"
}
},
"descriptionVersion": {
"type": "integer",
"minimum": 1,
"description": "Version of the patch description this record follows."
}
}
},
"description": "A patch, held in its creator's own repository."
},
"lineage": {
"type": "object",
"required": [
"uri",
"creatorDid"
],
"properties": {
"uri": {
"type": "string",
"format": "at-uri"
},
"patchId": {
"type": "string",
"maxLength": 128
},
"creatorDid": {
"type": "string",
"format": "did"
}
},
"description": "The patch this one was forked from, and its creator. Preserved even when the source is later deleted."
},
"inputRef": {
"type": "object",
"required": [
"instanceId",
"audioInput"
],
"properties": {
"audioInput": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"instanceId": {
"type": "string",
"maxLength": 64,
"minLength": 1
}
}
},
"position": {
"type": "object",
"required": [
"x",
"y"
],
"properties": {
"x": {
"type": "integer"
},
"y": {
"type": "integer"
}
}
},
"midiRoute": {
"type": "object",
"required": [
"instanceId",
"midiInput"
],
"properties": {
"midiInput": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"instanceId": {
"type": "string",
"maxLength": 64,
"minLength": 1
}
}
},
"moduleRef": {
"type": "object",
"required": [
"moduleId",
"versionKey",
"authorDid"
],
"properties": {
"moduleId": {
"type": "string",
"maxLength": 128,
"minLength": 1
},
"authorDid": {
"type": "string",
"format": "did"
},
"versionKey": {
"type": "string",
"maxLength": 128,
"minLength": 1
}
},
"description": "A pin to one exact published version of a module. Resolving it fetches that record, whoever authored it."
},
"outputRef": {
"type": "object",
"required": [
"instanceId",
"audioOutput"
],
"properties": {
"instanceId": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"audioOutput": {
"type": "string",
"maxLength": 64,
"minLength": 1
}
}
},
"connection": {
"type": "object",
"required": [
"from",
"to"
],
"properties": {
"to": {
"ref": "#inputRef",
"type": "ref"
},
"from": {
"ref": "#outputRef",
"type": "ref"
}
},
"description": "An audio connection between two module instances, naming the declared ports at each end."
},
"midiControl": {
"type": "object",
"required": [
"parameter",
"controller"
],
"properties": {
"parameter": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "The id of the exposed parameter this control moves. One parameter is moved by at most one controller; one controller may move several parameters."
},
"controller": {
"type": "integer",
"maximum": 127,
"minimum": 0,
"description": "The control change number. Five are spoken for by MIDI itself and cannot be bound: 64, the sustain pedal, and 6, 38, 100 and 101, which carry registered-parameter traffic."
}
},
"description": "One MIDI control change bound to one of the module's exposed parameters. The controller's 0 to 127 sweeps the parameter across the range the module declares, or, where the module declares a closed value set instead, across those values in order. A control is read from every input on every channel, like every other MIDI message here: there is nothing to configure."
},
"moduleInstance": {
"type": "object",
"required": [
"instanceId",
"module",
"voiceScope"
],
"properties": {
"module": {
"ref": "#moduleRef",
"type": "ref"
},
"enabled": {
"type": "boolean",
"description": "Whether this instance does its work. An instance that is switched off makes no sound of its own, and anything reaching its audio inputs leaves its audio outputs unaltered. Optional permanently: an instance that says nothing is on, which is what every record written before this field existed says."
},
"position": {
"ref": "#position",
"type": "ref",
"description": "Where the creator placed this instance in the patch's arrangement, so the arrangement travels with the patch and a fork inherits it. Optional permanently, and the only field in either description that exists for presentation."
},
"instanceId": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"voiceScope": {
"enum": [
"perNote",
"perPatch"
],
"type": "string",
"description": "Whether this instance is built once for each sounding note or once for the whole patch. One of the two, always: the choice is made when the module is added, from what the module is, and is the creator's to move afterwards. There is no third value and no leaving it out — an instance that said nothing left the answer to be worked out afresh every time the patch was played, which is a decision nobody could see and nobody could change."
},
"midiControls": {
"type": "array",
"items": {
"ref": "#midiControl",
"type": "ref"
},
"description": "Which MIDI control changes move this instance's parameters while it is played. A binding lives here, in the patch, because which knob moves what is a decision about this use of the module and not about the module."
},
"parameterValues": {
"type": "array",
"items": {
"ref": "#parameterValue",
"type": "ref"
}
},
"sampleSlotFills": {
"type": "array",
"items": {
"ref": "#sampleSlotFill",
"type": "ref"
},
"description": "Samples this instance supplies for the module's declared slots. A fill lives here, in the patch, so writing one never touches the module."
}
},
"description": "One use of one module version. A patch may use the same module more than once; each instance is separately addressable and carries its own parameter values and slot fills."
},
"parameterValue": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"value": {
"type": "unknown",
"description": "The value this patch sets the parameter to. A number that is not a whole number is carried as its decimal string — \"0.5\", not 0.5 — because the ATproto data model has no floating-point type and a PDS refuses one. A whole number is an ordinary integer, and a reader turns such a string back into a number. Where the module declares a closed set of values instead, this is one of those strings, and a label that looks like a number stays the label it is."
},
"useDefault": {
"type": "boolean",
"description": "Set where the patch explicitly defers to the module's default rather than recording a value."
}
},
"description": "A value for one of the module's exposed parameters, or an explicit fall-back to the module's declared default."
},
"sampleSlotFill": {
"type": "object",
"required": [
"slotId",
"blob",
"ownerDid"
],
"properties": {
"blob": {
"type": "blob",
"accept": [
"audio/wav"
],
"maxSize": 2097152
},
"slotId": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"ownerDid": {
"type": "string",
"format": "did"
}
}
}
},
"$type": "com.atproto.lexicon.schema",
"lexicon": 1,
"description": "A synth patch: which modules it uses, how they are wired, what their parameters are set to, and how it is played. A patch plus the module records it pins is everything needed to reproduce it."
}