at.atmosynth.module

atmosynth.at

Schema Diff

+34 -8

From

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

To

CID
bafyreifgfuhftmi...
Indexed At
2026-09-18 11:56 UTC
View this version

Compatibility Analysis

Breaking Changes Detected

8 breaking changes, 7 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 (7)
  • 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" }
  • 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.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:body.noteOutputs" }
  • AddedVertex { vertex_id: "at.atmosynth.module:body.noteOutputs:items" }
  • AddedVertex { vertex_id: "at.atmosynth.module:body.noteSource" }

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

Compare Other Versions

Lexicon Garden

@