@msb235/blits 0.13.0 → 0.15.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 +183 -0
- package/README.md +20 -3
- package/dist/ahead.d.ts +26 -0
- package/dist/ahead.js +264 -0
- package/dist/around.d.ts +11 -0
- package/dist/around.js +32 -0
- package/dist/bare.js +15 -7
- package/dist/blank.d.ts +10 -0
- package/dist/blank.js +26 -0
- package/dist/blend.d.ts +2 -1
- package/dist/blend.js +1 -6
- package/dist/bound.d.ts +70 -0
- package/dist/bound.js +351 -0
- package/dist/chain.d.ts +2 -1
- package/dist/chain.js +7 -5
- package/dist/changes.d.ts +24 -0
- package/dist/changes.js +189 -0
- package/dist/channels.d.ts +39 -13
- package/dist/channels.js +14 -5
- package/dist/closed.d.ts +1 -0
- package/dist/closed.js +45 -1
- package/dist/color.d.ts +12 -10
- package/dist/color.js +25 -25
- package/dist/columns.js +7 -3
- package/dist/contribution.d.ts +30 -0
- package/dist/contribution.js +374 -0
- package/dist/copyout.d.ts +10 -0
- package/dist/copyout.js +69 -24
- package/dist/crowd.d.ts +8 -2
- package/dist/crowd.js +4 -5
- package/dist/cue.d.ts +8 -1
- package/dist/cue.js +47 -14
- package/dist/cut.d.ts +8 -0
- package/dist/cut.js +4 -0
- package/dist/drop.d.ts +9 -0
- package/dist/drop.js +84 -0
- package/dist/due.d.ts +24 -5
- package/dist/due.js +113 -33
- package/dist/easing.d.ts +4 -4
- package/dist/easing.js +3 -3
- package/dist/everyone.d.ts +3 -2
- package/dist/everyone.js +3 -3
- package/dist/fade.d.ts +2 -1
- package/dist/fade.js +2 -1
- package/dist/fill.d.ts +3 -2
- package/dist/fill.js +51 -19
- package/dist/fit.d.ts +44 -26
- package/dist/fit.js +10 -9
- package/dist/fling.d.ts +66 -0
- package/dist/fling.js +162 -0
- package/dist/fold.d.ts +4 -37
- package/dist/fold.js +5 -512
- package/dist/gather.d.ts +12 -7
- package/dist/gather.js +179 -44
- package/dist/gone.js +2 -2
- package/dist/grid.d.ts +47 -0
- package/dist/grid.js +247 -0
- package/dist/handle.d.ts +3 -0
- package/dist/handle.js +19 -8
- package/dist/held.d.ts +2 -1
- package/dist/history.d.ts +6 -5
- package/dist/history.js +9 -9
- package/dist/hosts.js +9 -15
- package/dist/index.d.ts +5 -4
- package/dist/keyfill.d.ts +1 -1
- package/dist/keyfill.js +5 -3
- package/dist/keyrows.d.ts +12 -0
- package/dist/keyrows.js +99 -12
- package/dist/lane.d.ts +36 -6
- package/dist/lane.js +32 -1
- package/dist/lanes.d.ts +23 -8
- package/dist/lanes.js +29 -8
- package/dist/leavings.d.ts +2 -2
- package/dist/leavings.js +1 -1
- package/dist/lives.d.ts +47 -0
- package/dist/lives.js +180 -0
- package/dist/meet.d.ts +2 -2
- package/dist/meet.js +90 -4
- package/dist/mixer.d.ts +61 -35
- package/dist/mixer.js +64 -169
- package/dist/motion.d.ts +19 -106
- package/dist/motion.js +60 -13
- package/dist/motions.d.ts +62 -150
- package/dist/motions.js +57 -369
- package/dist/move.js +24 -1
- package/dist/moved.d.ts +1 -1
- package/dist/moved.js +16 -7
- package/dist/named.d.ts +0 -1
- package/dist/named.js +20 -2
- package/dist/numbers.d.ts +2 -0
- package/dist/numbers.js +4 -0
- package/dist/owed.d.ts +2 -0
- package/dist/owed.js +4 -0
- package/dist/pack.d.ts +3 -1
- package/dist/pack.js +4 -3
- package/dist/patch.d.ts +7 -3
- package/dist/patch.js +6 -2
- package/dist/places.d.ts +53 -0
- package/dist/places.js +171 -0
- package/dist/plot.d.ts +12 -0
- package/dist/plot.js +52 -0
- package/dist/project.d.ts +4 -4
- package/dist/project.js +9 -211
- package/dist/pull.js +11 -8
- package/dist/qualify.js +84 -21
- package/dist/reading.d.ts +6 -0
- package/dist/reading.js +5 -0
- package/dist/record.d.ts +5 -1
- package/dist/record.js +4 -2
- package/dist/relink.d.ts +1 -1
- package/dist/restored.d.ts +2 -2
- package/dist/restored.js +1 -1
- package/dist/rests.d.ts +9 -0
- package/dist/rests.js +76 -0
- package/dist/revive.d.ts +3 -2
- package/dist/revive.js +2 -2
- package/dist/{locus.d.ts → role.d.ts} +10 -9
- package/dist/{locus.js → role.js} +3 -3
- package/dist/roles.d.ts +10 -0
- package/dist/roles.js +158 -0
- package/dist/roster.js +3 -3
- package/dist/rotation.d.ts +1 -1
- package/dist/rotation.js +1 -1
- package/dist/rows.js +1 -1
- package/dist/sample.d.ts +2 -2
- package/dist/sample.js +33 -7
- package/dist/seek.js +13 -5
- package/dist/setting.d.ts +27 -0
- package/dist/setting.js +55 -0
- package/dist/shared.d.ts +1 -1
- package/dist/shared.js +1 -1
- package/dist/signals.d.ts +64 -32
- package/dist/signals.js +20 -18
- package/dist/stack.d.ts +5 -5
- package/dist/stack.js +5 -5
- package/dist/standing.d.ts +2 -1
- package/dist/standing.js +3 -2
- package/dist/store.d.ts +9 -0
- package/dist/store.js +24 -0
- package/dist/strays.d.ts +2 -1
- package/dist/strays.js +21 -14
- package/dist/stretch.d.ts +112 -0
- package/dist/stretch.js +9 -0
- package/dist/subject.d.ts +142 -0
- package/dist/subject.js +1 -0
- package/dist/tape.d.ts +9 -5
- package/dist/tape.js +5 -1
- package/dist/then.d.ts +9 -0
- package/dist/then.js +57 -0
- package/dist/ticker.d.ts +4 -4
- package/dist/transport.d.ts +0 -8
- package/dist/transport.js +0 -4
- package/dist/turns.d.ts +4 -3
- package/dist/turns.js +4 -3
- package/dist/types/arc.d.ts +12 -11
- package/dist/types/channel.d.ts +12 -8
- package/dist/types/history.d.ts +35 -19
- package/dist/types/mix.d.ts +222 -161
- package/dist/types/motion.d.ts +151 -0
- package/dist/types/motion.js +1 -0
- package/dist/types/patch.d.ts +69 -34
- package/dist/types/place.d.ts +51 -36
- package/dist/types/transport.d.ts +20 -18
- package/dist/types/voice.d.ts +145 -72
- package/dist/types/watch.d.ts +88 -40
- package/dist/types.d.ts +1 -0
- package/dist/voice.d.ts +9 -141
- package/dist/voice.js +30 -79
- package/dist/warn.d.ts +2 -0
- package/dist/warn.js +1 -1
- package/dist/watch.d.ts +2 -2
- package/dist/watch.js +5 -3
- package/dist/wave.d.ts +4 -3
- package/dist/wave.js +3 -2
- package/dist/weigh.d.ts +7 -1
- package/dist/weigh.js +27 -0
- package/docs/schema.html +223 -37
- package/package.json +6 -2
package/dist/mixer.d.ts
CHANGED
|
@@ -1,31 +1,40 @@
|
|
|
1
1
|
import { type Arc } from './arcs.js';
|
|
2
|
+
import { around } from './around.js';
|
|
2
3
|
import { blended, laneRead, shareKept } from './blend.js';
|
|
3
4
|
import type { Book } from './book.js';
|
|
4
5
|
import { aims, chain, linkable, relink } from './chain.js';
|
|
5
6
|
import { type LerpInto } from './channels.js';
|
|
6
7
|
import type { Column } from './columns.js';
|
|
8
|
+
import { baseFor, contribution, isRest, keyed, read, slopeFor, tick } from './contribution.js';
|
|
7
9
|
import { DepartedIndex } from './departed.js';
|
|
8
|
-
import
|
|
10
|
+
import { drop, forgetIn, recordDrop, releaseIn } from './drop.js';
|
|
11
|
+
import { DueQueue } from './due.js';
|
|
9
12
|
import { parting } from './fade.js';
|
|
10
|
-
import { apply,
|
|
13
|
+
import { apply, clamp, fold, foldDetour, folded, foldSharers, foldWith, type Key, linked, owedBy, passes, shared } from './fold.js';
|
|
11
14
|
import { GoneIndex } from './gone.js';
|
|
12
15
|
import type { HandleHost } from './handle.js';
|
|
13
16
|
import { held, shownOf, sinceOf, unreachedOf } from './held.js';
|
|
14
17
|
import { Lanes } from './lanes.js';
|
|
15
|
-
import {
|
|
16
|
-
import type { MotionOwner, Motions } from './motions.js';
|
|
18
|
+
import type { Motions } from './motions.js';
|
|
17
19
|
import type { Pace } from './pace.js';
|
|
18
20
|
import { Keys } from './paging.js';
|
|
21
|
+
import type { Places } from './places.js';
|
|
22
|
+
import { moved, place, plot, put } from './plot.js';
|
|
19
23
|
import { keep } from './pull.js';
|
|
20
24
|
import { Steps } from './relink.js';
|
|
25
|
+
import { atRest, restful, rests, restsKey, restsLaned, still } from './rests.js';
|
|
21
26
|
import { Outs } from './revive.js';
|
|
27
|
+
import { foldRole, type RoleScratch } from './role.js';
|
|
28
|
+
import { foldRoles } from './roles.js';
|
|
22
29
|
import { ScoreIndex } from './scored.js';
|
|
23
30
|
import { Fitting } from './spans.js';
|
|
24
31
|
import { Store } from './store.js';
|
|
32
|
+
import type { MotionOwner } from './stretch.js';
|
|
33
|
+
import type { Subject } from './subject.js';
|
|
25
34
|
import { type Announced, Transport } from './transport.js';
|
|
26
35
|
import type { ArcHandle, ArcSpec, BlendMember, Booker, BookOptions, Channel, Columns, Engine, Handle, Kit, Marked, Mix, MixOptions, OwnerSpec, Patch, Projection, Sent, Signal, SpanHandle, SpanSpec, Tape, VoiceSpec } from './types.js';
|
|
27
|
-
import { type
|
|
28
|
-
import { base, capped, fadeOf, horizonFor, ownedBy, ownerBase, prime, weigh, weighOwned } from './weigh.js';
|
|
36
|
+
import { type Voice } from './voice.js';
|
|
37
|
+
import { base, capped, fadeOf, horizonFor, ownedBy, ownerBase, prime, primeLaned, weigh, weighOwned } from './weigh.js';
|
|
29
38
|
/**
|
|
30
39
|
* What a mix takes where its options say nothing. Not exported from the package: the suite turns
|
|
31
40
|
* `lanes` off to run every test on the general path, which is what makes each one an equivalence check.
|
|
@@ -67,7 +76,7 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
67
76
|
fields: Record<string, unknown>;
|
|
68
77
|
} | undefined;
|
|
69
78
|
/** Each subject's last two poses and when they were probed, for `from: 'current'`. */
|
|
70
|
-
|
|
79
|
+
lastPoses: Store<I, {
|
|
71
80
|
pose: O;
|
|
72
81
|
at: number;
|
|
73
82
|
prev: O | undefined;
|
|
@@ -91,7 +100,7 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
91
100
|
/** The pose `pull` folds a subject into where it cannot read straight from the lanes. */
|
|
92
101
|
scratch: O | undefined;
|
|
93
102
|
/** Live voices by the earliest mix time `moveTo` would change each, a binary heap. */
|
|
94
|
-
due:
|
|
103
|
+
due: DueQueue<I, O>;
|
|
95
104
|
/** Voices retired since `moveTo` last pruned them, in the order they retired. */
|
|
96
105
|
retired: Voice<I, O>[];
|
|
97
106
|
/** Visit every voice each sync, as before the due queue; for tests that compare the two. */
|
|
@@ -114,6 +123,13 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
114
123
|
reducedNow: boolean;
|
|
115
124
|
/** Something was changed since the last sync, so the next frame may differ from this one. */
|
|
116
125
|
stirred: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* The host read `inert` as true since the last sync, so its frame loop may be asleep until a
|
|
128
|
+
* change wakes it; a host that never asks keeps no loop asleep on it.
|
|
129
|
+
*/
|
|
130
|
+
asleep: boolean;
|
|
131
|
+
/** Some voice cued while the mix slept waits for the next sync to set its start. */
|
|
132
|
+
waking: boolean;
|
|
117
133
|
/** Counts the changes `stir` records, which a frame's record of a probe is current only before. */
|
|
118
134
|
stirs: number;
|
|
119
135
|
syncing: boolean;
|
|
@@ -128,6 +144,8 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
128
144
|
*/
|
|
129
145
|
chains: Store<I, Subject<unknown>>;
|
|
130
146
|
version: number;
|
|
147
|
+
/** The positions `plot` gave, which a voice's `within` reads: see `bound.ts`. */
|
|
148
|
+
places: Places<I> | null;
|
|
131
149
|
/** What `prime` reads its clock, voice time and pass from: see `Primed`. */
|
|
132
150
|
readonly primed: Float64Array<ArrayBuffer>;
|
|
133
151
|
readonly steps: Steps<Voice<I, O>, I>;
|
|
@@ -159,8 +177,10 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
159
177
|
unshared: boolean;
|
|
160
178
|
/** 0 where a fold is a walk of the chain: see `detour` in `everyone.ts`. */
|
|
161
179
|
detours: number;
|
|
162
|
-
/** How many voices in the list carry a
|
|
163
|
-
|
|
180
|
+
/** How many voices in the list carry a role; with none, a fold allocates nothing. */
|
|
181
|
+
roleVoices: number;
|
|
182
|
+
/** The tags the mix's options declare roles. */
|
|
183
|
+
readonly roleTags: readonly string[] | undefined;
|
|
164
184
|
/** What every motion patch it plays asks for its voice's time, holding this mix weakly. */
|
|
165
185
|
owner: MotionOwner | null;
|
|
166
186
|
/** How many voices in the list are anchored, so a sync with none skips placing them. */
|
|
@@ -184,9 +204,9 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
184
204
|
readonly lerpsInto: (LerpInto | undefined)[];
|
|
185
205
|
/** By slot, a stock scalar channel's arithmetic, which a fold applies without calling the channel. */
|
|
186
206
|
readonly scalars: ('sum' | 'mul' | 'max' | undefined)[];
|
|
187
|
-
/** What a fold with a
|
|
188
|
-
readonly
|
|
189
|
-
|
|
207
|
+
/** What a fold with a role in play gathers into, one per depth of folds under way. */
|
|
208
|
+
readonly roleScratch: RoleScratch<I, O>[];
|
|
209
|
+
roleDepth: number;
|
|
190
210
|
readonly slotOf: Map<string, number>;
|
|
191
211
|
lanes: Lanes<I, O> | null;
|
|
192
212
|
handles: HandleHost<I, O> | null;
|
|
@@ -202,6 +222,7 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
202
222
|
keys: Keys | null;
|
|
203
223
|
/** With a history store, the voices it paged out whose handles are still held; null without one. */
|
|
204
224
|
outs: Outs | null;
|
|
225
|
+
readonly pose: () => O;
|
|
205
226
|
constructor(kit: Kit<O>, opts: MixOptions,
|
|
206
227
|
/** The lanes an entry was built with; null in one that leaves them out. */
|
|
207
228
|
lanesOf: typeof Lanes | null);
|
|
@@ -230,7 +251,7 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
230
251
|
off: number;
|
|
231
252
|
};
|
|
232
253
|
cue(spec: VoiceSpec<I, O>): Handle<I>;
|
|
233
|
-
blend(members: readonly (Patch<I, O, unknown> | BlendMember<I, O>)[], by: Signal<I>, spec?: Omit<VoiceSpec<I, O>, 'patch' | 'weight' | 'locus'>): Handle<I>[];
|
|
254
|
+
blend(members: readonly (Patch<I, O, unknown> | BlendMember<I, O>)[], by: Signal<I>, spec?: Omit<VoiceSpec<I, O>, 'patch' | 'weight' | 'role' | 'locus' | 'within'>): Handle<I>[];
|
|
234
255
|
owns(spec: OwnerSpec<I>): Handle<I>;
|
|
235
256
|
span(spec: SpanSpec<I>): SpanHandle<I>;
|
|
236
257
|
arc(spec: ArcSpec<I, O>): ArcHandle<I>;
|
|
@@ -253,8 +274,6 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
253
274
|
/** Throws for a mix taken off its transport. */
|
|
254
275
|
attached(): void;
|
|
255
276
|
marks(from: number, to: number): Marked[];
|
|
256
|
-
atRest(subject: I): boolean;
|
|
257
|
-
rests(pose: O): boolean;
|
|
258
277
|
rebase(): void;
|
|
259
278
|
voices(tag?: string): Handle<I>[];
|
|
260
279
|
get live(): boolean;
|
|
@@ -262,17 +281,10 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
262
281
|
get rate(): number;
|
|
263
282
|
set rate(r: number);
|
|
264
283
|
ramp(rate: number, over: number): void;
|
|
265
|
-
/** Whether a voice will change no pose from `now` on, short of a change made to it. */
|
|
266
|
-
still(voice: Voice<I, O>, now: number): boolean;
|
|
267
284
|
close(): void;
|
|
268
285
|
mute(opts?: {
|
|
269
286
|
over?: number;
|
|
270
287
|
}): void;
|
|
271
|
-
drop(subject: I): void;
|
|
272
|
-
/** Lets `voice` go of a dropped subject. Methods rather than closures, so a drop makes neither. */
|
|
273
|
-
private forgetIn;
|
|
274
|
-
private releaseIn;
|
|
275
|
-
private recordDrop;
|
|
276
288
|
touch(subject?: I): void;
|
|
277
289
|
drain<E = unknown>(tag?: string): Sent<I, E>[];
|
|
278
290
|
/** Voices whose stop 0 is mid-computation, so a fold for one cannot re-enter itself. */
|
|
@@ -284,15 +296,13 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
284
296
|
*/
|
|
285
297
|
restStamps: Store<I, number> | null;
|
|
286
298
|
/** What a probe's record of rest is good for: moved by a new frame, version, relink, or stir. */
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
299
|
+
restsEpoch: number;
|
|
300
|
+
restsFrame: number;
|
|
301
|
+
restsVersion: number;
|
|
302
|
+
restsRelinks: number;
|
|
303
|
+
restsStirs: number;
|
|
292
304
|
/** The pose `atRest` folds into where no probe this frame answers. */
|
|
293
|
-
|
|
294
|
-
private restsLaned;
|
|
295
|
-
private restsKey;
|
|
305
|
+
restScratch: O | undefined;
|
|
296
306
|
}
|
|
297
307
|
declare const methods: {
|
|
298
308
|
fold: typeof fold;
|
|
@@ -300,7 +310,7 @@ declare const methods: {
|
|
|
300
310
|
linked: typeof linked;
|
|
301
311
|
foldWith: typeof foldWith;
|
|
302
312
|
owedBy: typeof owedBy;
|
|
303
|
-
|
|
313
|
+
foldRoles: typeof foldRoles;
|
|
304
314
|
foldDetour: typeof foldDetour;
|
|
305
315
|
foldSharers: typeof foldSharers;
|
|
306
316
|
shared: typeof shared;
|
|
@@ -315,6 +325,7 @@ declare const methods: {
|
|
|
315
325
|
baseFor: typeof baseFor;
|
|
316
326
|
slopeFor: typeof slopeFor;
|
|
317
327
|
prime: typeof prime;
|
|
328
|
+
primeLaned: typeof primeLaned;
|
|
318
329
|
capped: typeof capped;
|
|
319
330
|
horizonFor: typeof horizonFor;
|
|
320
331
|
weigh: typeof weigh;
|
|
@@ -336,7 +347,22 @@ declare const methods: {
|
|
|
336
347
|
sinceOf: typeof sinceOf;
|
|
337
348
|
shownOf: typeof shownOf;
|
|
338
349
|
keep: typeof keep;
|
|
339
|
-
|
|
350
|
+
foldRole: typeof foldRole;
|
|
351
|
+
atRest: typeof atRest;
|
|
352
|
+
rests: typeof rests;
|
|
353
|
+
restful: typeof restful;
|
|
354
|
+
still: typeof still;
|
|
355
|
+
restsLaned: typeof restsLaned;
|
|
356
|
+
restsKey: typeof restsKey;
|
|
357
|
+
plot: typeof plot;
|
|
358
|
+
place: typeof place;
|
|
359
|
+
moved: typeof moved;
|
|
360
|
+
put: typeof put;
|
|
361
|
+
around: typeof around;
|
|
362
|
+
drop: typeof drop;
|
|
363
|
+
forgetIn: typeof forgetIn;
|
|
364
|
+
releaseIn: typeof releaseIn;
|
|
365
|
+
recordDrop: typeof recordDrop;
|
|
340
366
|
};
|
|
341
367
|
type Methods = typeof methods;
|
|
342
368
|
export interface Mixer<I, O> extends Methods {
|
|
@@ -344,13 +370,13 @@ export interface Mixer<I, O> extends Methods {
|
|
|
344
370
|
/** Makes a mix the host asked for, with the registry's history where it names none, and lists it there. */
|
|
345
371
|
export declare function made<I, O, H>(kit: Kit<O>, opts: MixOptions<H>, lanes: typeof Lanes | null): Mix<I, O, H>;
|
|
346
372
|
/**
|
|
347
|
-
* The
|
|
373
|
+
* The engine that ships, running every form on the CPU. It probes per subject on demand.
|
|
348
374
|
*
|
|
349
375
|
* @category engine
|
|
350
376
|
*/
|
|
351
377
|
export declare const mixer: Engine;
|
|
352
378
|
/**
|
|
353
|
-
* Makes a mix over a kit
|
|
379
|
+
* Makes a mix over a kit. It runs on the engine the options name, or the stock one.
|
|
354
380
|
*
|
|
355
381
|
* @category mix
|
|
356
382
|
*/
|
package/dist/mixer.js
CHANGED
|
@@ -1,35 +1,42 @@
|
|
|
1
1
|
import { cueArc } from './arcs.js';
|
|
2
|
+
import { around } from './around.js';
|
|
3
|
+
import { blanks } from './blank.js';
|
|
2
4
|
import { blended, blendOf, laneRead, shareKept } from './blend.js';
|
|
3
|
-
import { aims, chain,
|
|
5
|
+
import { aims, chain, linkable, relink } from './chain.js';
|
|
4
6
|
import { lerpInto, STOCK_BAND, scalarOp } from './channels.js';
|
|
5
|
-
import {
|
|
7
|
+
import { baseFor, contribution, isRest, keyed, read, slopeFor, tick } from './contribution.js';
|
|
8
|
+
import { cue, roleTags } from './cue.js';
|
|
6
9
|
import { DepartedIndex } from './departed.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
+
import { drop, forgetIn, recordDrop, releaseIn } from './drop.js';
|
|
11
|
+
import { DueQueue } from './due.js';
|
|
12
|
+
import { beginFade, parting } from './fade.js';
|
|
13
|
+
import { apply, clamp, fold, foldDetour, folded, foldSharers, foldWith, linked, owedBy, passes, shared, } from './fold.js';
|
|
14
|
+
import { GoneIndex } from './gone.js';
|
|
10
15
|
import { held, shownOf, sinceOf, unreachedOf } from './held.js';
|
|
11
|
-
import { releasing } from './history.js';
|
|
12
16
|
import { book, laneHost } from './hosts.js';
|
|
13
17
|
import { Lanes } from './lanes.js';
|
|
14
|
-
import { foldLocus } from './locus.js';
|
|
15
18
|
import { listed } from './marks.js';
|
|
16
19
|
import { nextFrame } from './move.js';
|
|
17
20
|
import { ownerPatch } from './owner.js';
|
|
18
21
|
import { Keys } from './paging.js';
|
|
22
|
+
import { moved, place, plot, put } from './plot.js';
|
|
19
23
|
import { projectAll } from './project.js';
|
|
20
24
|
import { keep, pull } from './pull.js';
|
|
21
25
|
import { Steps } from './relink.js';
|
|
26
|
+
import { atRest, restful, rests, restsKey, restsLaned, still } from './rests.js';
|
|
22
27
|
import { Outs } from './revive.js';
|
|
28
|
+
import { foldRole } from './role.js';
|
|
29
|
+
import { foldRoles } from './roles.js';
|
|
23
30
|
import { ScoreIndex } from './scored.js';
|
|
24
31
|
import { seek } from './seek.js';
|
|
25
32
|
import { Fitting, refit } from './spans.js';
|
|
26
|
-
import {
|
|
27
|
-
import { record
|
|
33
|
+
import { Store } from './store.js';
|
|
34
|
+
import { record } from './tape.js';
|
|
28
35
|
import { touch } from './touch.js';
|
|
29
36
|
import { announce, Transport } from './transport.js';
|
|
30
37
|
import { none } from './voice.js';
|
|
31
38
|
import { gave, historyFor, register, unregister } from './watch.js';
|
|
32
|
-
import { base, capped, fadeOf, horizonFor, ownedBy, ownerBase, prime, weigh, weighOwned, } from './weigh.js';
|
|
39
|
+
import { base, capped, fadeOf, horizonFor, ownedBy, ownerBase, prime, primeLaned, weigh, weighOwned, } from './weigh.js';
|
|
33
40
|
/**
|
|
34
41
|
* What a mix takes where its options say nothing. Not exported from the package: the suite turns
|
|
35
42
|
* `lanes` off to run every test on the general path, which is what makes each one an equivalence check.
|
|
@@ -63,7 +70,7 @@ export class Mixer {
|
|
|
63
70
|
hostLog = [];
|
|
64
71
|
hostThen;
|
|
65
72
|
/** Each subject's last two poses and when they were probed, for `from: 'current'`. */
|
|
66
|
-
|
|
73
|
+
lastPoses = new Store();
|
|
67
74
|
/** The clock this mix plays on, which also holds its tape and the marks announced on it. */
|
|
68
75
|
transport;
|
|
69
76
|
/** Its place among the mixes on its transport, in the order they joined. */
|
|
@@ -82,7 +89,7 @@ export class Mixer {
|
|
|
82
89
|
/** The pose `pull` folds a subject into where it cannot read straight from the lanes. */
|
|
83
90
|
scratch;
|
|
84
91
|
/** Live voices by the earliest mix time `moveTo` would change each, a binary heap. */
|
|
85
|
-
due =
|
|
92
|
+
due = new DueQueue();
|
|
86
93
|
/** Voices retired since `moveTo` last pruned them, in the order they retired. */
|
|
87
94
|
retired = [];
|
|
88
95
|
/** Visit every voice each sync, as before the due queue; for tests that compare the two. */
|
|
@@ -105,6 +112,13 @@ export class Mixer {
|
|
|
105
112
|
reducedNow = false;
|
|
106
113
|
/** Something was changed since the last sync, so the next frame may differ from this one. */
|
|
107
114
|
stirred = false;
|
|
115
|
+
/**
|
|
116
|
+
* The host read `inert` as true since the last sync, so its frame loop may be asleep until a
|
|
117
|
+
* change wakes it; a host that never asks keeps no loop asleep on it.
|
|
118
|
+
*/
|
|
119
|
+
asleep = false;
|
|
120
|
+
/** Some voice cued while the mix slept waits for the next sync to set its start. */
|
|
121
|
+
waking = false;
|
|
108
122
|
/** Counts the changes `stir` records, which a frame's record of a probe is current only before. */
|
|
109
123
|
stirs = 0;
|
|
110
124
|
syncing = false;
|
|
@@ -144,6 +158,8 @@ export class Mixer {
|
|
|
144
158
|
*/
|
|
145
159
|
chains = new Store();
|
|
146
160
|
version = 0;
|
|
161
|
+
/** The positions `plot` gave, which a voice's `within` reads: see `bound.ts`. */
|
|
162
|
+
places = null;
|
|
147
163
|
/** What `prime` reads its clock, voice time and pass from: see `Primed`. */
|
|
148
164
|
primed = new Float64Array(3 /* Primed.SIZE */);
|
|
149
165
|
steps = new Steps();
|
|
@@ -175,8 +191,10 @@ export class Mixer {
|
|
|
175
191
|
unshared = false;
|
|
176
192
|
/** 0 where a fold is a walk of the chain: see `detour` in `everyone.ts`. */
|
|
177
193
|
detours = 0;
|
|
178
|
-
/** How many voices in the list carry a
|
|
179
|
-
|
|
194
|
+
/** How many voices in the list carry a role; with none, a fold allocates nothing. */
|
|
195
|
+
roleVoices = 0;
|
|
196
|
+
/** The tags the mix's options declare roles. */
|
|
197
|
+
roleTags;
|
|
180
198
|
/** What every motion patch it plays asks for its voice's time, holding this mix weakly. */
|
|
181
199
|
owner = null;
|
|
182
200
|
/** How many voices in the list are anchored, so a sync with none skips placing them. */
|
|
@@ -211,9 +229,9 @@ export class Mixer {
|
|
|
211
229
|
lerpsInto;
|
|
212
230
|
/** By slot, a stock scalar channel's arithmetic, which a fold applies without calling the channel. */
|
|
213
231
|
scalars;
|
|
214
|
-
/** What a fold with a
|
|
215
|
-
|
|
216
|
-
|
|
232
|
+
/** What a fold with a role in play gathers into, one per depth of folds under way. */
|
|
233
|
+
roleScratch = [];
|
|
234
|
+
roleDepth = 0;
|
|
217
235
|
slotOf = new Map();
|
|
218
236
|
lanes;
|
|
219
237
|
handles = null;
|
|
@@ -229,6 +247,7 @@ export class Mixer {
|
|
|
229
247
|
keys = null;
|
|
230
248
|
/** With a history store, the voices it paged out whose handles are still held; null without one. */
|
|
231
249
|
outs = null;
|
|
250
|
+
pose;
|
|
232
251
|
constructor(kit, opts,
|
|
233
252
|
/** The lanes an entry was built with; null in one that leaves them out. */
|
|
234
253
|
lanesOf) {
|
|
@@ -239,6 +258,7 @@ export class Mixer {
|
|
|
239
258
|
this.channels = this.names.map((k) => kit[k]);
|
|
240
259
|
this.bounded = this.channels.flatMap((c, i) => (c.bounds ? [i] : []));
|
|
241
260
|
this.lerpsInto = this.channels.map((c) => lerpInto(c));
|
|
261
|
+
this.pose = blanks(this.names, this.channels);
|
|
242
262
|
this.scalars = this.channels.map((c) => scalarOp(c));
|
|
243
263
|
this.names.forEach((k, i) => {
|
|
244
264
|
this.slotOf.set(k, i);
|
|
@@ -248,6 +268,7 @@ export class Mixer {
|
|
|
248
268
|
this.lanes =
|
|
249
269
|
lanesOf !== null && (opts.lanes ?? defaults.lanes) ? new lanesOf(laneHost(this)) : null;
|
|
250
270
|
this.name = opts.name;
|
|
271
|
+
this.roleTags = roleTags(opts);
|
|
251
272
|
const shared = opts.transport;
|
|
252
273
|
if (shared !== undefined) {
|
|
253
274
|
if (opts.history !== undefined)
|
|
@@ -338,14 +359,14 @@ export class Mixer {
|
|
|
338
359
|
return cue(this, spec);
|
|
339
360
|
}
|
|
340
361
|
blend(members, by, spec = {}) {
|
|
341
|
-
const
|
|
362
|
+
const role = `blend:${this.nextId}`;
|
|
342
363
|
const of = blendOf(by, members.length - 1);
|
|
343
364
|
return members.map((member, i) => {
|
|
344
365
|
const own = {
|
|
345
366
|
...spec,
|
|
346
367
|
patch: member,
|
|
347
368
|
weight: by,
|
|
348
|
-
|
|
369
|
+
role,
|
|
349
370
|
};
|
|
350
371
|
if ('patch' in member) {
|
|
351
372
|
own.patch = member.patch;
|
|
@@ -426,38 +447,6 @@ export class Mixer {
|
|
|
426
447
|
marks(from, to) {
|
|
427
448
|
return listed(this, from, to).map(({ order: _, ...m }) => m);
|
|
428
449
|
}
|
|
429
|
-
atRest(subject) {
|
|
430
|
-
this.restStamps ??= new Store();
|
|
431
|
-
const head = this.linked(subject);
|
|
432
|
-
const laned = this.linkedLaned;
|
|
433
|
-
const lanes = this.lanes;
|
|
434
|
-
// Every voice on lanes and nothing to clamp: the pose a fold would make is the lanes' values.
|
|
435
|
-
if (laned && this.restsLaned()) {
|
|
436
|
-
const slot = head.slot;
|
|
437
|
-
if (!lanes.owes(slot))
|
|
438
|
-
return lanes.rests(slot);
|
|
439
|
-
}
|
|
440
|
-
// A probe this frame answers for the pose it gave the host.
|
|
441
|
-
const since = (this.restStamps.get(subject) ?? Number.NaN) - 2 * this.restsKey();
|
|
442
|
-
if (since >= 0)
|
|
443
|
-
return since === 1;
|
|
444
|
-
this.restScratch ??= {};
|
|
445
|
-
const pose = this.foldWith(subject, this.restScratch, head, laned, true);
|
|
446
|
-
return this.rests((this.bounded.length === 0 ? pose : this.clamp(pose)));
|
|
447
|
-
}
|
|
448
|
-
rests(pose) {
|
|
449
|
-
for (let i = 0; i < this.names.length; i++) {
|
|
450
|
-
const channel = this.channels[i];
|
|
451
|
-
const value = pose[this.names[i]];
|
|
452
|
-
if (channel.rest === undefined) {
|
|
453
|
-
if (value !== undefined)
|
|
454
|
-
return false;
|
|
455
|
-
}
|
|
456
|
-
else if (!near(value, channel.rest))
|
|
457
|
-
return false;
|
|
458
|
-
}
|
|
459
|
-
return true;
|
|
460
|
-
}
|
|
461
450
|
rebase() {
|
|
462
451
|
this.own('rebase').rebase();
|
|
463
452
|
}
|
|
@@ -474,14 +463,10 @@ export class Mixer {
|
|
|
474
463
|
get inert() {
|
|
475
464
|
if (this.stirred)
|
|
476
465
|
return false;
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
(v.state !== 'pending' &&
|
|
482
|
-
typeof v.spec.weight !== 'function' &&
|
|
483
|
-
v.spec.anchor === undefined));
|
|
484
|
-
return this.cued.every((v) => this.still(v, this.now));
|
|
466
|
+
const inert = this.restful();
|
|
467
|
+
if (inert && !Number.isNaN(this.now))
|
|
468
|
+
this.asleep = true;
|
|
469
|
+
return inert;
|
|
485
470
|
}
|
|
486
471
|
get rate() {
|
|
487
472
|
return this.transport.rate;
|
|
@@ -492,22 +477,6 @@ export class Mixer {
|
|
|
492
477
|
ramp(rate, over) {
|
|
493
478
|
this.own('ramp').ramp(rate, over);
|
|
494
479
|
}
|
|
495
|
-
/** Whether a voice will change no pose from `now` on, short of a change made to it. */
|
|
496
|
-
still(voice, now) {
|
|
497
|
-
if (voice.state === 'done')
|
|
498
|
-
return true;
|
|
499
|
-
if (voice.state !== 'frozen' && voice.state !== 'live')
|
|
500
|
-
return false;
|
|
501
|
-
if (typeof voice.spec.weight === 'function' || voice.parts !== null)
|
|
502
|
-
return false;
|
|
503
|
-
const fadeIn = this.reducedNow ? 0 : (voice.fade.in ?? 0);
|
|
504
|
-
if (fadeIn > 0 && now - this.sinceOf(voice, voice.latest) < fadeIn)
|
|
505
|
-
return false;
|
|
506
|
-
if (voice.state === 'frozen' || voice.holding !== null)
|
|
507
|
-
return true;
|
|
508
|
-
const motion = voice.motion;
|
|
509
|
-
return motion !== undefined && voice.elapsedAt(now) >= voice.latest && motion.landed();
|
|
510
|
-
}
|
|
511
480
|
close() {
|
|
512
481
|
unregister(this);
|
|
513
482
|
}
|
|
@@ -518,80 +487,6 @@ export class Mixer {
|
|
|
518
487
|
}
|
|
519
488
|
record(this, 'mute', (stage) => stage.mix(this)?.mute(opts));
|
|
520
489
|
}
|
|
521
|
-
drop(subject) {
|
|
522
|
-
this.frame = nextFrame();
|
|
523
|
-
const head = headOf(this, subject);
|
|
524
|
-
// Nothing that kept this head, such as `pull`'s remembered list, may take it as current again.
|
|
525
|
-
if (head !== undefined)
|
|
526
|
-
unlink(this, head);
|
|
527
|
-
// A number a seek carried over is released even where its chain is not linked since.
|
|
528
|
-
const slot = this.chains.get(subject)?.slot ?? -1;
|
|
529
|
-
if (slot >= 0 && this.lanes !== null)
|
|
530
|
-
this.lanes.release(slot);
|
|
531
|
-
// A read ahead's copy reads the live mix's poses, and so hides one where the mix deletes it.
|
|
532
|
-
if (this.projecting && !(this.pose instanceof Masked))
|
|
533
|
-
this.pose = new Masked(this.pose);
|
|
534
|
-
this.pose.delete(subject);
|
|
535
|
-
this.restStamps?.delete(subject);
|
|
536
|
-
this.chains.delete(subject);
|
|
537
|
-
this.stir();
|
|
538
|
-
// A record of it is only in a voice over every subject, one naming it, or one gone; a ramp out
|
|
539
|
-
// of a voice that does not name it is in `parters`, and a patch's own state in `motions`.
|
|
540
|
-
const kept = releasing(this);
|
|
541
|
-
for (const voice of this.general)
|
|
542
|
-
this.forgetIn(voice, subject, kept);
|
|
543
|
-
const named = this.named.get(subject);
|
|
544
|
-
if (named !== undefined)
|
|
545
|
-
for (const voice of [...named])
|
|
546
|
-
this.forgetIn(voice, subject, kept);
|
|
547
|
-
const gone = goneIndex(this);
|
|
548
|
-
for (const voice of gone.general)
|
|
549
|
-
this.forgetIn(voice, subject, kept);
|
|
550
|
-
const goneNaming = gone.named.get(subject);
|
|
551
|
-
if (goneNaming !== undefined)
|
|
552
|
-
for (const voice of goneNaming)
|
|
553
|
-
this.forgetIn(voice, subject, kept);
|
|
554
|
-
if (this.owners !== null)
|
|
555
|
-
for (const voice of this.owners)
|
|
556
|
-
this.forgetIn(voice, subject, kept);
|
|
557
|
-
for (const voice of this.parters) {
|
|
558
|
-
this.forgetIn(voice, subject, kept);
|
|
559
|
-
if (voice.parts?.size === 0)
|
|
560
|
-
voice.parts = null;
|
|
561
|
-
if (voice.parted?.size === 0)
|
|
562
|
-
voice.parted = null;
|
|
563
|
-
if (voice.parts === null && voice.parted === null)
|
|
564
|
-
this.parters.delete(voice);
|
|
565
|
-
}
|
|
566
|
-
const strays = this.strays.get(subject);
|
|
567
|
-
if (strays !== undefined)
|
|
568
|
-
for (const motion of strays)
|
|
569
|
-
this.releaseIn(motion, subject, kept);
|
|
570
|
-
this.strays.delete(subject);
|
|
571
|
-
for (const motion of this.strayAll)
|
|
572
|
-
this.releaseIn(motion, subject, kept);
|
|
573
|
-
this.recordDrop(subject);
|
|
574
|
-
}
|
|
575
|
-
/** Lets `voice` go of a dropped subject. Methods rather than closures, so a drop makes neither. */
|
|
576
|
-
forgetIn(voice, subject, kept) {
|
|
577
|
-
leaveVoice(this, voice, subject);
|
|
578
|
-
voice.subjects.delete(subject);
|
|
579
|
-
if (voice.motion !== undefined)
|
|
580
|
-
this.releaseIn(voice.motion, subject, kept);
|
|
581
|
-
voice.parts?.delete(subject);
|
|
582
|
-
voice.parted?.delete(subject);
|
|
583
|
-
voice.blend?.of.reads.delete(subject);
|
|
584
|
-
}
|
|
585
|
-
// A motion patch's state is the live mix's alone: a read ahead cannot start a subject afresh in it.
|
|
586
|
-
releaseIn(motion, subject, kept) {
|
|
587
|
-
if (!this.projecting)
|
|
588
|
-
motion.release(subject, kept[0], kept[1], kept[2]);
|
|
589
|
-
else if (motion.holds(subject))
|
|
590
|
-
unplayable('a drop of a subject a motion patch holds');
|
|
591
|
-
}
|
|
592
|
-
recordDrop(subject) {
|
|
593
|
-
record(this, 'drop', (stage) => stage.mix(this)?.drop(subject));
|
|
594
|
-
}
|
|
595
490
|
touch(subject) {
|
|
596
491
|
this.attached();
|
|
597
492
|
touch(this, subject);
|
|
@@ -628,22 +523,6 @@ export class Mixer {
|
|
|
628
523
|
restsStirs = -1;
|
|
629
524
|
/** The pose `atRest` folds into where no probe this frame answers. */
|
|
630
525
|
restScratch;
|
|
631
|
-
restsLaned() {
|
|
632
|
-
return this.lanes.whole && this.bounded.length === 0;
|
|
633
|
-
}
|
|
634
|
-
restsKey() {
|
|
635
|
-
if (this.frame !== this.restsFrame ||
|
|
636
|
-
this.version !== this.restsVersion ||
|
|
637
|
-
this.relinks !== this.restsRelinks ||
|
|
638
|
-
this.stirs !== this.restsStirs) {
|
|
639
|
-
this.restsEpoch++;
|
|
640
|
-
this.restsFrame = this.frame;
|
|
641
|
-
this.restsVersion = this.version;
|
|
642
|
-
this.restsRelinks = this.relinks;
|
|
643
|
-
this.restsStirs = this.stirs;
|
|
644
|
-
}
|
|
645
|
-
return this.restsEpoch;
|
|
646
|
-
}
|
|
647
526
|
}
|
|
648
527
|
// The probe's hot path is methods, installed here from the modules that own them: as functions
|
|
649
528
|
// called directly they made probes and fills up to 9% slower (bench/ab.sh on teitou, 2026-10-05).
|
|
@@ -653,7 +532,7 @@ const methods = {
|
|
|
653
532
|
linked,
|
|
654
533
|
foldWith,
|
|
655
534
|
owedBy,
|
|
656
|
-
|
|
535
|
+
foldRoles,
|
|
657
536
|
foldDetour,
|
|
658
537
|
foldSharers,
|
|
659
538
|
shared,
|
|
@@ -668,6 +547,7 @@ const methods = {
|
|
|
668
547
|
baseFor,
|
|
669
548
|
slopeFor,
|
|
670
549
|
prime,
|
|
550
|
+
primeLaned,
|
|
671
551
|
capped,
|
|
672
552
|
horizonFor,
|
|
673
553
|
weigh,
|
|
@@ -689,7 +569,22 @@ const methods = {
|
|
|
689
569
|
sinceOf,
|
|
690
570
|
shownOf,
|
|
691
571
|
keep,
|
|
692
|
-
|
|
572
|
+
foldRole,
|
|
573
|
+
atRest,
|
|
574
|
+
rests,
|
|
575
|
+
restful,
|
|
576
|
+
still,
|
|
577
|
+
restsLaned,
|
|
578
|
+
restsKey,
|
|
579
|
+
plot,
|
|
580
|
+
place,
|
|
581
|
+
moved,
|
|
582
|
+
put,
|
|
583
|
+
around,
|
|
584
|
+
drop,
|
|
585
|
+
forgetIn,
|
|
586
|
+
releaseIn,
|
|
587
|
+
recordDrop,
|
|
693
588
|
};
|
|
694
589
|
for (const [name, value] of Object.entries(methods))
|
|
695
590
|
Object.defineProperty(Mixer.prototype, name, { value, writable: true, configurable: true });
|
|
@@ -711,7 +606,7 @@ export function made(kit, opts, lanes) {
|
|
|
711
606
|
return m;
|
|
712
607
|
}
|
|
713
608
|
/**
|
|
714
|
-
* The
|
|
609
|
+
* The engine that ships, running every form on the CPU. It probes per subject on demand.
|
|
715
610
|
*
|
|
716
611
|
* @category engine
|
|
717
612
|
*/
|
|
@@ -723,7 +618,7 @@ export const mixer = {
|
|
|
723
618
|
},
|
|
724
619
|
};
|
|
725
620
|
/**
|
|
726
|
-
* Makes a mix over a kit
|
|
621
|
+
* Makes a mix over a kit. It runs on the engine the options name, or the stock one.
|
|
727
622
|
*
|
|
728
623
|
* @category mix
|
|
729
624
|
*/
|