at.atmosynth.module

atmosynth.at

Schema Diff

+33 -11

From

CID
bafyreif4uicvsyi...
Indexed At
2026-08-31 14:12 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#breakpoint.value", sort: "maxLength", value: "200" }
  • 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" }
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#breakpoint.value", sort: "maxLength", value: "200" }
  • ConstraintAdded ConstraintAdded { vertex_id: "at.atmosynth.module#parameter.default", sort: "maxLength", value: "200" }
  • ConstraintAdded ConstraintAdded { vertex_id: "at.atmosynth.module#range.max", 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."
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 +
            ]
61 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 152
          "type": "unknown",
135 -
          "description": "The node's settings, as its kind defines them. 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."
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."
136 154
        }
137 155
      },
138 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."
139 157
    },
140 158
    "port": {
141 159
      "type": "object",
142 160
      "required": [
143 161
        "id"
144 162
      ],
145 163
      "properties": {
146 164
        "id": {
147 165
          "type": "string",
148 166
          "maxLength": 64,
149 167
          "minLength": 1
150 168
        },
151 169
        "label": {
152 170
          "type": "string",
153 171
          "maxLength": 200
154 172
        }
155 173
      },
156 174
      "description": "One individually identified audio or MIDI boundary of the module."
157 175
    },
158 176
    "range": {
159 177
      "type": "object",
160 178
      "required": [
161 179
        "min",
162 180
        "max"
163 181
      ],
164 182
      "properties": {
165 183
        "max": {
166 -
          "type": "unknown",
167 -
          "description": "The high bound. 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."
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."
168 187
        },
169 188
        "min": {
170 -
          "type": "unknown",
171 -
          "description": "The low bound. 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."
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."
172 192
        }
173 193
      }
174 194
    },
175 195
    "source": {
176 196
      "type": "object",
177 197
      "required": [
178 198
        "node"
179 199
      ],
180 200
      "properties": {
181 201
        "node": {
182 202
          "type": "string",
183 203
          "maxLength": 64,
184 204
          "minLength": 1
185 205
        },
186 206
        "output": {
187 207
          "type": "integer",
188 208
          "minimum": 0
189 209
        }
190 210
      }
191 211
    },
192 212
    "target": {
193 213
      "type": "object",
194 214
      "required": [
195 215
        "node"
196 216
      ],
197 217
      "properties": {
198 218
        "node": {
199 219
          "type": "string",
200 220
          "maxLength": 64,
201 221
          "minLength": 1
202 222
        },
203 223
        "input": {
204 224
          "type": "integer",
205 225
          "minimum": 0
206 226
        },
207 227
        "param": {
208 228
          "type": "string",
209 229
          "maxLength": 64
210 230
        }
211 231
      },
212 232
      "description": "Exactly one of `input` or `param` is present. `param` is modulation: a node output reaching a named AudioParam."
213 233
    },
214 234
    "lineage": {
215 235
      "type": "object",
216 236
      "required": [
217 237
        "uri",
218 238
        "authorDid"
219 239
      ],
220 240
      "properties": {
221 241
        "uri": {
222 242
          "type": "string",
223 243
          "format": "at-uri"
224 244
        },
225 245
        "moduleId": {
226 246
          "type": "string",
227 247
          "maxLength": 128
228 248
        },
229 249
        "authorDid": {
230 250
          "type": "string",
231 251
          "format": "did"
232 252
        }
233 253
      },
234 254
      "description": "The module this one was forked from, and its author."
235 255
    },
236 256
    "parameter": {
237 257
      "type": "object",
238 258
      "required": [
239 259
        "id",
240 260
        "label",
241 261
        "targets"
242 262
      ],
243 263
      "properties": {
244 264
        "id": {
245 265
          "type": "string",
246 266
          "maxLength": 64,
247 267
          "minLength": 1
248 268
        },
249 269
        "label": {
250 270
          "type": "string",
251 271
          "maxLength": 200,
252 272
          "minLength": 1
253 273
        },
254 274
        "range": {
255 275
          "ref": "#range",
256 276
          "type": "ref"
257 277
        },
258 278
        "values": {
259 279
          "type": "array",
260 280
          "items": {
261 281
            "type": "string",
262 282
            "maxLength": 200
263 283
          },
264 284
          "description": "A closed value set, where the parameter is not numeric."
265 285
        },
266 286
        "default": {
267 -
          "type": "unknown",
268 -
          "description": "The value used where a patch sets none. 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 this parameter declares a closed value set, it is one of those strings."
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."
269 290
        },
270 291
        "targets": {
271 292
          "type": "array",
272 293
          "items": {
273 294
            "ref": "#parameterTarget",
274 295
            "type": "ref"
275 296
          },
276 297
          "minLength": 1
277 298
        }
278 299
      },
279 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."
280 301
    },
281 302
    "sampleRef": {
282 303
      "type": "object",
283 304
      "required": [
284 305
        "blob",
285 306
        "ownerDid"
286 307
      ],
287 308
      "properties": {
288 309
        "blob": {
289 310
          "type": "blob",
290 311
          "accept": [
291 312
            "audio/wav"
292 313
          ],
293 314
          "maxSize": 2097152
294 315
        },
295 316
        "ownerDid": {
296 317
          "type": "string",
297 318
          "format": "did"
298 319
        }
299 320
      },
300 321
      "description": "A sample blob and the account that holds it."
301 322
    },
302 323
    "automation": {
303 324
      "type": "object",
304 325
      "required": [
305 326
        "id",
306 327
        "target",
307 328
        "breakpoints"
308 329
      ],
309 330
      "properties": {
310 331
        "id": {
311 332
          "type": "string",
312 333
          "maxLength": 64,
313 334
          "minLength": 1
314 335
        },
315 336
        "label": {
316 337
          "type": "string",
317 338
          "maxLength": 200
318 339
        },
319 340
        "target": {
320 341
          "ref": "#paramTarget",
321 342
          "type": "ref"
322 343
        },
323 344
        "sustainAt": {
324 345
          "type": "integer",
325 346
          "minimum": 0,
326 347
          "description": "Index into breakpoints where the value holds while a note is held. Absent means a one-shot."
327 348
        },
328 349
        "breakpoints": {
329 350
          "type": "array",
330 351
          "items": {
331 352
            "ref": "#breakpoint",
332 353
            "type": "ref"
333 354
          },
334 355
          "minLength": 1
335 356
        }
336 357
      },
337 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."
338 359
    },
339 360
    "breakpoint": {
340 361
      "type": "object",
341 362
      "required": [
342 363
        "time",
343 364
        "value"
344 365
      ],
345 366
      "properties": {
346 367
        "time": {
347 368
          "type": "integer",
348 369
          "minimum": 0,
349 370
          "description": "Milliseconds from the trigger."
350 371
        },
351 372
        "curve": {
352 373
          "type": "string",
353 374
          "description": "How the value travels from the previous breakpoint.",
354 375
          "knownValues": [
355 376
            "step",
356 377
            "linear",
357 378
            "exponential"
358 379
          ]
359 380
        },
360 381
        "value": {
361 -
          "type": "unknown",
362 -
          "description": "The param's value at this instant. 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."
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."
363 385
        }
364 386
      }
365 387
    },
366 388
    "connection": {
367 389
      "type": "object",
368 390
      "required": [
369 391
        "from",
370 392
        "to"
371 393
      ],
372 394
      "properties": {
373 395
        "to": {
374 396
          "ref": "#target",
375 397
          "type": "ref"
376 398
        },
377 399
        "from": {
378 400
          "ref": "#source",
379 401
          "type": "ref"
380 402
        }
381 403
      },
382 404
      "description": "An audio connection from a node output to either an audio input or a named AudioParam."
383 405
    },
384 406
    "sampleSlot": {
385 407
      "type": "object",
386 408
      "required": [
387 409
        "id",
388 410
        "node",
389 411
        "property"
390 412
      ],
391 413
      "properties": {
392 414
        "id": {
393 415
          "type": "string",
394 416
          "maxLength": 64,
395 417
          "minLength": 1
396 418
        },
397 419
        "node": {
398 420
          "type": "string",
399 421
          "maxLength": 64,
400 422
          "minLength": 1
401 423
        },
402 424
        "label": {
403 425
          "type": "string",
404 426
          "maxLength": 200
405 427
        },
406 428
        "default": {
407 429
          "ref": "#sampleRef",
408 430
          "type": "ref"
409 431
        },
410 432
        "property": {
411 433
          "type": "string",
412 434
          "knownValues": [
413 435
            "buffer"
414 436
          ]
415 437
        }
416 438
      },
417 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."
418 440
    },
419 441
    "paramTarget": {
420 442
      "type": "object",
421 443
      "required": [
422 444
        "node",
423 445
        "param"
424 446
      ],
425 447
      "properties": {
426 448
        "node": {
427 449
          "type": "string",
428 450
          "maxLength": 64,
429 451
          "minLength": 1
430 452
        },
431 453
        "param": {
432 454
          "type": "string",
433 455
          "maxLength": 64,
434 456
          "minLength": 1
435 457
        }
436 458
      }
437 459
    },
438 460
    "parameterTarget": {
439 461
      "type": "object",
440 462
      "properties": {
441 463
        "node": {
442 464
          "type": "string",
443 465
          "maxLength": 64
444 466
        },
445 467
        "field": {
446 468
          "type": "string",
447 469
          "knownValues": [
448 470
            "time",
449 471
            "value"
450 472
          ]
451 473
        },
452 474
        "param": {
453 475
          "type": "string",
454 476
          "maxLength": 64
455 477
        },
456 478
        "option": {
457 479
          "type": "string",
458 480
          "maxLength": 64
459 481
        },
460 482
        "automation": {
461 483
          "type": "string",
462 484
          "maxLength": 64
463 485
        },
464 486
        "breakpoint": {
465 487
          "type": "integer",
466 488
          "minimum": 0
467 489
        }
468 490
      },
469 491
      "description": "One of: {node, param}, {node, option}, or {automation, breakpoint, field}."
470 492
    }
471 493
  },
472 494
  "$type": "com.atproto.lexicon.schema",
473 495
  "lexicon": 1,
474 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."
475 497
}

Compare Other Versions

Lexicon Garden

@