@msb235/blits 0.6.0 → 0.7.0
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.
- package/CHANGELOG.md +136 -0
- package/README.md +31 -7
- package/dist/bare.js +7 -1
- package/dist/book.d.ts +7 -0
- package/dist/book.js +35 -4
- package/dist/chain.d.ts +2 -1
- package/dist/chain.js +7 -3
- package/dist/channels.d.ts +12 -19
- package/dist/channels.js +18 -118
- package/dist/clock.d.ts +9 -2
- package/dist/clock.js +10 -2
- package/dist/closed.d.ts +15 -0
- package/dist/closed.js +144 -0
- package/dist/color.d.ts +61 -0
- package/dist/color.js +229 -0
- package/dist/columns.js +2 -1
- package/dist/crowd.d.ts +1 -1
- package/dist/crowd.js +4 -1
- package/dist/cue.d.ts +2 -0
- package/dist/cue.js +78 -27
- package/dist/due.js +3 -0
- package/dist/fade.d.ts +13 -0
- package/dist/fade.js +55 -4
- package/dist/fill.d.ts +1 -1
- package/dist/fill.js +15 -8
- package/dist/fit.d.ts +144 -0
- package/dist/fit.js +181 -0
- package/dist/fold.d.ts +3 -3
- package/dist/fold.js +18 -11
- package/dist/gather.d.ts +6 -0
- package/dist/gather.js +18 -0
- package/dist/handle.d.ts +27 -2
- package/dist/handle.js +60 -11
- package/dist/held.js +4 -0
- package/dist/history.d.ts +15 -2
- package/dist/history.js +54 -9
- package/dist/hosts.d.ts +2 -2
- package/dist/hosts.js +18 -5
- package/dist/index.d.ts +8 -2
- package/dist/index.js +5 -1
- package/dist/lane.d.ts +1 -1
- package/dist/lanes.d.ts +32 -9
- package/dist/lanes.js +53 -24
- package/dist/locus.d.ts +3 -3
- package/dist/locus.js +1 -1
- package/dist/marks.d.ts +3 -0
- package/dist/marks.js +80 -12
- package/dist/meet.d.ts +3 -2
- package/dist/meet.js +15 -3
- package/dist/mixer.d.ts +52 -36
- package/dist/mixer.js +148 -86
- package/dist/motion.d.ts +2 -199
- package/dist/motion.js +2 -652
- package/dist/motions.d.ts +266 -0
- package/dist/motions.js +724 -0
- package/dist/move.d.ts +1 -1
- package/dist/move.js +23 -7
- package/dist/owner.d.ts +1 -1
- package/dist/owner.js +3 -3
- package/dist/pace.d.ts +2 -0
- package/dist/pace.js +8 -0
- package/dist/pack.d.ts +31 -0
- package/dist/pack.js +65 -0
- package/dist/paging.d.ts +63 -0
- package/dist/paging.js +110 -0
- package/dist/patch.d.ts +3 -0
- package/dist/patch.js +2 -0
- package/dist/place.js +74 -25
- package/dist/project.d.ts +7 -4
- package/dist/project.js +117 -78
- package/dist/pull.js +4 -3
- package/dist/qualify.js +4 -2
- package/dist/revive.d.ts +58 -0
- package/dist/revive.js +158 -0
- package/dist/sample.d.ts +1 -1
- package/dist/sample.js +6 -1
- package/dist/seek.d.ts +3 -0
- package/dist/seek.js +311 -0
- package/dist/spans.d.ts +29 -0
- package/dist/spans.js +165 -0
- package/dist/strays.d.ts +1 -1
- package/dist/strays.js +21 -0
- package/dist/tape.d.ts +21 -0
- package/dist/tape.js +65 -0
- package/dist/ticker.d.ts +28 -3
- package/dist/ticker.js +3 -0
- package/dist/transport.d.ts +121 -0
- package/dist/transport.js +271 -0
- package/dist/types.d.ts +404 -38
- package/dist/unpage.d.ts +8 -0
- package/dist/unpage.js +163 -0
- package/dist/voice.d.ts +73 -7
- package/dist/voice.js +116 -4
- package/dist/weigh.js +2 -2
- package/docs/schema.html +120 -31
- package/package.json +2 -1
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Fit, Order, Strength } from './fit.js';
|
|
1
2
|
/**
|
|
2
3
|
* One field of a delta, with its own arithmetic.
|
|
3
4
|
*
|
|
@@ -18,7 +19,7 @@ export interface Channel<V> {
|
|
|
18
19
|
bounds?: readonly [min: number, max: number];
|
|
19
20
|
/** Identity. Absent means the channel has none: it replaces rather than contributes. */
|
|
20
21
|
rest?: V;
|
|
21
|
-
/** Fold two
|
|
22
|
+
/** Fold two contributions into one. */
|
|
22
23
|
merge(a: V, b: V): V;
|
|
23
24
|
/** Fade toward `rest` by weight 0..1. Required when `rest` is set; absent otherwise. */
|
|
24
25
|
scale?(v: V, w: number): V;
|
|
@@ -26,7 +27,7 @@ export interface Channel<V> {
|
|
|
26
27
|
lerp(a: V, b: V, u: number): V;
|
|
27
28
|
/**
|
|
28
29
|
* Optional: `merge(into, scale(v, w))`, written into `into` and returned, so a channel whose
|
|
29
|
-
* values are objects need not allocate per
|
|
30
|
+
* values are objects need not allocate per contribution. The mix only hands it a value it made.
|
|
30
31
|
*/
|
|
31
32
|
fold?(into: V, v: V, w: number): V;
|
|
32
33
|
}
|
|
@@ -94,17 +95,18 @@ export interface Setting<S = void, H = unknown> {
|
|
|
94
95
|
* The state `owner` keeps for this voice and this subject, made by `init` on first ask. The mix
|
|
95
96
|
* holds it, so a read at another time can copy it instead of moving it. A stateful signal keeps
|
|
96
97
|
* its state here and nowhere else. With lanes on, a patch or weight signal that first calls it
|
|
97
|
-
* partway through playing can have that state advanced once for one subject
|
|
98
|
-
*
|
|
99
|
-
* never does.
|
|
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.
|
|
100
101
|
*/
|
|
101
102
|
keep<K>(owner: object, init: () => K): K;
|
|
102
103
|
/**
|
|
103
104
|
* Reports an event at `timestamp`, for this voice and this subject. The mix queues it until the
|
|
104
105
|
* host drains it, and never calls back. Meant for `step`, where under `stepMs` the timestamp is
|
|
105
106
|
* the interval the event happened in rather than the frame that sampled it. Sent from a stateless
|
|
106
|
-
* patch's `at` while it runs on a lane, it goes out for every subject the
|
|
107
|
-
* frame or not; `at` is not asked for a subject at weight 0,
|
|
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.
|
|
108
110
|
*/
|
|
109
111
|
send(event: unknown): void;
|
|
110
112
|
}
|
|
@@ -175,7 +177,7 @@ export interface Patch<I, O, S = void, H = unknown> {
|
|
|
175
177
|
readonly reads?: readonly string[];
|
|
176
178
|
/**
|
|
177
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;
|
|
178
|
-
* `step` still runs.
|
|
180
|
+
* `step` still runs. A `keys` patch's stops are not read there either, unless its voice is in a locus.
|
|
179
181
|
*/
|
|
180
182
|
at(phase: number, subject: I, setting: Setting<S, H>): Partial<O>;
|
|
181
183
|
/** Per-subject state, created on the first frame this patch sees a subject. */
|
|
@@ -195,6 +197,13 @@ export interface Patch<I, O, S = void, H = unknown> {
|
|
|
195
197
|
* function needs its own.
|
|
196
198
|
*/
|
|
197
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;
|
|
198
207
|
}
|
|
199
208
|
/**
|
|
200
209
|
* A 0..1 scalar resolved per subject per frame from something outside the clock. `input` is set
|
|
@@ -217,12 +226,15 @@ export interface FadeSpec {
|
|
|
217
226
|
ease?: Easing;
|
|
218
227
|
}
|
|
219
228
|
/**
|
|
220
|
-
* The
|
|
221
|
-
* fully in (`in`), when its fade out begins (`out`), and when it
|
|
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.
|
|
222
234
|
*
|
|
223
235
|
* @category score
|
|
224
236
|
*/
|
|
225
|
-
export type Mark = 'start' | 'in' | 'out' | 'end';
|
|
237
|
+
export type Mark = 'start' | 'in' | 'coast' | 'out' | 'end';
|
|
226
238
|
/**
|
|
227
239
|
* Selects voices by what the plan knows of them, never by a channel's value, within the asking
|
|
228
240
|
* voice's own score unless it names another. Where several match,
|
|
@@ -243,7 +255,8 @@ export interface Query {
|
|
|
243
255
|
/**
|
|
244
256
|
* A time given by another voice: `mark` of the voice `of` selects, moved by `by` ms. `after` is
|
|
245
257
|
* sugar for that voice's `end`, `with` for its `start`, and `before` for its start less `by`. A
|
|
246
|
-
* string selects by name.
|
|
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.
|
|
247
260
|
*
|
|
248
261
|
* @category score
|
|
249
262
|
*/
|
|
@@ -260,6 +273,10 @@ export type Anchor = {
|
|
|
260
273
|
} | {
|
|
261
274
|
before: string | Query;
|
|
262
275
|
by?: number;
|
|
276
|
+
} | {
|
|
277
|
+
all: readonly Anchor[];
|
|
278
|
+
} | {
|
|
279
|
+
any: readonly Anchor[];
|
|
263
280
|
};
|
|
264
281
|
/**
|
|
265
282
|
* Where a voice sits on the mix clock: at most one of `start` and `in`, and at most one of `out`
|
|
@@ -276,21 +293,23 @@ export interface Placement {
|
|
|
276
293
|
end?: number | Anchor;
|
|
277
294
|
}
|
|
278
295
|
/**
|
|
279
|
-
* One mark as `marks` lists it: one of a voice's
|
|
280
|
-
*
|
|
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.
|
|
281
298
|
*
|
|
282
299
|
* @category score
|
|
283
300
|
*/
|
|
284
301
|
export interface Marked {
|
|
285
302
|
/** On the host's clock. */
|
|
286
303
|
timestamp: number;
|
|
287
|
-
/** Which of a voice's
|
|
304
|
+
/** Which of a voice's this is; undefined for an announced mark. */
|
|
288
305
|
mark: Mark | undefined;
|
|
289
306
|
/** The voice it belongs to; undefined for an announced mark. */
|
|
290
307
|
voice: number | undefined;
|
|
291
308
|
score: string | undefined;
|
|
292
309
|
name: string | undefined;
|
|
293
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;
|
|
294
313
|
}
|
|
295
314
|
/**
|
|
296
315
|
* An event at a time on a voice's own clock, which `book` hands a host ahead of time. It plays once
|
|
@@ -368,8 +387,31 @@ export interface Booker {
|
|
|
368
387
|
*
|
|
369
388
|
* @category voice
|
|
370
389
|
*/
|
|
371
|
-
|
|
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 {
|
|
372
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;
|
|
373
415
|
/**
|
|
374
416
|
* Which subjects this voice reaches. Default: all of them. The predicate is fixed at `cue`; it
|
|
375
417
|
* runs per subject the first time the mix sees that subject, and the answer is kept. Every
|
|
@@ -454,7 +496,7 @@ export interface VoiceSpec<I, O, H = unknown> {
|
|
|
454
496
|
*
|
|
455
497
|
* @category voice
|
|
456
498
|
*/
|
|
457
|
-
export interface OwnerSpec<I, H = unknown> {
|
|
499
|
+
export interface OwnerSpec<I, H = unknown> extends SpanHints {
|
|
458
500
|
/**
|
|
459
501
|
* When the owner starts, on its own owner's clock: the host's for an owner on the mix, as a
|
|
460
502
|
* voice's `start` is. Default: now.
|
|
@@ -484,6 +526,58 @@ export interface OwnerSpec<I, H = unknown> {
|
|
|
484
526
|
/** The owner it plays under, so owners nest. */
|
|
485
527
|
owner?: Handle<I>;
|
|
486
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
|
+
}
|
|
487
581
|
/**
|
|
488
582
|
* How a voice leaves when it is faded: the whole voice, or one subject.
|
|
489
583
|
*
|
|
@@ -492,8 +586,13 @@ export interface OwnerSpec<I, H = unknown> {
|
|
|
492
586
|
export type FadeOptions<I = unknown> = {
|
|
493
587
|
/** The ramp, ms. Defaults to the voice's own `fade.out`. */
|
|
494
588
|
over?: number;
|
|
495
|
-
/**
|
|
496
|
-
|
|
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';
|
|
497
596
|
/** Ms after which the voice leaves whether or not it rested. */
|
|
498
597
|
deadline?: number;
|
|
499
598
|
subject?: never;
|
|
@@ -534,6 +633,15 @@ export interface Handle<I = unknown> {
|
|
|
534
633
|
*/
|
|
535
634
|
seek(elapsed: number): void;
|
|
536
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;
|
|
537
645
|
/**
|
|
538
646
|
* The weight this voice gave `subject` the last frame that subject was probed: after its fades
|
|
539
647
|
* and its weight signal, before a locus folds it with its alternatives. 0 for a subject it does
|
|
@@ -562,7 +670,7 @@ export interface MixOptions<H = unknown> {
|
|
|
562
670
|
/** Merged into every `setting.host`. Its type is the mix's `H`, which every patch and signal it cues reads. */
|
|
563
671
|
host?: H;
|
|
564
672
|
/**
|
|
565
|
-
* The band a rest-less channel's
|
|
673
|
+
* The band a rest-less channel's contribution switches on and off across. It has to clear the frame
|
|
566
674
|
* noise in a real signal; these are placeholders until the klieg port measures one.
|
|
567
675
|
*/
|
|
568
676
|
band?: {
|
|
@@ -588,23 +696,232 @@ export interface MixOptions<H = unknown> {
|
|
|
588
696
|
* read back restores the nearest copy and steps forward from it. Off by default, and a mix without
|
|
589
697
|
* it keeps nothing. With `inputs`, it also keeps what each input signal on a voice's weight read
|
|
590
698
|
* per subject, and the host fields patches `reads`, each time they changed, so a read back over a
|
|
591
|
-
* `level` or a pointer is known rather than held.
|
|
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.
|
|
592
702
|
*/
|
|
593
|
-
history?:
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
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;
|
|
598
709
|
/**
|
|
599
710
|
* Whether a channel may run as a lane: computed for every subject at once in flat arrays, when
|
|
600
711
|
* every voice writing it can run that way. On by default; the pose is the same either way, so
|
|
601
712
|
* turning it off is for ruling a lane out, or for comparing against. Two things differ: a
|
|
602
|
-
* stateless patch's `setting.send` from `at` sends for every subject a lane fills, probed
|
|
603
|
-
* and a patch that first calls `setting.keep` partway through playing can
|
|
604
|
-
* more for one
|
|
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`).
|
|
605
716
|
*/
|
|
606
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;
|
|
607
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;
|
|
608
925
|
/**
|
|
609
926
|
* How sure a projection is of one channel: `exact` where only the clock and known changes drove
|
|
610
927
|
* it; `stepped` where state was advanced across a gap in one go, which is as good as the patch's
|
|
@@ -621,7 +938,7 @@ export type Doubt = 'exact' | 'stepped' | 'held';
|
|
|
621
938
|
* @category mix
|
|
622
939
|
*/
|
|
623
940
|
export interface Projection<I, O> {
|
|
624
|
-
/** The
|
|
941
|
+
/** The mix time it reads at. */
|
|
625
942
|
readonly timestamp: number;
|
|
626
943
|
/** The merged pose for one subject at this projection's timestamp. */
|
|
627
944
|
probe(subject: I, out?: O): O;
|
|
@@ -664,7 +981,20 @@ export interface Mix<I, O, H = unknown> {
|
|
|
664
981
|
* nest. Throws for a `loop`: a pass would have to restart its children.
|
|
665
982
|
*/
|
|
666
983
|
owns(spec: OwnerSpec<I, H>): Handle<I>;
|
|
667
|
-
/**
|
|
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
|
+
*/
|
|
668
998
|
sync(timestamp: number): void;
|
|
669
999
|
/**
|
|
670
1000
|
* The time between the last sync and the next one is not to count: a host calls it when a
|
|
@@ -673,7 +1003,7 @@ export interface Mix<I, O, H = unknown> {
|
|
|
673
1003
|
rebase(): void;
|
|
674
1004
|
/**
|
|
675
1005
|
* The mix's own playback rate, multiplied into every voice's: 1 is real time and 0 pauses the
|
|
676
|
-
* whole mix. A negative rate throws
|
|
1006
|
+
* whole mix. A negative rate throws: the mix plays only forward, and `seek` moves it back. Setting it changes speed at
|
|
677
1007
|
* once; `ramp` eases into a new one. It scales mix time, which everything a voice owns runs on:
|
|
678
1008
|
* its clock, its fades and a handle's ramp, `stagger`, an anchor's `by`, `stepMs`, `maxDt`,
|
|
679
1009
|
* `history.ms`, every `dt`, and `setting.timestamp`. Timestamps on the host's clock name the same
|
|
@@ -707,11 +1037,47 @@ export interface Mix<I, O, H = unknown> {
|
|
|
707
1037
|
*/
|
|
708
1038
|
pull(subjects: Iterable<I>, into: Columns<O>): void;
|
|
709
1039
|
/**
|
|
710
|
-
* Reads the mix at another
|
|
711
|
-
*
|
|
712
|
-
* older than the
|
|
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.
|
|
713
1077
|
*/
|
|
714
|
-
|
|
1078
|
+
readonly now: number;
|
|
1079
|
+
/** The tape `history.tape` made, undefined without one. */
|
|
1080
|
+
readonly tape: Tape | undefined;
|
|
715
1081
|
/**
|
|
716
1082
|
* Every channel at rest for this subject this frame, so a host can skip the write. After a probe
|
|
717
1083
|
* of the subject this frame, it answers for the pose that probe gave, without folding again.
|
|
@@ -766,8 +1132,8 @@ export interface Mix<I, O, H = unknown> {
|
|
|
766
1132
|
* Every event patches have sent since the last drain, earliest first, in the order they were sent
|
|
767
1133
|
* where two share a timestamp. A subject's events are made while it catches up, which is when it is
|
|
768
1134
|
* probed, so one nobody probes has sent nothing yet: promptness is the host's, by probing. A
|
|
769
|
-
* stateless patch's `at` on a lane is the exception: it runs
|
|
770
|
-
*
|
|
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
|
|
771
1137
|
* what is sent and when does not depend on how the host spaces its probes. Time `rebase` took out
|
|
772
1138
|
* sends nothing. Given a tag, it takes only the events of voices carrying it and leaves the rest for
|
|
773
1139
|
* whoever drains them.
|
package/dist/unpage.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Transport } from './transport.js';
|
|
2
|
+
/**
|
|
3
|
+
* Makes memory reach mix time `t` for a seek or read there, from what `prepare` loaded; true where
|
|
4
|
+
* it took records from the store. Throws before anything moves where it cannot.
|
|
5
|
+
*/
|
|
6
|
+
export declare function cover(transport: Transport, t: number): boolean;
|
|
7
|
+
/** A seek back to `t`: what the store and `prepare` hold after it is from a future the tape makes again. */
|
|
8
|
+
export declare function cut(transport: Transport, t: number, unpaged: boolean): void;
|