at.atmosynth.module
{
"$type": "com.atproto.lexicon.schema",
"defs": {
"automation": {
"description": "A breakpoint envelope scheduled onto an AudioParam. Breakpoints up to and including sustainAt are scheduled on note-on; those after it on note-off.",
"properties": {
"breakpoints": {
"items": {
"ref": "#breakpoint",
"type": "ref"
},
"minLength": 1,
"type": "array"
},
"id": {
"maxLength": 64,
"minLength": 1,
"type": "string"
},
"label": {
"maxLength": 200,
"type": "string"
},
"sustainAt": {
"description": "Index into breakpoints where the value holds while a note is held. Absent means a one-shot.",
"minimum": 0,
"type": "integer"
},
"target": {
"ref": "#paramTarget",
"type": "ref"
}
},
"required": [
"id",
"target",
"breakpoints"
],
"type": "object"
},
"breakpoint": {
"properties": {
"curve": {
"description": "How the value travels from the previous breakpoint.",
"knownValues": [
"step",
"linear",
"exponential"
],
"type": "string"
},
"time": {
"description": "Milliseconds from the trigger.",
"minimum": 0,
"type": "integer"
},
"value": {
"description": "The param's value at this instant, as its decimal form — \"0.25\", \"1\" — because the ATproto data model has no floating-point type and a PDS refuses one. An automation is numeric by definition, so a reader turns it back into a number without asking anything else.",
"maxLength": 200,
"type": "string"
}
},
"required": [
"time",
"value"
],
"type": "object"
},
"connection": {
"description": "An audio connection from a node output to either an audio input or a named AudioParam.",
"properties": {
"from": {
"ref": "#source",
"type": "ref"
},
"to": {
"ref": "#target",
"type": "ref"
}
},
"required": [
"from",
"to"
],
"type": "object"
},
"lineage": {
"description": "The module this one was forked from, and its author.",
"properties": {
"authorDid": {
"format": "did",
"type": "string"
},
"moduleId": {
"maxLength": 128,
"type": "string"
},
"uri": {
"format": "at-uri",
"type": "string"
}
},
"required": [
"uri",
"authorDid"
],
"type": "object"
},
"main": {
"description": "A module, held in its author's own repository.",
"key": "tid",
"record": {
"properties": {
"audioInputs": {
"description": "Zero or more individually identified audio inputs.",
"items": {
"ref": "#port",
"type": "ref"
},
"type": "array"
},
"audioOutputs": {
"items": {
"ref": "#port",
"type": "ref"
},
"type": "array"
},
"automation": {
"description": "Scheduled AudioParam envelopes. Web Audio has no envelope node, so these are their own structure.",
"items": {
"ref": "#automation",
"type": "ref"
},
"type": "array"
},
"connections": {
"items": {
"ref": "#connection",
"type": "ref"
},
"type": "array"
},
"createdAt": {
"format": "datetime",
"type": "string"
},
"description": {
"maxLength": 3000,
"type": "string"
},
"descriptionVersion": {
"description": "Version of the module description this record follows. A reader accepts any version at or below its own.",
"minimum": 1,
"type": "integer"
},
"forkedFrom": {
"ref": "#lineage",
"type": "ref"
},
"midiInputs": {
"description": "Zero or more note inputs. A note input carries note events — what is played, and when — from any note source: a sequencer's note output, or the player, which is the on-screen keys, the computer keyboard and every MIDI device at once. \"MIDI\" is the historical name; nothing arriving here need have come from MIDI.",
"items": {
"ref": "#port",
"type": "ref"
},
"type": "array"
},
"moduleId": {
"description": "Stable identity shared by every published version of this module.",
"maxLength": 128,
"type": "string"
},
"name": {
"maxLength": 200,
"minLength": 1,
"type": "string"
},
"nodes": {
"items": {
"ref": "#node",
"type": "ref"
},
"type": "array"
},
"noteOutputs": {
"description": "Zero or more note outputs. A note output carries note events — what is played, and when — rather than a signal, so it is wired to another instance's note input (`midiInputs`) rather than to an audio input. A module that declares one is a source of what is played; a module that declares none is what plays it.",
"items": {
"ref": "#port",
"type": "ref"
},
"type": "array"
},
"noteSource": {
"description": "What this module emits notes by, where it is not made of Web Audio nodes at all. A note source has no `nodes` and no `connections`: it produces note events, and the behaviour that produces them is named here rather than described, because there is no vocabulary of nodes for a thing that makes no sound. `range` emits none of its own: it passes on the notes wired into its input that fall inside the range its instance names (`noteRange` on the patch's instance), each still the note of whatever played it. `transpose` and `assign` emit none of their own either: they pass on every note wired into their input at another pitch — moved by the semitones the instance names (`transpose`), or at the one note it names (`assignedNote`) — each still the note of whatever played it, and starting and stopping when it did. `oneshot` emits none of its own either: it passes on every note wired into its input lasting as many milliseconds as the instance names (`noteLength`), however long whatever played it held it — each still the note of whatever played it, at its own pitch, and starting when it did. A reader that does not know the named behaviour cannot run the module, and says so rather than guessing.",
"knownValues": [
"keyboard",
"sequencer",
"range",
"transpose",
"assign",
"oneshot"
],
"maxLength": 64,
"type": "string"
},
"parameters": {
"items": {
"ref": "#parameter",
"type": "ref"
},
"type": "array"
},
"patternSource": {
"description": "What this module chooses a sequencer's loops by, where it is not made of Web Audio nodes at all. A pattern source emits neither sound nor notes: it is wired to a sequencer's pattern input and decides which of that sequencer's loops is played, and when. Like a note source it has no `nodes` and no `connections`, and its behaviour is named here rather than described. A module is a note source or a pattern source, never both. A reader that does not know the named behaviour cannot run the module, and says so rather than guessing.",
"knownValues": [
"arranger",
"scenes"
],
"maxLength": 64,
"type": "string"
},
"sampleSlots": {
"items": {
"ref": "#sampleSlot",
"type": "ref"
},
"type": "array"
},
"versionKey": {
"description": "The record key this version is published under, repeated in the record so a reader holding only the record knows which version it is. A patch's `moduleRef.versionKey` is this value, and it is the record key a reader fetches: a record whose `versionKey` differs from its own key is pinned by the key and misdescribed by this field.",
"maxLength": 128,
"type": "string"
}
},
"required": [
"descriptionVersion",
"moduleId",
"name",
"description",
"audioInputs",
"audioOutputs",
"midiInputs",
"nodes",
"connections",
"createdAt"
],
"type": "object"
},
"type": "record"
},
"node": {
"description": "One Web Audio node. `kind` is drawn from a closed vocabulary; `options` are its construction-time settings, which are not AudioParams and cannot be modulated.",
"properties": {
"id": {
"maxLength": 64,
"minLength": 1,
"type": "string"
},
"kind": {
"maxLength": 64,
"minLength": 1,
"type": "string"
},
"options": {
"description": "The node's settings, as its kind defines them. This is an object — which is the whole of what `unknown` means here — so the data model applies inside it: a whole number is an ordinary integer, and a number that is not a whole number is carried as its decimal string, \"0.5\" rather than 0.5, because the ATproto data model has no floating-point type and a PDS refuses one. That is the one difference from the fields this description types as strings, which have nowhere to put an integer.",
"type": "unknown"
}
},
"required": [
"id",
"kind"
],
"type": "object"
},
"paramTarget": {
"properties": {
"node": {
"maxLength": 64,
"minLength": 1,
"type": "string"
},
"param": {
"maxLength": 64,
"minLength": 1,
"type": "string"
}
},
"required": [
"node",
"param"
],
"type": "object"
},
"parameter": {
"description": "A parameter the module exposes for a patch to set. Each target reaches an AudioParam, a construction option, or one field of an automation breakpoint.",
"properties": {
"default": {
"description": "The value used where a patch sets none, always as text. A number is its decimal form — \"0.5\", and \"2\" for a whole one — because the ATproto data model has no floating-point type and a string is the only type that carries both a number and a word. Where this parameter declares a closed value set, it is one of those strings instead, and a label that looks like a number stays the label it is.",
"maxLength": 200,
"type": "string"
},
"id": {
"maxLength": 64,
"minLength": 1,
"type": "string"
},
"label": {
"maxLength": 200,
"minLength": 1,
"type": "string"
},
"range": {
"ref": "#range",
"type": "ref"
},
"scale": {
"description": "How a slider or a MIDI control moves through the range. linear moves by equal differences; log moves by equal ratios, which is how a frequency is heard, so the middle of a 20 to 20000 sweep is about 632 rather than about 10000. log needs a range above zero at both ends. Absent is linear. A parameter with a closed value set has no scale.",
"knownValues": [
"linear",
"log"
],
"type": "string"
},
"targets": {
"items": {
"ref": "#parameterTarget",
"type": "ref"
},
"minLength": 1,
"type": "array"
},
"values": {
"description": "A closed value set, where the parameter is not numeric. A construction option the parameter targets is given the chosen value itself; an AudioParam it targets is given the chosen value's position in this set, counting from zero, which is how a worklet offers a choice its own code interprets.",
"items": {
"maxLength": 200,
"type": "string"
},
"type": "array"
}
},
"required": [
"id",
"label",
"targets"
],
"type": "object"
},
"parameterTarget": {
"description": "One of: {node, param}, {node, option}, or {automation, breakpoint, field}.",
"properties": {
"automation": {
"maxLength": 64,
"type": "string"
},
"breakpoint": {
"minimum": 0,
"type": "integer"
},
"field": {
"knownValues": [
"time",
"value"
],
"type": "string"
},
"node": {
"maxLength": 64,
"type": "string"
},
"option": {
"maxLength": 64,
"type": "string"
},
"param": {
"maxLength": 64,
"type": "string"
}
},
"type": "object"
},
"port": {
"description": "One individually identified audio or MIDI boundary of the module.",
"properties": {
"id": {
"maxLength": 64,
"minLength": 1,
"type": "string"
},
"label": {
"maxLength": 200,
"type": "string"
}
},
"required": [
"id"
],
"type": "object"
},
"range": {
"properties": {
"max": {
"description": "The high bound, as its decimal form — \"20000\", \"0.5\" — because the ATproto data model has no floating-point type and a PDS refuses one. A range is numeric by definition, so a reader turns it back into a number without asking anything else.",
"maxLength": 200,
"type": "string"
},
"min": {
"description": "The low bound, as its decimal form — \"0.0001\", \"-1\" — because the ATproto data model has no floating-point type and a PDS refuses one. A range is numeric by definition, so a reader turns it back into a number without asking anything else.",
"maxLength": 200,
"type": "string"
}
},
"required": [
"min",
"max"
],
"type": "object"
},
"sampleRef": {
"description": "A sample blob and the account that holds it.",
"properties": {
"blob": {
"accept": [
"audio/wav"
],
"maxSize": 10485760,
"type": "blob"
},
"ownerDid": {
"format": "did",
"type": "string"
}
},
"required": [
"blob",
"ownerDid"
],
"type": "object"
},
"sampleSlot": {
"description": "A named slot a patch instance may fill with its own sample. `node` names a node in this graph and `property` the thing the sample feeds.",
"properties": {
"default": {
"ref": "#sampleRef",
"type": "ref"
},
"id": {
"maxLength": 64,
"minLength": 1,
"type": "string"
},
"label": {
"maxLength": 200,
"type": "string"
},
"node": {
"maxLength": 64,
"minLength": 1,
"type": "string"
},
"property": {
"knownValues": [
"buffer"
],
"type": "string"
}
},
"required": [
"id",
"node",
"property"
],
"type": "object"
},
"source": {
"properties": {
"node": {
"maxLength": 64,
"minLength": 1,
"type": "string"
},
"output": {
"minimum": 0,
"type": "integer"
}
},
"required": [
"node"
],
"type": "object"
},
"target": {
"description": "Exactly one of `input` or `param` is present. `param` is modulation: a node output reaching a named AudioParam.",
"properties": {
"input": {
"minimum": 0,
"type": "integer"
},
"node": {
"maxLength": 64,
"minLength": 1,
"type": "string"
},
"param": {
"maxLength": 64,
"type": "string"
}
},
"required": [
"node"
],
"type": "object"
}
},
"description": "A reusable synth module: Web Audio nodes wired together, with declared audio and MIDI boundaries, exposed parameters, automation and sample slots. Each published version is its own record; records sharing a moduleId form a series.",
"id": "at.atmosynth.module",
"lexicon": 1
}
Metadata
- DID
-
did:plc:fzjkahpwapmoqxybwdjb6ysf - CID
-
bafyreigkd32vga2ozhpcy5m27j5omajfheumq37vrrku7vzurpfrkb2kgy - Indexed At
- 2026-10-06 13:10 UTC
- AT-URI
-
at://did:plc:fzjkahpwapmoqxybwdjb6ysf/com.atproto.lexicon.schema/at.atmosynth.module
Version History (12 versions)
- 2026-10-06 13:10 UTC (current)
- 2026-09-29 09:38 UTC diff
- 2026-09-28 20:02 UTC diff
- 2026-09-25 10:58 UTC diff
- 2026-09-24 12:51 UTC diff
- 2026-09-22 18:36 UTC diff
- 2026-09-21 13:47 UTC diff
- 2026-09-18 11:56 UTC diff
- 2026-09-09 12:09 UTC diff
- 2026-09-08 07:18 UTC diff
- 2026-08-31 14:12 UTC diff
- 2026-08-31 13:27 UTC diff
Similar Lexicons
Lexicons whose schemas describe something close to this one. Check them before publishing a new one that overlaps.
-
at.atmosynth.patch record
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.