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