at.atmosynth.module

atmosynth.at

Schema Diff

+5 -2

From

CID
bafyreie7vbl2bxf...
Indexed At
2026-09-22 18:36 UTC
View this version

To

CID
bafyreibyikm6cn4...
Indexed At
2026-09-24 12:51 UTC
View this version

Compatibility Analysis

Breaking Changes Detected

1 breaking change, 0 non-breaking changes.

Breaking Changes (1)
  • ConstraintTightened ConstraintTightened { vertex_id: "at.atmosynth.module:body.noteSource", sort: "knownValues", old_value: "[\"keyboard\",\"sequencer\"]", new_value: "[\"keyboard\",\"sequencer\",\"range\",\"transpose\",\"assign\"]" }

Migration Guidance

Constraint Changes

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

Compare Other Versions

Lexicon Garden

@