@msb235/blits 0.10.0 → 0.12.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.
Files changed (126) hide show
  1. package/CHANGELOG.md +248 -0
  2. package/README.md +15 -4
  3. package/dist/arcs.d.ts +40 -0
  4. package/dist/arcs.js +239 -0
  5. package/dist/blend.js +1 -5
  6. package/dist/book.d.ts +2 -0
  7. package/dist/book.js +27 -3
  8. package/dist/chain.d.ts +17 -1
  9. package/dist/chain.js +57 -15
  10. package/dist/channels.d.ts +2 -0
  11. package/dist/channels.js +12 -1
  12. package/dist/clock.d.ts +14 -0
  13. package/dist/clock.js +9 -1
  14. package/dist/clone.js +16 -4
  15. package/dist/columns.d.ts +4 -5
  16. package/dist/columns.js +11 -5
  17. package/dist/crowd.d.ts +1 -1
  18. package/dist/crowd.js +4 -1
  19. package/dist/cue.js +63 -7
  20. package/dist/departed.d.ts +8 -3
  21. package/dist/departed.js +76 -29
  22. package/dist/due.d.ts +4 -0
  23. package/dist/due.js +16 -3
  24. package/dist/easing.d.ts +12 -1
  25. package/dist/easing.js +7 -1
  26. package/dist/everyone.d.ts +14 -1
  27. package/dist/everyone.js +27 -2
  28. package/dist/fade.d.ts +12 -5
  29. package/dist/fade.js +57 -19
  30. package/dist/fill.js +16 -9
  31. package/dist/fit.d.ts +8 -1
  32. package/dist/fit.js +7 -3
  33. package/dist/fold.d.ts +1 -1
  34. package/dist/fold.js +112 -9
  35. package/dist/frames.d.ts +2 -0
  36. package/dist/frames.js +17 -0
  37. package/dist/gather.js +38 -7
  38. package/dist/handle.d.ts +7 -2
  39. package/dist/handle.js +28 -12
  40. package/dist/held.d.ts +13 -2
  41. package/dist/held.js +43 -9
  42. package/dist/history.d.ts +25 -2
  43. package/dist/history.js +163 -35
  44. package/dist/hosts.js +45 -17
  45. package/dist/index.d.ts +5 -2
  46. package/dist/index.js +3 -1
  47. package/dist/keyfill.js +3 -1
  48. package/dist/lane.d.ts +1 -1
  49. package/dist/lane.js +3 -1
  50. package/dist/lanes.d.ts +31 -7
  51. package/dist/lanes.js +57 -6
  52. package/dist/lean.d.ts +15 -0
  53. package/dist/lean.js +23 -0
  54. package/dist/leavings.d.ts +6 -1
  55. package/dist/leavings.js +16 -2
  56. package/dist/marks.d.ts +7 -3
  57. package/dist/marks.js +105 -27
  58. package/dist/meet.js +1 -0
  59. package/dist/mixer.d.ts +35 -6
  60. package/dist/mixer.js +113 -45
  61. package/dist/motion.d.ts +4 -1
  62. package/dist/motion.js +16 -2
  63. package/dist/motions.d.ts +4 -0
  64. package/dist/motions.js +45 -11
  65. package/dist/move.js +35 -12
  66. package/dist/numbers.d.ts +5 -1
  67. package/dist/numbers.js +4 -0
  68. package/dist/owner.d.ts +18 -2
  69. package/dist/owner.js +44 -3
  70. package/dist/pack.d.ts +1 -0
  71. package/dist/pack.js +3 -0
  72. package/dist/place.d.ts +8 -0
  73. package/dist/place.js +16 -8
  74. package/dist/placed.d.ts +19 -0
  75. package/dist/placed.js +54 -0
  76. package/dist/project.d.ts +5 -2
  77. package/dist/project.js +238 -34
  78. package/dist/pull.js +37 -8
  79. package/dist/qualify.d.ts +10 -0
  80. package/dist/qualify.js +60 -3
  81. package/dist/reading.d.ts +8 -1
  82. package/dist/reading.js +8 -1
  83. package/dist/record.d.ts +6 -0
  84. package/dist/record.js +2 -0
  85. package/dist/restored.d.ts +69 -17
  86. package/dist/restored.js +163 -50
  87. package/dist/revive.d.ts +6 -3
  88. package/dist/revive.js +11 -3
  89. package/dist/roster.js +2 -1
  90. package/dist/rows.js +15 -5
  91. package/dist/seek.d.ts +7 -2
  92. package/dist/seek.js +152 -43
  93. package/dist/shared.d.ts +5 -0
  94. package/dist/shared.js +5 -0
  95. package/dist/signals.d.ts +10 -0
  96. package/dist/signals.js +17 -0
  97. package/dist/spans.d.ts +5 -0
  98. package/dist/spans.js +75 -5
  99. package/dist/store.d.ts +13 -0
  100. package/dist/store.js +23 -0
  101. package/dist/strays.js +50 -2
  102. package/dist/tape.d.ts +29 -4
  103. package/dist/tape.js +49 -11
  104. package/dist/touch.js +3 -2
  105. package/dist/transport.d.ts +11 -2
  106. package/dist/transport.js +26 -10
  107. package/dist/types/arc.d.ts +55 -0
  108. package/dist/types/arc.js +1 -0
  109. package/dist/types/mix.d.ts +57 -14
  110. package/dist/types/patch.d.ts +5 -1
  111. package/dist/types/place.d.ts +11 -4
  112. package/dist/types/transport.d.ts +12 -3
  113. package/dist/types/voice.d.ts +72 -5
  114. package/dist/types/watch.d.ts +126 -0
  115. package/dist/types/watch.js +1 -0
  116. package/dist/types.d.ts +2 -0
  117. package/dist/unpage.d.ts +6 -1
  118. package/dist/unpage.js +34 -2
  119. package/dist/voice.d.ts +93 -16
  120. package/dist/voice.js +60 -3
  121. package/dist/watch.d.ts +26 -0
  122. package/dist/watch.js +441 -0
  123. package/dist/weigh.d.ts +13 -2
  124. package/dist/weigh.js +10 -3
  125. package/docs/schema.html +106 -38
  126. package/package.json +10 -4
@@ -3,7 +3,7 @@ import type { Motion, Value } from '../motion.js';
3
3
  import type { Described } from './history.js';
4
4
  import type { Doubt } from './mix.js';
5
5
  import type { Easing, Patch, Signal } from './patch.js';
6
- import type { Hit, Placement } from './place.js';
6
+ import type { Anchor, Hit, Placement } from './place.js';
7
7
  /**
8
8
  * A voice's own ramps in and out, in ms, and the curve both take.
9
9
  *
@@ -31,6 +31,15 @@ export interface SpanHints {
31
31
  ballast?: boolean;
32
32
  /** How hard its own length holds against the span's budget. Default `weak`. */
33
33
  priority?: Strength;
34
+ /**
35
+ * The soonest it may start: a time on the span's clock, or an anchor. The fit never places it
36
+ * sooner, and the children after it are laid out from where it starts. One already past when it is
37
+ * cued places it there, partway through. One whose anchor has no answer yet waits, and under `queue` or
38
+ * `stagger` so does every child after it.
39
+ */
40
+ earliest?: number | Anchor;
41
+ /** Where it plays among the span's children still to start: lower first, ties as cued. Default 0. */
42
+ rank?: number;
34
43
  }
35
44
  /**
36
45
  * What `cue` takes: a patch, and the clock, weight and reach it plays with.
@@ -81,10 +90,24 @@ export interface VoiceSpec<I, O, H = unknown> extends SpanHints {
81
90
  * so one cued backward with no `seek` has ended as it starts.
82
91
  */
83
92
  seek?: number;
93
+ /**
94
+ * The interval this voice's `step` runs at, in ms of mix time, in place of the mix's `stepMs`.
95
+ * 0 steps it once a frame by the frame's gap, whatever the mix sets. Default: the mix's.
96
+ */
97
+ stepMs?: number;
98
+ /**
99
+ * How a stateful subject first probed after its delay ran out starts stepping. `exact` steps it
100
+ * from that origin, in one step capped by `maxDt` or every `stepMs` interval since, so its state
101
+ * is the same however late the host looked. `fresh` starts it from the probe that first meets it,
102
+ * with fresh state and no catch-up, on the `stepMs` grid counted from the origin: cheaper for a
103
+ * subject met long after its voice started, and probe-dependent by design. A subject met on time,
104
+ * and a handle `seek`'s rebuild, step the same either way. Default: `exact`.
105
+ */
106
+ catchUp?: 'exact' | 'fresh';
84
107
  /**
85
108
  * true loops for good, false plays one pass, n plays n passes. A finite loop leaves when its
86
109
  * passes are done for the latest-staggered subject it has seen — over `fade.out` where one is
87
- * set, at once where none is — unless it freezes after. Default: true.
110
+ * set, at once where none is — unless it freezes after. Default: false.
88
111
  */
89
112
  loop?: boolean | number;
90
113
  /**
@@ -127,6 +150,14 @@ export interface VoiceSpec<I, O, H = unknown> extends SpanHints {
127
150
  * events are not known ahead, so they stay drain-only; these are the plan.
128
151
  */
129
152
  hits?: readonly Hit[];
153
+ /**
154
+ * Named marks inside the voice, beside its five, each at voice ms into a pass as a hit's `at` is:
155
+ * `{ drop: 340 }`. An anchor names one as it names the five, `{ of: 'lead', mark: 'drop' }`, and
156
+ * `marks` lists it and `book` books it under its name. Each is reached once: on the first pass
157
+ * that reaches it from where the voice starts, while its clock runs forward and before it ends.
158
+ * A name cannot be one of the five.
159
+ */
160
+ marks?: Readonly<Record<string, number>>;
130
161
  /**
131
162
  * The owner this voice plays under, a handle `owns` returned. Its `start` and `anchor` are then on
132
163
  * the owner's clock, in ms from when the owner starts, and default to where that clock is now; a
@@ -136,6 +167,22 @@ export interface VoiceSpec<I, O, H = unknown> extends SpanHints {
136
167
  */
137
168
  owner?: Handle<I>;
138
169
  }
170
+ /**
171
+ * One of `mix.blend`'s members, with the labels it carries in place of the spec's: each set here
172
+ * replaces the spec's for this member alone. The rest of the spec times and places every member
173
+ * alike, so they stay one blend.
174
+ *
175
+ * @category blending
176
+ */
177
+ export interface BlendMember<I, O, H = unknown> {
178
+ patch: Patch<I, O, unknown, H>;
179
+ /** What other voices call this member by. Default: the spec's `name`. */
180
+ name?: string;
181
+ /** Default: the spec's `tags`. */
182
+ tags?: readonly string[];
183
+ /** Events at times on this member's clock, as a voice's `hits`. Default: the spec's. */
184
+ hits?: readonly Hit[];
185
+ }
139
186
  /**
140
187
  * What `owns` takes: an owner has no patch, and plays only through the voices it holds.
141
188
  *
@@ -147,8 +194,19 @@ export interface OwnerSpec<I, H = unknown> extends SpanHints {
147
194
  * voice's `start` is. Default: now.
148
195
  */
149
196
  start?: number;
150
- /** Its clock's rate, multiplied into every child's own. Default 1. */
197
+ /**
198
+ * Its clock's rate, multiplied into every child's own. Default 1. Below 0 its clock runs back,
199
+ * and so does every child's: a child plays backward to its start and leaves there, as a voice cued
200
+ * backward does, and the owner leaves with its last child. A span is not cued backward, since it
201
+ * lays out its children forward from its start; its handle's `rate` turns it once it plays.
202
+ */
151
203
  rate?: number;
204
+ /**
205
+ * Where its clock starts, ms, as `seek` on its handle sets: its children play as far in as that
206
+ * puts them. Default 0, cued backward too, since an owner has no end of its own to start from; one
207
+ * cued at a rate below 0 with no seek runs back from 0, before any child placed on its clock.
208
+ */
209
+ seek?: number;
152
210
  /**
153
211
  * Multiplied into every child's weight per subject, as the child's own fade is, before the child's
154
212
  * locus folds it: a number, or a signal read per subject per frame. Default 1.
@@ -166,6 +224,14 @@ export interface OwnerSpec<I, H = unknown> extends SpanHints {
166
224
  score?: string;
167
225
  /** Where it sits relative to its own owner's clock or to other voices, in place of `start`. */
168
226
  anchor?: Placement;
227
+ /**
228
+ * Events at times on its own clock, the one its children's `start` counts on, which `book`
229
+ * hands a host ahead of time with its `score` and `tags`. An owner does not loop, so each is
230
+ * booked once, while it plays: none past where it leaves, and none while its clock runs back.
231
+ */
232
+ hits?: readonly Hit[];
233
+ /** Named marks at times on its own clock, as a voice's `marks`. */
234
+ marks?: Readonly<Record<string, number>>;
169
235
  /** The owner it plays under, so owners nest. */
170
236
  owner?: Handle<I>;
171
237
  }
@@ -294,7 +360,8 @@ export interface Handle<I = unknown> {
294
360
  * Turns a fade out around: the voice climbs back from where its fade had got to, up the same
295
361
  * curve, over `over` ms for the whole curve (default its `fade.in`, else its `fade.out`), and
296
362
  * plays on as if never faded. A fade waiting for rest is taken back at once; a voice not fading
297
- * is left as it is. A voice whose own end began the fade starts it again at its next frame.
363
+ * is left as it is. A voice whose own end began the fade starts it again at its next frame. A
364
+ * voice faded before its start goes back to `pending` and starts on time.
298
365
  */
299
366
  rise(opts?: {
300
367
  over?: number;
@@ -303,7 +370,7 @@ export interface Handle<I = unknown> {
303
370
  * The weight this voice gave `subject` the last frame that subject was probed: after its fades
304
371
  * and its weight signal, before a locus folds it with its alternatives. 0 for a subject it does
305
372
  * not reach, has not started on and does not freeze before, has left at rest, or has never been
306
- * probed for; 0 once done.
373
+ * probed for; 0 once done, and 0 after `mix.seek` goes back until the subject is probed again.
307
374
  * Costs nothing until it is asked.
308
375
  */
309
376
  weightOf(subject: I): number;
@@ -0,0 +1,126 @@
1
+ import type { HistoryOptions } from './history.js';
2
+ import type { Mix } from './mix.js';
3
+ import type { Sent } from './patch.js';
4
+ import type { Handle } from './voice.js';
5
+ /**
6
+ * Every mix made on the page, for a debugger: shared by every copy of blits loaded, so a mix one
7
+ * copy made is listed by another. `watched()` returns it.
8
+ *
9
+ * @category mix
10
+ */
11
+ export interface Registry {
12
+ /** The mixes still alive, in the order they were made. */
13
+ entries(): Watched[];
14
+ /** Hears each mix made, and each one collected, by its entry's `id`. Returns an unsubscribe. */
15
+ on(fn: (change: {
16
+ kind: 'add';
17
+ entry: Watched;
18
+ } | {
19
+ kind: 'gone';
20
+ id: number;
21
+ }) => void): () => void;
22
+ /**
23
+ * The history a mix made from now on keeps when its options name none and it is on no
24
+ * transport, so a debugger present before the page's mixes can scrub them. Undefined by default.
25
+ */
26
+ history: HistoryOptions | undefined;
27
+ }
28
+ /**
29
+ * One mix as a debugger sees it. Built by the copy of blits that made the mix, so a debugger
30
+ * reads mixes from other releases through it alike.
31
+ *
32
+ * @category mix
33
+ */
34
+ export interface Watched<I = unknown, O = unknown> {
35
+ /** Numbers mixes in the order they were made, across copies; what a `gone` change names. */
36
+ readonly id: number;
37
+ /** The release of the copy that made it. */
38
+ readonly release: string;
39
+ readonly name: string | undefined;
40
+ readonly mix: Mix<I, O>;
41
+ /** What history it keeps, and whether the registry's `history` gave it; undefined for none. */
42
+ readonly history: {
43
+ readonly ms: number;
44
+ readonly tape: boolean;
45
+ readonly added: boolean;
46
+ } | undefined;
47
+ /** The earliest mix time `read` reaches back to: `mix.now` without history. */
48
+ readonly reach: number;
49
+ /** The kit's channel names, in kit order. */
50
+ readonly channels: readonly string[];
51
+ /** What a voice was cued with that its handle does not carry; undefined for a handle not on this mix. */
52
+ voice(handle: Handle<I>): {
53
+ readonly name: string | undefined;
54
+ readonly tags: readonly string[];
55
+ } | undefined;
56
+ /** What to call a subject: the mix's `labelOf`, else a guess from the subject itself. */
57
+ label(subject: I): string;
58
+ /**
59
+ * Calls `fn` with each frame the host read, once the next one begins. While anyone watches, the
60
+ * mix records what `probe`, `pull` and `drain` give the host, and nothing else changes. Returns
61
+ * a function that stops watching.
62
+ */
63
+ watch(fn: (frame: WatchedFrame<I, O>) => void): () => void;
64
+ /** The subjects its voices still playing name, and those the host read in the last two frames while watched. */
65
+ subjects(): I[];
66
+ /**
67
+ * One subject's pose at mix time `at`, default now, read through `project`, which moves nothing:
68
+ * never a probe. A time behind now needs history that reaches it.
69
+ */
70
+ read(subject: I, at?: number): O;
71
+ /** Takes the clock from the host: see `Hold`. Throws while another hold has it. */
72
+ hold(): Hold;
73
+ }
74
+ /**
75
+ * What the host read in one frame.
76
+ *
77
+ * @category mix
78
+ */
79
+ export interface WatchedFrame<I, O> {
80
+ seq: number;
81
+ /** The mix clock the frame stood at. */
82
+ now: number;
83
+ /** The host's timestamp at the frame's sync. */
84
+ timestamp: number;
85
+ /** Each probe, in order, with a copy of the pose it returned. */
86
+ probed: {
87
+ subject: I;
88
+ pose: O;
89
+ }[];
90
+ /** Each pull, with copies of the columns it wrote. */
91
+ pulled: {
92
+ subjects: I[];
93
+ columns: Record<string, Float64Array>;
94
+ }[];
95
+ /** What `drain` handed the host. */
96
+ sent: Sent<I, unknown>[];
97
+ voices: Handle<I>[];
98
+ }
99
+ /**
100
+ * A mix's clock in a debugger's hands, and every mix's on the same transport. The host's `sync`
101
+ * still begins each frame, but the frame's gap counts at `rate`, so the mix moves at `rate` times
102
+ * its own rate; the host's own clock calls (`seek`, `rate`, `ramp`, `rebase`) wait for `free`.
103
+ * Nothing done through a hold is recorded on the tape or in the mix's rate, and each change wakes
104
+ * a host sleeping on `inert`.
105
+ *
106
+ * @category mix
107
+ */
108
+ export interface Hold {
109
+ readonly mixes: Mix<unknown, unknown>[];
110
+ /** The mix clock. */
111
+ readonly now: number;
112
+ /** The earliest mix time `seek` reaches: `now` without history and a tape. */
113
+ readonly reach: number;
114
+ /** How much of each of the host's frames the held mix plays; 0 pauses it. Starts at 0. */
115
+ rate: number;
116
+ /** Moves the mixes to mix time `to`, back within `reach` or ahead. */
117
+ seek(to: number): void;
118
+ /** Plays the mixes `ms` of mix time further on, in one frame. */
119
+ step(ms: number): void;
120
+ /**
121
+ * Gives the clock back: the host's next sync carries on from where the hold left the mix, and
122
+ * its clock calls made meanwhile are made, in order. A call made while the tape holds later
123
+ * calls acts on the mix but is not recorded, so those calls still play.
124
+ */
125
+ free(): void;
126
+ }
@@ -0,0 +1 @@
1
+ export {};
package/dist/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export type * from './types/arc.js';
1
2
  export type * from './types/channel.js';
2
3
  export type * from './types/history.js';
3
4
  export type * from './types/mix.js';
@@ -5,3 +6,4 @@ export type * from './types/patch.js';
5
6
  export type * from './types/place.js';
6
7
  export type * from './types/transport.js';
7
8
  export type * from './types/voice.js';
9
+ export type * from './types/watch.js';
package/dist/unpage.d.ts CHANGED
@@ -1,8 +1,13 @@
1
- import type { Transport } from './transport.js';
1
+ import type { Frame, Transport } from './transport.js';
2
2
  /**
3
3
  * Makes memory reach mix time `t` for a seek or read there, from what `prepare` loaded; true where
4
4
  * it took records from the store. Throws before anything moves where it cannot.
5
5
  */
6
6
  export declare function cover(transport: Transport, t: number): boolean;
7
+ /**
8
+ * The frame numbered `seq` for a seek or read to it, memory made to reach it from what `prepare`
9
+ * loaded. Throws before anything moves for a frame history does not hold.
10
+ */
11
+ export declare function coverFrame(transport: Transport, seq: number): Frame;
7
12
  /** A seek back to frame `seq`: what the store and `prepare` hold after it is from a future the tape makes again. */
8
13
  export declare function cut(transport: Transport, seq: number): void;
package/dist/unpage.js CHANGED
@@ -29,6 +29,29 @@ export function cover(transport, t) {
29
29
  transport.floor = loaded.t;
30
30
  return true;
31
31
  }
32
+ /**
33
+ * The frame numbered `seq` for a seek or read to it, memory made to reach it from what `prepare`
34
+ * loaded. Throws before anything moves for a frame history does not hold.
35
+ */
36
+ export function coverFrame(transport, seq) {
37
+ if (!Number.isInteger(seq))
38
+ throw new RangeError(`blits: a frame is a number \`seq\` read, not ${seq}`);
39
+ let frame = transport.frames.numbered(seq);
40
+ const pager = transport.pager;
41
+ if (frame === undefined && pager !== null && seq <= transport.seq) {
42
+ const paged = pager.loaded?.records.find((r) => r.stream === 'frame' && r.mix === '' && r.seq === seq);
43
+ if (paged !== undefined) {
44
+ cover(transport, paged.at);
45
+ frame = transport.frames.numbered(seq);
46
+ }
47
+ else if (seq < (transport.frames.all()[0]?.seq ?? Number.POSITIVE_INFINITY))
48
+ throw new Error(`blits: frame ${seq} reaches past memory; await prepare with its mix time first`);
49
+ }
50
+ if (frame === undefined)
51
+ throw new Error(`blits: frame ${seq} is not one this mix's history holds: not played yet, let go, or after a moment a seek went back to`);
52
+ cover(transport, frame.at);
53
+ return frame;
54
+ }
32
55
  /** A seek back to frame `seq`: what the store and `prepare` hold after it is from a future the tape makes again. */
33
56
  export function cut(transport, seq) {
34
57
  const pager = transport.pager;
@@ -117,8 +140,17 @@ function unpageVoice(voice, records, keys) {
117
140
  const subject = keys.subject(r.subject);
118
141
  if (left.some((e) => e.seq === r.seq && Object.is(e.subject, subject)))
119
142
  continue;
120
- const [p, sync] = r.data;
121
- left.push({ subject, at: r.at, seq: r.seq, sync, held: unpackHeld(voice, p) });
143
+ // A store written before a leaving kept its fades holds two.
144
+ const [p, sync, ramp = null, parted = null] = r.data;
145
+ left.push({
146
+ subject,
147
+ at: r.at,
148
+ seq: r.seq,
149
+ sync,
150
+ held: unpackHeld(voice, p),
151
+ ramp,
152
+ parted,
153
+ });
122
154
  }
123
155
  left.sort((a, b) => a.seq - b.seq);
124
156
  voice.left = Leavings.from(left);
package/dist/voice.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { Arc } from './arcs.js';
1
2
  import type { Blend } from './blend.js';
2
3
  import { type Clock } from './clock.js';
3
4
  import { type Curve } from './easing.js';
@@ -7,12 +8,14 @@ import { Named } from './named.js';
7
8
  import type { Past } from './origin.js';
8
9
  import { Holding } from './owner.js';
9
10
  import { type Built, intosOf, type Scratch } from './patch.js';
11
+ import type { Stamp } from './restored.js';
10
12
  import type { Fitting } from './spans.js';
11
13
  import { Store } from './store.js';
12
14
  import type { Anchor, Channel, FadeSpec, Handle, Patch, Setting, VoiceSpec } from './types.js';
13
15
  /**
14
16
  * A subject's record as it left a voice, faded out of it or dropped: the mix time and frame it
15
- * left at, and `sync` where the frame's sync made it, before the frame was read.
17
+ * left at, and `sync` where it shows in its own frame: left in the frame's sync, or before anything
18
+ * read the mix that frame.
16
19
  */
17
20
  export interface Left<I> {
18
21
  subject: I;
@@ -20,8 +23,55 @@ export interface Left<I> {
20
23
  seq: number;
21
24
  sync: boolean;
22
25
  held: Subject<unknown>;
26
+ /**
27
+ * The voice's fade of the subject as it stood on leaving, which a seek or read back to before
28
+ * puts back: its ramp out, while running, or its having faded out.
29
+ */
30
+ ramp: Parting | null;
31
+ parted: Parted | null;
32
+ }
33
+ /** A subject's ramp out of one voice: when it began, how long it runs, and the frame it was asked in. */
34
+ export interface Parting {
35
+ at: number;
36
+ over: number;
37
+ seq: number;
38
+ }
39
+ export interface Parted {
40
+ at: number;
41
+ seq: number;
42
+ ramp: Parting | undefined;
23
43
  }
24
44
  export declare const none: readonly string[];
45
+ /**
46
+ * What a copy of a record keeps for the seeks that put a record back from it: the copy's state
47
+ * stepped on to `ticks`, as it stood near `at`, a moment one of them sought.
48
+ */
49
+ export interface Ahead<S> {
50
+ /** The record the last seek put back, and the moment it sought, until that record steps. */
51
+ put: Subject<S> | null;
52
+ sought: number;
53
+ /** The `since` of the record put back, which the steps in `state` were counted from. */
54
+ since: number;
55
+ at: number;
56
+ ticks: number;
57
+ /** Undefined until a record has stepped on from the copy. */
58
+ state: S | undefined;
59
+ /**
60
+ * The state the record a seek replaced had stepped on to from the copy, at `leftTicks`; undefined
61
+ * until one had.
62
+ */
63
+ leftTicks: number;
64
+ left: S | undefined;
65
+ }
66
+ /** A copy of a record kept under `history`, by the mix time and frame it was taken at. */
67
+ export interface Snap<S> {
68
+ at: number;
69
+ seq: number;
70
+ held: Subject<S>;
71
+ ahead?: Ahead<S>;
72
+ /** Set where another record's list holds it too, so a seek cutting it from one lets go of it. */
73
+ shared?: true;
74
+ }
25
75
  /** Everything one voice holds for one subject, chained through the next voice that reaches it. */
26
76
  export interface Subject<S> {
27
77
  /** The voice's `target` answer, fixed on first sight. */
@@ -56,6 +106,8 @@ export interface Subject<S> {
56
106
  seeks: number;
57
107
  /** The voice's `rebuilds` when its state was last made, so a seek's rebuild reaches it once. */
58
108
  rebuilt: number;
109
+ /** Its kept signal state was stepped on in one go from a copy history kept, by a seek. */
110
+ copied: boolean;
59
111
  /** Stop 0 for a `from: 'current'` voice, taken the first frame this subject is seen. */
60
112
  base?: Record<string, unknown>;
61
113
  /** The pose's velocity per channel at that moment, units per ms, so the first segment leaves at it. */
@@ -65,11 +117,7 @@ export interface Subject<S> {
65
117
  /** Kept state a history store gave back, which each owner takes in turn on its first keep. */
66
118
  unkept?: unknown[];
67
119
  /** Under `history`, copies of this record by the mix time they were taken, oldest first. */
68
- snaps?: {
69
- at: number;
70
- seq: number;
71
- held: Subject<S>;
72
- }[];
120
+ snaps?: Snap<S>[];
73
121
  /** In a projection: where this record started from, and whether nothing known could be. */
74
122
  from?: number;
75
123
  unknown?: boolean;
@@ -100,6 +148,8 @@ export interface Subject<S> {
100
148
  /** A motion voice's number for this subject in its patch, good while `freed` is the patch's own. */
101
149
  run: number;
102
150
  freed: number;
151
+ /** In a voice's store once a seek has gone back, the stamp of the seek it was last put back or written at. */
152
+ restored: Stamp | null;
103
153
  }
104
154
  /** A voice's clock, weight and fade from one mix time on, kept under `history`. */
105
155
  export interface Controls extends Clock {
@@ -116,6 +166,8 @@ export interface Controls extends Clock {
116
166
  outOver: number;
117
167
  outSet: boolean;
118
168
  rebuilds: number;
169
+ /** An arc's hold. */
170
+ hold: number;
119
171
  /** How many of the voice's past clocks it had then. */
120
172
  past: number;
121
173
  /** Shows in its own frame: made by a sync, or before anything read the mix that frame. */
@@ -200,19 +252,17 @@ export declare class Voice<I, O> {
200
252
  rebuilds: number;
201
253
  /** Whether its span's last fit jumped it to its end, which leaves it no time in that fit. */
202
254
  skipped: boolean;
255
+ /** What its `earliest` answered at its span's last fit, span ms; NaN while unknown or absent. */
256
+ floorSeen: number;
203
257
  /** Whether its patch has kept state on a record through `setting.keep`, which makes it stateful. */
204
258
  keeping: boolean;
205
259
  /** Subjects fading out of this voice alone, by the ramp each started; null while none are. */
206
- parts: Map<I, {
207
- at: number;
208
- over: number;
209
- seq: number;
210
- }> | null;
211
- /** Subjects faded out of this voice, by the mix time and frame each left at; null while none have. */
212
- parted: Map<I, {
213
- at: number;
214
- seq: number;
215
- }> | null;
260
+ parts: Map<I, Parting> | null;
261
+ /**
262
+ * Subjects faded out of this voice, by the mix time and frame each left at, and the ramp that
263
+ * took it out, which a seek or a read back into it puts back; null while none have.
264
+ */
265
+ parted: Map<I, Parted> | null;
216
266
  /**
217
267
  * Under history, the records of subjects that left this voice, by the mix time and frame each
218
268
  * left at, while a seek or a read back may reach them; null while none have.
@@ -237,6 +287,8 @@ export declare class Voice<I, O> {
237
287
  readonly freezesAfter: boolean;
238
288
  /** The mix time it first showed: when it was cued, or the first sync after. */
239
289
  opened: number;
290
+ /** Whether no delta its patch's `at` returned has been checked against `writes` yet. */
291
+ unchecked: boolean;
240
292
  /** Which of its entries in the mix's due queue is current; older ones are skipped when popped. */
241
293
  dueToken: number;
242
294
  /**
@@ -255,6 +307,8 @@ export declare class Voice<I, O> {
255
307
  /** The least stagger of any subject seen, 0 or below, which a voice running back ends at. */
256
308
  soonest: number;
257
309
  restedCount: number;
310
+ /** Whether a seek back to before its cue has it out of the mix, until the mix plays the cue again. */
311
+ parked: boolean;
258
312
  /** The mix time it was cued at; -Infinity before the first sync. */
259
313
  cuedAt: number;
260
314
  /** The frame it was cued in. */
@@ -294,12 +348,19 @@ export declare class Voice<I, O> {
294
348
  of: Blend<I, O>;
295
349
  i: number;
296
350
  } | null;
351
+ /**
352
+ * Copies the latest seek back cut from its records' lists that no other list holds, for the
353
+ * copies its probes keep next to be written over; null until a seek cuts one.
354
+ */
355
+ spares: Snap<unknown>[] | null;
297
356
  /** The one record of every subject it does not reach. */
298
357
  unreached: Subject<unknown> | null;
299
358
  /** By subject number, a bit set where `unreached` stands for the subject; null until one is. */
300
359
  unreachedBits: Uint32Array | null;
301
360
  /** Whether one record stands for every subject: see `shares` in `everyone.ts`. */
302
361
  sharing: boolean;
362
+ /** The frames it has played sharing it. */
363
+ shared: number;
303
364
  /** That record, null until a chain first asks and once the voice shares no more. */
304
365
  everyone: Subject<unknown> | null;
305
366
  /** While sharing, by subject number: a bit where a chain has asked about the subject. */
@@ -320,6 +381,12 @@ export declare class Voice<I, O> {
320
381
  holding: Holding<Voice<I, O>> | null;
321
382
  /** For a span, its budget and how its children were last fitted; null for any other voice. */
322
383
  fitting: Fitting | null;
384
+ /** For an arc, how its parts are laid out; null for any other voice. */
385
+ arc: Arc | null;
386
+ /** For an arc, how long its hold lasts, ms on its clock: Infinity while open. */
387
+ hold: number;
388
+ /** For a voice an arc holds, which part it plays: 0 enter, 1 active, 2 exit; -1 for any other. */
389
+ part: number;
323
390
  /**
324
391
  * `done` and `played`, made when first asked for, already settled if the voice is: most hosts
325
392
  * never await either, and a mix may hold tens of thousands of voices.
@@ -411,6 +478,11 @@ export declare class Voice<I, O> {
411
478
  * fading out from where it ran back to its start, as one fading from its end shows its last.
412
479
  */
413
480
  get holdsFirst(): boolean;
481
+ /**
482
+ * Whether a subject past the end of its passes shows nothing: its clock runs back, so it has yet
483
+ * to reach them, and it does not freeze after.
484
+ */
485
+ get hidesPast(): boolean;
414
486
  /** A subject's voice time at `raw` once the voice's freezes apply; NaN where it shows nothing. */
415
487
  shownAt(raw: number): number;
416
488
  /** Records this voice's controls as they stand, from mix time `at` in frame `seq`. */
@@ -426,3 +498,8 @@ export declare class Voice<I, O> {
426
498
  /** Moves the anchor to `now`, carrying what is left of a ramp. */
427
499
  rebase(now: number): void;
428
500
  }
501
+ /**
502
+ * Warns, once a patch outside production, of a key the first delta `voice` read returns outside its
503
+ * patch's `writes`, which the mix drops.
504
+ */
505
+ export declare function checkWrites<I, O>(voice: Voice<I, O>, delta: object | null): void;