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