at.atmosynth.module

atmosynth.at

Schema Diff

+17 -12

From

CID
bafyreifevnggceg...
Indexed At
2026-09-08 07:18 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, 0 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#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" }
  • ConstraintAdded ConstraintAdded { vertex_id: "at.atmosynth.module#parameter.default", sort: "maxLength", value: "200" }

Migration Guidance

Constraint Changes

  • 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" }
  • 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" }

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

Compare Other Versions

Lexicon Garden

@