@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
package/dist/lean.js ADDED
@@ -0,0 +1,23 @@
1
+ import { made } from './mixer.js';
2
+ export * from './index.js';
3
+ /**
4
+ * The stock engine without lanes: every voice folds subject by subject, to the same values, and a
5
+ * bundle that takes `mix` from here leaves the lanes' code out. `lanes: true` is refused.
6
+ *
7
+ * @category engine
8
+ */
9
+ export const lean = {
10
+ name: 'lean',
11
+ runs: new Set(['fn', 'keys', 'motion']),
12
+ create(kit, opts) {
13
+ return made(kit, opts, null);
14
+ },
15
+ };
16
+ /**
17
+ * Makes a mix over a kit, on the engine the options name or the lean one.
18
+ *
19
+ * @category mix
20
+ */
21
+ export function mix(kit, opts = {}) {
22
+ return (opts.engine ?? lean).create(kit, opts);
23
+ }
@@ -17,8 +17,13 @@ export declare class Leavings<I> {
17
17
  * front: entries are in the order they left, and mix time does not run back along it.
18
18
  */
19
19
  expire(reach: number, out: ((e: Left<I>) => void) | null): void;
20
- /** The record `subject` had at `cut` and left with after it, if it left after `cut`. */
20
+ /**
21
+ * The record `subject` had at `cut` and left with after it, if it left after `cut`. None where it
22
+ * left saying only that it had faded out, after `cut`, of a voice that had not met it.
23
+ */
21
24
  at(subject: I, cut: Cut): Subject<unknown> | undefined;
25
+ /** Each subject's first leaving after `cut`, which holds what it had at `cut`. */
26
+ after(cut: Cut): Left<I>[];
22
27
  /** Each time `subject` left, oldest first. */
23
28
  of(subject: I): readonly Left<I>[];
24
29
  /** Every entry, oldest first. */
package/dist/leavings.js CHANGED
@@ -49,16 +49,30 @@ export class Leavings {
49
49
  this.head = 0;
50
50
  }
51
51
  }
52
- /** The record `subject` had at `cut` and left with after it, if it left after `cut`. */
52
+ /**
53
+ * The record `subject` had at `cut` and left with after it, if it left after `cut`. None where it
54
+ * left saying only that it had faded out, after `cut`, of a voice that had not met it.
55
+ */
53
56
  at(subject, cut) {
54
57
  const own = this.by.get(subject);
55
58
  if (own === undefined)
56
59
  return undefined;
57
60
  for (const e of own)
58
61
  if (!within(cut, e.seq, e.sync))
59
- return e.held;
62
+ return !e.held.reaches && e.parted !== null && e.parted.seq > cut.seq ? undefined : e.held;
60
63
  return undefined;
61
64
  }
65
+ /** Each subject's first leaving after `cut`, which holds what it had at `cut`. */
66
+ after(cut) {
67
+ const out = [];
68
+ const seen = new Set();
69
+ for (const e of this.all())
70
+ if (!within(cut, e.seq, e.sync) && !seen.has(e.subject)) {
71
+ seen.add(e.subject);
72
+ out.push(e);
73
+ }
74
+ return out;
75
+ }
62
76
  /** Each time `subject` left, oldest first. */
63
77
  of(subject) {
64
78
  return this.by.get(subject) ?? [];
package/dist/marks.d.ts CHANGED
@@ -1,8 +1,12 @@
1
- import type { Listed } from './book.js';
1
+ import { type Listed } from './book.js';
2
2
  import type { Mixer } from './mixer.js';
3
3
  import type { Transport } from './transport.js';
4
- import type { Mark } from './types.js';
4
+ import type { MarkName } from './types.js';
5
5
  import { type Voice } from './voice.js';
6
+ /** A voice's marks, in the order `marks` lists those at one time. */
7
+ export declare const voiceMarks: readonly ["start", "in", "coast", "out", "end"];
8
+ /** Refuses marks placed inside a voice under one of its own five names, or that it could never reach. */
9
+ export declare function checkMarks(marks: Readonly<Record<string, number>>, duration: number): void;
6
10
  /** The host timestamp the mix clock reads mix time `t` at; Infinity where it never will. */
7
11
  export declare function hostOf<I, O>(mix: Mixer<I, O>, t: number): number;
8
12
  /** What the mix clock reads at host time `u`, by the clock in force then. */
@@ -12,4 +16,4 @@ export declare function listed<I, O>(mix: Mixer<I, O>, from: number, to: number)
12
16
  /** Every mark of every mix on a transport and every one announced on it, earliest first. */
13
17
  export declare function listedAll(transport: Transport, from: number, to: number): Listed[];
14
18
  /** When a voice reaches a mark, mix time, or undefined while nothing has fixed it. */
15
- export declare function markOf<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, mark: Mark): number | undefined;
19
+ export declare function markOf<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, mark: MarkName): number | undefined;
package/dist/marks.js CHANGED
@@ -1,5 +1,21 @@
1
+ import { arcMark } from './arcs.js';
2
+ import { inPass } from './book.js';
1
3
  import { startOf } from './place.js';
2
4
  import { none } from './voice.js';
5
+ /** A voice's marks, in the order `marks` lists those at one time. */
6
+ export const voiceMarks = ['start', 'in', 'coast', 'out', 'end'];
7
+ /** Refuses marks placed inside a voice under one of its own five names, or that it could never reach. */
8
+ export function checkMarks(marks, duration) {
9
+ for (const name of Object.keys(marks)) {
10
+ if (voiceMarks.includes(name))
11
+ throw new Error(`blits: ${name} is one of a voice's own marks; a mark placed inside it needs another name`);
12
+ const at = marks[name];
13
+ if (!inPass(at, duration))
14
+ throw new RangeError(duration > 0
15
+ ? `blits: mark ${name} is voice ms into a pass, 0 up to ${duration}, not ${at}`
16
+ : `blits: mark ${name} is voice ms, 0 or more, not ${at}`);
17
+ }
18
+ }
3
19
  /** The host timestamp the mix clock reads mix time `t` at; Infinity where it never will. */
4
20
  export function hostOf(mix, t) {
5
21
  return (mix.pace === null ? t : mix.pace.timeOf(t)) + mix.offset;
@@ -10,7 +26,7 @@ export function readingAt(mix, u) {
10
26
  }
11
27
  /** Every mark between two host timestamps, earliest first, with the order that tells each apart. */
12
28
  export function listed(mix, from, to) {
13
- const out = voiceMarks(mix, from, to);
29
+ const out = marksOf(mix, from, to);
14
30
  for (const a of announcedMarks(mix.transport, from, to))
15
31
  if (a.score !== undefined || a.slot === mix.slot)
16
32
  out.push(a.listed);
@@ -20,7 +36,7 @@ export function listed(mix, from, to) {
20
36
  export function listedAll(transport, from, to) {
21
37
  const out = [];
22
38
  for (const m of transport.members)
23
- out.push(...voiceMarks(m, from, to));
39
+ out.push(...marksOf(m, from, to));
24
40
  for (const a of announcedMarks(transport, from, to))
25
41
  out.push(a.listed);
26
42
  return sorted(out);
@@ -50,30 +66,36 @@ function announcedMarks(transport, from, to) {
50
66
  });
51
67
  return out;
52
68
  }
53
- function voiceMarks(mix, from, to) {
69
+ function marksOf(mix, from, to) {
54
70
  const lo = from - mix.offset;
55
71
  const hi = to - mix.offset;
56
72
  const out = [];
57
73
  for (const voice of [...mix.cued, ...mix.gone]) {
58
- for (const mark of ['start', 'in', 'coast', 'out', 'end']) {
59
- const m = markOf(mix, voice, mark);
60
- const t = m === undefined ? m : hostOf(mix, m) - mix.offset;
61
- if (t === undefined || t < lo || t > hi)
62
- continue;
63
- out.push({
64
- timestamp: t + mix.offset,
65
- mark,
66
- voice: voice.id,
67
- score: voice.spec.score,
68
- name: voice.spec.name,
69
- tags: voice.spec.tags ?? none,
70
- mix: mix.name,
71
- order: voice.id,
72
- });
73
- }
74
+ for (const mark of voiceMarks)
75
+ listOne(mix, voice, mark, lo, hi, out);
76
+ const inner = voice.spec.marks;
77
+ if (inner !== undefined)
78
+ for (const mark of Object.keys(inner))
79
+ listOne(mix, voice, mark, lo, hi, out);
74
80
  }
75
81
  return out;
76
82
  }
83
+ function listOne(mix, voice, mark, lo, hi, out) {
84
+ const m = markOf(mix, voice, mark);
85
+ const t = m === undefined ? m : hostOf(mix, m) - mix.offset;
86
+ if (t === undefined || t < lo || t > hi)
87
+ return;
88
+ out.push({
89
+ timestamp: t + mix.offset,
90
+ mark,
91
+ voice: voice.id,
92
+ score: voice.spec.score,
93
+ name: voice.spec.name,
94
+ tags: voice.spec.tags ?? none,
95
+ mix: mix.name,
96
+ order: voice.id,
97
+ });
98
+ }
77
99
  /** When a voice reaches a mark, mix time, or undefined while nothing has fixed it. */
78
100
  export function markOf(mix, voice, mark) {
79
101
  if (!Number.isFinite(voice.start))
@@ -84,12 +106,18 @@ export function markOf(mix, voice, mark) {
84
106
  return undefined;
85
107
  if (mark === 'start')
86
108
  return start;
109
+ if (voice.arc !== null && (mark === 'in' || mark === 'coast' || mark === 'out' || mark === 'end'))
110
+ return arcMark(voice, start, mark);
87
111
  if (mark === 'in')
88
112
  return start + (voice.fade.in ?? 0);
89
113
  if (mark === 'coast')
90
114
  return coastOf(mix, voice, start);
115
+ if (mark !== 'out' && mark !== 'end')
116
+ return insideOf(mix, voice, start, mark);
91
117
  const out = voice.out;
92
118
  let outAt;
119
+ // An owner leaves with its last child, over no fade of its own.
120
+ let leaves = false;
93
121
  if (out !== null)
94
122
  outAt = out.at;
95
123
  else if (Number.isFinite(voice.outAt))
@@ -99,6 +127,13 @@ export function markOf(mix, voice, mark) {
99
127
  if (Number.isFinite(t))
100
128
  outAt = Math.max(start, t);
101
129
  }
130
+ else if (voice.holding !== null) {
131
+ const t = lastChild(mix, voice.holding.children, 'end');
132
+ if (t !== undefined) {
133
+ outAt = Math.max(start, t);
134
+ leaves = true;
135
+ }
136
+ }
102
137
  else if (!(voice.backs ? voice.freezesBefore : voice.freezesAfter)) {
103
138
  const t = voice.endsAt();
104
139
  if (Number.isFinite(t))
@@ -113,9 +148,38 @@ export function markOf(mix, voice, mark) {
113
148
  return out.deadline === undefined ? undefined : out.at + out.deadline;
114
149
  return out.at + out.over;
115
150
  }
151
+ if (leaves)
152
+ return outAt;
116
153
  const over = Number.isNaN(voice.outOver) ? (voice.fade.out ?? 0) : voice.outOver;
117
154
  return outAt === undefined ? undefined : outAt + (mix.reduced ? 0 : over);
118
155
  }
156
+ /** Voice ms within which a mark placed inside a voice counts as reached where the voice starts. */
157
+ const REACHED = 1e-9;
158
+ /**
159
+ * When a voice reaches a mark it placed inside itself, mix time: `at` into the first pass that
160
+ * reaches it from where the voice starts, while its clock runs forward and before it ends. None for
161
+ * a mark it does not place.
162
+ */
163
+ function insideOf(mix, voice, start, name) {
164
+ const marks = voice.spec.marks;
165
+ if (marks === undefined || !Object.hasOwn(marks, name) || voice.backs)
166
+ return undefined;
167
+ const at = marks[name];
168
+ const from = voice.elapsedAt(start);
169
+ const d = voice.duration;
170
+ let pass = 0;
171
+ if (d > 0)
172
+ pass = Math.max(0, Math.ceil((from - at) / d - REACHED));
173
+ else if (at < from - REACHED)
174
+ return undefined;
175
+ if (pass >= voice.passes)
176
+ return undefined;
177
+ const t = voice.timeAt(pass * d + at);
178
+ if (!Number.isFinite(t))
179
+ return undefined;
180
+ const end = markOf(mix, voice, 'end');
181
+ return end !== undefined && t >= end ? undefined : Math.max(start, t);
182
+ }
119
183
  /**
120
184
  * When a voice's last pass ends, mix time: an owner's when its fit ends, or its last child's. None
121
185
  * for a voice that never ends its passes, or that leaves or begins to fade before they end.
@@ -127,15 +191,15 @@ function coastOf(mix, voice, start) {
127
191
  if (voice.fitting !== null)
128
192
  t = voice.timeAt(voice.fitting.end);
129
193
  else if (voice.holding !== null) {
130
- const children = voice.holding.children;
131
- if (children.length === 0)
194
+ const h = voice.holding;
195
+ if (h.cutSeq !== Number.POSITIVE_INFINITY)
132
196
  return undefined;
133
- t = Number.NEGATIVE_INFINITY;
134
- for (const child of children) {
135
- const c = markOf(mix, child, 'coast');
136
- if (c === undefined)
137
- return undefined;
138
- t = Math.max(t, c);
197
+ if (h.children.length === 0)
198
+ t = voice.state === 'done' ? h.coast : undefined;
199
+ else {
200
+ t = lastChild(mix, h.children, 'coast');
201
+ if (t !== undefined)
202
+ t = Math.max(t, h.coast);
139
203
  }
140
204
  }
141
205
  else
@@ -146,3 +210,17 @@ function coastOf(mix, voice, start) {
146
210
  const cut = voice.out !== null ? voice.out.at : voice.state === 'done' ? voice.doneAt : voice.outAt;
147
211
  return cut < t ? undefined : t;
148
212
  }
213
+ /** The latest of the children's `mark`; undefined for none, or while one has not fixed it. */
214
+ function lastChild(mix, children, mark) {
215
+ if (children.length === 0)
216
+ return undefined;
217
+ let t = Number.NEGATIVE_INFINITY;
218
+ for (const child of children) {
219
+ const c = markOf(mix, child, mark);
220
+ if (c === undefined)
221
+ return undefined;
222
+ if (c > t)
223
+ t = c;
224
+ }
225
+ return t;
226
+ }
package/dist/meet.js CHANGED
@@ -110,6 +110,7 @@ function place(lanes, voice, slot, subject, from, head) {
110
110
  return false;
111
111
  const o = p * 8 /* Row.STRIDE */;
112
112
  c.list[p] = slot;
113
+ lanes.placed.add(slot, voice.id);
113
114
  c.data[o + 0 /* Row.DELAY */] = held.delay;
114
115
  c.data[o + 1 /* Row.SINCE */] = held.shown;
115
116
  c.data[o + 2 /* Row.WEIGHT */] = 0;
package/dist/mixer.d.ts CHANGED
@@ -1,7 +1,9 @@
1
+ import { type Arc } from './arcs.js';
1
2
  import { blended, laneRead, shareKept } from './blend.js';
2
3
  import type { Book } from './book.js';
3
4
  import { aims, chain, linkable, relink } from './chain.js';
4
5
  import { type LerpInto } from './channels.js';
6
+ import type { Column } from './columns.js';
5
7
  import { DepartedIndex } from './departed.js';
6
8
  import type { Due } from './due.js';
7
9
  import { parting } from './fade.js';
@@ -21,7 +23,7 @@ import { ScoreIndex } from './scored.js';
21
23
  import { Fitting } from './spans.js';
22
24
  import { Store } from './store.js';
23
25
  import { type Announced, Transport } from './transport.js';
24
- import type { Booker, BookOptions, Channel, Columns, Engine, Handle, Kit, Marked, Mix, MixOptions, OwnerSpec, Patch, Projection, Sent, Signal, SpanHandle, SpanSpec, Tape, VoiceSpec } from './types.js';
26
+ 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';
25
27
  import { type Subject, type Voice } from './voice.js';
26
28
  import { base, capped, fadeOf, horizonFor, ownedBy, ownerBase, prime, weigh, weighOwned } from './weigh.js';
27
29
  /**
@@ -34,6 +36,8 @@ export declare const defaults: {
34
36
  export declare class Mixer<I, O> implements Mix<I, O> {
35
37
  readonly kit: Kit<O>;
36
38
  readonly opts: MixOptions;
39
+ /** The lanes an entry was built with; null in one that leaves them out. */
40
+ readonly lanesOf: typeof Lanes | null;
37
41
  cued: Voice<I, O>[];
38
42
  /** Under `history`, voices that have left but that a read back may still reach. */
39
43
  gone: Voice<I, O>[];
@@ -95,10 +99,15 @@ export declare class Mixer<I, O> implements Mix<I, O> {
95
99
  /** The last array `pull` read, by position, with each subject's chain head, to skip the lookup. */
96
100
  pulled: I[];
97
101
  pulledHeads: (Subject<unknown> | undefined)[];
98
- /** Each remembered head's lane slot, and the `version` and `relinks` they were all current at. */
102
+ /**
103
+ * Each remembered head's lane slot, -1 at a position with none, and the `version` and `relinks`
104
+ * they were all current at.
105
+ */
99
106
  pulledSlots: Int32Array<ArrayBuffer>;
100
107
  pulledVersion: number;
101
108
  pulledRelinks: number;
109
+ /** What `pull` knows of each channel it has written, by name; none until the first pull. */
110
+ pullColumns: Map<string, Column> | null;
102
111
  /** Counts chains made stale one subject at a time, which `version` does not. */
103
112
  relinks: number;
104
113
  /** Read once a sync, so a `reduce` function is not called per voice per subject. */
@@ -119,6 +128,8 @@ export declare class Mixer<I, O> implements Mix<I, O> {
119
128
  */
120
129
  chains: Store<I, Subject<unknown>>;
121
130
  version: number;
131
+ /** What `prime` reads its clock, voice time and pass from: see `Primed`. */
132
+ readonly primed: Float64Array<ArrayBuffer>;
122
133
  readonly steps: Steps<Voice<I, O>, I>;
123
134
  /** Per subject, the voices whose `subjects` name it, in voice order. */
124
135
  named: Store<I, Voice<I, O>[]>;
@@ -171,6 +182,8 @@ export declare class Mixer<I, O> implements Mix<I, O> {
171
182
  readonly bounded: number[];
172
183
  /** By slot, a stock array channel's in-place `lerp`. */
173
184
  readonly lerpsInto: (LerpInto | undefined)[];
185
+ /** By slot, a stock scalar channel's arithmetic, which a fold applies without calling the channel. */
186
+ readonly scalars: ('sum' | 'mul' | 'max' | undefined)[];
174
187
  /** What a fold with a locus in play gathers into, one per depth of folds under way. */
175
188
  readonly locusScratch: LocusScratch<I, O>[];
176
189
  locusDepth: number;
@@ -181,13 +194,17 @@ export declare class Mixer<I, O> implements Mix<I, O> {
181
194
  bookers: Book<I, O>[] | null;
182
195
  /** The fit a span being cued takes, which `cue` hands its voice. */
183
196
  fitting: Fitting | null;
197
+ /** What an arc being cued keeps, which `cue` hands its voice. */
198
+ arcing: Arc | null;
184
199
  /** Every owner still in the mix, null until one is cued. */
185
200
  owners: Voice<I, O>[] | null;
186
201
  /** With a history store, the key each subject is paged under; null without one. */
187
202
  keys: Keys | null;
188
203
  /** With a history store, the voices it paged out whose handles are still held; null without one. */
189
204
  outs: Outs | null;
190
- constructor(kit: Kit<O>, opts: MixOptions);
205
+ constructor(kit: Kit<O>, opts: MixOptions,
206
+ /** The lanes an entry was built with; null in one that leaves them out. */
207
+ lanesOf: typeof Lanes | null);
191
208
  /** Throws where the clock is a shared transport's, which only the transport moves. */
192
209
  private own;
193
210
  get now(): number;
@@ -203,6 +220,7 @@ export declare class Mixer<I, O> implements Mix<I, O> {
203
220
  get nextId(): number;
204
221
  set nextId(v: number);
205
222
  get timestamp(): number;
223
+ get seq(): number;
206
224
  get last(): number;
207
225
  get tape(): Tape | undefined;
208
226
  get replaying(): boolean;
@@ -212,16 +230,21 @@ export declare class Mixer<I, O> implements Mix<I, O> {
212
230
  off: number;
213
231
  };
214
232
  cue(spec: VoiceSpec<I, O>): Handle<I>;
215
- blend(patches: readonly Patch<I, O, unknown>[], by: Signal<I>, spec?: Omit<VoiceSpec<I, O>, 'patch' | 'weight' | 'locus'>): 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>[];
216
234
  owns(spec: OwnerSpec<I>): Handle<I>;
217
235
  span(spec: SpanSpec<I>): SpanHandle<I>;
236
+ arc(spec: ArcSpec<I, O>): ArcHandle<I>;
218
237
  sync(timestamp: number): void;
219
238
  book<E = unknown>(opts: BookOptions<E, I>): Booker;
220
239
  probe(subject: I, out?: O): O;
221
240
  pull(subjects: Iterable<I>, into: Columns<O>): void;
222
- seek(time: number): void;
241
+ seek(to: number | {
242
+ readonly frame: number;
243
+ }): void;
223
244
  prepare(time: number): Promise<void>;
224
- project(time: number): Projection<I, O>;
245
+ project(at: number | {
246
+ readonly frame: number;
247
+ }): Projection<I, O>;
225
248
  announce(name: string, opts?: {
226
249
  at?: number;
227
250
  score?: string;
@@ -245,6 +268,10 @@ export declare class Mixer<I, O> implements Mix<I, O> {
245
268
  over?: number;
246
269
  }): void;
247
270
  drop(subject: I): void;
271
+ /** Lets `voice` go of a dropped subject. Methods rather than closures, so a drop makes neither. */
272
+ private forgetIn;
273
+ private releaseIn;
274
+ private recordDrop;
248
275
  touch(subject?: I): void;
249
276
  drain<E = unknown>(tag?: string): Sent<I, E>[];
250
277
  /** Voices whose stop 0 is mid-computation, so a fold for one cannot re-enter itself. */
@@ -313,6 +340,8 @@ declare const methods: {
313
340
  type Methods = typeof methods;
314
341
  export interface Mixer<I, O> extends Methods {
315
342
  }
343
+ /** Makes a mix the host asked for, with the registry's history where it names none, and lists it there. */
344
+ export declare function made<I, O, H>(kit: Kit<O>, opts: MixOptions<H>, lanes: typeof Lanes | null): Mix<I, O, H>;
316
345
  /**
317
346
  * The one that ships: every form on the CPU, probed per subject on demand.
318
347
  *