at.atmosynth.module
Schema Diff
+14 -4
Compatibility Analysis
Breaking Changes Detected
2 breaking changes, 2 non-breaking changes.
Breaking Changes (2)
- 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\"]" }
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" }
Constraint Changes
- 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\"]" }
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
-
"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
},
317
+
"scale": {
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.",
319
+
"knownValues": [
320
+
"linear",
321
+
"log"
322
+
],
323
+
"type": "string"
324
+
},
315
325
"targets": {
316
326
"items": {
317
327
"ref": "#parameterTarget",
318
328
"type": "ref"
319
329
},
320
330
"minLength": 1,
321
331
"type": "array"
322
332
},
323
333
"values": {
324
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.",
325
335
"items": {
326
336
"maxLength": 200,
327
337
"type": "string"
328
338
},
329
339
"type": "array"
330
340
}
331
341
},
332
342
"required": [
333
343
"id",
334
344
"label",
335
345
"targets"
336
346
],
337
347
"type": "object"
338
348
},
339
349
"parameterTarget": {
340
350
"description": "One of: {node, param}, {node, option}, or {automation, breakpoint, field}.",
341
351
"properties": {
342
352
"automation": {
343
353
"maxLength": 64,
344
354
"type": "string"
345
355
},
346
356
"breakpoint": {
347
357
"minimum": 0,
348
358
"type": "integer"
349
359
},
350
360
"field": {
351
361
"knownValues": [
352
362
"time",
353
363
"value"
354
364
],
355
365
"type": "string"
356
366
},
357
367
"node": {
358
368
"maxLength": 64,
359
369
"type": "string"
360
370
},
361
371
"option": {
362
372
"maxLength": 64,
363
373
"type": "string"
364
374
},
365
375
"param": {
366
376
"maxLength": 64,
367
377
"type": "string"
368
378
}
369
379
},
370
380
"type": "object"
371
381
},
372
382
"port": {
373
383
"description": "One individually identified audio or MIDI boundary of the module.",
374
384
"properties": {
375
385
"id": {
376
386
"maxLength": 64,
377
387
"minLength": 1,
378
388
"type": "string"
379
389
},
380
390
"label": {
381
391
"maxLength": 200,
382
392
"type": "string"
383
393
}
384
394
},
385
395
"required": [
386
396
"id"
387
397
],
388
398
"type": "object"
389
399
},
390
400
"range": {
391
401
"properties": {
392
402
"max": {
393
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.",
394
404
"maxLength": 200,
395
405
"type": "string"
396
406
},
397
407
"min": {
398
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.",
399
409
"maxLength": 200,
400
410
"type": "string"
401
411
}
402
412
},
403
413
"required": [
404
414
"min",
405
415
"max"
406
416
],
407
417
"type": "object"
408
418
},
409
419
"sampleRef": {
410
420
"description": "A sample blob and the account that holds it.",
411
421
"properties": {
412
422
"blob": {
413
423
"accept": [
414
424
"audio/wav"
415
425
],
416
-
"maxSize": 2097152,
426
+
"maxSize": 10485760,
417
427
"type": "blob"
418
428
},
419
429
"ownerDid": {
420
430
"format": "did",
421
431
"type": "string"
422
432
}
423
433
},
424
434
"required": [
425
435
"blob",
426
436
"ownerDid"
427
437
],
428
438
"type": "object"
429
439
},
430
440
"sampleSlot": {
431
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.",
432
442
"properties": {
433
443
"default": {
434
444
"ref": "#sampleRef",
435
445
"type": "ref"
436
446
},
437
447
"id": {
438
448
"maxLength": 64,
439
449
"minLength": 1,
440
450
"type": "string"
441
451
},
442
452
"label": {
443
453
"maxLength": 200,
444
454
"type": "string"
445
455
},
446
456
"node": {
447
457
"maxLength": 64,
448
458
"minLength": 1,
449
459
"type": "string"
450
460
},
451
461
"property": {
452
462
"knownValues": [
453
463
"buffer"
454
464
],
455
465
"type": "string"
456
466
}
457
467
},
458
468
"required": [
459
469
"id",
460
470
"node",
461
471
"property"
462
472
],
463
473
"type": "object"
464
474
},
465
475
"source": {
466
476
"properties": {
467
477
"node": {
468
478
"maxLength": 64,
469
479
"minLength": 1,
470
480
"type": "string"
471
481
},
472
482
"output": {
473
483
"minimum": 0,
474
484
"type": "integer"
475
485
}
476
486
},
477
487
"required": [
478
488
"node"
479
489
],
480
490
"type": "object"
481
491
},
482
492
"target": {
483
493
"description": "Exactly one of `input` or `param` is present. `param` is modulation: a node output reaching a named AudioParam.",
484
494
"properties": {
485
495
"input": {
486
496
"minimum": 0,
487
497
"type": "integer"
488
498
},
489
499
"node": {
490
500
"maxLength": 64,
491
501
"minLength": 1,
492
502
"type": "string"
493
503
},
494
504
"param": {
495
505
"maxLength": 64,
496
506
"type": "string"
497
507
}
498
508
},
499
509
"required": [
500
510
"node"
501
511
],
502
512
"type": "object"
503
513
}
504
514
},
505
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.",
506
516
"id": "at.atmosynth.module",
507
517
"lexicon": 1
508
518
}