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