at.atmosynth.patch
Schema Diff
+30 -0
Compatibility Analysis
Breaking Changes Detected
2 breaking changes, 8 non-breaking changes.
Breaking Changes (2)
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "at.atmosynth.patch#midiControl", src: "at.atmosynth.patch#midiControl", tgt: "at.atmosynth.patch#midiControl.controller", kind: "prop", name: Some("controller") }
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "at.atmosynth.patch#midiControl", src: "at.atmosynth.patch#midiControl", tgt: "at.atmosynth.patch#midiControl.parameter", kind: "prop", name: Some("parameter") }
Non-Breaking Changes (8)
- AddedVertex AddedVertex { vertex_id: "at.atmosynth.patch#midiControl" }
- AddedVertex AddedVertex { vertex_id: "at.atmosynth.patch#midiControl.controller" }
- AddedVertex AddedVertex { vertex_id: "at.atmosynth.patch#midiControl.parameter" }
- AddedVertex AddedVertex { vertex_id: "at.atmosynth.patch#moduleInstance.midiControls" }
- AddedVertex AddedVertex { vertex_id: "at.atmosynth.patch#moduleInstance.midiControls:items" }
- AddedEdge AddedEdge { src: "at.atmosynth.patch#moduleInstance", tgt: "at.atmosynth.patch#moduleInstance.midiControls", kind: "prop", name: Some("midiControls") }
- AddedEdge AddedEdge { src: "at.atmosynth.patch#moduleInstance.midiControls", tgt: "at.atmosynth.patch#moduleInstance.midiControls:items", kind: "items", name: None }
- AddedEdge AddedEdge { src: "at.atmosynth.patch#moduleInstance.midiControls:items", tgt: "at.atmosynth.patch#midiControl", kind: "ref", name: None }
Migration Guidance
Added Elements
AddedVertex { vertex_id: "at.atmosynth.patch#midiControl" }AddedVertex { vertex_id: "at.atmosynth.patch#midiControl.controller" }AddedVertex { vertex_id: "at.atmosynth.patch#midiControl.parameter" }AddedVertex { vertex_id: "at.atmosynth.patch#moduleInstance.midiControls" }AddedVertex { vertex_id: "at.atmosynth.patch#moduleInstance.midiControls:items" }
Additional Notes
- Breaking: RequiredEdgeAdded { vertex_id: "at.atmosynth.patch#midiControl", src: "at.atmosynth.patch#midiControl", tgt: "at.atmosynth.patch#midiControl.controller", kind: "prop", name: Some("controller") }
- Breaking: RequiredEdgeAdded { vertex_id: "at.atmosynth.patch#midiControl", src: "at.atmosynth.patch#midiControl", tgt: "at.atmosynth.patch#midiControl.parameter", kind: "prop", name: Some("parameter") }
- Non-breaking: AddedEdge { src: "at.atmosynth.patch#moduleInstance", tgt: "at.atmosynth.patch#moduleInstance.midiControls", kind: "prop", name: Some("midiControls") }
- Non-breaking: AddedEdge { src: "at.atmosynth.patch#moduleInstance.midiControls", tgt: "at.atmosynth.patch#moduleInstance.midiControls:items", kind: "items", name: None }
- Non-breaking: AddedEdge { src: "at.atmosynth.patch#moduleInstance.midiControls:items", tgt: "at.atmosynth.patch#midiControl", kind: "ref", name: None }
1
1
{
2
2
"id": "at.atmosynth.patch",
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
"name",
12
12
"description",
13
13
"moduleInstances",
14
14
"createdAt"
15
15
],
16
16
"properties": {
17
17
"name": {
18
18
"type": "string",
19
19
"maxLength": 200,
20
20
"minLength": 1
21
21
},
22
22
"tags": {
23
23
"type": "array",
24
24
"items": {
25
25
"type": "string",
26
26
"maxLength": 128
27
27
},
28
28
"description": "Freely created tags, lower-cased on write so one hashtag matches one set of patches."
29
29
},
30
30
"types": {
31
31
"type": "array",
32
32
"items": {
33
33
"type": "string",
34
34
"knownValues": [
35
35
"Lead",
36
36
"Pad",
37
37
"Bass",
38
38
"Plucked",
39
39
"Percussion",
40
40
"Keys",
41
41
"Brass",
42
42
"Strings",
43
43
"Vocal",
44
44
"SFX"
45
45
]
46
46
},
47
47
"description": "Zero or more of the ten fixed types. A patch may carry several."
48
48
},
49
49
"output": {
50
50
"ref": "#outputRef",
51
51
"type": "ref",
52
52
"description": "Which instance reaches the audio output."
53
53
},
54
54
"createdAt": {
55
55
"type": "string",
56
56
"format": "datetime"
57
57
},
58
58
"forkedFrom": {
59
59
"ref": "#lineage",
60
60
"type": "ref"
61
61
},
62
62
"connections": {
63
63
"type": "array",
64
64
"items": {
65
65
"ref": "#connection",
66
66
"type": "ref"
67
67
}
68
68
},
69
69
"description": {
70
70
"type": "string",
71
71
"maxLength": 3000
72
72
},
73
73
"midiRouting": {
74
74
"type": "array",
75
75
"items": {
76
76
"ref": "#midiRoute",
77
77
"type": "ref"
78
78
},
79
79
"description": "Which module instances receive MIDI input."
80
80
},
81
81
"moduleInstances": {
82
82
"type": "array",
83
83
"items": {
84
84
"ref": "#moduleInstance",
85
85
"type": "ref"
86
86
}
87
87
},
88
88
"descriptionVersion": {
89
89
"type": "integer",
90
90
"minimum": 1,
91
91
"description": "Version of the patch description this record follows."
92
92
}
93
93
}
94
94
},
95
95
"description": "A patch, held in its creator's own repository."
96
96
},
97
97
"lineage": {
98
98
"type": "object",
99
99
"required": [
100
100
"uri",
101
101
"creatorDid"
102
102
],
103
103
"properties": {
104
104
"uri": {
105
105
"type": "string",
106
106
"format": "at-uri"
107
107
},
108
108
"patchId": {
109
109
"type": "string",
110
110
"maxLength": 128
111
111
},
112
112
"creatorDid": {
113
113
"type": "string",
114
114
"format": "did"
115
115
}
116
116
},
117
117
"description": "The patch this one was forked from, and its creator. Preserved even when the source is later deleted."
118
118
},
119
119
"inputRef": {
120
120
"type": "object",
121
121
"required": [
122
122
"instanceId",
123
123
"audioInput"
124
124
],
125
125
"properties": {
126
126
"audioInput": {
127
127
"type": "string",
128
128
"maxLength": 64,
129
129
"minLength": 1
130
130
},
131
131
"instanceId": {
132
132
"type": "string",
133
133
"maxLength": 64,
134
134
"minLength": 1
135
135
}
136
136
}
137
137
},
138
138
"position": {
139
139
"type": "object",
140
140
"required": [
141
141
"x",
142
142
"y"
143
143
],
144
144
"properties": {
145
145
"x": {
146
146
"type": "integer"
147
147
},
148
148
"y": {
149
149
"type": "integer"
150
150
}
151
151
}
152
152
},
153
153
"midiRoute": {
154
154
"type": "object",
155
155
"required": [
156
156
"instanceId",
157
157
"midiInput"
158
158
],
159
159
"properties": {
160
160
"midiInput": {
161
161
"type": "string",
162
162
"maxLength": 64,
163
163
"minLength": 1
164
164
},
165
165
"instanceId": {
166
166
"type": "string",
167
167
"maxLength": 64,
168
168
"minLength": 1
169
169
}
170
170
}
171
171
},
172
172
"moduleRef": {
173
173
"type": "object",
174
174
"required": [
175
175
"moduleId",
176
176
"versionKey",
177
177
"authorDid"
178
178
],
179
179
"properties": {
180
180
"moduleId": {
181
181
"type": "string",
182
182
"maxLength": 128,
183
183
"minLength": 1
184
184
},
185
185
"authorDid": {
186
186
"type": "string",
187
187
"format": "did"
188
188
},
189
189
"versionKey": {
190
190
"type": "string",
191
191
"maxLength": 128,
192
192
"minLength": 1
193
193
}
194
194
},
195
195
"description": "A pin to one exact published version of a module. Resolving it fetches that record, whoever authored it."
196
196
},
197
197
"outputRef": {
198
198
"type": "object",
199
199
"required": [
200
200
"instanceId",
201
201
"audioOutput"
202
202
],
203
203
"properties": {
204
204
"instanceId": {
205
205
"type": "string",
206
206
"maxLength": 64,
207
207
"minLength": 1
208
208
},
209
209
"audioOutput": {
210
210
"type": "string",
211
211
"maxLength": 64,
212
212
"minLength": 1
213
213
}
214
214
}
215
215
},
216
216
"connection": {
217
217
"type": "object",
218
218
"required": [
219
219
"from",
220
220
"to"
221
221
],
222
222
"properties": {
223
223
"to": {
224
224
"ref": "#inputRef",
225
225
"type": "ref"
226
226
},
227
227
"from": {
228
228
"ref": "#outputRef",
229
229
"type": "ref"
230
230
}
231
231
},
232
232
"description": "An audio connection between two module instances, naming the declared ports at each end."
233
233
},
234
+
"midiControl": {
235
+
"type": "object",
236
+
"required": [
237
+
"parameter",
238
+
"controller"
239
+
],
240
+
"properties": {
241
+
"parameter": {
242
+
"type": "string",
243
+
"maxLength": 64,
244
+
"minLength": 1,
245
+
"description": "The id of the exposed parameter this control moves. One parameter is moved by at most one controller; one controller may move several parameters."
246
+
},
247
+
"controller": {
248
+
"type": "integer",
249
+
"maximum": 127,
250
+
"minimum": 0,
251
+
"description": "The control change number. Five are spoken for by MIDI itself and cannot be bound: 64, the sustain pedal, and 6, 38, 100 and 101, which carry registered-parameter traffic."
252
+
}
253
+
},
254
+
"description": "One MIDI control change bound to one of the module's exposed parameters. The controller's 0 to 127 sweeps the parameter across the range the module declares, or, where the module declares a closed value set instead, across those values in order. A control is read from every input on every channel, like every other MIDI message here: there is nothing to configure."
255
+
},
234
256
"moduleInstance": {
235
257
"type": "object",
236
258
"required": [
237
259
"instanceId",
238
260
"module"
239
261
],
240
262
"properties": {
241
263
"module": {
242
264
"ref": "#moduleRef",
243
265
"type": "ref"
244
266
},
245
267
"position": {
246
268
"ref": "#position",
247
269
"type": "ref",
248
270
"description": "Where the creator placed this instance in the patch's arrangement, so the arrangement travels with the patch and a fork inherits it. Optional permanently, and the only field in either description that exists for presentation."
249
271
},
250
272
"instanceId": {
251
273
"type": "string",
252
274
"maxLength": 64,
253
275
"minLength": 1
254
276
},
255
277
"voiceScope": {
256
278
"type": "string",
257
279
"description": "Whether this instance is built once for each sounding note or once for the whole patch. Optional permanently: an unset scope is worked out when the patch is played, and is never written on a creator's behalf.",
258
280
"knownValues": [
259
281
"perNote",
260
282
"perPatch"
261
283
]
262
284
},
285
+
"midiControls": {
286
+
"type": "array",
287
+
"items": {
288
+
"ref": "#midiControl",
289
+
"type": "ref"
290
+
},
291
+
"description": "Which MIDI control changes move this instance's parameters while it is played. A binding lives here, in the patch, because which knob moves what is a decision about this use of the module and not about the module."
292
+
},
263
293
"parameterValues": {
264
294
"type": "array",
265
295
"items": {
266
296
"ref": "#parameterValue",
267
297
"type": "ref"
268
298
}
269
299
},
270
300
"sampleSlotFills": {
271
301
"type": "array",
272
302
"items": {
273
303
"ref": "#sampleSlotFill",
274
304
"type": "ref"
275
305
},
276
306
"description": "Samples this instance supplies for the module's declared slots. A fill lives here, in the patch, so writing one never touches the module."
277
307
}
278
308
},
279
309
"description": "One use of one module version. A patch may use the same module more than once; each instance is separately addressable and carries its own parameter values and slot fills."
280
310
},
281
311
"parameterValue": {
282
312
"type": "object",
283
313
"required": [
284
314
"id"
285
315
],
286
316
"properties": {
287
317
"id": {
288
318
"type": "string",
289
319
"maxLength": 64,
290
320
"minLength": 1
291
321
},
292
322
"value": {
293
323
"type": "unknown",
294
324
"description": "The value this patch sets the parameter to. 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 the module declares a closed set of values instead, this is one of those strings, and a label that looks like a number stays the label it is."
295
325
},
296
326
"useDefault": {
297
327
"type": "boolean",
298
328
"description": "Set where the patch explicitly defers to the module's default rather than recording a value."
299
329
}
300
330
},
301
331
"description": "A value for one of the module's exposed parameters, or an explicit fall-back to the module's declared default."
302
332
},
303
333
"sampleSlotFill": {
304
334
"type": "object",
305
335
"required": [
306
336
"slotId",
307
337
"blob",
308
338
"ownerDid"
309
339
],
310
340
"properties": {
311
341
"blob": {
312
342
"type": "blob",
313
343
"accept": [
314
344
"audio/wav"
315
345
],
316
346
"maxSize": 2097152
317
347
},
318
348
"slotId": {
319
349
"type": "string",
320
350
"maxLength": 64,
321
351
"minLength": 1
322
352
},
323
353
"ownerDid": {
324
354
"type": "string",
325
355
"format": "did"
326
356
}
327
357
}
328
358
}
329
359
},
330
360
"$type": "com.atproto.lexicon.schema",
331
361
"lexicon": 1,
332
362
"description": "A synth patch: which modules it uses, how they are wired, what their parameters are set to, and how it is played. A patch plus the module records it pins is everything needed to reproduce it."
333
363
}