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