@msb235/blits 0.7.1 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/CHANGELOG.md +193 -0
  2. package/README.md +22 -4
  3. package/dist/book.js +4 -4
  4. package/dist/chain.d.ts +1 -1
  5. package/dist/chain.js +57 -54
  6. package/dist/channels.d.ts +26 -5
  7. package/dist/channels.js +12 -8
  8. package/dist/clock.d.ts +8 -1
  9. package/dist/clock.js +14 -3
  10. package/dist/clone.d.ts +8 -0
  11. package/dist/clone.js +22 -0
  12. package/dist/closed.d.ts +1 -1
  13. package/dist/closed.js +3 -2
  14. package/dist/color.d.ts +0 -11
  15. package/dist/color.js +4 -24
  16. package/dist/columns.js +0 -1
  17. package/dist/copyout.d.ts +6 -0
  18. package/dist/copyout.js +38 -0
  19. package/dist/crowd.d.ts +7 -5
  20. package/dist/crowd.js +32 -18
  21. package/dist/cue.d.ts +3 -1
  22. package/dist/cue.js +31 -20
  23. package/dist/departed.d.ts +34 -0
  24. package/dist/departed.js +73 -0
  25. package/dist/easing.d.ts +5 -0
  26. package/dist/easing.js +31 -2
  27. package/dist/everyone.d.ts +56 -0
  28. package/dist/everyone.js +221 -0
  29. package/dist/fade.d.ts +8 -1
  30. package/dist/fade.js +34 -6
  31. package/dist/fill.d.ts +22 -13
  32. package/dist/fill.js +104 -41
  33. package/dist/fit.js +2 -1
  34. package/dist/fold.d.ts +37 -0
  35. package/dist/fold.js +216 -31
  36. package/dist/frames.d.ts +21 -0
  37. package/dist/frames.js +59 -0
  38. package/dist/gather.d.ts +15 -9
  39. package/dist/gather.js +60 -25
  40. package/dist/gone.js +10 -0
  41. package/dist/handle.d.ts +16 -5
  42. package/dist/handle.js +56 -6
  43. package/dist/held.d.ts +8 -5
  44. package/dist/held.js +56 -58
  45. package/dist/history.d.ts +17 -13
  46. package/dist/history.js +47 -28
  47. package/dist/hosts.js +55 -8
  48. package/dist/index.d.ts +9 -4
  49. package/dist/index.js +5 -2
  50. package/dist/keyfill.d.ts +7 -0
  51. package/dist/keyfill.js +124 -0
  52. package/dist/keyrows.d.ts +1 -0
  53. package/dist/keyrows.js +1 -1
  54. package/dist/lane.d.ts +32 -2
  55. package/dist/lane.js +5 -0
  56. package/dist/lanes.d.ts +32 -8
  57. package/dist/lanes.js +69 -37
  58. package/dist/leavings.d.ts +26 -0
  59. package/dist/leavings.js +70 -0
  60. package/dist/locus.js +2 -2
  61. package/dist/meet.js +14 -8
  62. package/dist/mixer.d.ts +39 -7
  63. package/dist/mixer.js +50 -10
  64. package/dist/motion.d.ts +2 -0
  65. package/dist/motion.js +4 -1
  66. package/dist/motions.d.ts +22 -15
  67. package/dist/motions.js +40 -34
  68. package/dist/move.js +23 -16
  69. package/dist/moved.d.ts +11 -0
  70. package/dist/moved.js +29 -0
  71. package/dist/origin.d.ts +19 -0
  72. package/dist/origin.js +68 -0
  73. package/dist/owed.d.ts +4 -4
  74. package/dist/owed.js +8 -8
  75. package/dist/owner.d.ts +1 -1
  76. package/dist/owner.js +2 -2
  77. package/dist/pace.d.ts +13 -5
  78. package/dist/pace.js +21 -8
  79. package/dist/pack.d.ts +3 -1
  80. package/dist/pack.js +15 -24
  81. package/dist/paging.d.ts +8 -2
  82. package/dist/paging.js +39 -4
  83. package/dist/patch.d.ts +14 -9
  84. package/dist/patch.js +83 -21
  85. package/dist/place.js +18 -3
  86. package/dist/project.d.ts +12 -1
  87. package/dist/project.js +101 -83
  88. package/dist/pull.d.ts +2 -0
  89. package/dist/pull.js +8 -0
  90. package/dist/qualify.js +10 -2
  91. package/dist/reading.d.ts +5 -0
  92. package/dist/reading.js +5 -0
  93. package/dist/record.d.ts +9 -0
  94. package/dist/record.js +42 -0
  95. package/dist/relink.d.ts +11 -5
  96. package/dist/relink.js +7 -5
  97. package/dist/restored.d.ts +41 -0
  98. package/dist/restored.js +91 -0
  99. package/dist/revive.d.ts +10 -3
  100. package/dist/revive.js +31 -23
  101. package/dist/roster.d.ts +11 -0
  102. package/dist/roster.js +46 -0
  103. package/dist/rotation.d.ts +29 -0
  104. package/dist/rotation.js +91 -0
  105. package/dist/rows.d.ts +5 -5
  106. package/dist/rows.js +5 -5
  107. package/dist/sample.d.ts +3 -2
  108. package/dist/sample.js +32 -15
  109. package/dist/seek.js +97 -114
  110. package/dist/shared.d.ts +6 -0
  111. package/dist/shared.js +15 -0
  112. package/dist/signals.d.ts +24 -3
  113. package/dist/signals.js +50 -11
  114. package/dist/spans.js +7 -0
  115. package/dist/stack.d.ts +11 -0
  116. package/dist/stack.js +47 -0
  117. package/dist/standing.d.ts +10 -0
  118. package/dist/standing.js +79 -0
  119. package/dist/store.d.ts +3 -3
  120. package/dist/store.js +3 -3
  121. package/dist/strays.js +3 -0
  122. package/dist/tape.d.ts +8 -5
  123. package/dist/tape.js +21 -13
  124. package/dist/testing.d.ts +35 -0
  125. package/dist/testing.js +116 -0
  126. package/dist/touch.d.ts +6 -0
  127. package/dist/touch.js +28 -0
  128. package/dist/transport.d.ts +45 -6
  129. package/dist/transport.js +64 -19
  130. package/dist/turns.d.ts +18 -0
  131. package/dist/turns.js +72 -0
  132. package/dist/tweened.js +1 -1
  133. package/dist/types/channel.d.ts +46 -0
  134. package/dist/types/channel.js +1 -0
  135. package/dist/types/history.d.ts +139 -0
  136. package/dist/types/history.js +1 -0
  137. package/dist/types/mix.d.ts +336 -0
  138. package/dist/types/mix.js +1 -0
  139. package/dist/types/patch.d.ts +187 -0
  140. package/dist/types/patch.js +1 -0
  141. package/dist/types/place.d.ts +157 -0
  142. package/dist/types/place.js +1 -0
  143. package/dist/types/transport.d.ts +71 -0
  144. package/dist/types/transport.js +1 -0
  145. package/dist/types/voice.d.ts +323 -0
  146. package/dist/types/voice.js +1 -0
  147. package/dist/types.d.ts +7 -1162
  148. package/dist/unpage.d.ts +2 -2
  149. package/dist/unpage.js +53 -25
  150. package/dist/voice.d.ts +90 -22
  151. package/dist/voice.js +105 -43
  152. package/dist/wave.d.ts +42 -0
  153. package/dist/wave.js +62 -0
  154. package/dist/weigh.js +1 -1
  155. package/docs/schema.html +42 -36
  156. package/package.json +8 -3
package/dist/types.d.ts CHANGED
@@ -1,1162 +1,7 @@
1
- import type { Fit, Order, Strength } from './fit.js';
2
- /**
3
- * One field of a delta, with its own arithmetic.
4
- *
5
- * @category channel
6
- */
7
- export interface Channel<V> {
8
- /**
9
- * Names this channel's arithmetic, so a patch written against one channel can be checked against
10
- * another of the same name. Two channels of one kind must fold identically; the stock ones set it,
11
- * as `'sum'` or `'vec(3, sum)'`. Absent, a channel matches only itself.
12
- */
13
- kind?: string;
14
- /**
15
- * The range a numeric value means anything in, such as 0..1 for an opacity. The mix clamps the
16
- * folded value to it, axis by axis for an array, so neither stacked voices nor a retarget that
17
- * carries speed can push it out; overshoot stops flat at the bound.
18
- */
19
- bounds?: readonly [min: number, max: number];
20
- /** Identity. Absent means the channel has none: it replaces rather than contributes. */
21
- rest?: V;
22
- /** Fold two contributions into one. */
23
- merge(a: V, b: V): V;
24
- /** Fade toward `rest` by weight 0..1. Required when `rest` is set; absent otherwise. */
25
- scale?(v: V, w: number): V;
26
- /** Interpolate, for retargeting, for blending alternatives, and for folding a locus. */
27
- lerp(a: V, b: V, u: number): V;
28
- /**
29
- * Optional: `merge(into, scale(v, w))`, written into `into` and returned, so a channel whose
30
- * values are objects need not allocate per contribution. The mix only hands it a value it made.
31
- */
32
- fold?(into: V, v: V, w: number): V;
33
- }
34
- /**
35
- * The channel set for one kind of delta.
36
- *
37
- * @category channel
38
- */
39
- export type Kit<O> = {
40
- readonly [K in keyof O]-?: Channel<NonNullable<O[K]>>;
41
- };
42
- /**
43
- * A curve on 0..1, as data where it can be: CSS's names, a `cubic-bezier`, or `steps`, which a
44
- * WAAPI or GPU engine can read. The function form runs on the CPU engine only.
45
- *
46
- * @category patch
47
- */
48
- export type Easing = ((u: number) => number) | 'linear' | 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out' | {
49
- readonly bezier: readonly [x1: number, y1: number, x2: number, y2: number];
50
- } | {
51
- readonly steps: number;
52
- readonly jump?: 'start' | 'end';
53
- };
54
- /**
55
- * One stop of a `keys` patch.
56
- *
57
- * @category patch
58
- */
59
- export interface Keyframe<O> {
60
- /** Phase, 0..1. */
61
- at: number;
62
- delta: Partial<O>;
63
- ease?: Easing;
64
- }
65
- /**
66
- * What a patch may read and did not compute, for one subject this frame. The mix reuses the object,
67
- * so it is valid only during the call it is handed to.
68
- *
69
- * @category state
70
- */
71
- export interface Setting<S = void, H = unknown> {
72
- /**
73
- * The mix clock at this frame: the host's timestamp less any time `rebase` took out, run at the
74
- * mix's `rate`. Identical for every probe in the frame.
75
- */
76
- timestamp: number;
77
- /**
78
- * The gap this subject is catching up by: milliseconds since it last advanced, which is the gap
79
- * since the previous sync only for a subject sampled every frame. Infinity under reduced motion;
80
- * no more than `maxDt` where the mix sets one. Inside a `step` under `stepMs`, it is `stepMs`, and
81
- * `timestamp` is the end of that interval.
82
- */
83
- dt: number;
84
- /** Milliseconds this voice has been playing, rate applied. */
85
- elapsed: number;
86
- /** Which pass this is, 0 first. */
87
- pass: number;
88
- /** This voice's weight for this subject this frame, after fades, signals and any locus. */
89
- weight: number;
90
- /** This subject's state, when the patch declares one. */
91
- state: S;
92
- /** Anything the host adds for its own patches: the mix's `host`, typed as its `H`. */
93
- host: H;
94
- /**
95
- * The state `owner` keeps for this voice and this subject, made by `init` on first ask. The mix
96
- * holds it, so a read at another time can copy it instead of moving it. A stateful signal keeps
97
- * its state here and nowhere else. With lanes on, a patch or weight signal that first calls it
98
- * partway through playing can have that state advanced once for one subject probed the frame
99
- * before it starts and not on that frame; one that keeps state from its first call, or a patch
100
- * that declares `state`, never does.
101
- */
102
- keep<K>(owner: object, init: () => K): K;
103
- /**
104
- * Reports an event at `timestamp`, for this voice and this subject. The mix queues it until the
105
- * host drains it, and never calls back. Meant for `step`, where under `stepMs` the timestamp is
106
- * the interval the event happened in rather than the frame that sampled it. Sent from a stateless
107
- * patch's `at` while it runs on a lane, it goes out for every subject the lane fills, probed that
108
- * frame or not: each probed that frame or the last; `at` is not asked for a subject at weight 0,
109
- * so nothing is sent from it there.
110
- */
111
- send(event: unknown): void;
112
- }
113
- /**
114
- * One event a patch sent, as `drain` hands it back.
115
- *
116
- * @category state
117
- */
118
- export interface Sent<I, E = unknown> {
119
- /** The mix clock when it was sent. */
120
- timestamp: number;
121
- subject: I;
122
- /** The id of the voice whose patch sent it, as its handle reports. */
123
- voice: number;
124
- /** That voice's tags. */
125
- tags: readonly string[];
126
- event: E;
127
- }
128
- /**
129
- * What a `'motion'` patch is made of, as data an engine can read: the kind of motion and its
130
- * constants. Each subject's start, target and starting velocity stay on the patch, since they may
131
- * be functions of the subject.
132
- *
133
- * @category patch
134
- */
135
- export type MotionSpec = {
136
- readonly kind: 'spring';
137
- /** Per second squared. */
138
- readonly stiffness: number;
139
- /** Per second. */
140
- readonly damping: number;
141
- readonly mass: number;
142
- readonly settle: number;
143
- } | {
144
- readonly kind: 'glide';
145
- /** The friction's time constant, ms. */
146
- readonly ms: number;
147
- readonly settle: number;
148
- } | {
149
- readonly kind: 'tween';
150
- /** How long a stretch takes; undefined where it varies by subject, kept on the patch then. */
151
- readonly ms: number | undefined;
152
- readonly ease: Easing;
153
- };
154
- /**
155
- * A pure function of phase and a subject that returns a delta. Optionally stateful.
156
- *
157
- * @category patch
158
- */
159
- export interface Patch<I, O, S = void, H = unknown> {
160
- /**
161
- * Which authoring form built it: `'fn'` from `patch`, `'keys'` from `keys`, `'motion'` from
162
- * `spring`, `glide` or `tween`. An engine declares which forms it runs.
163
- */
164
- readonly form: 'fn' | 'keys' | 'motion';
165
- /** Milliseconds one pass lasts, whether or not the voice loops. 0 has no passes: phase and pass stay 0. */
166
- readonly duration: number;
167
- /** @deprecated Use `duration`. A patch that sets only `period` still plays. */
168
- readonly period?: number;
169
- /** The channels this patch contributes to. Every key `at` sets, and no others. */
170
- readonly writes: readonly (keyof O)[];
171
- /**
172
- * The channels this patch was written against. `cue` refuses a mix whose channel of the same name
173
- * is of another kind, so a patch published in one package cannot fold by another's arithmetic.
174
- */
175
- readonly kit?: Partial<Kit<O>>;
176
- /** The fields of `setting.host` this patch reads. `cue` refuses a mix whose host lacks one. */
177
- readonly reads?: readonly string[];
178
- /**
179
- * `phase` is 0..1 across one pass, wrapping. Not asked for a subject its voice gives no weight, unless the voice is fading to rest;
180
- * `step` still runs. A `keys` patch's stops are not read there either, unless its voice is in a locus.
181
- */
182
- at(phase: number, subject: I, setting: Setting<S, H>): Partial<O>;
183
- /** Per-subject state, created on the first frame this patch sees a subject. */
184
- state?(subject: I): S;
185
- /**
186
- * Advances state once per subject per sampled frame, by the whole gap since it last advanced; or,
187
- * where the mix sets `stepMs`, once per whole interval of that length.
188
- */
189
- step?(state: S, dt: number, subject: I, setting: Setting<S, H>): void;
190
- /** Present when the patch was authored as keyframes, so an engine that reads data can. */
191
- readonly keys?: readonly Keyframe<O>[];
192
- /** Present on a `'motion'` patch: its kind and constants, for an engine that reads data. */
193
- readonly motion?: MotionSpec;
194
- /**
195
- * A copy of `state` that shares nothing with it, for a read at another time. Default
196
- * `structuredClone`, which is enough for plain data; a state holding a class instance or a
197
- * function needs its own.
198
- */
199
- clone?(state: S): S;
200
- /**
201
- * `state` as data that survives `structuredClone`, for a history `store` to keep; `unpack` makes
202
- * a state from it again. With a store, a patch with `state` or `step` needs both, or `cue`
203
- * refuses it.
204
- */
205
- pack?(state: S): unknown;
206
- unpack?(data: unknown): S;
207
- }
208
- /**
209
- * A 0..1 scalar resolved per subject per frame from something outside the clock. `input` is set
210
- * when it reads something the clock does not drive, such as a value the host writes; a signal
211
- * built on one inherits it.
212
- *
213
- * @category signal
214
- */
215
- export type Signal<I, H = unknown> = ((subject: I, setting: Setting<void, H>) => number) & {
216
- readonly input?: boolean;
217
- };
218
- /**
219
- * A voice's own ramps in and out, in ms, and the curve both take.
220
- *
221
- * @category blending
222
- */
223
- export interface FadeSpec {
224
- in?: number;
225
- out?: number;
226
- ease?: Easing;
227
- }
228
- /**
229
- * The times a voice is known by on the mix clock: when its fade in begins (`start`), when it is
230
- * fully in (`in`), when its last pass ends (`coast`), when its fade out begins (`out`), and when it
231
- * is gone (`end`). A voice coasts when `played` resolves true, for its latest-staggered subject: at
232
- * its `out` where it does not freeze, and where it starts showing its last frame where it does. A
233
- * voice that loops for good, or fades before its last pass ends, never coasts.
234
- *
235
- * @category score
236
- */
237
- export type Mark = 'start' | 'in' | 'coast' | 'out' | 'end';
238
- /**
239
- * Selects voices by what the plan knows of them, never by a channel's value, within the asking
240
- * voice's own score unless it names another. Where several match,
241
- * the resolver picks one: `last` cued (the default), `first` cued, `next` (the earliest whose mark
242
- * is still to come), `earliest` or `latest` by the mark's time.
243
- *
244
- * @category score
245
- */
246
- export interface Query {
247
- /** The score to look in. Default: the asking voice's own. */
248
- score?: string;
249
- name?: string;
250
- tag?: string;
251
- /** A channel the voice's patch writes. */
252
- writes?: string;
253
- resolver?: 'last' | 'first' | 'next' | 'earliest' | 'latest';
254
- }
255
- /**
256
- * A time given by another voice: `mark` of the voice `of` selects, moved by `by` ms. `after` is
257
- * sugar for that voice's `end`, `with` for its `start`, and `before` for its start less `by`. A
258
- * string selects by name. `all` is the latest of its anchors, known once every one is; `any` the
259
- * earliest, known once one has passed or every one is known.
260
- *
261
- * @category score
262
- */
263
- export type Anchor = {
264
- of: string | Query;
265
- mark: Mark;
266
- by?: number;
267
- } | {
268
- after: string | Query;
269
- by?: number;
270
- } | {
271
- with: string | Query;
272
- by?: number;
273
- } | {
274
- before: string | Query;
275
- by?: number;
276
- } | {
277
- all: readonly Anchor[];
278
- } | {
279
- any: readonly Anchor[];
280
- };
281
- /**
282
- * Where a voice sits on the mix clock: at most one of `start` and `in`, and at most one of `out`
283
- * and `end`, each a timestamp on the host's clock or an anchor to another voice. A voice whose
284
- * anchor has no answer yet waits pending; one whose anchored mark is already past starts partway
285
- * through, as playback does from the middle of a region.
286
- *
287
- * @category score
288
- */
289
- export interface Placement {
290
- start?: number | Anchor;
291
- in?: number | Anchor;
292
- out?: number | Anchor;
293
- end?: number | Anchor;
294
- }
295
- /**
296
- * One mark as `marks` lists it: one of a voice's, or one the host announced on a score, which has a
297
- * name and no voice.
298
- *
299
- * @category score
300
- */
301
- export interface Marked {
302
- /** On the host's clock. */
303
- timestamp: number;
304
- /** Which of a voice's this is; undefined for an announced mark. */
305
- mark: Mark | undefined;
306
- /** The voice it belongs to; undefined for an announced mark. */
307
- voice: number | undefined;
308
- score: string | undefined;
309
- name: string | undefined;
310
- tags: readonly string[];
311
- /** The `name` of the mix the voice is in, or that announced the mark; undefined for none. */
312
- mix: string | undefined;
313
- }
314
- /**
315
- * An event at a time on a voice's own clock, which `book` hands a host ahead of time. It plays once
316
- * per pass, for the voice and not per subject, so `stagger` does not spread it.
317
- *
318
- * @category score
319
- */
320
- export interface Hit<E = unknown> {
321
- /** Voice ms into each pass: 0 up to the patch's `duration`, or any time at all for a patch with none. */
322
- at: number;
323
- event: E;
324
- }
325
- /**
326
- * One pass of one hit, as `book` takes it.
327
- *
328
- * @category score
329
- */
330
- export interface BookedHit<E = unknown> {
331
- /** On the host's clock. */
332
- timestamp: number;
333
- voice: number;
334
- /** Which of the voice's `hits`, by index. */
335
- hit: number;
336
- /** Which pass, 0 first. */
337
- pass: number;
338
- event: E;
339
- score: string | undefined;
340
- name: string | undefined;
341
- tags: readonly string[];
342
- }
343
- /**
344
- * What `book` takes: an outside clock, how far ahead to book on it, and what to do with each item.
345
- *
346
- * @category score
347
- */
348
- export interface BookOptions<E = unknown> {
349
- /**
350
- * The outside clock, in ms: `audio.currentTime * 1000`, `performance.now()`, or whatever the host
351
- * schedules against. Read once a sync. The mix maps its host time onto it by an offset that folds
352
- * in 5% of each frame's difference, and starts over from the clock's own reading on a jump past
353
- * 50 ms, such as a suspended context or a hidden tab.
354
- */
355
- clock: () => number;
356
- /** How far ahead to book, host ms. It has to cover the longest gap between two syncs. */
357
- ahead: number;
358
- /** How far past an item first seen late may be and still be taken, host ms. */
359
- late: number;
360
- /**
361
- * Called once per item: a mark as `marks` lists it, or a hit. `when` is on the outside clock;
362
- * `lateBy` is how many host ms past the item was when first seen, 0 for one booked ahead, which
363
- * is then taken at the clock's now. Return a `stop` to hear about a booking whose time moved by
364
- * more than 1 ms or that went away (a seek, a rate or ramp on the voice or the mix, a fade, a
365
- * `rebase`, an anchor's target moving, the voice leaving); the item is then booked again, at its
366
- * new time, at the same sync.
367
- */
368
- take(item: Marked | BookedHit<E>, when: number, lateBy: number): {
369
- stop(): void;
370
- } | undefined;
371
- /** Book only the voices, and announced marks, carrying this tag. */
372
- tag?: string;
373
- /** Book only this score's voices and marks. */
374
- score?: string;
375
- }
376
- /**
377
- * A running booker, returned by `book`.
378
- *
379
- * @category score
380
- */
381
- export interface Booker {
382
- /** Stops every booking still ahead, and books nothing more. */
383
- stop(): void;
384
- }
385
- /**
386
- * What `cue` takes: a patch, and the clock, weight and reach it plays with.
387
- *
388
- * @category voice
389
- */
390
- /**
391
- * How a voice or owner held by a span may give way so the span keeps its budget, which the span's
392
- * fit reads. Anything it does not allow, it will not do. Read only under a span.
393
- *
394
- * @category score
395
- */
396
- export interface SpanHints {
397
- /** How many times faster than its own rate it may play. Default 1: no faster. */
398
- faster?: number;
399
- /** How many times slower than its own rate it may play. Default 1: no slower. */
400
- slower?: number;
401
- /** Whether it may start before the one before it ends, where the span's order would not. */
402
- overlap?: boolean;
403
- /** Whether it may jump to its end instead of playing. A span held by a span is never skipped. */
404
- ballast?: boolean;
405
- /** How hard its own length holds against the span's budget. Default `weak`. */
406
- priority?: Strength;
407
- }
408
- export interface VoiceSpec<I, O, H = unknown> extends SpanHints {
409
- patch: Patch<I, O, unknown, H>;
410
- /**
411
- * What `history.revive` rebuilds this spec from, so a history `store` can page the voice out once
412
- * it has left. A voice cued without it stays in memory for as long as history reaches it.
413
- */
414
- as?: Described;
415
- /**
416
- * Which subjects this voice reaches. Default: all of them. The predicate is fixed at `cue`; it
417
- * runs per subject the first time the mix sees that subject, and the answer is kept. Every
418
- * voice's predicate meets every subject, so voices that each reach a known few cost the square
419
- * of their number in time; name those with `subjects` instead. A no is kept as a bit by the
420
- * number lanes give the subject, but with `lanes: false` as a map entry per voice per subject
421
- * asked (about 37 MB for 1,000 such voices over 1,000 subjects).
422
- */
423
- target?: (subject: I) => boolean;
424
- /**
425
- * The subjects this voice reaches, fixed at `cue` and matched by identity; a probe of any other
426
- * never asks this voice. Takes the place of `target`, and a cue giving both is refused: a
427
- * predicate over a fixed list is that list filtered, which the host can do before cueing.
428
- */
429
- subjects?: readonly I[];
430
- /**
431
- * When the voice starts, in ms on the host's clock, the one it passes `sync`: a rAF timestamp and
432
- * `performance.now()` share an origin, `Date.now()` does not. Default: the next sync.
433
- */
434
- start?: number;
435
- /** Playback rate. 1 is real time; 0 freezes. */
436
- rate?: number;
437
- /**
438
- * true loops for good, false plays one pass, n plays n passes. A finite loop leaves when its
439
- * passes are done for the latest-staggered subject it has seen — over `fade.out` where one is
440
- * set, at once where none is — unless it freezes after.
441
- */
442
- loop?: boolean | number;
443
- /**
444
- * Per-subject delay in voice ms, klieg's stagger grammar reduced to the one thing the mix needs.
445
- * Like `target`, it runs once per subject on first sight, and the answer is kept.
446
- */
447
- stagger?: (subject: I) => number;
448
- /**
449
- * Show a subject the first frame before it starts — while the voice is pending and while the
450
- * subject waits out its `stagger` — the last frame of the last pass after a finite loop plays
451
- * out, or both. A frozen subject's clock stands still: `at` is asked for the edge frame and `step`
452
- * does not run, past one last step to the end of the last pass. `fade.in` counts from the first
453
- * frame the voice shows. A voice freezing after stays, `frozen`, until `fade()` or an anchored
454
- * `out` takes it out, so every one cued must be faded or it stays in the mix for good. Does
455
- * nothing to a motion patch, which keeps its target already. Default: neither.
456
- */
457
- freeze?: 'before' | 'after' | 'both';
458
- /** @deprecated Use `freeze`. A voice that sets only `hold` still freezes; `freeze` wins over it. */
459
- hold?: 'before' | 'after' | 'both';
460
- /** Steady weight, or a signal read per subject per frame. Default 1. */
461
- weight?: number | Signal<I, H>;
462
- /** Ramp in and out, ms. Out applies on `fade()` and when a finite loop ends. */
463
- fade?: FadeSpec;
464
- /** Voices sharing a locus are alternatives: the mix folds them through each channel's `lerp`. */
465
- locus?: string;
466
- /** A `keys` voice whose first stop reads wherever this subject is now. */
467
- from?: 'current';
468
- /** Words a source attaches to this voice, so its events and its handle can be taken as a set. */
469
- tags?: readonly string[];
470
- /** What other voices call this one by. A label blits never reads. */
471
- name?: string;
472
- /**
473
- * The plan this voice belongs to. Each source keeps its own, so two sources can use one name
474
- * without meeting: a bare name in an anchor means a voice in the same score, and a query names
475
- * `score` to reach into another. Default: the mix's one unnamed score.
476
- */
477
- score?: string;
478
- /** Where it sits relative to the clock or to other voices, in place of `start`. */
479
- anchor?: Placement;
480
- /**
481
- * Events at times on this voice's clock, which `book` hands a host ahead of time. Patch-sent
482
- * events are not known ahead, so they stay drain-only; these are the plan.
483
- */
484
- hits?: readonly Hit[];
485
- /**
486
- * The owner this voice plays under, a handle `owns` returned. Its `start` and `anchor` are then on
487
- * the owner's clock, in ms from when the owner starts, and default to where that clock is now; a
488
- * bare name in an anchor means a sibling, another voice the owner holds. Its clock runs on the
489
- * owner's, so the owner's rate, ramp and seeks move it, and its weight is multiplied by the
490
- * owner's weight and fade. Without a `freeze` of its own it takes the owner's.
491
- */
492
- owner?: Handle<I>;
493
- }
494
- /**
495
- * What `owns` takes: an owner has no patch, and plays only through the voices it holds.
496
- *
497
- * @category voice
498
- */
499
- export interface OwnerSpec<I, H = unknown> extends SpanHints {
500
- /**
501
- * When the owner starts, on its own owner's clock: the host's for an owner on the mix, as a
502
- * voice's `start` is. Default: now.
503
- */
504
- start?: number;
505
- /** Its clock's rate, multiplied into every child's own. Default 1. */
506
- rate?: number;
507
- /**
508
- * Multiplied into every child's weight per subject, as the child's own fade is, before the child's
509
- * locus folds it: a number, or a signal read per subject per frame. Default 1.
510
- */
511
- weight?: number | Signal<I, H>;
512
- /** One ramp in and out over every child, multiplied into their weights as `weight` is. */
513
- fade?: FadeSpec;
514
- /** The freeze every child without one of its own takes. */
515
- freeze?: 'before' | 'after' | 'both';
516
- /** @deprecated Use `freeze`. An owner that sets only `hold` still freezes; `freeze` wins over it. */
517
- hold?: 'before' | 'after' | 'both';
518
- /** Words a source attaches to it, as a voice's. */
519
- tags?: readonly string[];
520
- /** What other voices call it by, among its siblings. */
521
- name?: string;
522
- /** The plan it belongs to, as a voice's. */
523
- score?: string;
524
- /** Where it sits relative to its own owner's clock or to other voices, in place of `start`. */
525
- anchor?: Placement;
526
- /** The owner it plays under, so owners nest. */
527
- owner?: Handle<I>;
528
- }
529
- /**
530
- * What `span` takes: an owner with a budget, which lays out the voices it holds in an order and
531
- * fits them into the budget.
532
- *
533
- * @category score
534
- */
535
- export interface SpanSpec<I, H = unknown> extends OwnerSpec<I, H> {
536
- /** Its budget, ms on its own clock. Default: none, so its children only keep their order. */
537
- duration?: number;
538
- /** How hard the budget holds against its children's own lengths. Default `strong`. */
539
- priority?: Strength;
540
- /** How its children are laid out, in the order they were cued. Default `queue`. */
541
- order?: Order;
542
- /** How far through the one before a child starts under `stagger`, 0..1. Default 0.5. */
543
- share?: number;
544
- /**
545
- * How the children are fitted once they are retimed toward the budget, faster or slower as
546
- * their hints allow. Default `pipe(condense(), shed())`.
547
- */
548
- fit?: Fit;
549
- /**
550
- * What happens where the fit leaves them too long for a span at least `strong`: `instant` jumps
551
- * every child weaker than the span to its end at once, and `overrun` lets them run long.
552
- * Default `instant`.
553
- */
554
- spill?: 'instant' | 'overrun';
555
- }
556
- /**
557
- * How a span's last fit came out.
558
- *
559
- * @category score
560
- */
561
- export interface FitResult {
562
- /** Its budget, ms on its own clock; Infinity for none. */
563
- budget: number;
564
- /** Where its children end, ms on its own clock from its start. */
565
- length: number;
566
- /** How far `length` runs past the budget, 0 where it does not. */
567
- over: number;
568
- /** How many children it jumps to their end. */
569
- skipped: number;
570
- /** Whether the fit failed and `spill` decided. */
571
- fell: boolean;
572
- }
573
- /**
574
- * A span's handle: an owner's, and how its children were last fitted.
575
- *
576
- * @category score
577
- */
578
- export interface SpanHandle<I = unknown> extends Handle<I> {
579
- readonly result: FitResult;
580
- }
581
- /**
582
- * How a voice leaves when it is faded: the whole voice, or one subject.
583
- *
584
- * @category blending
585
- */
586
- export type FadeOptions<I = unknown> = {
587
- /** The ramp, ms. Defaults to the voice's own `fade.out`. */
588
- over?: number;
589
- /**
590
- * When the fade begins. A mix time: ahead, the voice plays untouched until then and begins
591
- * its fade exactly there, its `out` mark fixed from now, and `rise` before then takes it
592
- * back with nothing changed; at or behind now, the fade began then and is partway. `'rest'`:
593
- * leave per subject at the first frame that subject's contribution is at rest. Default now.
594
- */
595
- at?: number | 'rest';
596
- /** Ms after which the voice leaves whether or not it rested. */
597
- deadline?: number;
598
- subject?: never;
599
- } | {
600
- /**
601
- * The one subject to fade out of this voice, which plays on for the rest. Once the ramp ends
602
- * the voice forgets the subject and reaches it no more, until a motion patch's `to` brings it
603
- * back, met afresh: `from`, `target` and `stagger` asked again.
604
- */
605
- subject: I;
606
- /** The ramp, ms. Defaults to the voice's own `fade.out`; 0 takes the subject out at once. */
607
- over?: number;
608
- };
609
- /**
610
- * The live controls on one voice, returned by `cue`.
611
- *
612
- * @category voice
613
- */
614
- export interface Handle<I = unknown> {
615
- readonly id: number;
616
- /** `frozen`: a voice freezing after has played every pass and shows its last frame until faded. */
617
- readonly state: 'pending' | 'live' | 'frozen' | 'fading' | 'done';
618
- /** The handle of the owner this voice plays under; undefined for one on the mix clock. */
619
- readonly owner: Handle<I> | undefined;
620
- /** Live. Writes land on the next sync. */
621
- weight: number;
622
- /** Playback rate now. Setting it changes speed at once; `ramp` eases into a new one. */
623
- rate: number;
624
- /**
625
- * Moves the rate to `rate` linearly over `over` mix ms, so a pause or a slow-motion eases in
626
- * rather than snapping. The voice clock integrates the ramp, so its position stays continuous and
627
- * its speed does too. A later `rate` write or `ramp` replaces it; `seek` keeps it.
628
- */
629
- ramp(rate: number, over: number): void;
630
- /**
631
- * Moves this voice's clock, forward or back. Phase is computed from the reading rather than
632
- * accumulated into, so state is left where it is and never run forward to meet the new position.
633
- */
634
- seek(elapsed: number): void;
635
- fade(opts?: FadeOptions<I>): void;
636
- /**
637
- * Turns a fade out around: the voice climbs back from where its fade had got to, up the same
638
- * curve, over `over` ms for the whole curve (default its `fade.in`, else its `fade.out`), and
639
- * plays on as if never faded. A fade waiting for rest is taken back at once; a voice not fading
640
- * is left as it is. A voice whose own end began the fade starts it again at its next frame.
641
- */
642
- rise(opts?: {
643
- over?: number;
644
- }): void;
645
- /**
646
- * The weight this voice gave `subject` the last frame that subject was probed: after its fades
647
- * and its weight signal, before a locus folds it with its alternatives. 0 for a subject it does
648
- * not reach, has not started on and does not freeze before, has left at rest, or has never been
649
- * probed for; 0 once done.
650
- * Costs nothing until it is asked.
651
- */
652
- weightOf(subject: I): number;
653
- /** Resolves when the voice has been removed from the mix, however that happened. */
654
- readonly done: Promise<void>;
655
- /**
656
- * Resolves true when a finite loop's last pass ends, for the latest-staggered subject it has
657
- * seen, and false if the voice leaves before that. Never rejects.
658
- */
659
- readonly played: Promise<boolean>;
660
- }
661
- /**
662
- * How a mix is built: its engine, reduced motion, the host, and its limits.
663
- *
664
- * @category mix
665
- */
666
- export interface MixOptions<H = unknown> {
667
- engine?: Engine;
668
- /** Reduced motion: fades and warm-ups snap, `dt` reads Infinity. */
669
- reduce?: boolean | (() => boolean);
670
- /** Merged into every `setting.host`. Its type is the mix's `H`, which every patch and signal it cues reads. */
671
- host?: H;
672
- /**
673
- * The band a rest-less channel's contribution switches on and off across. It has to clear the frame
674
- * noise in a real signal; these are placeholders until the klieg port measures one.
675
- */
676
- band?: {
677
- on: number;
678
- off: number;
679
- };
680
- /**
681
- * The most `dt` a `step` or signal is handed, however long the gap. Off by default, since a
682
- * patch with a closed form wants the whole gap; an integrator wants this set.
683
- */
684
- maxDt?: number;
685
- /**
686
- * Run every `step` at this fixed interval, ms, instead of once by the frame's gap, so stateful
687
- * patches play the same at any frame rate. Intervals count from when a subject's delay ran out,
688
- * the remainder carrying to the next sample; `maxDt` then caps how many one sample may run.
689
- * Signals and `at` still see the frame. Off by default.
690
- */
691
- stepMs?: number;
692
- /**
693
- * How far back `project` may read, in ms of mix time, and how often a stateful voice's state is
694
- * kept per subject on the way, `every` ms (default 200). Within it the mix remembers what it cued,
695
- * every change a handle made and when, the voices that have left, and those copies of state, so a
696
- * read back restores the nearest copy and steps forward from it. Off by default, and a mix without
697
- * it keeps nothing. With `inputs`, it also keeps what each input signal on a voice's weight read
698
- * per subject, and the host fields patches `reads`, each time they changed, so a read back over a
699
- * `level` or a pointer is known rather than held. With `tape`, the mix also records every call
700
- * the host makes on it, its handles and its motion patches, so `seek` can move it and play those
701
- * calls again.
702
- */
703
- history?: HistoryOptions;
704
- /**
705
- * A subject's key, for a history `store`: unique among this mix's subjects for the session. A
706
- * string or number subject is its own key; with a store, an object subject needs this.
707
- */
708
- keyOf?(subject: never): string | number;
709
- /**
710
- * Whether a channel may run as a lane: computed for every subject at once in flat arrays, when
711
- * every voice writing it can run that way. On by default; the pose is the same either way, so
712
- * turning it off is for ruling a lane out, or for comparing against. Two things differ: a
713
- * stateless patch's `setting.send` from `at` sends for every subject a lane fills, those probed
714
- * this frame or the last, and a patch that first calls `setting.keep` partway through playing can
715
- * advance that state once more for one subject probed the frame before (see `Setting.keep`).
716
- */
717
- lanes?: boolean;
718
- /**
719
- * The transport this mix plays on, shared with other mixes, so they keep one clock and a query
720
- * naming a score looks in all of them. The transport's `sync`, `rebase`, `rate`, `ramp` and
721
- * `seek` move it, and the mix's own throw. Its history is the transport's, so the mix takes no
722
- * `history` of its own.
723
- */
724
- transport?: Transport;
725
- /** What `Marked.mix` and errors call this mix. */
726
- name?: string;
727
- }
728
- /**
729
- * What a mix or transport remembers, for `seek` and `project` to read back: see
730
- * `MixOptions.history`.
731
- *
732
- * @category mix
733
- */
734
- export interface HistoryOptions {
735
- /** How much stays in memory, ms of mix time. With a `store`, the rest is paged out, not dropped. */
736
- ms: number;
737
- every?: number;
738
- inputs?: boolean;
739
- tape?: TapeMaker;
740
- /**
741
- * Where history older than `ms` goes instead of being dropped. A `seek` or `project` reaching
742
- * past memory needs `prepare` first, or throws `HistoryMiss`. With a store, blits never prunes
743
- * the tape: the host bounds it.
744
- */
745
- store?: HistoryStore;
746
- /** Rebuilds a cued voice's spec from the descriptor it was cued with, so the voice can be paged out. */
747
- revive?(d: Described): VoiceSpec<any, any>;
748
- }
749
- /**
750
- * A voice as plain data: `kind` names what built it, and `data` survives `structuredClone`.
751
- *
752
- * @category mix
753
- */
754
- export interface Described {
755
- kind: string;
756
- data: unknown;
757
- }
758
- /**
759
- * Where a history `store` keeps what memory let go of. blits decides what is kept and when it is
760
- * read back; the store decides where it lives.
761
- *
762
- * @category mix
763
- */
764
- export interface HistoryStore {
765
- /** Records leaving memory. One brought back by a seek may be paged again: keep one per key and `at`. */
766
- page(out: readonly Paged[]): void;
767
- /**
768
- * What a restore to mix time `t` needs, for every mix: from each stream, per voice and subject,
769
- * the latest record at or before `t` and every record after it. Returning everything is fine.
770
- */
771
- load(t: number): Promise<readonly Paged[]>;
772
- /** A seek went back to `t`: every record after it is from a future the tape makes again. Forget them. */
773
- cut(t: number): void;
774
- }
775
- /**
776
- * What a history record holds: a voice's `controls`, a stateful record's `snap`, an `input`
777
- * signal's reading, a subject's record when it `left` a voice, a motion subject's `released` run
778
- * or older `stretch`, the `host` fields patches read, or a whole `voice` that has left.
779
- *
780
- * @category mix
781
- */
782
- export type PagedStream = 'voice' | 'snap' | 'input' | 'left' | 'released' | 'stretch' | 'host' | 'controls';
783
- /**
784
- * One history record leaving memory, as plain data.
785
- *
786
- * @category mix
787
- */
788
- export interface Paged {
789
- /** The mix's `name`; '' for a mix made alone without one. */
790
- mix: string;
791
- stream: PagedStream;
792
- /** The voice's id, for every stream but `host`. */
793
- voice?: number;
794
- /** The subject's key, for a record of one subject. */
795
- subject?: string | number;
796
- /** Mix time. */
797
- at: number;
798
- data: unknown;
799
- }
800
- /**
801
- * How a transport is made: what history it keeps for every mix on it.
802
- *
803
- * @category mix
804
- */
805
- export interface TransportOptions {
806
- history?: MixOptions['history'];
807
- }
808
- /**
809
- * Every mix on a transport read at another mix time, with nothing live moved: `of` gives one mix's
810
- * reading. Valid until the transport is next synced or a mix on it cued.
811
- *
812
- * @category mix
813
- */
814
- export interface TransportProjection {
815
- readonly timestamp: number;
816
- of<I, O, H>(mix: Mix<I, O, H>): Projection<I, O>;
817
- }
818
- /**
819
- * One clock several mixes play on, each over its own kit: one sync, one rate, one seek and one
820
- * tape for all of them, and a score that spans them, so an anchor in one mix waits on a voice in
821
- * another by naming the score they share. A query naming no score stays in its own mix.
822
- *
823
- * @category mix
824
- */
825
- export interface Transport {
826
- /** The host reports the clock once a frame, after the frame's cues, as `Mix.sync` does. */
827
- sync(timestamp: number): void;
828
- /** As `Mix.rebase`, for every mix on it. */
829
- rebase(): void;
830
- /** As `Mix.rate`, multiplied into every voice of every mix on it. */
831
- rate: number;
832
- ramp(rate: number, over: number): void;
833
- /**
834
- * As `Mix.seek`, for every mix on it at once: back, each mix restores itself; forward, the one
835
- * tape plays every mix's calls again in the order they were made, so an anchor across mixes
836
- * answers as it did. A mix dropped after the moment sought is back on the transport.
837
- */
838
- seek(time: number): void;
839
- /**
840
- * Loads from the history `store` what `seek(time)` and `project(time)` will need, where that
841
- * reaches past memory. Without a store, or within memory, it loads nothing.
842
- */
843
- prepare(time: number): Promise<void>;
844
- readonly now: number;
845
- readonly tape: Tape | undefined;
846
- /** Puts a named mark on a score every mix on it sees. Throws without a `score`. */
847
- announce(name: string, opts: {
848
- at?: number;
849
- score: string;
850
- tags?: readonly string[];
851
- }): void;
852
- /** Every mark of every mix on it, and every mark announced on it, earliest first. */
853
- marks(from: number, to: number): Marked[];
854
- /** Every mix on it read at mix time `time`, together, so anchors across them answer. */
855
- project(time: number): TransportProjection;
856
- /** Any mix on it live. */
857
- readonly live: boolean;
858
- /** Every mix on it inert. */
859
- readonly inert: boolean;
860
- /** Calls `fn` when any mix on it needs frames again after a sync, once until the next sync. */
861
- onWake(fn: () => void): () => void;
862
- /**
863
- * Takes a mix off: it is no longer synced and takes no more calls. With history, a seek back
864
- * before the drop puts it back as it was then; without, it is let go.
865
- */
866
- drop<I, O, H>(mix: Mix<I, O, H>): void;
867
- }
868
- /**
869
- * One host call a mix recorded on its tape: `apply` makes it again, and `invert` does nothing,
870
- * since a mix goes back by restoring what it kept rather than by undoing calls.
871
- *
872
- * @category mix
873
- */
874
- export interface TapeOp {
875
- apply(adapter: unknown): void;
876
- invert(): TapeOp;
877
- label?: string;
878
- }
879
- /**
880
- * One future a tape keeps at its current entry: the calls the host made after the mix last went
881
- * back here, before it made new ones.
882
- *
883
- * @category mix
884
- */
885
- export interface TapeBranch {
886
- /** Its first entry's id, which `switchBranch` takes. */
887
- id: number;
888
- label: string;
889
- timestamp: number;
890
- /** How many entries run along it from here. */
891
- length: number;
892
- /** Whether the mix plays it on from here. */
893
- current: boolean;
894
- }
895
- /**
896
- * Where a mix keeps the host's calls, by mix time, for `seek`. weasel-history's `History`
897
- * (`@weasel-js/history`) has this shape. A host reads `branches` and calls `switchBranch` to pick
898
- * which recorded future plays on; moving it any other way is the mix's job.
899
- *
900
- * @category mix
901
- */
902
- export interface Tape {
903
- recordEntry(ops: TapeOp[], label: string): void;
904
- undoDepth(): number;
905
- timestampAt(i: number): number | undefined;
906
- depthAt(t: number): number;
907
- goto(n: number): void;
908
- redo(): void;
909
- prune(t: number): void;
910
- branches(): readonly TapeBranch[];
911
- switchBranch(id: number): void;
912
- }
913
- /**
914
- * Makes a mix's tape: weasel-history's `createHistory` is one. The mix passes the clock it stamps
915
- * calls with, branching on, so a call made after going back keeps the old future as a branch, and
916
- * coalescing off.
917
- *
918
- * @category mix
919
- */
920
- export type TapeMaker = (adapter: unknown, opts: {
921
- now: () => number;
922
- branching: boolean;
923
- coalesceWindowMs: number;
924
- }) => Tape;
925
- /**
926
- * How sure a projection is of one channel: `exact` where only the clock and known changes drove
927
- * it; `stepped` where state was advanced across a gap in one go, which is as good as the patch's
928
- * step makes it; `held` where it depends on input from outside the clock, whose value at that time
929
- * is not known, so the value it had is held.
930
- *
931
- * @category mix
932
- */
933
- export type Doubt = 'exact' | 'stepped' | 'held';
934
- /**
935
- * The mix read at another time: what `probe` would give at that timestamp, with nothing in the
936
- * live mix moved. Valid until the mix is next synced or cued.
937
- *
938
- * @category mix
939
- */
940
- export interface Projection<I, O> {
941
- /** The mix time it reads at. */
942
- readonly timestamp: number;
943
- /** The merged pose for one subject at this projection's timestamp. */
944
- probe(subject: I, out?: O): O;
945
- /** Per channel, how sure that pose is; the least sure voice that fed a channel decides. */
946
- assess(subject: I): {
947
- [K in keyof O]-?: Doubt;
948
- };
949
- }
950
- /**
951
- * Arrays for `pull` to write, one per channel it reads: any channel whose value is a number or an
952
- * array of numbers.
953
- *
954
- * @category mix
955
- */
956
- export type Columns<O> = {
957
- [K in keyof O as NonNullable<O[K]> extends number | readonly number[] ? K : never]?: Float64Array;
958
- };
959
- /**
960
- * The live voices over one kit, folded into one pose per subject per frame.
961
- *
962
- * @category mix
963
- */
964
- export interface Mix<I, O, H = unknown> {
965
- /** Cues a voice. Throws when the engine cannot run the patch's form, or the kit lacks a channel. */
966
- cue(spec: VoiceSpec<I, O, H>): Handle<I>;
967
- /**
968
- * N voices whose weights split one signal, cued into one locus so they fold as alternatives. The
969
- * signal is read once per subject per frame, with the first member's setting, and every member
970
- * takes its share of that one reading; a signal keeping state keeps it once, not per member.
971
- */
972
- blend(patches: readonly Patch<I, O, unknown, H>[], by: Signal<I, H>, spec?: Omit<VoiceSpec<I, O, H>, 'patch' | 'weight' | 'locus'>): Handle<I>[];
973
- /**
974
- * Cues an owner: a voice with no patch that holds the voices cued with `owner` set to its handle,
975
- * and plays them on its own clock, so they can be placed, timed and faded as one. Its handle acts
976
- * on all of them: `rate` and `ramp` multiply into theirs, `seek` moves their clocks with its own
977
- * and leaves their state where it is, and `weight` and `fade()` multiply into their weights, by
978
- * what its `weightOf` reports; it fades as a whole, not by subject or at rest. It is
979
- * `played` once every voice it held has finished its passes, and leaves, `done`, with its last; a
980
- * fade that ends takes the rest with it. One that never holds a voice stays until faded. Owners
981
- * nest. Throws for a `loop`: a pass would have to restart its children.
982
- */
983
- owns(spec: OwnerSpec<I, H>): Handle<I>;
984
- /**
985
- * Cues a span: an owner that lays out the voices it holds in `order` and fits them into its
986
- * `duration`, again each time one joins or leaves early. A child's start and rate are the
987
- * span's to set, so it takes neither `start` nor an anchored start; its `SpanHints` say how it
988
- * may give way. A span with a budget stays until the budget has passed, though its children
989
- * finish sooner, so late ones can still join, and its `end` mark is where its children end or
990
- * its budget does, whichever is later. A voice that loops for good cannot join one.
991
- */
992
- span(spec: SpanSpec<I, H>): SpanHandle<I>;
993
- /**
994
- * The host reports the clock, once a frame. Nothing advances at the call. Throws for a timestamp
995
- * earlier than the last sync's, short of a `rebase`: the host's clock only goes forward, and
996
- * `seek` moves the mix.
997
- */
998
- sync(timestamp: number): void;
999
- /**
1000
- * The time between the last sync and the next one is not to count: a host calls it when a
1001
- * hidden tab comes back. Every voice, fade and subject resumes where it was left.
1002
- */
1003
- rebase(): void;
1004
- /**
1005
- * The mix's own playback rate, multiplied into every voice's: 1 is real time and 0 pauses the
1006
- * whole mix. A negative rate throws: the mix plays only forward, and `seek` moves it back. Setting it changes speed at
1007
- * once; `ramp` eases into a new one. It scales mix time, which everything a voice owns runs on:
1008
- * its clock, its fades and a handle's ramp, `stagger`, an anchor's `by`, `stepMs`, `maxDt`,
1009
- * `history.ms`, every `dt`, and `setting.timestamp`. Timestamps on the host's clock name the same
1010
- * moment whatever the rate does: a `start`, an anchor given as a number, an announced mark, what
1011
- * `marks` reports and the time `project` reads, so a start ahead of a paused mix waits for the
1012
- * host's clock to reach it. A weight signal is still asked at every probe, so one reading host
1013
- * input follows it while the mix is paused.
1014
- */
1015
- rate: number;
1016
- /**
1017
- * Moves the mix's rate to `rate` linearly over `over` ms of the host's clock, as `Handle.ramp`
1018
- * moves a voice's. Mix time integrates the ramp and a voice's clock integrates mix time, so a ramp
1019
- * on both multiplies and every position stays continuous. A later `rate` write or `ramp` replaces
1020
- * it.
1021
- */
1022
- ramp(rate: number, over: number): void;
1023
- /**
1024
- * The merged pose for one subject at the synced frame, written into `out` when given. Without
1025
- * it, each call makes a new object, so a host reading every subject every frame passes `out` or
1026
- * reads by `pull`.
1027
- */
1028
- probe(subject: I, out?: O): O;
1029
- /**
1030
- * Writes each subject's pose into arrays, one per channel, subject by subject in the order given:
1031
- * what `probe(subject, out)` gives, without a pose object per subject. A channel of `n` numbers
1032
- * takes `n` places per subject, side by side; one with no value for a subject writes NaN there.
1033
- * Fastest while every voice runs on a lane, and when `subjects` is an array read again in the
1034
- * same order: the mix remembers the last array's subjects by position, holding them until the
1035
- * next `pull`, and skips looking up any still in its place. Throws when an array is too short for
1036
- * the subjects.
1037
- */
1038
- pull(subjects: Iterable<I>, into: Columns<O>): void;
1039
- /**
1040
- * Reads the mix at another mix time, without moving it. Ahead of the mix it plays what is cued
1041
- * forward, and throws for a time past a call the tape will play again after a `seek` back, which
1042
- * only a seek there makes; behind it, it needs `history`, and throws for a time older than the
1043
- * history reaches. On a transport it reads every mix on it together, so anchors across them
1044
- * answer.
1045
- */
1046
- project(time: number): Projection<I, O>;
1047
- /**
1048
- * Moves the mix to mix time `time`, as it stood at the end of that frame, and plays on from
1049
- * there. Needs `history` with a `tape`, which records the host's calls by mix time.
1050
- *
1051
- * Back, the mix restores itself: controls, records, voices and marks as they stood then. Voices
1052
- * that left after it are back on the handles the host holds, their `done` and `played` starting
1053
- * over where they had settled since. Voices cued after it wait as `pending` until the mix plays
1054
- * their cue again. Stateful voices restart from the copy `history` kept nearest before it and
1055
- * step once to it, exact under `stepMs`. A subject faded out of a voice or dropped after it comes
1056
- * back with the record it had, a motion patch's state included. Recorded input and host fields
1057
- * after it are let go: after a seek back, signals and host fields read live again, and `assess`
1058
- * reports what they fed as `held`.
1059
- *
1060
- * Forward, through a sync or a later seek, the mix plays the recorded calls again at the mix
1061
- * times they were made: cues, handle writes, fades, retargets and pushes, its rate, marks,
1062
- * `mute` and `drop`. A call the host makes while there are recorded calls ahead starts a new
1063
- * branch, and the tape keeps the old future beside it; `tape.switchBranch` picks one back.
1064
- * Playing past a time again sends its events and books its marks and hits again.
1065
- *
1066
- * The host goes on passing its own clock: the next `sync` reads the moment sought plus the
1067
- * host's time since its last sync. Throws for a time older than history reaches, and before
1068
- * the first sync. With a history `store`, a time older than memory needs `prepare` first, or
1069
- * throws `HistoryMiss` before anything moves.
1070
- */
1071
- seek(time: number): void;
1072
- /** As `Transport.prepare`, for a mix made alone. */
1073
- prepare(time: number): Promise<void>;
1074
- /**
1075
- * The mix clock at the last sync or seek, which `seek` and `project` take; NaN before the first
1076
- * sync. Host time at the mix's rate, less what `rebase` took out and `seek` moved.
1077
- */
1078
- readonly now: number;
1079
- /** The tape `history.tape` made, undefined without one. */
1080
- readonly tape: Tape | undefined;
1081
- /**
1082
- * Every channel at rest for this subject this frame, so a host can skip the write. After a probe
1083
- * of the subject this frame, it answers for the pose that probe gave, without folding again.
1084
- */
1085
- atRest(subject: I): boolean;
1086
- /**
1087
- * A handle on every voice still in the mix, pending, live, frozen or fading, in the order they were
1088
- * cued; given a tag, only the voices whose `tags` carry it. Each is the handle `cue` returned for
1089
- * that voice, so a listed handle is `===` the cued one.
1090
- */
1091
- voices(tag?: string): Handle<I>[];
1092
- /** Anything still contributing, fading, or pending. */
1093
- readonly live: boolean;
1094
- /**
1095
- * Another frame would change no pose, so a host's frame loop may sleep: every voice is done, frozen
1096
- * at a plain weight, or a motion whose every subject has landed on its target. At rate 0 it is
1097
- * enough that every voice not done has started, at a plain weight, with no anchor. A change made
1098
- * since the last sync, a retarget or a rate included, makes it false until the next.
1099
- */
1100
- readonly inert: boolean;
1101
- /**
1102
- * Calls `fn` when a host call makes the mix need frames again after a sync: a cue, a fade, a
1103
- * handle's or the mix's rate, a seek, a `drop`, a motion retargeted. It fires once until the next
1104
- * sync clears the change, and never during `sync`. Returns a function that unsubscribes `fn`.
1105
- * A frame loop sleeping on `inert` subscribes here to wake.
1106
- */
1107
- onWake(fn: () => void): () => void;
1108
- /** Fades every voice out: over `over` when given, over each voice's own `fade.out` otherwise. */
1109
- mute(opts?: {
1110
- over?: number;
1111
- }): void;
1112
- /** Forgets per-subject state, a motion patch's for the subject included. */
1113
- drop(subject: I): void;
1114
- /**
1115
- * Puts a named mark on a score, for anchors to target as they target a voice's marks: a voice
1116
- * placed `{ with: 'reply' }` waits until the host announces `reply`. `at` is a timestamp on the
1117
- * host's clock, default now, and may lie ahead, so a read ahead sees it. A mark stays while it is
1118
- * ahead or while the mix's history reaches it.
1119
- */
1120
- announce(name: string, opts?: {
1121
- at?: number;
1122
- score?: string;
1123
- tags?: readonly string[];
1124
- }): void;
1125
- /**
1126
- * Every mark the plan knows between two timestamps on the host's clock, earliest first: when
1127
- * voices start, are fully in, begin to fade and are gone, and what the host announced. A mark
1128
- * nothing has fixed yet, such as the out of a voice that loops for good, is not listed.
1129
- */
1130
- marks(from: number, to: number): Marked[];
1131
- /**
1132
- * Every event patches have sent since the last drain, earliest first, in the order they were sent
1133
- * where two share a timestamp. A subject's events are made while it catches up, which is when it is
1134
- * probed, so one nobody probes has sent nothing yet: promptness is the host's, by probing. A
1135
- * stateless patch's `at` on a lane is the exception: it runs at the frame's first probe for every
1136
- * subject probed that frame or the last. Under `stepMs` each carries the end of the interval it happened in, so
1137
- * what is sent and when does not depend on how the host spaces its probes. Time `rebase` took out
1138
- * sends nothing. Given a tag, it takes only the events of voices carrying it and leaves the rest for
1139
- * whoever drains them.
1140
- */
1141
- drain<E = unknown>(tag?: string): Sent<I, E>[];
1142
- /**
1143
- * Hands the host each mark and hit before it comes, against a clock of its own, so it can schedule
1144
- * the thing itself: a sound on an `AudioContext`, a MIDI message with a timestamp, a video loaded
1145
- * before the voice that shows it starts. Booking runs at each `sync`, `ahead` ms out, and a
1146
- * booking whose time moves is stopped and taken again. Nothing is booked twice: a mark is known by
1147
- * its voice and which mark, a hit by its voice, index and pass. `project` books nothing, and
1148
- * nothing about booking is replayed under `history`. A mix with no booker pays nothing for it.
1149
- */
1150
- book<E = unknown>(opts: BookOptions<E>): Booker;
1151
- }
1152
- /**
1153
- * The implementation behind a mix: which patch forms it runs, and how it makes one.
1154
- *
1155
- * @category engine
1156
- */
1157
- export interface Engine {
1158
- readonly name: string;
1159
- /** Which patch forms this engine can run. A voice it cannot run is refused at `cue`, by name. */
1160
- readonly runs: ReadonlySet<'fn' | 'keys' | 'motion'>;
1161
- create<I, O, H = unknown>(kit: Kit<O>, opts: MixOptions<H>): Mix<I, O, H>;
1162
- }
1
+ export type * from './types/channel.js';
2
+ export type * from './types/history.js';
3
+ export type * from './types/mix.js';
4
+ export type * from './types/patch.js';
5
+ export type * from './types/place.js';
6
+ export type * from './types/transport.js';
7
+ export type * from './types/voice.js';