at.atmosynth.module

atmosynth.at

Schema Diff

+17 -0

From

CID
bafyreif4uicvsyi...
Indexed At
2026-08-31 14:12 UTC
View this version

To

CID
bafyreifevnggceg...
Indexed At
2026-09-08 07:18 UTC
View this version

Compatibility Analysis

Backward Compatible

Backward compatible. 7 non-breaking changes.

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

Additional Notes

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

Compare Other Versions

Lexicon Garden

@