at.atmosynth.module

atmosynth.at

Schema Diff

+55 -8

From

CID
bafyreibwkmr5b32...
Indexed At
2026-08-31 13:27 UTC
View this version

To

CID
bafyreigkd32vga2...
Indexed At
2026-10-06 13:10 UTC
View this version

Compatibility Analysis

Breaking Changes Detected

8 breaking changes, 11 non-breaking changes.

Breaking Changes (8)
  • KindChanged KindChanged { vertex_id: "at.atmosynth.module#breakpoint.value", old_kind: "unknown", new_kind: "string" }
  • KindChanged KindChanged { vertex_id: "at.atmosynth.module#parameter.default", old_kind: "unknown", new_kind: "string" }
  • KindChanged KindChanged { vertex_id: "at.atmosynth.module#range.max", old_kind: "unknown", new_kind: "string" }
  • KindChanged KindChanged { vertex_id: "at.atmosynth.module#range.min", old_kind: "unknown", new_kind: "string" }
  • ConstraintAdded ConstraintAdded { vertex_id: "at.atmosynth.module#parameter.default", sort: "maxLength", value: "200" }
  • ConstraintAdded ConstraintAdded { vertex_id: "at.atmosynth.module#range.min", sort: "maxLength", value: "200" }
  • ConstraintAdded ConstraintAdded { vertex_id: "at.atmosynth.module#breakpoint.value", sort: "maxLength", value: "200" }
  • ConstraintAdded ConstraintAdded { vertex_id: "at.atmosynth.module#range.max", sort: "maxLength", value: "200" }
Non-Breaking Changes (11)
  • AddedVertex AddedVertex { vertex_id: "at.atmosynth.module#parameter.scale" }
  • AddedVertex AddedVertex { vertex_id: "at.atmosynth.module:body.noteOutputs" }
  • AddedVertex AddedVertex { vertex_id: "at.atmosynth.module:body.noteOutputs:items" }
  • AddedVertex AddedVertex { vertex_id: "at.atmosynth.module:body.noteSource" }
  • AddedVertex AddedVertex { vertex_id: "at.atmosynth.module:body.patternSource" }
  • AddedEdge AddedEdge { src: "at.atmosynth.module#parameter", tgt: "at.atmosynth.module#parameter.scale", kind: "prop", name: Some("scale") }
  • AddedEdge AddedEdge { src: "at.atmosynth.module:body", tgt: "at.atmosynth.module:body.noteOutputs", kind: "prop", name: Some("noteOutputs") }
  • AddedEdge AddedEdge { src: "at.atmosynth.module:body", tgt: "at.atmosynth.module:body.noteSource", kind: "prop", name: Some("noteSource") }
  • AddedEdge AddedEdge { src: "at.atmosynth.module:body", tgt: "at.atmosynth.module:body.patternSource", kind: "prop", name: Some("patternSource") }
  • AddedEdge AddedEdge { src: "at.atmosynth.module:body.noteOutputs", tgt: "at.atmosynth.module:body.noteOutputs:items", kind: "items", name: None }
  • AddedEdge AddedEdge { src: "at.atmosynth.module:body.noteOutputs:items", tgt: "at.atmosynth.module#port", kind: "ref", name: None }

Migration Guidance

Added Elements

  • AddedVertex { vertex_id: "at.atmosynth.module#parameter.scale" }
  • AddedVertex { vertex_id: "at.atmosynth.module:body.noteOutputs" }
  • AddedVertex { vertex_id: "at.atmosynth.module:body.noteOutputs:items" }
  • AddedVertex { vertex_id: "at.atmosynth.module:body.noteSource" }
  • AddedVertex { vertex_id: "at.atmosynth.module:body.patternSource" }

Constraint Changes

  • ConstraintAdded ConstraintAdded { vertex_id: "at.atmosynth.module#range.min", sort: "maxLength", value: "200" }
  • ConstraintAdded ConstraintAdded { vertex_id: "at.atmosynth.module#range.max", sort: "maxLength", value: "200" }
  • ConstraintAdded ConstraintAdded { vertex_id: "at.atmosynth.module#parameter.default", sort: "maxLength", value: "200" }
  • ConstraintAdded ConstraintAdded { vertex_id: "at.atmosynth.module#breakpoint.value", sort: "maxLength", value: "200" }

Additional Notes

  • Breaking: KindChanged { vertex_id: "at.atmosynth.module#breakpoint.value", old_kind: "unknown", new_kind: "string" }
  • Breaking: KindChanged { vertex_id: "at.atmosynth.module#parameter.default", old_kind: "unknown", new_kind: "string" }
  • Breaking: KindChanged { vertex_id: "at.atmosynth.module#range.max", old_kind: "unknown", new_kind: "string" }
  • Breaking: KindChanged { vertex_id: "at.atmosynth.module#range.min", old_kind: "unknown", new_kind: "string" }
  • Non-breaking: AddedEdge { src: "at.atmosynth.module#parameter", tgt: "at.atmosynth.module#parameter.scale", kind: "prop", name: Some("scale") }
  • Non-breaking: AddedEdge { src: "at.atmosynth.module:body", tgt: "at.atmosynth.module:body.noteOutputs", kind: "prop", name: Some("noteOutputs") }
  • Non-breaking: AddedEdge { src: "at.atmosynth.module:body", tgt: "at.atmosynth.module:body.noteSource", kind: "prop", name: Some("noteSource") }
  • Non-breaking: AddedEdge { src: "at.atmosynth.module:body", tgt: "at.atmosynth.module:body.patternSource", kind: "prop", name: Some("patternSource") }
  • Non-breaking: AddedEdge { src: "at.atmosynth.module:body.noteOutputs", tgt: "at.atmosynth.module:body.noteOutputs:items", kind: "items", name: None }
  • Non-breaking: AddedEdge { src: "at.atmosynth.module:body.noteOutputs:items", tgt: "at.atmosynth.module#port", kind: "ref", name: None }
1 1
{
2 2
  "$type": "com.atproto.lexicon.schema",
3 3
  "defs": {
4 4
    "automation": {
5 5
      "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.",
6 6
      "properties": {
7 7
        "breakpoints": {
8 8
          "items": {
9 9
            "ref": "#breakpoint",
10 10
            "type": "ref"
11 11
          },
12 12
          "minLength": 1,
13 13
          "type": "array"
14 14
        },
15 15
        "id": {
16 16
          "maxLength": 64,
17 17
          "minLength": 1,
18 18
          "type": "string"
19 19
        },
20 20
        "label": {
21 21
          "maxLength": 200,
22 22
          "type": "string"
23 23
        },
24 24
        "sustainAt": {
25 25
          "description": "Index into breakpoints where the value holds while a note is held. Absent means a one-shot.",
26 26
          "minimum": 0,
27 27
          "type": "integer"
28 28
        },
29 29
        "target": {
30 30
          "ref": "#paramTarget",
31 31
          "type": "ref"
32 32
        }
33 33
      },
34 34
      "required": [
35 35
        "id",
36 36
        "target",
37 37
        "breakpoints"
38 38
      ],
39 39
      "type": "object"
40 40
    },
41 41
    "breakpoint": {
42 42
      "properties": {
43 43
        "curve": {
44 44
          "description": "How the value travels from the previous breakpoint.",
45 45
          "knownValues": [
46 46
            "step",
47 47
            "linear",
48 48
            "exponential"
49 49
          ],
50 50
          "type": "string"
51 51
        },
52 52
        "time": {
53 53
          "description": "Milliseconds from the trigger.",
54 54
          "minimum": 0,
55 55
          "type": "integer"
56 56
        },
57 57
        "value": {
58 -
          "description": "The param's value at this instant.",
59 -
          "type": "unknown"
58 +
          "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.",
59 +
          "maxLength": 200,
60 +
          "type": "string"
60 61
        }
61 62
      },
62 63
      "required": [
63 64
        "time",
64 65
        "value"
65 66
      ],
66 67
      "type": "object"
67 68
    },
68 69
    "connection": {
69 70
      "description": "An audio connection from a node output to either an audio input or a named AudioParam.",
70 71
      "properties": {
71 72
        "from": {
72 73
          "ref": "#source",
73 74
          "type": "ref"
74 75
        },
75 76
        "to": {
76 77
          "ref": "#target",
77 78
          "type": "ref"
78 79
        }
79 80
      },
80 81
      "required": [
81 82
        "from",
82 83
        "to"
83 84
      ],
84 85
      "type": "object"
85 86
    },
86 87
    "lineage": {
87 88
      "description": "The module this one was forked from, and its author.",
88 89
      "properties": {
89 90
        "authorDid": {
90 91
          "format": "did",
91 92
          "type": "string"
92 93
        },
93 94
        "moduleId": {
94 95
          "maxLength": 128,
95 96
          "type": "string"
96 97
        },
97 98
        "uri": {
98 99
          "format": "at-uri",
99 100
          "type": "string"
100 101
        }
101 102
      },
102 103
      "required": [
103 104
        "uri",
104 105
        "authorDid"
105 106
      ],
106 107
      "type": "object"
107 108
    },
108 109
    "main": {
109 110
      "description": "A module, held in its author's own repository.",
110 111
      "key": "tid",
111 112
      "record": {
112 113
        "properties": {
113 114
          "audioInputs": {
114 115
            "description": "Zero or more individually identified audio inputs.",
115 116
            "items": {
116 117
              "ref": "#port",
117 118
              "type": "ref"
118 119
            },
119 120
            "type": "array"
120 121
          },
121 122
          "audioOutputs": {
122 123
            "items": {
123 124
              "ref": "#port",
124 125
              "type": "ref"
125 126
            },
126 127
            "type": "array"
127 128
          },
128 129
          "automation": {
129 130
            "description": "Scheduled AudioParam envelopes. Web Audio has no envelope node, so these are their own structure.",
130 131
            "items": {
131 132
              "ref": "#automation",
132 133
              "type": "ref"
133 134
            },
134 135
            "type": "array"
135 136
          },
136 137
          "connections": {
137 138
            "items": {
138 139
              "ref": "#connection",
139 140
              "type": "ref"
140 141
            },
141 142
            "type": "array"
142 143
          },
143 144
          "createdAt": {
144 145
            "format": "datetime",
145 146
            "type": "string"
146 147
          },
147 148
          "description": {
148 149
            "maxLength": 3000,
149 150
            "type": "string"
150 151
          },
151 152
          "descriptionVersion": {
152 153
            "description": "Version of the module description this record follows. A reader accepts any version at or below its own.",
153 154
            "minimum": 1,
154 155
            "type": "integer"
155 156
          },
156 157
          "forkedFrom": {
157 158
            "ref": "#lineage",
158 159
            "type": "ref"
159 160
          },
160 161
          "midiInputs": {
162 +
            "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.",
161 163
            "items": {
162 164
              "ref": "#port",
163 165
              "type": "ref"
164 166
            },
165 167
            "type": "array"
166 168
          },
167 169
          "moduleId": {
168 170
            "description": "Stable identity shared by every published version of this module.",
169 171
            "maxLength": 128,
170 172
            "type": "string"
171 173
          },
172 174
          "name": {
173 175
            "maxLength": 200,
174 176
            "minLength": 1,
175 177
            "type": "string"
176 178
          },
177 179
          "nodes": {
178 180
            "items": {
179 181
              "ref": "#node",
180 182
              "type": "ref"
181 183
            },
182 184
            "type": "array"
183 185
          },
186 +
          "noteOutputs": {
187 +
            "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.",
188 +
            "items": {
189 +
              "ref": "#port",
190 +
              "type": "ref"
191 +
            },
192 +
            "type": "array"
193 +
          },
194 +
          "noteSource": {
195 +
            "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.",
196 +
            "knownValues": [
197 +
              "keyboard",
198 +
              "sequencer",
199 +
              "range",
200 +
              "transpose",
201 +
              "assign",
202 +
              "oneshot"
203 +
            ],
204 +
            "maxLength": 64,
205 +
            "type": "string"
206 +
          },
184 207
          "parameters": {
185 208
            "items": {
186 209
              "ref": "#parameter",
187 210
              "type": "ref"
188 211
            },
189 212
            "type": "array"
190 213
          },
214 +
          "patternSource": {
215 +
            "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.",
216 +
            "knownValues": [
217 +
              "arranger",
218 +
              "scenes"
219 +
            ],
220 +
            "maxLength": 64,
221 +
            "type": "string"
222 +
          },
191 223
          "sampleSlots": {
192 224
            "items": {
193 225
              "ref": "#sampleSlot",
194 226
              "type": "ref"
195 227
            },
196 228
            "type": "array"
197 229
          },
198 230
          "versionKey": {
199 -
            "description": "This record's own key within the series. Informational; the record key is authoritative.",
231 +
            "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.",
200 232
            "maxLength": 128,
201 233
            "type": "string"
202 234
          }
203 235
        },
204 236
        "required": [
205 237
          "descriptionVersion",
206 238
          "moduleId",
207 239
          "name",
208 240
          "description",
209 241
          "audioInputs",
210 242
          "audioOutputs",
211 243
          "midiInputs",
212 244
          "nodes",
213 245
          "connections",
214 246
          "createdAt"
215 247
        ],
216 248
        "type": "object"
217 249
      },
218 250
      "type": "record"
219 251
    },
220 252
    "node": {
221 253
      "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.",
222 254
      "properties": {
223 255
        "id": {
224 256
          "maxLength": 64,
225 257
          "minLength": 1,
226 258
          "type": "string"
227 259
        },
228 260
        "kind": {
229 261
          "maxLength": 64,
230 262
          "minLength": 1,
231 263
          "type": "string"
232 264
        },
233 265
        "options": {
266 +
          "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.",
234 267
          "type": "unknown"
235 268
        }
236 269
      },
237 270
      "required": [
238 271
        "id",
239 272
        "kind"
240 273
      ],
241 274
      "type": "object"
242 275
    },
243 276
    "paramTarget": {
244 277
      "properties": {
245 278
        "node": {
246 279
          "maxLength": 64,
247 280
          "minLength": 1,
248 281
          "type": "string"
249 282
        },
250 283
        "param": {
251 284
          "maxLength": 64,
252 285
          "minLength": 1,
253 286
          "type": "string"
254 287
        }
255 288
      },
256 289
      "required": [
257 290
        "node",
258 291
        "param"
259 292
      ],
260 293
      "type": "object"
261 294
    },
262 295
    "parameter": {
263 296
      "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.",
264 297
      "properties": {
265 298
        "default": {
266 -
          "type": "unknown"
299 +
          "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.",
300 +
          "maxLength": 200,
301 +
          "type": "string"
267 302
        },
268 303
        "id": {
269 304
          "maxLength": 64,
270 305
          "minLength": 1,
271 306
          "type": "string"
272 307
        },
273 308
        "label": {
274 309
          "maxLength": 200,
275 310
          "minLength": 1,
276 311
          "type": "string"
277 312
        },
278 313
        "range": {
279 314
          "ref": "#range",
280 315
          "type": "ref"
281 316
        },
317 +
        "scale": {
318 +
          "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.",
319 +
          "knownValues": [
320 +
            "linear",
321 +
            "log"
322 +
          ],
323 +
          "type": "string"
324 +
        },
282 325
        "targets": {
283 326
          "items": {
284 327
            "ref": "#parameterTarget",
285 328
            "type": "ref"
286 329
          },
287 330
          "minLength": 1,
288 331
          "type": "array"
289 332
        },
290 333
        "values": {
291 -
          "description": "A closed value set, where the parameter is not numeric.",
334 +
          "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.",
292 335
          "items": {
293 336
            "maxLength": 200,
294 337
            "type": "string"
295 338
          },
296 339
          "type": "array"
297 340
        }
298 341
      },
299 342
      "required": [
300 343
        "id",
301 344
        "label",
302 345
        "targets"
303 346
      ],
304 347
      "type": "object"
305 348
    },
306 349
    "parameterTarget": {
307 350
      "description": "One of: {node, param}, {node, option}, or {automation, breakpoint, field}.",
308 351
      "properties": {
309 352
        "automation": {
310 353
          "maxLength": 64,
311 354
          "type": "string"
312 355
        },
313 356
        "breakpoint": {
314 357
          "minimum": 0,
315 358
          "type": "integer"
316 359
        },
317 360
        "field": {
318 361
          "knownValues": [
319 362
            "time",
320 363
            "value"
321 364
          ],
322 365
          "type": "string"
323 366
        },
324 367
        "node": {
325 368
          "maxLength": 64,
326 369
          "type": "string"
327 370
        },
328 371
        "option": {
329 372
          "maxLength": 64,
330 373
          "type": "string"
331 374
        },
332 375
        "param": {
333 376
          "maxLength": 64,
334 377
          "type": "string"
335 378
        }
336 379
      },
337 380
      "type": "object"
338 381
    },
339 382
    "port": {
340 383
      "description": "One individually identified audio or MIDI boundary of the module.",
341 384
      "properties": {
342 385
        "id": {
343 386
          "maxLength": 64,
344 387
          "minLength": 1,
345 388
          "type": "string"
346 389
        },
347 390
        "label": {
348 391
          "maxLength": 200,
349 392
          "type": "string"
350 393
        }
351 394
      },
352 395
      "required": [
353 396
        "id"
354 397
      ],
355 398
      "type": "object"
356 399
    },
357 400
    "range": {
358 401
      "properties": {
359 402
        "max": {
360 -
          "type": "unknown"
403 +
          "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.",
404 +
          "maxLength": 200,
405 +
          "type": "string"
361 406
        },
362 407
        "min": {
363 -
          "type": "unknown"
408 +
          "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.",
409 +
          "maxLength": 200,
410 +
          "type": "string"
364 411
        }
365 412
      },
366 413
      "required": [
367 414
        "min",
368 415
        "max"
369 416
      ],
370 417
      "type": "object"
371 418
    },
372 419
    "sampleRef": {
373 420
      "description": "A sample blob and the account that holds it.",
374 421
      "properties": {
375 422
        "blob": {
376 423
          "accept": [
377 424
            "audio/wav"
378 425
          ],
379 -
          "maxSize": 2097152,
426 +
          "maxSize": 10485760,
380 427
          "type": "blob"
381 428
        },
382 429
        "ownerDid": {
383 430
          "format": "did",
384 431
          "type": "string"
385 432
        }
386 433
      },
387 434
      "required": [
388 435
        "blob",
389 436
        "ownerDid"
390 437
      ],
391 438
      "type": "object"
392 439
    },
393 440
    "sampleSlot": {
394 441
      "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.",
395 442
      "properties": {
396 443
        "default": {
397 444
          "ref": "#sampleRef",
398 445
          "type": "ref"
399 446
        },
400 447
        "id": {
401 448
          "maxLength": 64,
402 449
          "minLength": 1,
403 450
          "type": "string"
404 451
        },
405 452
        "label": {
406 453
          "maxLength": 200,
407 454
          "type": "string"
408 455
        },
409 456
        "node": {
410 457
          "maxLength": 64,
411 458
          "minLength": 1,
412 459
          "type": "string"
413 460
        },
414 461
        "property": {
415 462
          "knownValues": [
416 463
            "buffer"
417 464
          ],
418 465
          "type": "string"
419 466
        }
420 467
      },
421 468
      "required": [
422 469
        "id",
423 470
        "node",
424 471
        "property"
425 472
      ],
426 473
      "type": "object"
427 474
    },
428 475
    "source": {
429 476
      "properties": {
430 477
        "node": {
431 478
          "maxLength": 64,
432 479
          "minLength": 1,
433 480
          "type": "string"
434 481
        },
435 482
        "output": {
436 483
          "minimum": 0,
437 484
          "type": "integer"
438 485
        }
439 486
      },
440 487
      "required": [
441 488
        "node"
442 489
      ],
443 490
      "type": "object"
444 491
    },
445 492
    "target": {
446 493
      "description": "Exactly one of `input` or `param` is present. `param` is modulation: a node output reaching a named AudioParam.",
447 494
      "properties": {
448 495
        "input": {
449 496
          "minimum": 0,
450 497
          "type": "integer"
451 498
        },
452 499
        "node": {
453 500
          "maxLength": 64,
454 501
          "minLength": 1,
455 502
          "type": "string"
456 503
        },
457 504
        "param": {
458 505
          "maxLength": 64,
459 506
          "type": "string"
460 507
        }
461 508
      },
462 509
      "required": [
463 510
        "node"
464 511
      ],
465 512
      "type": "object"
466 513
    }
467 514
  },
468 515
  "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.",
469 516
  "id": "at.atmosynth.module",
470 517
  "lexicon": 1
471 518
}

Compare Other Versions

Lexicon Garden

@