@msb235/blits 0.14.0 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +198 -0
- package/README.md +3 -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 +37 -14
- 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/color.d.ts +12 -10
- package/dist/color.js +25 -25
- package/dist/columns.d.ts +2 -1
- package/dist/columns.js +62 -38
- 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 +16 -6
- package/dist/crowd.js +20 -11
- package/dist/cue.d.ts +8 -1
- package/dist/cue.js +39 -13
- package/dist/cut.d.ts +8 -0
- package/dist/cut.js +4 -0
- package/dist/delay.d.ts +3 -0
- package/dist/delay.js +7 -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 +114 -34
- package/dist/easing.d.ts +6 -4
- package/dist/easing.js +7 -3
- package/dist/everyone.d.ts +8 -2
- package/dist/everyone.js +33 -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 +52 -20
- package/dist/fit.d.ts +44 -26
- package/dist/fit.js +10 -9
- package/dist/fold.d.ts +4 -37
- package/dist/fold.js +5 -513
- 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 +2 -0
- package/dist/handle.js +14 -8
- package/dist/held.d.ts +2 -1
- package/dist/held.js +2 -1
- package/dist/history.d.ts +6 -5
- package/dist/history.js +7 -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 +38 -11
- package/dist/lane.js +46 -11
- package/dist/lanes.d.ts +30 -12
- package/dist/lanes.js +56 -36
- 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 +95 -7
- package/dist/mixer.d.ts +56 -37
- package/dist/mixer.js +57 -171
- package/dist/motion.d.ts +14 -118
- package/dist/motion.js +16 -8
- package/dist/motions.d.ts +62 -155
- package/dist/motions.js +56 -370
- package/dist/moved.d.ts +1 -1
- package/dist/moved.js +16 -7
- package/dist/named.d.ts +6 -2
- package/dist/named.js +49 -3
- package/dist/numbers.d.ts +7 -0
- package/dist/numbers.js +33 -0
- package/dist/owed.d.ts +2 -0
- package/dist/owed.js +4 -0
- package/dist/pack.d.ts +2 -1
- package/dist/pack.js +2 -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 -212
- package/dist/pull.js +22 -9
- package/dist/qualify.js +93 -31
- package/dist/reading.d.ts +6 -0
- package/dist/reading.js +5 -0
- package/dist/record.d.ts +5 -1
- package/dist/record.js +3 -2
- package/dist/relink.d.ts +1 -1
- package/dist/renumber.d.ts +10 -0
- package/dist/renumber.js +75 -0
- 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 +28 -20
- package/dist/sample.d.ts +2 -2
- package/dist/sample.js +33 -7
- package/dist/seat.d.ts +17 -0
- package/dist/seat.js +25 -0
- package/dist/seek.js +5 -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 +23 -15
- 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/trace.d.ts +4 -0
- package/dist/trace.js +255 -0
- 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 +237 -163
- package/dist/types/motion.d.ts +151 -0
- package/dist/types/motion.js +1 -0
- package/dist/types/patch.d.ts +67 -34
- package/dist/types/place.d.ts +51 -36
- package/dist/types/trace.d.ts +51 -0
- package/dist/types/trace.js +1 -0
- package/dist/types/transport.d.ts +20 -18
- package/dist/types/voice.d.ts +144 -73
- package/dist/types/watch.d.ts +88 -40
- package/dist/types.d.ts +2 -0
- package/dist/unreached.d.ts +2 -0
- package/dist/unreached.js +7 -0
- package/dist/voice.d.ts +10 -143
- package/dist/voice.js +37 -82
- 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 -34
- package/package.json +2 -2
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Mixer } from './mixer.js';
|
|
2
|
+
import type { Subject } from './subject.js';
|
|
3
|
+
import { type Voice } from './voice.js';
|
|
4
|
+
/**
|
|
5
|
+
* One live voice's delta for one subject this frame, through its record for the subject, or null
|
|
6
|
+
* when it does not reach. Its weight is left in `w`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function contribution<I, O>(this: Mixer<I, O>, voice: Voice<I, O>, subject: I, now: number, held: Subject<unknown>): Record<string, unknown> | null;
|
|
9
|
+
/** Reads a keys voice's stops at `held.phase` into the subject's delta, through the voice's scratch. */
|
|
10
|
+
export declare function keyed<I, O>(this: Mixer<I, O>, voice: Voice<I, O>, subject: I, held: Subject<unknown>): Record<string, unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* Runs `step` once per whole interval between where this subject last stopped and now, on a grid
|
|
13
|
+
* counted from when its delay ran out, and leaves the remainder for the next sample. Counting
|
|
14
|
+
* rather than adding keeps the grid where it is however many samples it is reached through.
|
|
15
|
+
*/
|
|
16
|
+
export declare function tick<I, O>(this: Mixer<I, O>, voice: Voice<I, O>, subject: I, held: Subject<unknown>, tick: number, to: number): void;
|
|
17
|
+
/**
|
|
18
|
+
* Stop 0 for a retargeting voice: the subject's pose in the frame before this voice contributes.
|
|
19
|
+
* With no such frame on record — a voice cued before the subject was ever probed, or a host that
|
|
20
|
+
* samples into its own object — it is this frame's pose with every other voice folded in.
|
|
21
|
+
*/
|
|
22
|
+
export declare function baseFor<I, O>(this: Mixer<I, O>, voice: Voice<I, O>, subject: I): Record<string, unknown>;
|
|
23
|
+
/**
|
|
24
|
+
* How fast each numeric channel this voice writes was moving, from the subject's last two probed
|
|
25
|
+
* poses, in units per ms. Undefined with fewer than two on record, which starts the voice at rest.
|
|
26
|
+
*/
|
|
27
|
+
export declare function slopeFor<I, O>(this: Mixer<I, O>, voice: Voice<I, O>, subject: I): Record<string, unknown> | undefined;
|
|
28
|
+
export declare function isRest<I, O>(this: Mixer<I, O>, delta: Record<string, unknown>): boolean;
|
|
29
|
+
/** `contribution`, or for a dry fold a subject already probed this frame, without advancing it. */
|
|
30
|
+
export declare function read<I, O>(this: Mixer<I, O>, voice: Voice<I, O>, subject: I, now: number, dry: boolean, held: Subject<unknown>): Record<string, unknown> | null;
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import { inBound } from './bound.js';
|
|
2
|
+
import { passAt, phaseAt, phaseBefore, silent, stepOf } from './clock.js';
|
|
3
|
+
import { copy as copyValue } from './clone.js';
|
|
4
|
+
import { near } from './fold.js';
|
|
5
|
+
import { waits } from './held.js';
|
|
6
|
+
import { apart, copyState, record, recordHost, remember } from './history.js';
|
|
7
|
+
import { stateful } from './hosts.js';
|
|
8
|
+
import { moved } from './moved.js';
|
|
9
|
+
import { readKeys } from './patch.js';
|
|
10
|
+
import { reading } from './reading.js';
|
|
11
|
+
import { isRested } from './record.js';
|
|
12
|
+
import { checkWrites } from './voice.js';
|
|
13
|
+
// V8 reads a local const as a constant, where it reads an import from its module on every call.
|
|
14
|
+
const copy = copyValue;
|
|
15
|
+
/**
|
|
16
|
+
* A record after a seek that rebuilds: fresh state, stepped again from where the voice's clock now
|
|
17
|
+
* puts this subject's start, which under `stepMs` lands where a voice cued fresh would.
|
|
18
|
+
*/
|
|
19
|
+
function rebuild(mix, voice, subject, now, held) {
|
|
20
|
+
held.rebuilt = voice.rebuilds;
|
|
21
|
+
const patch = voice.patch;
|
|
22
|
+
if (patch.state === undefined && patch.step === undefined && held.kept === null)
|
|
23
|
+
return;
|
|
24
|
+
held.state = patch.state ? patch.state(subject) : undefined;
|
|
25
|
+
held.kept = null;
|
|
26
|
+
held.unkept = undefined;
|
|
27
|
+
held.since = mix.sinceOf(voice, held.delay);
|
|
28
|
+
held.shown = mix.shownOf(voice, held.since);
|
|
29
|
+
held.ticks = 0;
|
|
30
|
+
held.stepped = held.since < now ? held.since : now;
|
|
31
|
+
held.probed = Number.NaN;
|
|
32
|
+
}
|
|
33
|
+
/** Whether a seek since its last read moved a stateful record's origin, as one back before it does. */
|
|
34
|
+
function sentBack(mix, voice, held) {
|
|
35
|
+
const p = voice.patch;
|
|
36
|
+
if (p.state === undefined && p.step === undefined && !voice.keeping)
|
|
37
|
+
return false;
|
|
38
|
+
return mix.sinceOf(voice, held.delay) !== held.since;
|
|
39
|
+
}
|
|
40
|
+
/** The phase `elapsed` voice ms puts a voice at, before its start included. */
|
|
41
|
+
function phaseOf(elapsed, duration, passes) {
|
|
42
|
+
return elapsed < 0 ? phaseBefore(elapsed, duration) : phaseAt(elapsed, duration, passes);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* One live voice's delta for one subject this frame, through its record for the subject, or null
|
|
46
|
+
* when it does not reach. Its weight is left in `w`.
|
|
47
|
+
*/
|
|
48
|
+
export function contribution(voice, subject, now, held) {
|
|
49
|
+
held.weight = 0;
|
|
50
|
+
if (!held.reaches)
|
|
51
|
+
return null;
|
|
52
|
+
// Outside its bound the signal reads 0 unread. What a read at weight 0 still does is done there:
|
|
53
|
+
// a patch that steps steps, a `from: 'current'` voice takes its base, and an input is recorded.
|
|
54
|
+
// A read back of recorded inputs reads them, not the bound as it stands now.
|
|
55
|
+
const outside = voice.bound !== null && held.replay === undefined && !inBound(this, voice.bound, subject);
|
|
56
|
+
const recorded = outside && voice.spec.weight.input === true && !!this.opts.history?.inputs;
|
|
57
|
+
if (outside && !recorded && voice.patch.step === undefined && voice.spec.from !== 'current')
|
|
58
|
+
return null;
|
|
59
|
+
if (voice.out?.rest && isRested(held))
|
|
60
|
+
return null;
|
|
61
|
+
if (held.rebuilt !== voice.rebuilds)
|
|
62
|
+
rebuild(this, voice, subject, now, held);
|
|
63
|
+
else if (held.seeks !== voice.seeks && sentBack(this, voice, held)) {
|
|
64
|
+
// A seek sent it back before its start, so it starts afresh there, whatever state it kept.
|
|
65
|
+
rebuild(this, voice, subject, now, held);
|
|
66
|
+
waits(voice, held, now);
|
|
67
|
+
}
|
|
68
|
+
const raw = voice.rawAt(now, held.delay);
|
|
69
|
+
const early = voice.before(raw, now);
|
|
70
|
+
if (early && !voice.holdsFirst)
|
|
71
|
+
return null;
|
|
72
|
+
const elapsed = voice.shownAt(raw);
|
|
73
|
+
if (Number.isNaN(elapsed))
|
|
74
|
+
return null;
|
|
75
|
+
// A frozen subject's clock stands still at the edge it freezes at: -1 before, 1 after, 0 playing.
|
|
76
|
+
const still = early ? -1 : voice.freezesAfter && raw > voice.span ? 1 : 0;
|
|
77
|
+
const duration = voice.duration;
|
|
78
|
+
const pass = passAt(elapsed, duration, voice.passes);
|
|
79
|
+
const primed = this.primed;
|
|
80
|
+
primed[0 /* Primed.NOW */] = now;
|
|
81
|
+
primed[1 /* Primed.ELAPSED */] = elapsed;
|
|
82
|
+
primed[2 /* Primed.PASS */] = pass;
|
|
83
|
+
this.prime(voice, held);
|
|
84
|
+
const setting = voice.setting;
|
|
85
|
+
// A signal that keeps state makes its voice stateful, as a patch that does: a lane would call
|
|
86
|
+
// it for subjects no probe asked about.
|
|
87
|
+
const keptAtWeigh = reading.kept;
|
|
88
|
+
const weight = outside ? 0 : this.weigh(voice, subject, now, held);
|
|
89
|
+
if (recorded)
|
|
90
|
+
record(this, voice, subject, held, 0);
|
|
91
|
+
if (reading.kept !== keptAtWeigh && !voice.keeping)
|
|
92
|
+
stateful(this, voice);
|
|
93
|
+
setting.weight = weight;
|
|
94
|
+
held.weight = weight;
|
|
95
|
+
if (held.probed === now && held.delta && held.seeks === voice.seeks) {
|
|
96
|
+
if (voice.holder !== held && voice.scratch.length > 0)
|
|
97
|
+
this.keyed(voice, subject, held);
|
|
98
|
+
this.w = weight;
|
|
99
|
+
return held.delta;
|
|
100
|
+
}
|
|
101
|
+
const keptBefore = reading.kept;
|
|
102
|
+
const history = this.opts.history;
|
|
103
|
+
if (history?.inputs && voice.patch.reads !== undefined && !this.projecting)
|
|
104
|
+
recordHost(this, now);
|
|
105
|
+
// Only a motion reads it.
|
|
106
|
+
if (voice.motion !== undefined)
|
|
107
|
+
reading.horizon = this.horizonFor(voice, held.delay, now);
|
|
108
|
+
if (voice.patch.step && held.probed !== now) {
|
|
109
|
+
// Frozen after, it steps once more to where its last pass ended, and no further; run back
|
|
110
|
+
// past its start, to where it reached it. Before a start it has yet to reach, it does not step.
|
|
111
|
+
const to = still === 0
|
|
112
|
+
? now
|
|
113
|
+
: still === 1
|
|
114
|
+
? voice.timeAt(held.delay + voice.span)
|
|
115
|
+
: voice.ranBackTo(held.delay, now);
|
|
116
|
+
// Never probed, it may be a record a seek put back, sharing its copy's state until it steps.
|
|
117
|
+
const snaps = held.snaps;
|
|
118
|
+
const sought = Number.isNaN(held.probed) && snaps !== undefined;
|
|
119
|
+
if (!Number.isNaN(to)) {
|
|
120
|
+
if (held.stepped < held.since) {
|
|
121
|
+
held.stepped = held.since;
|
|
122
|
+
setting.dt = this.capped(now - held.since);
|
|
123
|
+
}
|
|
124
|
+
const tick = stepOf(this, voice);
|
|
125
|
+
if (tick !== undefined && sought)
|
|
126
|
+
ahead(this, voice, subject, held, snaps, tick, to);
|
|
127
|
+
if (sought)
|
|
128
|
+
own(voice, held);
|
|
129
|
+
if (tick !== undefined)
|
|
130
|
+
this.tick(voice, subject, held, tick, to);
|
|
131
|
+
else if (still === 0 ? now !== held.stepped : to > held.stepped) {
|
|
132
|
+
if (still !== 0)
|
|
133
|
+
setting.dt = this.capped(to - held.stepped);
|
|
134
|
+
voice.patch.step(held.state, setting.dt, subject, setting);
|
|
135
|
+
held.stepped = to;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else if (sought)
|
|
139
|
+
own(voice, held);
|
|
140
|
+
}
|
|
141
|
+
let delta = null;
|
|
142
|
+
// A keys voice in a role reads at weight 0 too: having a delta makes it a member, and the
|
|
143
|
+
// role folds at its first member's place.
|
|
144
|
+
if (silent(voice, weight) && (voice.built === null || voice.spec.role === undefined)) {
|
|
145
|
+
// A `from: 'current'` voice takes its base on its first read, silent or not.
|
|
146
|
+
if (voice.built && voice.spec.from === 'current' && held.base === undefined) {
|
|
147
|
+
held.base = this.baseFor(voice, subject);
|
|
148
|
+
held.slope = this.slopeFor(voice, subject);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else if (voice.built) {
|
|
152
|
+
held.phase = phaseOf(elapsed, duration, voice.passes);
|
|
153
|
+
delta = this.keyed(voice, subject, held);
|
|
154
|
+
}
|
|
155
|
+
else if (voice.motion !== undefined) {
|
|
156
|
+
delta = moved(voice.motion, voice.patch.writes[0], subject, setting, held);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
const phase = phaseOf(elapsed, duration, voice.passes);
|
|
160
|
+
delta = voice.patch.at(phase, subject, setting);
|
|
161
|
+
if (voice.unchecked)
|
|
162
|
+
checkWrites(voice, delta);
|
|
163
|
+
}
|
|
164
|
+
held.delta = delta;
|
|
165
|
+
held.probed = now;
|
|
166
|
+
held.seeks = voice.seeks;
|
|
167
|
+
if (history !== undefined)
|
|
168
|
+
remember(this, voice, subject, held);
|
|
169
|
+
if (reading.kept !== keptBefore && !voice.keeping)
|
|
170
|
+
stateful(this, voice);
|
|
171
|
+
if (delta === null)
|
|
172
|
+
return null;
|
|
173
|
+
if (voice.out?.rest && this.isRest(delta)) {
|
|
174
|
+
held.weight = 0;
|
|
175
|
+
held.restedAt = now;
|
|
176
|
+
voice.restedCount++;
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
this.w = weight;
|
|
180
|
+
return delta;
|
|
181
|
+
}
|
|
182
|
+
/** Reads a keys voice's stops at `held.phase` into the subject's delta, through the voice's scratch. */
|
|
183
|
+
export function keyed(voice, subject, held) {
|
|
184
|
+
let base;
|
|
185
|
+
if (voice.spec.from === 'current') {
|
|
186
|
+
if (held.base === undefined) {
|
|
187
|
+
held.base = this.baseFor(voice, subject);
|
|
188
|
+
held.slope = this.slopeFor(voice, subject);
|
|
189
|
+
}
|
|
190
|
+
base = held.base;
|
|
191
|
+
}
|
|
192
|
+
const delta = readKeys(voice.built, held.phase, held.delta ?? {}, base, voice.lerps, held.slope, voice.intos, voice.scratch);
|
|
193
|
+
held.delta = delta;
|
|
194
|
+
if (voice.scratch.length > 0)
|
|
195
|
+
voice.holder = held;
|
|
196
|
+
return delta;
|
|
197
|
+
}
|
|
198
|
+
/** How many whole intervals of `tick` a subject's step grid holds by mix time `to`. */
|
|
199
|
+
function dueBy(held, tick, to) {
|
|
200
|
+
// The epsilon keeps an interval like 1000 / 120 from landing a hair short of a whole count.
|
|
201
|
+
return Math.floor((to - held.since) / tick + 1e-9);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* The first step of a record a seek put back from a copy: takes up the furthest state stepped on
|
|
205
|
+
* from that copy that the steps due now run past, the one the record the seek replaced reached or
|
|
206
|
+
* the one the copy was last stepped ahead to, and otherwise keeps the copy's stepped ahead to the
|
|
207
|
+
* moment sought, so a mix sought back time after time does not step from the copy each time, nor a
|
|
208
|
+
* mix sought back and returned step again to where it was. Only where the same steps give the same
|
|
209
|
+
* state: a fixed interval, no `maxDt`, no host field read.
|
|
210
|
+
*/
|
|
211
|
+
function ahead(mix, voice, subject, held, snaps, tick, to) {
|
|
212
|
+
const from = snaps[snaps.length - 1];
|
|
213
|
+
const got = from?.ahead;
|
|
214
|
+
if (from === undefined || got === undefined || got.put !== held)
|
|
215
|
+
return;
|
|
216
|
+
got.put = null;
|
|
217
|
+
const reads = voice.patch.reads;
|
|
218
|
+
if (mix.opts.maxDt !== undefined || (reads !== undefined && reads.length > 0))
|
|
219
|
+
return;
|
|
220
|
+
// Stepped, rebuilt or placed anew since it was put back, its steps are no longer the copy's.
|
|
221
|
+
const was = from.held;
|
|
222
|
+
if (held.ticks !== was.ticks || held.since !== got.since || held.rebuilt !== was.rebuilt)
|
|
223
|
+
return;
|
|
224
|
+
const at = got.sought;
|
|
225
|
+
const due = dueBy(held, tick, to);
|
|
226
|
+
const usable = got.state !== undefined && got.ticks <= due;
|
|
227
|
+
if (got.left !== undefined && got.leftTicks <= due && !(usable && got.ticks > got.leftTicks)) {
|
|
228
|
+
// Taken, not copied: the next seek back keeps the state this record steps on to in its place.
|
|
229
|
+
held.state = got.left;
|
|
230
|
+
got.left = undefined;
|
|
231
|
+
voice.setting.state = held.state;
|
|
232
|
+
held.ticks = got.leftTicks;
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (usable) {
|
|
236
|
+
held.state = copyState(voice, got.state);
|
|
237
|
+
voice.setting.state = held.state;
|
|
238
|
+
held.ticks = got.ticks;
|
|
239
|
+
}
|
|
240
|
+
const last = usable ? got.at : from.at;
|
|
241
|
+
if (!(at < to) || at - last < apart(mix.opts.history))
|
|
242
|
+
return;
|
|
243
|
+
own(voice, held);
|
|
244
|
+
mix.tick(voice, subject, held, tick, at);
|
|
245
|
+
got.state = copyState(voice, held.state);
|
|
246
|
+
got.ticks = held.ticks;
|
|
247
|
+
got.at = at;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* A record a seek put back shares the state of the copy it was made from, which no read changes,
|
|
251
|
+
* until its first probe: before it steps, it takes a copy of its own.
|
|
252
|
+
*/
|
|
253
|
+
function own(voice, held) {
|
|
254
|
+
const snaps = held.snaps;
|
|
255
|
+
const from = snaps[snaps.length - 1];
|
|
256
|
+
if (from !== undefined && held.state !== undefined && held.state === from.held.state) {
|
|
257
|
+
held.state = copyState(voice, held.state);
|
|
258
|
+
voice.setting.state = held.state;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Runs `step` once per whole interval between where this subject last stopped and now, on a grid
|
|
263
|
+
* counted from when its delay ran out, and leaves the remainder for the next sample. Counting
|
|
264
|
+
* rather than adding keeps the grid where it is however many samples it is reached through.
|
|
265
|
+
*/
|
|
266
|
+
export function tick(voice, subject, held, tick, to) {
|
|
267
|
+
const now = this.now;
|
|
268
|
+
const setting = voice.setting;
|
|
269
|
+
const frameDt = setting.dt;
|
|
270
|
+
let n = held.ticks;
|
|
271
|
+
const due = dueBy(held, tick, to);
|
|
272
|
+
const cap = this.opts.maxDt;
|
|
273
|
+
if (cap !== undefined) {
|
|
274
|
+
const most = Math.floor(cap / tick);
|
|
275
|
+
if (due - n > most)
|
|
276
|
+
n = due - most;
|
|
277
|
+
}
|
|
278
|
+
const step = voice.patch.step;
|
|
279
|
+
setting.dt = tick;
|
|
280
|
+
for (n++; n <= due; n++) {
|
|
281
|
+
setting.timestamp = held.since + n * tick;
|
|
282
|
+
step(held.state, tick, subject, setting);
|
|
283
|
+
}
|
|
284
|
+
held.ticks = due > held.ticks ? due : held.ticks;
|
|
285
|
+
held.stepped = held.since + held.ticks * tick;
|
|
286
|
+
setting.timestamp = now;
|
|
287
|
+
setting.dt = frameDt;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Stop 0 for a retargeting voice: the subject's pose in the frame before this voice contributes.
|
|
291
|
+
* With no such frame on record — a voice cued before the subject was ever probed, or a host that
|
|
292
|
+
* samples into its own object — it is this frame's pose with every other voice folded in.
|
|
293
|
+
*/
|
|
294
|
+
export function baseFor(voice, subject) {
|
|
295
|
+
let prior = this.lastPoses.get(subject)?.pose;
|
|
296
|
+
if (prior === undefined && !this.folding.has(voice.id)) {
|
|
297
|
+
this.folding.add(voice.id);
|
|
298
|
+
try {
|
|
299
|
+
prior = this.fold(subject, undefined, false, voice.id);
|
|
300
|
+
}
|
|
301
|
+
finally {
|
|
302
|
+
this.folding.delete(voice.id);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
const base = {};
|
|
306
|
+
for (const key of voice.patch.writes) {
|
|
307
|
+
const channel = this.kit[key];
|
|
308
|
+
const value = prior?.[key];
|
|
309
|
+
const fallback = channel.rest;
|
|
310
|
+
if (value !== undefined)
|
|
311
|
+
base[key] = copy(value);
|
|
312
|
+
else if (fallback !== undefined)
|
|
313
|
+
base[key] = copy(fallback);
|
|
314
|
+
}
|
|
315
|
+
return base;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* How fast each numeric channel this voice writes was moving, from the subject's last two probed
|
|
319
|
+
* poses, in units per ms. Undefined with fewer than two on record, which starts the voice at rest.
|
|
320
|
+
*/
|
|
321
|
+
export function slopeFor(voice, subject) {
|
|
322
|
+
const rec = this.lastPoses.get(subject);
|
|
323
|
+
if (rec?.prev === undefined || !(rec.at > rec.prevAt))
|
|
324
|
+
return undefined;
|
|
325
|
+
const dt = rec.at - rec.prevAt;
|
|
326
|
+
const now = rec.pose;
|
|
327
|
+
const before = rec.prev;
|
|
328
|
+
const slope = {};
|
|
329
|
+
for (const key of voice.patch.writes) {
|
|
330
|
+
const a = before[key];
|
|
331
|
+
const b = now[key];
|
|
332
|
+
if (typeof a === 'number' && typeof b === 'number')
|
|
333
|
+
slope[key] = (b - a) / dt;
|
|
334
|
+
else if (Array.isArray(a) && Array.isArray(b) && a.length === b.length)
|
|
335
|
+
slope[key] = b.map((v, i) => (v - a[i]) / dt);
|
|
336
|
+
}
|
|
337
|
+
return slope;
|
|
338
|
+
}
|
|
339
|
+
export function isRest(delta) {
|
|
340
|
+
for (const key of Object.keys(delta)) {
|
|
341
|
+
if (delta[key] === undefined)
|
|
342
|
+
continue;
|
|
343
|
+
const channel = this.kit[key];
|
|
344
|
+
if (channel.rest === undefined)
|
|
345
|
+
return false;
|
|
346
|
+
if (!near(delta[key], channel.rest))
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
/** `contribution`, or for a dry fold a subject already probed this frame, without advancing it. */
|
|
352
|
+
export function read(voice, subject, now, dry, held) {
|
|
353
|
+
if (dry) {
|
|
354
|
+
if (held.reaches && held.probed === now && held.delta && held.seeks === voice.seeks) {
|
|
355
|
+
const setting = voice.setting;
|
|
356
|
+
// The setting the probe that read the delta had, but for `dt`: a dry read advances nothing.
|
|
357
|
+
const elapsed = voice.shownAt(voice.rawAt(now, held.delay));
|
|
358
|
+
setting.timestamp = now;
|
|
359
|
+
setting.dt = 0;
|
|
360
|
+
setting.elapsed = elapsed;
|
|
361
|
+
setting.pass = passAt(elapsed, voice.duration, voice.passes);
|
|
362
|
+
setting.weight = 0;
|
|
363
|
+
setting.state = held.state;
|
|
364
|
+
setting.mark = 0;
|
|
365
|
+
voice.keepOn = held;
|
|
366
|
+
this.w = this.weigh(voice, subject, now, held);
|
|
367
|
+
held.weight = this.w;
|
|
368
|
+
if (voice.holder !== held && voice.scratch.length > 0)
|
|
369
|
+
this.keyed(voice, subject, held);
|
|
370
|
+
return held.delta;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return this.contribution(voice, subject, now, held);
|
|
374
|
+
}
|
package/dist/copyout.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
|
+
import type { Laned } from './lane.js';
|
|
1
2
|
import type { Lanes } from './lanes.js';
|
|
3
|
+
/** Writes a subject's laned values into a pose. */
|
|
4
|
+
export type Copier = (pose: Record<string, unknown>, slot: number) => void;
|
|
2
5
|
/**
|
|
3
6
|
* Writes a subject's laned values into a pose, each array channel into the array the pose holds
|
|
4
7
|
* for it where that is the length a new one would be, as a host's `out` holds from its last probe.
|
|
5
8
|
*/
|
|
6
9
|
export declare function copy<I, O>(this: Lanes<I, O>, slot: number, pose: Record<string, unknown>): void;
|
|
10
|
+
/** The array to hold an array channel's values for `slot`: `held` written over where it fits. */
|
|
11
|
+
export declare function filled(ch: Laned, slot: number, held: unknown): number[];
|
|
12
|
+
/**
|
|
13
|
+
* A copier for these channels, written out with each channel's name in place: a store under a name
|
|
14
|
+
* that varies boxes every number it writes. Where `Function` is refused, a loop over them.
|
|
15
|
+
*/
|
|
16
|
+
export declare function copier(laned: readonly Laned[]): Copier;
|
package/dist/copyout.js
CHANGED
|
@@ -3,36 +3,81 @@
|
|
|
3
3
|
* for it where that is the length a new one would be, as a host's `out` holds from its last probe.
|
|
4
4
|
*/
|
|
5
5
|
export function copy(slot, pose) {
|
|
6
|
-
|
|
6
|
+
if (this.copier === null)
|
|
7
|
+
this.copier = copier(this.laned);
|
|
8
|
+
this.copier(pose, slot);
|
|
9
|
+
}
|
|
10
|
+
/** The array to hold an array channel's values for `slot`: `held` written over where it fits. */
|
|
11
|
+
export function filled(ch, slot, held) {
|
|
12
|
+
// Made as the general path makes it, a copy of rest, so poses from either path share a shape.
|
|
13
|
+
const start = ch.start;
|
|
14
|
+
const axes = ch.axes;
|
|
15
|
+
const base = slot * axes;
|
|
16
|
+
if (Array.isArray(held) &&
|
|
17
|
+
held !== start &&
|
|
18
|
+
held.length === (start.length > axes ? start.length : axes)) {
|
|
19
|
+
for (let a = 0; a < axes; a++)
|
|
20
|
+
held[a] = ch.values[base + a];
|
|
21
|
+
for (let a = axes; a < start.length; a++)
|
|
22
|
+
held[a] = start[a];
|
|
23
|
+
return held;
|
|
24
|
+
}
|
|
25
|
+
const arr = [...start];
|
|
26
|
+
for (let a = 0; a < axes; a++)
|
|
27
|
+
arr[a] = ch.values[base + a];
|
|
28
|
+
return arr;
|
|
29
|
+
}
|
|
30
|
+
/** Each set of laned channels' copier, made once from its source and bound to the channels. */
|
|
31
|
+
const made = new Map();
|
|
32
|
+
/** `Function` refused once: under a CSP each refusal fires a violation, so it is not asked again. */
|
|
33
|
+
let refused = false;
|
|
34
|
+
/**
|
|
35
|
+
* A copier for these channels, written out with each channel's name in place: a store under a name
|
|
36
|
+
* that varies boxes every number it writes. Where `Function` is refused, a loop over them.
|
|
37
|
+
*/
|
|
38
|
+
export function copier(laned) {
|
|
39
|
+
const lines = [];
|
|
7
40
|
for (let c = 0; c < laned.length; c++) {
|
|
8
41
|
const ch = laned[c];
|
|
9
|
-
const
|
|
42
|
+
const key = `o[${JSON.stringify(ch.name)}]`;
|
|
43
|
+
const at = ch.scalar ? 's' : `s * ${ch.axes}`;
|
|
10
44
|
// Never `delete`: it drops a reused out object into dictionary mode for good.
|
|
11
|
-
|
|
45
|
+
const absent = `if (${key} !== undefined) ${key} = undefined;`;
|
|
46
|
+
const write = ch.scalar
|
|
47
|
+
? `${key} = v;`
|
|
48
|
+
: `{ const h = ${key}, a = f(c${c}, s, h); if (a !== h) ${key} = a; }`;
|
|
49
|
+
lines.push(`{ const v = c${c}.values[${at}];`);
|
|
50
|
+
lines.push(ch.op === 'last' ? `if (v !== v) { ${absent} } else ${write} }` : `${write} }`);
|
|
51
|
+
}
|
|
52
|
+
const body = lines.join('\n');
|
|
53
|
+
let make = made.get(body);
|
|
54
|
+
if (make === undefined && !refused) {
|
|
55
|
+
const bind = laned.map((_, c) => `const c${c} = chans[${c}];`).join(' ');
|
|
56
|
+
try {
|
|
57
|
+
make = new Function('chans', 'f', `${bind}\nreturn function copyLaned(o, s) {\n${body}\n};`);
|
|
58
|
+
made.set(body, make);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
refused = true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return make === undefined ? (pose, slot) => loop(laned, pose, slot) : make(laned, filled);
|
|
65
|
+
}
|
|
66
|
+
function loop(laned, pose, slot) {
|
|
67
|
+
for (let c = 0; c < laned.length; c++) {
|
|
68
|
+
const ch = laned[c];
|
|
69
|
+
const v = ch.values[ch.scalar ? slot : slot * ch.axes];
|
|
70
|
+
if (ch.op === 'last' && Number.isNaN(v)) {
|
|
12
71
|
if (pose[ch.name] !== undefined)
|
|
13
72
|
pose[ch.name] = undefined;
|
|
14
|
-
continue;
|
|
15
|
-
}
|
|
16
|
-
if (ch.scalar) {
|
|
17
|
-
pose[ch.name] = ch.values[slot];
|
|
18
|
-
continue;
|
|
19
73
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
for (let a = 0; a < axes; a++)
|
|
28
|
-
held[a] = ch.values[base + a];
|
|
29
|
-
for (let a = axes; a < start.length; a++)
|
|
30
|
-
held[a] = start[a];
|
|
31
|
-
continue;
|
|
74
|
+
else if (ch.scalar)
|
|
75
|
+
pose[ch.name] = v;
|
|
76
|
+
else {
|
|
77
|
+
const held = pose[ch.name];
|
|
78
|
+
const arr = filled(ch, slot, held);
|
|
79
|
+
if (arr !== held)
|
|
80
|
+
pose[ch.name] = arr;
|
|
32
81
|
}
|
|
33
|
-
const arr = [...start];
|
|
34
|
-
for (let a = 0; a < axes; a++)
|
|
35
|
-
arr[a] = ch.values[base + a];
|
|
36
|
-
pose[ch.name] = arr;
|
|
37
82
|
}
|
|
38
83
|
}
|
package/dist/crowd.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ import { type Laned, type Positions } from './lane.js';
|
|
|
4
4
|
import type { Lanes } from './lanes.js';
|
|
5
5
|
import type { Motions } from './motions.js';
|
|
6
6
|
import type { Scratch } from './patch.js';
|
|
7
|
-
import type { Subject
|
|
7
|
+
import type { Subject } from './subject.js';
|
|
8
|
+
import type { Voice } from './voice.js';
|
|
8
9
|
/**
|
|
9
10
|
* Whether a laned voice belongs in a crowd: one naming a single subject, which shares nothing
|
|
10
11
|
* across subjects for a lane to save. A motion voice writes one channel; a keys or fn voice may
|
|
@@ -24,10 +25,15 @@ export declare const enum Hot {
|
|
|
24
25
|
SEEKS = 5,
|
|
25
26
|
EPOCH = 6,
|
|
26
27
|
ID = 7,
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
/**
|
|
29
|
+
* A `Flag.READY` row's mix time from which its tween has landed, so a fill folds its `to` as it
|
|
30
|
+
* stands; Infinity until `bareRows` sees it land at a positive rate. Unread on any other row.
|
|
31
|
+
*/
|
|
32
|
+
LANDED = 8,
|
|
33
|
+
AT = 9,
|
|
34
|
+
MS = 10,
|
|
29
35
|
/** `x0`, `v0` and `to`, `axes` numbers each. */
|
|
30
|
-
X0 =
|
|
36
|
+
X0 = 11
|
|
31
37
|
}
|
|
32
38
|
/** A crowd row's flags, at `Hot.FLAGS`. */
|
|
33
39
|
export declare const enum Flag {
|
|
@@ -52,7 +58,12 @@ export declare const enum Flag {
|
|
|
52
58
|
/** A keys row whose stops `keys` holds, at `Hot.AT`, with its duration at `Hot.X0` and passes at `Hot.MS`. */
|
|
53
59
|
FLAT = 512,
|
|
54
60
|
/** The row's patch is a tween. */
|
|
55
|
-
TWEEN = 1024
|
|
61
|
+
TWEEN = 1024,
|
|
62
|
+
/**
|
|
63
|
+
* `bareRows` found its stretch numbered, its subject met and its sample `Sampled.BARE`; cleared
|
|
64
|
+
* by `unbare` and `restale`, through which everything that undoes one of those goes.
|
|
65
|
+
*/
|
|
66
|
+
READY = 2048
|
|
56
67
|
}
|
|
57
68
|
/** Whether a row's flags let `bareRows` take it. */
|
|
58
69
|
export declare function bare(f: number): boolean;
|
|
@@ -80,7 +91,6 @@ export declare class Crowd<I, O> implements Positions<I, O> {
|
|
|
80
91
|
eases: (Curve | undefined)[];
|
|
81
92
|
/** Each row's patch law, one array shared by every row whose law is the same. */
|
|
82
93
|
laws: Float64Array[];
|
|
83
|
-
readonly rowOf: Map<number, number>;
|
|
84
94
|
idle: boolean;
|
|
85
95
|
readonly line: {
|
|
86
96
|
stop: number;
|
package/dist/crowd.js
CHANGED
|
@@ -2,7 +2,7 @@ import { bareRows, clock, unbare } from './bare.js';
|
|
|
2
2
|
import { clampWeight, passAt, phaseAt, weighed } from './clock.js';
|
|
3
3
|
import { closed } from './closed.js';
|
|
4
4
|
import { KeyRows } from './keyrows.js';
|
|
5
|
-
import {
|
|
5
|
+
import { keepProbed, SPARSE } from './lane.js';
|
|
6
6
|
import { move } from './sample.js';
|
|
7
7
|
/**
|
|
8
8
|
* Whether a laned voice belongs in a crowd: one naming a single subject, which shares nothing
|
|
@@ -12,7 +12,7 @@ import { move } from './sample.js';
|
|
|
12
12
|
export function crowdable(v) {
|
|
13
13
|
return (v.named !== null &&
|
|
14
14
|
v.named.size === 1 &&
|
|
15
|
-
v.spec.
|
|
15
|
+
v.spec.role === undefined &&
|
|
16
16
|
(v.slots.length === 1 || v.motion === undefined));
|
|
17
17
|
}
|
|
18
18
|
/** The law of a row that has none, a keys or fn voice's. */
|
|
@@ -45,7 +45,6 @@ export class Crowd {
|
|
|
45
45
|
eases = [];
|
|
46
46
|
/** Each row's patch law, one array shared by every row whose law is the same. */
|
|
47
47
|
laws = [];
|
|
48
|
-
rowOf = new Map();
|
|
49
48
|
idle = false;
|
|
50
49
|
line = SPARSE.other;
|
|
51
50
|
/** Where the fill now under way has reached. */
|
|
@@ -69,7 +68,7 @@ export class Crowd {
|
|
|
69
68
|
constructor(chans, axes) {
|
|
70
69
|
this.chans = chans;
|
|
71
70
|
this.axes = axes;
|
|
72
|
-
this.stride =
|
|
71
|
+
this.stride = 11 /* Hot.X0 */ + 3 * axes;
|
|
73
72
|
this.xs = new Float64Array(axes);
|
|
74
73
|
this.vs = new Float64Array(axes);
|
|
75
74
|
}
|
|
@@ -82,7 +81,7 @@ export class Crowd {
|
|
|
82
81
|
numbered() { }
|
|
83
82
|
/** Marks row `p` to copy its stretch from its patch again before the next fill reads it. */
|
|
84
83
|
restale(p, flags) {
|
|
85
|
-
this.hot[p * this.stride + 0 /* Hot.FLAGS */] = flags | 4 /* Flag.STALE */;
|
|
84
|
+
this.hot[p * this.stride + 0 /* Hot.FLAGS */] = (flags | 4 /* Flag.STALE */) & ~2048 /* Flag.READY */;
|
|
86
85
|
this.stale = true;
|
|
87
86
|
this.staleRows.push(p);
|
|
88
87
|
}
|
|
@@ -210,8 +209,7 @@ function rows(lanes, c, first, id) {
|
|
|
210
209
|
const slot = list[p];
|
|
211
210
|
const o = p * 8 /* Row.STRIDE */;
|
|
212
211
|
const q = slot * 6 /* Per.SLOT */;
|
|
213
|
-
|
|
214
|
-
data[o + 3 /* Row.PROBED */] = data[o + 2 /* Row.WEIGHT */];
|
|
212
|
+
keepProbed(data, o, per, q, fills);
|
|
215
213
|
if (lanes.lately >= 0 && lanes.unread(slot))
|
|
216
214
|
continue;
|
|
217
215
|
const delay = data[o + 0 /* Row.DELAY */];
|
|
@@ -219,8 +217,19 @@ function rows(lanes, c, first, id) {
|
|
|
219
217
|
const voice = c.voices[p];
|
|
220
218
|
const elapsedNow = fast ? clock(hot, h, now) : voice.elapsedAt(now);
|
|
221
219
|
let elapsed = elapsedNow - delay;
|
|
220
|
+
// Its freezes applied as `one` applies them, written out: a function for it stays out of line.
|
|
222
221
|
if ((f & 256 /* Flag.FREEZES */) !== 0)
|
|
223
|
-
elapsed =
|
|
222
|
+
elapsed = !(elapsed >= 0)
|
|
223
|
+
? voice.freezesBefore
|
|
224
|
+
? 0
|
|
225
|
+
: Number.NaN
|
|
226
|
+
: elapsed > voice.span
|
|
227
|
+
? voice.hidesPast
|
|
228
|
+
? Number.NaN
|
|
229
|
+
: voice.freezesAfter
|
|
230
|
+
? voice.span
|
|
231
|
+
: elapsed
|
|
232
|
+
: elapsed;
|
|
224
233
|
if (!(elapsed >= 0)) {
|
|
225
234
|
data[o + 2 /* Row.WEIGHT */] = 0;
|
|
226
235
|
continue;
|
|
@@ -245,7 +254,7 @@ function rows(lanes, c, first, id) {
|
|
|
245
254
|
data[o + 2 /* Row.WEIGHT */] = w;
|
|
246
255
|
if ((f & 512 /* Flag.FLAT */) !== 0) {
|
|
247
256
|
if (w > 0)
|
|
248
|
-
c.keys.fold(hot[h +
|
|
257
|
+
c.keys.fold(hot[h + 9 /* Hot.AT */], phaseAt(elapsed, hot[h + 11 /* Hot.X0 */], hot[h + 10 /* Hot.MS */]), c.chans, slot, w);
|
|
249
258
|
continue;
|
|
250
259
|
}
|
|
251
260
|
arg[1 /* Arg.ELAPSED */] = elapsed;
|
|
@@ -275,7 +284,7 @@ function rows(lanes, c, first, id) {
|
|
|
275
284
|
c.restale(p, hot[h + 0 /* Hot.FLAGS */]);
|
|
276
285
|
continue;
|
|
277
286
|
}
|
|
278
|
-
closed(c.laws[p], c.eases[p], n, hot[h +
|
|
287
|
+
closed(c.laws[p], c.eases[p], n, hot[h + 9 /* Hot.AT */], hot[h + 10 /* Hot.MS */], hot, h + 11 /* Hot.X0 */, hot, h + 11 /* Hot.X0 */ + n, hot, h + 11 /* Hot.X0 */ + 2 * n, elapsed, xs, vs);
|
|
279
288
|
for (let a = 0; a < n; a++)
|
|
280
289
|
samples[p * n + a] = xs[a];
|
|
281
290
|
if (c.deltas[p] !== null)
|
|
@@ -372,7 +381,7 @@ function copyStretch(c, p, ms) {
|
|
|
372
381
|
const h = p * c.stride;
|
|
373
382
|
let f = c.hot[h + 0 /* Hot.FLAGS */] & ~(4 /* Flag.STALE */ | 8 /* Flag.BARE */ | 32 /* Flag.FOLDS */);
|
|
374
383
|
const ch = c.chans[0];
|
|
375
|
-
if (run.n === c.axes && run.stretchInto(ms, c.hot, h +
|
|
384
|
+
if (run.n === c.axes && run.stretchInto(ms, c.hot, h + 9 /* Hot.AT */)) {
|
|
376
385
|
f |= 8 /* Flag.BARE */;
|
|
377
386
|
if (run.scalar(ms) === ch.scalar && ch.plain)
|
|
378
387
|
f |= 32 /* Flag.FOLDS */;
|