at.atmosynth.patch

atmosynth.at

Schema Diff

+6 -5

From

CID
bafyreibwpt2pxub...
Indexed At
2026-09-04 13:59 UTC
View this version

To

CID
bafyreid2jeqzuw3...
Indexed At
2026-09-06 19:07 UTC
View this version

Compatibility Analysis

Breaking Changes Detected

2 breaking changes, 1 non-breaking change.

Breaking Changes (2)
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "at.atmosynth.patch#moduleInstance", src: "at.atmosynth.patch#moduleInstance", tgt: "at.atmosynth.patch#moduleInstance.voiceScope", kind: "prop", name: Some("voiceScope") }
  • ConstraintAdded ConstraintAdded { vertex_id: "at.atmosynth.patch#moduleInstance.voiceScope", sort: "enum", value: "perNote,perPatch" }
Non-Breaking Changes (1)
  • ConstraintRemoved ConstraintRemoved { vertex_id: "at.atmosynth.patch#moduleInstance.voiceScope", sort: "knownValues" }

Migration Guidance

Constraint Changes

  • ConstraintAdded ConstraintAdded { vertex_id: "at.atmosynth.patch#moduleInstance.voiceScope", sort: "enum", value: "perNote,perPatch" }
  • ConstraintRemoved ConstraintRemoved { vertex_id: "at.atmosynth.patch#moduleInstance.voiceScope", sort: "knownValues" }

Additional Notes

  • Breaking: RequiredEdgeAdded { vertex_id: "at.atmosynth.patch#moduleInstance", src: "at.atmosynth.patch#moduleInstance", tgt: "at.atmosynth.patch#moduleInstance.voiceScope", kind: "prop", name: Some("voiceScope") }
1 1
{
2 2
  "id": "at.atmosynth.patch",
3 3
  "defs": {
4 4
    "main": {
5 5
      "key": "tid",
6 6
      "type": "record",
7 7
      "record": {
8 8
        "type": "object",
9 9
        "required": [
10 10
          "descriptionVersion",
11 11
          "name",
12 12
          "description",
13 13
          "moduleInstances",
14 14
          "createdAt"
15 15
        ],
16 16
        "properties": {
17 17
          "name": {
18 18
            "type": "string",
19 19
            "maxLength": 200,
20 20
            "minLength": 1
21 21
          },
22 22
          "tags": {
23 23
            "type": "array",
24 24
            "items": {
25 25
              "type": "string",
26 26
              "maxLength": 128
27 27
            },
28 28
            "description": "Freely created tags, lower-cased on write so one hashtag matches one set of patches."
29 29
          },
30 30
          "types": {
31 31
            "type": "array",
32 32
            "items": {
33 33
              "type": "string",
34 34
              "knownValues": [
35 35
                "Lead",
36 36
                "Pad",
37 37
                "Bass",
38 38
                "Plucked",
39 39
                "Percussion",
40 40
                "Keys",
41 41
                "Brass",
42 42
                "Strings",
43 43
                "Vocal",
44 44
                "SFX"
45 45
              ]
46 46
            },
47 47
            "description": "Zero or more of the ten fixed types. A patch may carry several."
48 48
          },
49 49
          "output": {
50 50
            "ref": "#outputRef",
51 51
            "type": "ref",
52 52
            "description": "Which instance reaches the audio output."
53 53
          },
54 54
          "createdAt": {
55 55
            "type": "string",
56 56
            "format": "datetime"
57 57
          },
58 58
          "forkedFrom": {
59 59
            "ref": "#lineage",
60 60
            "type": "ref"
61 61
          },
62 62
          "connections": {
63 63
            "type": "array",
64 64
            "items": {
65 65
              "ref": "#connection",
66 66
              "type": "ref"
67 67
            }
68 68
          },
69 69
          "description": {
70 70
            "type": "string",
71 71
            "maxLength": 3000
72 72
          },
73 73
          "midiRouting": {
74 74
            "type": "array",
75 75
            "items": {
76 76
              "ref": "#midiRoute",
77 77
              "type": "ref"
78 78
            },
79 79
            "description": "Which module instances receive MIDI input."
80 80
          },
81 81
          "moduleInstances": {
82 82
            "type": "array",
83 83
            "items": {
84 84
              "ref": "#moduleInstance",
85 85
              "type": "ref"
86 86
            }
87 87
          },
88 88
          "descriptionVersion": {
89 89
            "type": "integer",
90 90
            "minimum": 1,
91 91
            "description": "Version of the patch description this record follows."
92 92
          }
93 93
        }
94 94
      },
95 95
      "description": "A patch, held in its creator's own repository."
96 96
    },
97 97
    "lineage": {
98 98
      "type": "object",
99 99
      "required": [
100 100
        "uri",
101 101
        "creatorDid"
102 102
      ],
103 103
      "properties": {
104 104
        "uri": {
105 105
          "type": "string",
106 106
          "format": "at-uri"
107 107
        },
108 108
        "patchId": {
109 109
          "type": "string",
110 110
          "maxLength": 128
111 111
        },
112 112
        "creatorDid": {
113 113
          "type": "string",
114 114
          "format": "did"
115 115
        }
116 116
      },
117 117
      "description": "The patch this one was forked from, and its creator. Preserved even when the source is later deleted."
118 118
    },
119 119
    "inputRef": {
120 120
      "type": "object",
121 121
      "required": [
122 122
        "instanceId",
123 123
        "audioInput"
124 124
      ],
125 125
      "properties": {
126 126
        "audioInput": {
127 127
          "type": "string",
128 128
          "maxLength": 64,
129 129
          "minLength": 1
130 130
        },
131 131
        "instanceId": {
132 132
          "type": "string",
133 133
          "maxLength": 64,
134 134
          "minLength": 1
135 135
        }
136 136
      }
137 137
    },
138 138
    "position": {
139 139
      "type": "object",
140 140
      "required": [
141 141
        "x",
142 142
        "y"
143 143
      ],
144 144
      "properties": {
145 145
        "x": {
146 146
          "type": "integer"
147 147
        },
148 148
        "y": {
149 149
          "type": "integer"
150 150
        }
151 151
      }
152 152
    },
153 153
    "midiRoute": {
154 154
      "type": "object",
155 155
      "required": [
156 156
        "instanceId",
157 157
        "midiInput"
158 158
      ],
159 159
      "properties": {
160 160
        "midiInput": {
161 161
          "type": "string",
162 162
          "maxLength": 64,
163 163
          "minLength": 1
164 164
        },
165 165
        "instanceId": {
166 166
          "type": "string",
167 167
          "maxLength": 64,
168 168
          "minLength": 1
169 169
        }
170 170
      }
171 171
    },
172 172
    "moduleRef": {
173 173
      "type": "object",
174 174
      "required": [
175 175
        "moduleId",
176 176
        "versionKey",
177 177
        "authorDid"
178 178
      ],
179 179
      "properties": {
180 180
        "moduleId": {
181 181
          "type": "string",
182 182
          "maxLength": 128,
183 183
          "minLength": 1
184 184
        },
185 185
        "authorDid": {
186 186
          "type": "string",
187 187
          "format": "did"
188 188
        },
189 189
        "versionKey": {
190 190
          "type": "string",
191 191
          "maxLength": 128,
192 192
          "minLength": 1
193 193
        }
194 194
      },
195 195
      "description": "A pin to one exact published version of a module. Resolving it fetches that record, whoever authored it."
196 196
    },
197 197
    "outputRef": {
198 198
      "type": "object",
199 199
      "required": [
200 200
        "instanceId",
201 201
        "audioOutput"
202 202
      ],
203 203
      "properties": {
204 204
        "instanceId": {
205 205
          "type": "string",
206 206
          "maxLength": 64,
207 207
          "minLength": 1
208 208
        },
209 209
        "audioOutput": {
210 210
          "type": "string",
211 211
          "maxLength": 64,
212 212
          "minLength": 1
213 213
        }
214 214
      }
215 215
    },
216 216
    "connection": {
217 217
      "type": "object",
218 218
      "required": [
219 219
        "from",
220 220
        "to"
221 221
      ],
222 222
      "properties": {
223 223
        "to": {
224 224
          "ref": "#inputRef",
225 225
          "type": "ref"
226 226
        },
227 227
        "from": {
228 228
          "ref": "#outputRef",
229 229
          "type": "ref"
230 230
        }
231 231
      },
232 232
      "description": "An audio connection between two module instances, naming the declared ports at each end."
233 233
    },
234 234
    "midiControl": {
235 235
      "type": "object",
236 236
      "required": [
237 237
        "parameter",
238 238
        "controller"
239 239
      ],
240 240
      "properties": {
241 241
        "parameter": {
242 242
          "type": "string",
243 243
          "maxLength": 64,
244 244
          "minLength": 1,
245 245
          "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."
246 246
        },
247 247
        "controller": {
248 248
          "type": "integer",
249 249
          "maximum": 127,
250 250
          "minimum": 0,
251 251
          "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."
252 252
        }
253 253
      },
254 254
      "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."
255 255
    },
256 256
    "moduleInstance": {
257 257
      "type": "object",
258 258
      "required": [
259 259
        "instanceId",
260 -
        "module"
260 +
        "module",
261 +
        "voiceScope"
261 262
      ],
262 263
      "properties": {
263 264
        "module": {
264 265
          "ref": "#moduleRef",
265 266
          "type": "ref"
266 267
        },
267 268
        "enabled": {
268 269
          "type": "boolean",
269 270
          "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."
270 271
        },
271 272
        "position": {
272 273
          "ref": "#position",
273 274
          "type": "ref",
274 275
          "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."
275 276
        },
276 277
        "instanceId": {
277 278
          "type": "string",
278 279
          "maxLength": 64,
279 280
          "minLength": 1
280 281
        },
281 282
        "voiceScope": {
282 -
          "type": "string",
283 -
          "description": "Whether this instance is built once for each sounding note or once for the whole patch. Optional permanently: an unset scope is worked out when the patch is played, and is never written on a creator's behalf.",
284 -
          "knownValues": [
283 +
          "enum": [
285 284
            "perNote",
286 285
            "perPatch"
287 -
          ]
286 +
          ],
287 +
          "type": "string",
288 +
          "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."
288 289
        },
289 290
        "midiControls": {
290 291
          "type": "array",
291 292
          "items": {
292 293
            "ref": "#midiControl",
293 294
            "type": "ref"
294 295
          },
295 296
          "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."
296 297
        },
297 298
        "parameterValues": {
298 299
          "type": "array",
299 300
          "items": {
300 301
            "ref": "#parameterValue",
301 302
            "type": "ref"
302 303
          }
303 304
        },
304 305
        "sampleSlotFills": {
305 306
          "type": "array",
306 307
          "items": {
307 308
            "ref": "#sampleSlotFill",
308 309
            "type": "ref"
309 310
          },
310 311
          "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."
311 312
        }
312 313
      },
313 314
      "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."
314 315
    },
315 316
    "parameterValue": {
316 317
      "type": "object",
317 318
      "required": [
318 319
        "id"
319 320
      ],
320 321
      "properties": {
321 322
        "id": {
322 323
          "type": "string",
323 324
          "maxLength": 64,
324 325
          "minLength": 1
325 326
        },
326 327
        "value": {
327 328
          "type": "unknown",
328 329
          "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."
329 330
        },
330 331
        "useDefault": {
331 332
          "type": "boolean",
332 333
          "description": "Set where the patch explicitly defers to the module's default rather than recording a value."
333 334
        }
334 335
      },
335 336
      "description": "A value for one of the module's exposed parameters, or an explicit fall-back to the module's declared default."
336 337
    },
337 338
    "sampleSlotFill": {
338 339
      "type": "object",
339 340
      "required": [
340 341
        "slotId",
341 342
        "blob",
342 343
        "ownerDid"
343 344
      ],
344 345
      "properties": {
345 346
        "blob": {
346 347
          "type": "blob",
347 348
          "accept": [
348 349
            "audio/wav"
349 350
          ],
350 351
          "maxSize": 2097152
351 352
        },
352 353
        "slotId": {
353 354
          "type": "string",
354 355
          "maxLength": 64,
355 356
          "minLength": 1
356 357
        },
357 358
        "ownerDid": {
358 359
          "type": "string",
359 360
          "format": "did"
360 361
        }
361 362
      }
362 363
    }
363 364
  },
364 365
  "$type": "com.atproto.lexicon.schema",
365 366
  "lexicon": 1,
366 367
  "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."
367 368
}

Compare Other Versions

Lexicon Garden

@