at.atmosynth.patch

atmosynth.at

Schema Diff

+33 -0

From

CID
bafyreicuqb5sjlc...
Indexed At
2026-09-22 18:36 UTC
View this version

To

CID
bafyreicmogdgg4j...
Indexed At
2026-09-23 07:51 UTC
View this version

Compatibility Analysis

Breaking Changes Detected

2 breaking changes, 11 non-breaking changes.

Breaking Changes (2)
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "at.atmosynth.patch#inputRoute", src: "at.atmosynth.patch#inputRoute", tgt: "at.atmosynth.patch#inputRoute.from", kind: "prop", name: Some("from") }
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "at.atmosynth.patch#inputRoute", src: "at.atmosynth.patch#inputRoute", tgt: "at.atmosynth.patch#inputRoute.instanceId", kind: "prop", name: Some("instanceId") }
Non-Breaking Changes (11)
  • AddedVertex AddedVertex { vertex_id: "at.atmosynth.patch#inputRoute" }
  • AddedVertex AddedVertex { vertex_id: "at.atmosynth.patch#inputRoute.from" }
  • AddedVertex AddedVertex { vertex_id: "at.atmosynth.patch#inputRoute.instanceId" }
  • AddedVertex AddedVertex { vertex_id: "at.atmosynth.patch#moduleInstance.thru" }
  • AddedVertex AddedVertex { vertex_id: "at.atmosynth.patch:body.inputRouting" }
  • AddedVertex AddedVertex { vertex_id: "at.atmosynth.patch:body.inputRouting:items" }
  • AddedEdge AddedEdge { src: "at.atmosynth.patch#inputRoute.from", tgt: "at.atmosynth.patch#noteOutputRef", kind: "ref", name: None }
  • AddedEdge AddedEdge { src: "at.atmosynth.patch#moduleInstance", tgt: "at.atmosynth.patch#moduleInstance.thru", kind: "prop", name: Some("thru") }
  • AddedEdge AddedEdge { src: "at.atmosynth.patch:body", tgt: "at.atmosynth.patch:body.inputRouting", kind: "prop", name: Some("inputRouting") }
  • AddedEdge AddedEdge { src: "at.atmosynth.patch:body.inputRouting", tgt: "at.atmosynth.patch:body.inputRouting:items", kind: "items", name: None }
  • AddedEdge AddedEdge { src: "at.atmosynth.patch:body.inputRouting:items", tgt: "at.atmosynth.patch#inputRoute", kind: "ref", name: None }

Migration Guidance

Added Elements

  • AddedVertex { vertex_id: "at.atmosynth.patch#inputRoute" }
  • AddedVertex { vertex_id: "at.atmosynth.patch#inputRoute.from" }
  • AddedVertex { vertex_id: "at.atmosynth.patch#inputRoute.instanceId" }
  • AddedVertex { vertex_id: "at.atmosynth.patch#moduleInstance.thru" }
  • AddedVertex { vertex_id: "at.atmosynth.patch:body.inputRouting" }
  • AddedVertex { vertex_id: "at.atmosynth.patch:body.inputRouting:items" }

Additional Notes

  • Breaking: RequiredEdgeAdded { vertex_id: "at.atmosynth.patch#inputRoute", src: "at.atmosynth.patch#inputRoute", tgt: "at.atmosynth.patch#inputRoute.from", kind: "prop", name: Some("from") }
  • Breaking: RequiredEdgeAdded { vertex_id: "at.atmosynth.patch#inputRoute", src: "at.atmosynth.patch#inputRoute", tgt: "at.atmosynth.patch#inputRoute.instanceId", kind: "prop", name: Some("instanceId") }
  • Non-breaking: AddedEdge { src: "at.atmosynth.patch#inputRoute.from", tgt: "at.atmosynth.patch#noteOutputRef", kind: "ref", name: None }
  • Non-breaking: AddedEdge { src: "at.atmosynth.patch#moduleInstance", tgt: "at.atmosynth.patch#moduleInstance.thru", kind: "prop", name: Some("thru") }
  • Non-breaking: AddedEdge { src: "at.atmosynth.patch:body", tgt: "at.atmosynth.patch:body.inputRouting", kind: "prop", name: Some("inputRouting") }
  • Non-breaking: AddedEdge { src: "at.atmosynth.patch:body.inputRouting", tgt: "at.atmosynth.patch:body.inputRouting:items", kind: "items", name: None }
  • Non-breaking: AddedEdge { src: "at.atmosynth.patch:body.inputRouting:items", tgt: "at.atmosynth.patch#inputRoute", kind: "ref", name: None }
1 1
{
2 2
  "$type": "com.atproto.lexicon.schema",
3 3
  "defs": {
4 4
    "alternatePattern": {
5 5
      "description": "One of the loops after the first on a sequencer. It has its own length and its own notes, and shares the grid written beside the first.",
6 6
      "properties": {
7 7
        "bars": {
8 8
          "description": "How long this loop is, in bars of four beats.",
9 9
          "maximum": 8,
10 10
          "minimum": 1,
11 11
          "type": "integer"
12 12
        },
13 13
        "events": {
14 14
          "description": "The notes in this loop.",
15 15
          "items": {
16 16
            "ref": "#noteEvent",
17 17
            "type": "ref"
18 18
          },
19 19
          "maxLength": 2048,
20 20
          "type": "array"
21 21
        },
22 22
        "name": {
23 23
          "description": "What the creator called this loop. Optional permanently: a loop that says nothing is called by its place.",
24 24
          "maxGraphemes": 32,
25 25
          "maxLength": 320,
26 26
          "minLength": 1,
27 27
          "type": "string"
28 28
        }
29 29
      },
30 30
      "required": [
31 31
        "bars"
32 32
      ],
33 33
      "type": "object"
34 34
    },
35 35
    "connection": {
36 36
      "description": "An audio connection between two module instances, naming the declared ports at each end.",
37 37
      "properties": {
38 38
        "from": {
39 39
          "ref": "#outputRef",
40 40
          "type": "ref"
41 41
        },
42 42
        "to": {
43 43
          "ref": "#inputRef",
44 44
          "type": "ref"
45 45
        }
46 46
      },
47 47
      "required": [
48 48
        "from",
49 49
        "to"
50 50
      ],
51 51
      "type": "object"
52 52
    },
53 53
    "glide": {
54 54
      "description": "How one sequencer's notes slide into one another. Its presence is the switch: an instance carrying it slides, and one carrying nothing does not. The speed is written one of two ways, and which field is present says which — a duration, or a note value at the player's tempo, so a slide that is a sixteenth long stays a sixteenth when the song is played faster. A slide moves one note to the next, so a loop with a glide plays one note at a time.",
55 55
      "properties": {
56 56
        "fromLast": {
57 57
          "description": "Whether a note struck after a rest slides in from the note before it. Absent is yes, so every note of the loop slides; false is fingered portamento, where only a note held over the next one slides into it and a note after a rest starts where it means to.",
58 58
          "type": "boolean"
59 59
        },
60 60
        "ms": {
61 61
          "description": "How long a note takes to reach the next, in milliseconds.",
62 62
          "maximum": 5000,
63 63
          "minimum": 1,
64 64
          "type": "integer"
65 65
        },
66 66
        "rate": {
67 67
          "description": "Or: how long, as a note value at the tempo. The same vocabulary the grid is written in.",
68 68
          "knownValues": [
69 69
            "bar",
70 70
            "1/2",
71 71
            "1/4",
72 72
            "1/8",
73 73
            "1/16",
74 74
            "1/32",
75 75
            "1/64",
76 76
            "1/128"
77 77
          ],
78 78
          "type": "string"
79 79
        }
80 80
      },
81 81
      "type": "object"
82 82
    },
83 83
    "inputRef": {
84 84
      "properties": {
85 85
        "audioInput": {
86 86
          "maxLength": 64,
87 87
          "minLength": 1,
88 88
          "type": "string"
89 89
        },
90 90
        "instanceId": {
91 91
          "maxLength": 64,
92 92
          "minLength": 1,
93 93
          "type": "string"
94 94
        }
95 95
      },
96 96
      "required": [
97 97
        "instanceId",
98 98
        "audioInput"
99 99
      ],
100 100
      "type": "object"
101 101
    },
102 +
    "inputRoute": {
103 +
      "description": "One note source wired into a sequencer's input. Notes arriving there are what the sequencer records, and what it passes on to the instances it plays unless its instance says `thru: false`.",
104 +
      "properties": {
105 +
        "from": {
106 +
          "description": "The note output these notes leave: a keyboard's, or another sequencer's.",
107 +
          "ref": "#noteOutputRef",
108 +
          "type": "ref"
109 +
        },
110 +
        "instanceId": {
111 +
          "description": "The sequencer, at its input.",
112 +
          "maxLength": 64,
113 +
          "minLength": 1,
114 +
          "type": "string"
115 +
        }
116 +
      },
117 +
      "required": [
118 +
        "from",
119 +
        "instanceId"
120 +
      ],
121 +
      "type": "object"
122 +
    },
102 123
    "lineage": {
103 124
      "description": "The patch this one was forked from, and its creator. Preserved even when the source is later deleted.",
104 125
      "properties": {
105 126
        "creatorDid": {
106 127
          "format": "did",
107 128
          "type": "string"
108 129
        },
109 130
        "patchId": {
110 131
          "maxLength": 128,
111 132
          "type": "string"
112 133
        },
113 134
        "uri": {
114 135
          "format": "at-uri",
115 136
          "type": "string"
116 137
        }
117 138
      },
118 139
      "required": [
119 140
        "uri",
120 141
        "creatorDid"
121 142
      ],
122 143
      "type": "object"
123 144
    },
124 145
    "main": {
125 146
      "description": "A patch, held in its creator's own repository.",
126 147
      "key": "tid",
127 148
      "record": {
128 149
        "properties": {
129 150
          "connections": {
130 151
            "items": {
131 152
              "ref": "#connection",
132 153
              "type": "ref"
133 154
            },
134 155
            "type": "array"
135 156
          },
136 157
          "createdAt": {
137 158
            "format": "datetime",
138 159
            "type": "string"
139 160
          },
140 161
          "description": {
141 162
            "maxLength": 3000,
142 163
            "type": "string"
143 164
          },
144 165
          "descriptionVersion": {
145 166
            "description": "Version of the patch description this record follows.",
146 167
            "minimum": 1,
147 168
            "type": "integer"
148 169
          },
149 170
          "forkedFrom": {
150 171
            "ref": "#lineage",
151 172
            "type": "ref"
152 173
          },
174 +
          "inputRouting": {
175 +
            "description": "What reaches each sequencer's own input: which note sources it hears, to record from and — unless it says otherwise (`thru`) — to pass on to whatever it plays. A sequencer with nothing wired here records nothing. Optional permanently: a patch that says nothing has nothing wired into any sequencer, which is what every patch written before the input existed says.",
176 +
            "items": {
177 +
              "ref": "#inputRoute",
178 +
              "type": "ref"
179 +
            },
180 +
            "type": "array"
181 +
          },
153 182
          "midiRouting": {
154 183
            "description": "The note plane: which note inputs receive note events, and from which note source — a sequencer, or the player's keys and MIDI devices. \"MIDI\" is the historical name; what travels here is notes, whatever produced them.",
155 184
            "items": {
156 185
              "ref": "#midiRoute",
157 186
              "type": "ref"
158 187
            },
159 188
            "type": "array"
160 189
          },
161 190
          "moduleInstances": {
162 191
            "items": {
163 192
              "ref": "#moduleInstance",
164 193
              "type": "ref"
165 194
            },
166 195
            "type": "array"
167 196
          },
168 197
          "name": {
169 198
            "maxLength": 200,
170 199
            "minLength": 1,
171 200
            "type": "string"
172 201
          },
173 202
          "output": {
174 203
            "description": "Which instance reaches the audio output.",
175 204
            "ref": "#outputRef",
176 205
            "type": "ref"
177 206
          },
178 207
          "patternRouting": {
179 208
            "description": "The song plane: which sequencers each arranger chooses the loops of. A sequencer has one pattern input, so it appears here at most once. Optional permanently: a patch that says nothing has no arranger in it, and every sequencer plays the loop it names as active.",
180 209
            "items": {
181 210
              "ref": "#patternRoute",
182 211
              "type": "ref"
183 212
            },
184 213
            "type": "array"
185 214
          },
186 215
          "tags": {
187 216
            "description": "Freely created tags, lower-cased on write so one hashtag matches one set of patches.",
188 217
            "items": {
189 218
              "maxLength": 128,
190 219
              "type": "string"
191 220
            },
192 221
            "type": "array"
193 222
          },
194 223
          "tempo": {
195 224
            "description": "The tempo this patch was written at, in beats per minute. It is what a sequenced patch counts its bars against, so a patch that plays itself arrives at the speed its creator meant. It seeds the player's own tempo rather than replacing it: how fast a visitor plays is still theirs, and moving it moves everything counting against it. Optional permanently — a patch that says nothing is played at whatever tempo the player already had.",
196 225
            "maximum": 300,
197 226
            "minimum": 20,
198 227
            "type": "integer"
199 228
          },
200 229
          "types": {
201 230
            "description": "Zero or more of the ten fixed types. A patch may carry several.",
202 231
            "items": {
203 232
              "knownValues": [
204 233
                "Lead",
205 234
                "Pad",
206 235
                "Bass",
207 236
                "Plucked",
208 237
                "Percussion",
209 238
                "Keys",
210 239
                "Brass",
211 240
                "Strings",
212 241
                "Vocal",
213 242
                "SFX"
214 243
              ],
215 244
              "type": "string"
216 245
            },
217 246
            "type": "array"
218 247
          }
219 248
        },
220 249
        "required": [
221 250
          "descriptionVersion",
222 251
          "name",
223 252
          "description",
224 253
          "moduleInstances",
225 254
          "createdAt"
226 255
        ],
227 256
        "type": "object"
228 257
      },
229 258
      "type": "record"
230 259
    },
231 260
    "midiControl": {
232 261
      "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.",
233 262
      "properties": {
234 263
        "controller": {
235 264
          "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.",
236 265
          "maximum": 127,
237 266
          "minimum": 0,
238 267
          "type": "integer"
239 268
        },
240 269
        "parameter": {
241 270
          "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.",
242 271
          "maxLength": 64,
243 272
          "minLength": 1,
244 273
          "type": "string"
245 274
        }
246 275
      },
247 276
      "required": [
248 277
        "parameter",
249 278
        "controller"
250 279
      ],
251 280
      "type": "object"
252 281
    },
253 282
    "midiRoute": {
254 283
      "description": "Where one instance's notes come from. `instanceId` and `midiInput` name the note input they arrive at; `from` names the note output they leave. \"MIDI\" in these names is historical: a route carries note events from any note source, a sequencer as much as a MIDI device. **A route with no `from` comes from the player** — the on-screen keys, the computer keyboard and every MIDI device at once — which is what every route written before note sources existed says, and what it goes on saying.",
255 284
      "properties": {
256 285
        "from": {
257 286
          "description": "The note output these notes leave. Absent where they come from the player.",
258 287
          "ref": "#noteOutputRef",
259 288
          "type": "ref"
260 289
        },
261 290
        "instanceId": {
262 291
          "maxLength": 64,
263 292
          "minLength": 1,
264 293
          "type": "string"
265 294
        },
266 295
        "midiInput": {
267 296
          "description": "The note input, one of the module's `midiInputs`, these notes arrive at. It receives note events from any note source; \"MIDI\" is the historical name.",
268 297
          "maxLength": 64,
269 298
          "minLength": 1,
270 299
          "type": "string"
271 300
        }
272 301
      },
273 302
      "required": [
274 303
        "instanceId",
275 304
        "midiInput"
276 305
      ],
277 306
      "type": "object"
278 307
    },
279 308
    "moduleInstance": {
280 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.",
281 310
      "properties": {
282 311
        "enabled": {
283 312
          "description": "Whether this instance does its work. An instance that is switched off makes no sound of its own, and anything reaching its audio inputs leaves its audio outputs unaltered. Optional permanently: an instance that says nothing is on, which is what every record written before this field existed says.",
284 313
          "type": "boolean"
285 314
        },
286 315
        "glide": {
287 316
          "description": "Whether the notes this instance plays slide into one another, and how. It lives here, in the patch, beside the unison and for the unison's reason: how a line slides is a decision about this use of the module, and forks with the patch. The player's own glide is a setting of their browser and says nothing about this one, so a loop written to slide slides for everyone who opens the patch, and a loop that does not is never made monophonic by the player's. Optional permanently: an instance that says nothing has no glide, which is what every record written before this field existed says.",
288 317
          "ref": "#glide",
289 318
          "type": "ref"
290 319
        },
291 320
        "instanceId": {
292 321
          "maxLength": 64,
293 322
          "minLength": 1,
294 323
          "type": "string"
295 324
        },
296 325
        "midiControls": {
297 326
          "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.",
298 327
          "items": {
299 328
            "ref": "#midiControl",
300 329
            "type": "ref"
301 330
          },
302 331
          "type": "array"
303 332
        },
304 333
        "module": {
305 334
          "ref": "#moduleRef",
306 335
          "type": "ref"
307 336
        },
308 337
        "notePattern": {
309 338
          "description": "The pattern this instance loops, where its module is a sequencer. It lives here, in the patch, for the reason a sample slot fill and a control binding do: what is played is a decision about this use of the module, and writing one never touches the module's record. Absent on every instance whose module is not a note source.",
310 339
          "ref": "#notePattern",
311 340
          "type": "ref"
312 341
        },
313 342
        "parameterValues": {
314 343
          "items": {
315 344
            "ref": "#parameterValue",
316 345
            "type": "ref"
317 346
          },
318 347
          "type": "array"
319 348
        },
320 349
        "position": {
321 350
          "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.",
322 351
          "ref": "#position",
323 352
          "type": "ref"
324 353
        },
325 354
        "sampleSlotFills": {
326 355
          "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.",
327 356
          "items": {
328 357
            "ref": "#sampleSlotFill",
329 358
            "type": "ref"
330 359
          },
331 360
          "type": "array"
332 361
        },
333 362
        "song": {
334 363
          "description": "The song this instance plays, where its module is an arranger: which loop each sequencer wired to it plays, section by section. It lives here, in the patch, for the reason a pattern does: what is played is a decision about this use of the module. Absent on every instance whose module is not an arranger.",
335 364
          "ref": "#song",
336 365
          "type": "ref"
337 366
        },
367 +
        "thru": {
368 +
          "description": "Whether the notes reaching this instance's input are passed on to whatever it plays, where its module is a sequencer: a keyboard wired into it is then heard through it as well as recorded by it. It lives here, in the patch, because what a sequencer passes on is part of how the patch sounds. Optional permanently: an instance that says nothing passes them on, and only `false` is ever written.",
369 +
          "type": "boolean"
370 +
        },
338 371
        "unison": {
339 372
          "description": "How many voices each note this instance plays is sounded by, detuned narrowly against each other and centred on the note. It lives here, in the patch, for the reason the pattern above it does: how a loop is voiced is a decision about this use of the module. The player's own unison is a setting of their browser and says nothing about this one, so a loop written thick stays thick for everyone who opens the patch. Optional permanently: an instance that says nothing plays one voice per note, which is what every record written before this field existed says.",
340 373
          "maximum": 6,
341 374
          "minimum": 1,
342 375
          "type": "integer"
343 376
        },
344 377
        "voiceScope": {
345 378
          "description": "Whether this instance is built once for each sounding note or once for the whole patch. One of the two, always: the choice is made when the module is added, from what the module is, and is the creator's to move afterwards. There is no third value and no leaving it out — an instance that said nothing left the answer to be worked out afresh every time the patch was played, which is a decision nobody could see and nobody could change.",
346 379
          "enum": [
347 380
            "perNote",
348 381
            "perPatch"
349 382
          ],
350 383
          "type": "string"
351 384
        }
352 385
      },
353 386
      "required": [
354 387
        "instanceId",
355 388
        "module",
356 389
        "voiceScope"
357 390
      ],
358 391
      "type": "object"
359 392
    },
360 393
    "moduleRef": {
361 394
      "description": "A pin to one exact published version of a module. Resolving it fetches that record, whoever authored it.",
362 395
      "properties": {
363 396
        "authorDid": {
364 397
          "format": "did",
365 398
          "type": "string"
366 399
        },
367 400
        "moduleId": {
368 401
          "maxLength": 128,
369 402
          "minLength": 1,
370 403
          "type": "string"
371 404
        },
372 405
        "versionKey": {
373 406
          "description": "The pinned version's record key, which is also the `versionKey` that version carries. A reader fetches the module record at this key.",
374 407
          "maxLength": 128,
375 408
          "minLength": 1,
376 409
          "type": "string"
377 410
        }
378 411
      },
379 412
      "required": [
380 413
        "moduleId",
381 414
        "versionKey",
382 415
        "authorDid"
383 416
      ],
384 417
      "type": "object"
385 418
    },
386 419
    "noteEvent": {
387 420
      "description": "One note struck at one moment of the loop, held from it, and struck as hard and as often as it says. It is written one of two ways: a note written now says the tick it is at and how many ticks it is held for, and a note written while the grid was part of what a note was says the step of that grid and how many of those steps it was held for. Both are read; the first is written.",
388 421
      "properties": {
389 422
        "at": {
390 423
          "description": "The tick of the loop this note is struck at, counted from its start at 96 ticks to the beat. Ticks rather than steps of the grid, because a note is at a moment and the grid is a guide over it: 96 is divided exactly by every grid this description offers, so a note keeps its moment however the grid is changed.",
391 424
          "minimum": 0,
392 425
          "type": "integer"
393 426
        },
394 427
        "hold": {
395 428
          "description": "How many ticks this note is held for. Counted in ticks rather than in seconds for the reason the start is: a phrase written at 90 is the same phrase, held notes and all, at 140. A note is cut off by the loop's end and by the next note of its own pitch, since the same pitch overlapping itself is one voice rather than two.",
396 429
          "minimum": 1,
397 430
          "type": "integer"
398 431
        },
399 432
        "length": {
400 433
          "description": "How many steps of the grid this note is held for, where its start is written as a step. Absent is one, which is what every pattern written before notes had a length says.",
401 434
          "minimum": 1,
402 435
          "type": "integer"
403 436
        },
404 437
        "note": {
405 438
          "description": "The MIDI note number. 60 is middle C.",
406 439
          "maximum": 127,
407 440
          "minimum": 0,
408 441
          "type": "integer"
409 442
        },
410 443
        "probability": {
411 444
          "description": "How likely this note is to be struck each time the loop comes round, in percent, asked afresh on every pass. Optional permanently: a note that says nothing is struck every time, which is what every pattern written before a note could say otherwise says, and a certain note writes no field. Nought is not offered, for the reason a velocity of nought is not.",
412 445
          "maximum": 100,
413 446
          "minimum": 1,
414 447
          "type": "integer"
415 448
        },
416 449
        "step": {
417 450
          "description": "Which step of the grid this note is on, counted from the start of the loop. The older way of saying where a note is, read from every pattern published before a note carried a tick and written by none.",
418 451
          "minimum": 0,
419 452
          "type": "integer"
420 453
        },
421 454
        "velocity": {
422 455
          "description": "How hard this note is struck, on the MIDI scale. It is part of what is played rather than how it is listened to — a phrase is written with its accents in it, and a loop where every note lands identically is a loop nobody wrote. Optional permanently: a note that says nothing is struck at 100, which is what every pattern written before a note could say says, and a note struck at 100 writes no field. Nought is not offered, since a note that could never be heard is a note taken off the loop rather than one written onto it.",
423 456
          "maximum": 127,
424 457
          "minimum": 1,
425 458
          "type": "integer"
426 459
        }
427 460
      },
428 461
      "required": [
429 462
        "note"
430 463
      ],
431 464
      "type": "object"
432 465
    },
433 466
    "noteOutputRef": {
434 467
      "properties": {
435 468
        "instanceId": {
436 469
          "maxLength": 64,
437 470
          "minLength": 1,
438 471
          "type": "string"
439 472
        },
440 473
        "noteOutput": {
441 474
          "maxLength": 64,
442 475
          "minLength": 1,
443 476
          "type": "string"
444 477
        }
445 478
      },
446 479
      "required": [
447 480
        "instanceId",
448 481
        "noteOutput"
449 482
      ],
450 483
      "type": "object"
451 484
    },
452 485
    "notePattern": {
453 486
      "description": "The loops one sequencer holds, and the grid they are written on. A loop is a whole number of bars and the notes in it are counted in ticks of the beat, so a pattern means the same thing at any tempo — what a tick is worth in seconds is the player's tempo's business and not the pattern's. The first loop is written here, where a pattern has always been written; any after it are alternates.",
454 487
      "properties": {
455 488
        "active": {
456 489
          "description": "Which loop is played, counting the one written here as zero. Absent is the first. It is in the record because it is what a visitor opening the patch hears — unlike stopping a loop, which is how a browser is listening and is written nowhere. Every loop counts from the same downbeat and wraps at its own length whether or not it is the one being heard, so switching between them reveals where the other had got to rather than starting it.",
457 490
          "minimum": 0,
458 491
          "type": "integer"
459 492
        },
460 493
        "alternates": {
461 494
          "description": "The loops after the first. Absent while the sequencer holds a single pattern, which is what every sequencer written before there could be more than one says.",
462 495
          "items": {
463 496
            "ref": "#alternatePattern",
464 497
            "type": "ref"
465 498
          },
466 499
          "maxLength": 7,
467 500
          "type": "array"
468 501
        },
469 502
        "bars": {
470 503
          "description": "How long the first loop is, in bars of four beats. There is no time signature anywhere here, and 4/4 is what a bar means to everyone who has not been told otherwise. Each loop keeps its own length: one may be four bars and the next five.",
471 504
          "maximum": 8,
472 505
          "minimum": 1,
473 506
          "type": "integer"
474 507
        },
475 508
        "events": {
476 509
          "description": "The notes in the first loop. A moment carrying no note is a rest; a note starting outside the loop's length is not played.",
477 510
          "items": {
478 511
            "ref": "#noteEvent",
479 512
            "type": "ref"
480 513
          },
481 514
          "maxLength": 2048,
482 515
          "type": "array"
483 516
        },
484 517
        "name": {
485 518
          "description": "What the creator called the first loop. Optional permanently: a loop that says nothing is called by its place, which is what every loop written before a loop could be named says.",
486 519
          "maxGraphemes": 32,
487 520
          "maxLength": 320,
488 521
          "minLength": 1,
489 522
          "type": "string"
490 523
        },
491 524
        "resolution": {
492 525
          "description": "The grid every loop on this sequencer is drawn and snapped to. It is a guide and not a part of what is played: it decides where a note being put down lands, and changing it moves nothing already written, so a loop may hold a note no line of the current grid passes through.",
493 526
          "ref": "#resolution",
494 527
          "type": "ref"
495 528
        }
496 529
      },
497 530
      "required": [
498 531
        "bars",
499 532
        "resolution"
500 533
      ],
501 534
      "type": "object"
502 535
    },
503 536
    "outputRef": {
504 537
      "properties": {
505 538
        "audioOutput": {
506 539
          "maxLength": 64,
507 540
          "minLength": 1,
508 541
          "type": "string"
509 542
        },
510 543
        "instanceId": {
511 544
          "maxLength": 64,
512 545
          "minLength": 1,
513 546
          "type": "string"
514 547
        }
515 548
      },
516 549
      "required": [
517 550
        "instanceId",
518 551
        "audioOutput"
519 552
      ],
520 553
      "type": "object"
521 554
    },
522 555
    "parameterValue": {
523 556
      "description": "A value for one of the module's exposed parameters, or an explicit fall-back to the module's declared default.",
524 557
      "properties": {
525 558
        "id": {
526 559
          "maxLength": 64,
527 560
          "minLength": 1,
528 561
          "type": "string"
529 562
        },
530 563
        "useDefault": {
531 564
          "description": "Set where the patch explicitly defers to the module's default rather than recording a value.",
532 565
          "type": "boolean"
533 566
        },
534 567
        "value": {
535 568
          "description": "The value this patch sets the parameter to, 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 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: the module's own description says which of the two this parameter is.",
536 569
          "maxLength": 200,
537 570
          "type": "string"
538 571
        }
539 572
      },
540 573
      "required": [
541 574
        "id"
542 575
      ],
543 576
      "type": "object"
544 577
    },
545 578
    "patternRoute": {
546 579
      "description": "One sequencer whose loops an arranger chooses.",
547 580
      "properties": {
548 581
        "from": {
549 582
          "description": "The arranger.",
550 583
          "maxLength": 64,
551 584
          "minLength": 1,
552 585
          "type": "string"
553 586
        },
554 587
        "instanceId": {
555 588
          "description": "The sequencer, at its pattern input.",
556 589
          "maxLength": 64,
557 590
          "minLength": 1,
558 591
          "type": "string"
559 592
        }
560 593
      },
561 594
      "required": [
562 595
        "from",
563 596
        "instanceId"
564 597
      ],
565 598
      "type": "object"
566 599
    },
567 600
    "position": {
568 601
      "properties": {
569 602
        "x": {
570 603
          "type": "integer"
571 604
        },
572 605
        "y": {
573 606
          "type": "integer"
574 607
        }
575 608
      },
576 609
      "required": [
577 610
        "x",
578 611
        "y"
579 612
      ],
580 613
      "type": "object"
581 614
    },
582 615
    "resolution": {
583 616
      "description": "One note value, as a length and what that length is multiplied by. The same vocabulary the player's own musical time is counted in.",
584 617
      "properties": {
585 618
        "unit": {
586 619
          "description": "Three of them into the time of two, or not. Absent is normal. A dotted grid is not offered: it does not divide a bar evenly, so it would leave a pattern whose steps do not line up with its own loop.",
587 620
          "knownValues": [
588 621
            "normal",
589 622
            "triplet"
590 623
          ],
591 624
          "type": "string"
592 625
        },
593 626
        "value": {
594 627
          "description": "The note value one step is worth. A bar is four beats.",
595 628
          "knownValues": [
596 629
            "bar",
597 630
            "1/2",
598 631
            "1/4",
599 632
            "1/8",
600 633
            "1/16",
601 634
            "1/32",
602 635
            "1/64",
603 636
            "1/128"
604 637
          ],
605 638
          "type": "string"
606 639
        }
607 640
      },
608 641
      "required": [
609 642
        "value"
610 643
      ],
611 644
      "type": "object"
612 645
    },
613 646
    "sampleSlotFill": {
614 647
      "properties": {
615 648
        "blob": {
616 649
          "accept": [
617 650
            "audio/wav"
618 651
          ],
619 652
          "maxSize": 2097152,
620 653
          "type": "blob"
621 654
        },
622 655
        "ownerDid": {
623 656
          "format": "did",
624 657
          "type": "string"
625 658
        },
626 659
        "slotId": {
627 660
          "maxLength": 64,
628 661
          "minLength": 1,
629 662
          "type": "string"
630 663
        }
631 664
      },
632 665
      "required": [
633 666
        "slotId",
634 667
        "blob",
635 668
        "ownerDid"
636 669
      ],
637 670
      "type": "object"
638 671
    },
639 672
    "section": {
640 673
      "description": "One section of a song: how long it is, and which loop each arranged sequencer plays for that long.",
641 674
      "properties": {
642 675
        "bars": {
643 676
          "description": "How long this section is, in bars of four beats.",
644 677
          "maximum": 64,
645 678
          "minimum": 1,
646 679
          "type": "integer"
647 680
        },
648 681
        "loops": {
649 682
          "description": "Which loop each sequencer plays for this section. A sequencer wired to the arranger with no entry here rests for the section.",
650 683
          "items": {
651 684
            "ref": "#sectionLoop",
652 685
            "type": "ref"
653 686
          },
654 687
          "maxLength": 64,
655 688
          "type": "array"
656 689
        },
657 690
        "name": {
658 691
          "description": "What the creator called this section. Optional permanently: a section that says nothing is called by its place.",
659 692
          "maxGraphemes": 32,
660 693
          "maxLength": 320,
661 694
          "minLength": 1,
662 695
          "type": "string"
663 696
        }
664 697
      },
665 698
      "required": [
666 699
        "bars"
667 700
      ],
668 701
      "type": "object"
669 702
    },
670 703
    "sectionLoop": {
671 704
      "properties": {
672 705
        "instanceId": {
673 706
          "description": "The sequencer.",
674 707
          "maxLength": 64,
675 708
          "minLength": 1,
676 709
          "type": "string"
677 710
        },
678 711
        "loop": {
679 712
          "description": "Which of the sequencer's loops it plays, counting the one its pattern writes first as zero. One it does not hold is played as its last.",
680 713
          "maximum": 7,
681 714
          "minimum": 0,
682 715
          "type": "integer"
683 716
        }
684 717
      },
685 718
      "required": [
686 719
        "instanceId",
687 720
        "loop"
688 721
      ],
689 722
      "type": "object"
690 723
    },
691 724
    "song": {
692 725
      "description": "An arranger's song: sections played one after another from its first beat. Each section starts every loop it names from that loop's first step, and lets go of whatever is still sounding when it ends, so a loop shorter than its section repeats and one longer is cut off.",
693 726
      "properties": {
694 727
        "end": {
695 728
          "description": "What happens when the last section ends: `stop` leaves the sequencers it arranges silent, `loop` plays the song again from its first section, and `hold` keeps playing the last section. Optional permanently: absent is `stop`.",
696 729
          "knownValues": [
697 730
            "stop",
698 731
            "loop",
699 732
            "hold"
700 733
          ],
701 734
          "type": "string"
702 735
        },
703 736
        "sections": {
704 737
          "description": "The sections, in the order they are played.",
705 738
          "items": {
706 739
            "ref": "#section",
707 740
            "type": "ref"
708 741
          },
709 742
          "maxLength": 64,
710 743
          "type": "array"
711 744
        }
712 745
      },
713 746
      "type": "object"
714 747
    }
715 748
  },
716 749
  "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.",
717 750
  "id": "at.atmosynth.patch",
718 751
  "lexicon": 1
719 752
}

Compare Other Versions

Lexicon Garden

@