at.atmosynth.module

atmosynth.at

Schema Diff

+8 -0

From

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

To

CID
bafyreifijav3zpz...
Indexed At
2026-09-25 10:58 UTC
View this version

Compatibility Analysis

Backward Compatible

Backward compatible. 2 non-breaking changes.

Non-Breaking Changes (2)
  • AddedVertex AddedVertex { vertex_id: "at.atmosynth.module#parameter.scale" }
  • AddedEdge AddedEdge { src: "at.atmosynth.module#parameter", tgt: "at.atmosynth.module#parameter.scale", kind: "prop", name: Some("scale") }

Migration Guidance

Added Elements

  • AddedVertex { vertex_id: "at.atmosynth.module#parameter.scale" }

Additional Notes

  • Non-breaking: AddedEdge { src: "at.atmosynth.module#parameter", tgt: "at.atmosynth.module#parameter.scale", kind: "prop", name: Some("scale") }
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 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 198
              "sequencer",
199 199
              "range",
200 200
              "transpose",
201 201
              "assign"
202 202
            ],
203 203
            "maxLength": 64,
204 204
            "type": "string"
205 205
          },
206 206
          "parameters": {
207 207
            "items": {
208 208
              "ref": "#parameter",
209 209
              "type": "ref"
210 210
            },
211 211
            "type": "array"
212 212
          },
213 213
          "patternSource": {
214 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.",
215 215
            "knownValues": [
216 216
              "arranger"
217 217
            ],
218 218
            "maxLength": 64,
219 219
            "type": "string"
220 220
          },
221 221
          "sampleSlots": {
222 222
            "items": {
223 223
              "ref": "#sampleSlot",
224 224
              "type": "ref"
225 225
            },
226 226
            "type": "array"
227 227
          },
228 228
          "versionKey": {
229 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.",
230 230
            "maxLength": 128,
231 231
            "type": "string"
232 232
          }
233 233
        },
234 234
        "required": [
235 235
          "descriptionVersion",
236 236
          "moduleId",
237 237
          "name",
238 238
          "description",
239 239
          "audioInputs",
240 240
          "audioOutputs",
241 241
          "midiInputs",
242 242
          "nodes",
243 243
          "connections",
244 244
          "createdAt"
245 245
        ],
246 246
        "type": "object"
247 247
      },
248 248
      "type": "record"
249 249
    },
250 250
    "node": {
251 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.",
252 252
      "properties": {
253 253
        "id": {
254 254
          "maxLength": 64,
255 255
          "minLength": 1,
256 256
          "type": "string"
257 257
        },
258 258
        "kind": {
259 259
          "maxLength": 64,
260 260
          "minLength": 1,
261 261
          "type": "string"
262 262
        },
263 263
        "options": {
264 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.",
265 265
          "type": "unknown"
266 266
        }
267 267
      },
268 268
      "required": [
269 269
        "id",
270 270
        "kind"
271 271
      ],
272 272
      "type": "object"
273 273
    },
274 274
    "paramTarget": {
275 275
      "properties": {
276 276
        "node": {
277 277
          "maxLength": 64,
278 278
          "minLength": 1,
279 279
          "type": "string"
280 280
        },
281 281
        "param": {
282 282
          "maxLength": 64,
283 283
          "minLength": 1,
284 284
          "type": "string"
285 285
        }
286 286
      },
287 287
      "required": [
288 288
        "node",
289 289
        "param"
290 290
      ],
291 291
      "type": "object"
292 292
    },
293 293
    "parameter": {
294 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.",
295 295
      "properties": {
296 296
        "default": {
297 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.",
298 298
          "maxLength": 200,
299 299
          "type": "string"
300 300
        },
301 301
        "id": {
302 302
          "maxLength": 64,
303 303
          "minLength": 1,
304 304
          "type": "string"
305 305
        },
306 306
        "label": {
307 307
          "maxLength": 200,
308 308
          "minLength": 1,
309 309
          "type": "string"
310 310
        },
311 311
        "range": {
312 312
          "ref": "#range",
313 313
          "type": "ref"
314 314
        },
315 +
        "scale": {
316 +
          "description": "How a slider or a MIDI control moves through the range. linear moves by equal differences; log moves by equal ratios, which is how a frequency is heard, so the middle of a 20 to 20000 sweep is about 632 rather than about 10000. log needs a range above zero at both ends. Absent is linear. A parameter with a closed value set has no scale.",
317 +
          "knownValues": [
318 +
            "linear",
319 +
            "log"
320 +
          ],
321 +
          "type": "string"
322 +
        },
315 323
        "targets": {
316 324
          "items": {
317 325
            "ref": "#parameterTarget",
318 326
            "type": "ref"
319 327
          },
320 328
          "minLength": 1,
321 329
          "type": "array"
322 330
        },
323 331
        "values": {
324 332
          "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.",
325 333
          "items": {
326 334
            "maxLength": 200,
327 335
            "type": "string"
328 336
          },
329 337
          "type": "array"
330 338
        }
331 339
      },
332 340
      "required": [
333 341
        "id",
334 342
        "label",
335 343
        "targets"
336 344
      ],
337 345
      "type": "object"
338 346
    },
339 347
    "parameterTarget": {
340 348
      "description": "One of: {node, param}, {node, option}, or {automation, breakpoint, field}.",
341 349
      "properties": {
342 350
        "automation": {
343 351
          "maxLength": 64,
344 352
          "type": "string"
345 353
        },
346 354
        "breakpoint": {
347 355
          "minimum": 0,
348 356
          "type": "integer"
349 357
        },
350 358
        "field": {
351 359
          "knownValues": [
352 360
            "time",
353 361
            "value"
354 362
          ],
355 363
          "type": "string"
356 364
        },
357 365
        "node": {
358 366
          "maxLength": 64,
359 367
          "type": "string"
360 368
        },
361 369
        "option": {
362 370
          "maxLength": 64,
363 371
          "type": "string"
364 372
        },
365 373
        "param": {
366 374
          "maxLength": 64,
367 375
          "type": "string"
368 376
        }
369 377
      },
370 378
      "type": "object"
371 379
    },
372 380
    "port": {
373 381
      "description": "One individually identified audio or MIDI boundary of the module.",
374 382
      "properties": {
375 383
        "id": {
376 384
          "maxLength": 64,
377 385
          "minLength": 1,
378 386
          "type": "string"
379 387
        },
380 388
        "label": {
381 389
          "maxLength": 200,
382 390
          "type": "string"
383 391
        }
384 392
      },
385 393
      "required": [
386 394
        "id"
387 395
      ],
388 396
      "type": "object"
389 397
    },
390 398
    "range": {
391 399
      "properties": {
392 400
        "max": {
393 401
          "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.",
394 402
          "maxLength": 200,
395 403
          "type": "string"
396 404
        },
397 405
        "min": {
398 406
          "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.",
399 407
          "maxLength": 200,
400 408
          "type": "string"
401 409
        }
402 410
      },
403 411
      "required": [
404 412
        "min",
405 413
        "max"
406 414
      ],
407 415
      "type": "object"
408 416
    },
409 417
    "sampleRef": {
410 418
      "description": "A sample blob and the account that holds it.",
411 419
      "properties": {
412 420
        "blob": {
413 421
          "accept": [
414 422
            "audio/wav"
415 423
          ],
416 424
          "maxSize": 2097152,
417 425
          "type": "blob"
418 426
        },
419 427
        "ownerDid": {
420 428
          "format": "did",
421 429
          "type": "string"
422 430
        }
423 431
      },
424 432
      "required": [
425 433
        "blob",
426 434
        "ownerDid"
427 435
      ],
428 436
      "type": "object"
429 437
    },
430 438
    "sampleSlot": {
431 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.",
432 440
      "properties": {
433 441
        "default": {
434 442
          "ref": "#sampleRef",
435 443
          "type": "ref"
436 444
        },
437 445
        "id": {
438 446
          "maxLength": 64,
439 447
          "minLength": 1,
440 448
          "type": "string"
441 449
        },
442 450
        "label": {
443 451
          "maxLength": 200,
444 452
          "type": "string"
445 453
        },
446 454
        "node": {
447 455
          "maxLength": 64,
448 456
          "minLength": 1,
449 457
          "type": "string"
450 458
        },
451 459
        "property": {
452 460
          "knownValues": [
453 461
            "buffer"
454 462
          ],
455 463
          "type": "string"
456 464
        }
457 465
      },
458 466
      "required": [
459 467
        "id",
460 468
        "node",
461 469
        "property"
462 470
      ],
463 471
      "type": "object"
464 472
    },
465 473
    "source": {
466 474
      "properties": {
467 475
        "node": {
468 476
          "maxLength": 64,
469 477
          "minLength": 1,
470 478
          "type": "string"
471 479
        },
472 480
        "output": {
473 481
          "minimum": 0,
474 482
          "type": "integer"
475 483
        }
476 484
      },
477 485
      "required": [
478 486
        "node"
479 487
      ],
480 488
      "type": "object"
481 489
    },
482 490
    "target": {
483 491
      "description": "Exactly one of `input` or `param` is present. `param` is modulation: a node output reaching a named AudioParam.",
484 492
      "properties": {
485 493
        "input": {
486 494
          "minimum": 0,
487 495
          "type": "integer"
488 496
        },
489 497
        "node": {
490 498
          "maxLength": 64,
491 499
          "minLength": 1,
492 500
          "type": "string"
493 501
        },
494 502
        "param": {
495 503
          "maxLength": 64,
496 504
          "type": "string"
497 505
        }
498 506
      },
499 507
      "required": [
500 508
        "node"
501 509
      ],
502 510
      "type": "object"
503 511
    }
504 512
  },
505 513
  "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.",
506 514
  "id": "at.atmosynth.module",
507 515
  "lexicon": 1
508 516
}

Compare Other Versions

Lexicon Garden

@