@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
package/dist/sample.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { unbareLane } from './bare.js';
|
|
2
2
|
import { foldNumber } from './channels.js';
|
|
3
3
|
import { clampWeight, passAt, same, weighed } from './clock.js';
|
|
4
|
+
import { keepProbed } from './lane.js';
|
|
4
5
|
import { absent } from './numbers.js';
|
|
5
6
|
import { reading } from './reading.js';
|
|
6
7
|
import { between, left, progress } from './tweened.js';
|
|
@@ -50,6 +51,11 @@ export function runMotion(lanes, lane, run) {
|
|
|
50
51
|
}
|
|
51
52
|
const own = ease !== undefined && !signal && run.watcher === lanes && run.watchId === voice.id;
|
|
52
53
|
const folds = n === ch.axes && ch.plain;
|
|
54
|
+
// The weight a voice with a fade and no subject ramps gives every subject at one fade: worked
|
|
55
|
+
// out again for a zero, whose sign a hit by `===` would not keep.
|
|
56
|
+
let fadeOf = Number.NaN;
|
|
57
|
+
let baseOf = Number.NaN;
|
|
58
|
+
let faded = 0;
|
|
53
59
|
for (let p = 0; p < list.length; p++) {
|
|
54
60
|
// Its signal just made kept state: no further call this fill, the general path makes them.
|
|
55
61
|
if (signal && voice.keeping)
|
|
@@ -57,8 +63,7 @@ export function runMotion(lanes, lane, run) {
|
|
|
57
63
|
const slot = list[p];
|
|
58
64
|
const o = p * 8 /* Row.STRIDE */;
|
|
59
65
|
const q = slot * 6 /* Per.SLOT */;
|
|
60
|
-
|
|
61
|
-
data[o + 3 /* Row.PROBED */] = data[o + 2 /* Row.WEIGHT */];
|
|
66
|
+
keepProbed(data, o, per, q, fills);
|
|
62
67
|
if (lately >= 0 && lanes.unread(slot)) {
|
|
63
68
|
unbareLane(lane, p);
|
|
64
69
|
continue;
|
|
@@ -89,8 +94,20 @@ export function runMotion(lanes, lane, run) {
|
|
|
89
94
|
}
|
|
90
95
|
w = arg[0 /* Arg.WEIGHT */];
|
|
91
96
|
}
|
|
92
|
-
else
|
|
93
|
-
w =
|
|
97
|
+
else if (parts)
|
|
98
|
+
w = weighed(voice.weight, lane.fade, lanes.parting(voice, slot));
|
|
99
|
+
else if (flat)
|
|
100
|
+
w = whole;
|
|
101
|
+
else {
|
|
102
|
+
const fade = lane.fade;
|
|
103
|
+
const base = voice.weight;
|
|
104
|
+
if (fade !== fadeOf || base !== baseOf || fade === 0 || base === 0) {
|
|
105
|
+
fadeOf = fade;
|
|
106
|
+
baseOf = base;
|
|
107
|
+
faded = weighed(base, fade, 1);
|
|
108
|
+
}
|
|
109
|
+
w = faded;
|
|
110
|
+
}
|
|
94
111
|
data[o + 2 /* Row.WEIGHT */] = w;
|
|
95
112
|
if (data[o + 7 /* Row.MET */] === 0) {
|
|
96
113
|
if (Number.isNaN(records[p].probed)) {
|
|
@@ -101,7 +118,16 @@ export function runMotion(lanes, lane, run) {
|
|
|
101
118
|
data[o + 7 /* Row.MET */] = 1;
|
|
102
119
|
}
|
|
103
120
|
const ms = data[o + 4 /* Row.MSLOT */];
|
|
104
|
-
|
|
121
|
+
// `bareAt` and `scalar` written out: V8 leaves them and `base` out of line here.
|
|
122
|
+
let b = -1;
|
|
123
|
+
let scalar = false;
|
|
124
|
+
if (ms >= 0) {
|
|
125
|
+
b = 5 /* Law.HEAD */ + ms * run.stride;
|
|
126
|
+
const f = run.runs[b + 1];
|
|
127
|
+
if ((f & (2 /* RunFlag.PENDING */ | 4 /* RunFlag.OLDER */)) !== 0)
|
|
128
|
+
b = -1;
|
|
129
|
+
scalar = (f & 1 /* RunFlag.SCALAR */) !== 0;
|
|
130
|
+
}
|
|
105
131
|
if (b < 0 ||
|
|
106
132
|
(probed &&
|
|
107
133
|
(per[q + 3 /* Per.LANE_PROBE */] > from ||
|
|
@@ -113,7 +139,7 @@ export function runMotion(lanes, lane, run) {
|
|
|
113
139
|
continue;
|
|
114
140
|
}
|
|
115
141
|
const runs = run.runs;
|
|
116
|
-
if (own && folds &&
|
|
142
|
+
if (own && folds && scalar === ch.scalar) {
|
|
117
143
|
if (data[o + 5 /* Row.SAMPLED */] !== -2 /* Sampled.BARE */) {
|
|
118
144
|
data[o + 5 /* Row.SAMPLED */] = -2 /* Sampled.BARE */;
|
|
119
145
|
lane.deltas[p] = null;
|
|
@@ -147,7 +173,7 @@ export function runMotion(lanes, lane, run) {
|
|
|
147
173
|
data[o + 6 /* Row.SEEKS */] = seeks;
|
|
148
174
|
if (w <= 0)
|
|
149
175
|
continue;
|
|
150
|
-
if (folds &&
|
|
176
|
+
if (folds && scalar === ch.scalar) {
|
|
151
177
|
const values = ch.values;
|
|
152
178
|
const base = slot * n;
|
|
153
179
|
for (let a = 0; a < n; a++)
|
package/dist/seat.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Crowd } from './crowd.js';
|
|
2
|
+
import type { Voice } from './voice.js';
|
|
3
|
+
/**
|
|
4
|
+
* A crowd voice's row, held on the voice and by its id in its lanes' `seats`: one place to read
|
|
5
|
+
* both its crowd and its row, where two maps by id were two cache misses a stop at 40,000 voices.
|
|
6
|
+
* `lanes` is the lanes it was given in, null once they let it go.
|
|
7
|
+
*/
|
|
8
|
+
export declare class Seat<I, O> {
|
|
9
|
+
lanes: object | null;
|
|
10
|
+
readonly crowd: Crowd<I, O>;
|
|
11
|
+
row: number;
|
|
12
|
+
constructor(lanes: object | null, crowd: Crowd<I, O>, row: number);
|
|
13
|
+
}
|
|
14
|
+
/** `voice`'s seat in `lanes`, null where it has none there. */
|
|
15
|
+
export declare function seatOf<I, O>(lanes: object, voice: Voice<I, O>): Seat<I, O> | null;
|
|
16
|
+
/** Whether row `p` of `c` is `voice`'s seat in `lanes`, not a row it has left. */
|
|
17
|
+
export declare function seated<I, O>(lanes: object, voice: Voice<I, O>, c: Crowd<I, O>, p: number): boolean;
|
package/dist/seat.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A crowd voice's row, held on the voice and by its id in its lanes' `seats`: one place to read
|
|
3
|
+
* both its crowd and its row, where two maps by id were two cache misses a stop at 40,000 voices.
|
|
4
|
+
* `lanes` is the lanes it was given in, null once they let it go.
|
|
5
|
+
*/
|
|
6
|
+
export class Seat {
|
|
7
|
+
lanes;
|
|
8
|
+
crowd;
|
|
9
|
+
row;
|
|
10
|
+
constructor(lanes, crowd, row) {
|
|
11
|
+
this.lanes = lanes;
|
|
12
|
+
this.crowd = crowd;
|
|
13
|
+
this.row = row;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** `voice`'s seat in `lanes`, null where it has none there. */
|
|
17
|
+
export function seatOf(lanes, voice) {
|
|
18
|
+
const s = voice.seat;
|
|
19
|
+
return s !== null && s.lanes === lanes ? s : null;
|
|
20
|
+
}
|
|
21
|
+
/** Whether row `p` of `c` is `voice`'s seat in `lanes`, not a row it has left. */
|
|
22
|
+
export function seated(lanes, voice, c, p) {
|
|
23
|
+
const s = seatOf(lanes, voice);
|
|
24
|
+
return s !== null && s.crowd === c && s.row === p;
|
|
25
|
+
}
|
package/dist/seek.js
CHANGED
|
@@ -9,6 +9,7 @@ import { move, nextFrame } from './move.js';
|
|
|
9
9
|
import { ownerReading } from './owner.js';
|
|
10
10
|
import { place } from './place.js';
|
|
11
11
|
import { unpull } from './pull.js';
|
|
12
|
+
import { isRested } from './record.js';
|
|
12
13
|
import { Restored } from './restored.js';
|
|
13
14
|
import { recount } from './roster.js';
|
|
14
15
|
import { refitAll } from './spans.js';
|
|
@@ -113,8 +114,7 @@ function restore(mix, voice, live, at, every, mine) {
|
|
|
113
114
|
* subject may have rested and moved on since, so a probe at `t` would not find it at rest again.
|
|
114
115
|
*/
|
|
115
116
|
function restedBy(h, live, t) {
|
|
116
|
-
h.
|
|
117
|
-
h.restedAt = h.rested ? live.restedAt : Number.NaN;
|
|
117
|
+
h.restedAt = live.restedAt <= t ? live.restedAt : Number.NaN;
|
|
118
118
|
}
|
|
119
119
|
/** Cuts a record's list of copies to its first `kept`, keeping those no other list holds as spares. */
|
|
120
120
|
function trim(voice, snaps, kept) {
|
|
@@ -196,7 +196,7 @@ function restoreVoice(mix, voice, t, seq) {
|
|
|
196
196
|
return h;
|
|
197
197
|
if (h.reaches)
|
|
198
198
|
voice.seen++;
|
|
199
|
-
if (h
|
|
199
|
+
if (isRested(h))
|
|
200
200
|
voice.restedCount++;
|
|
201
201
|
if (!(h.since <= restored.top)) {
|
|
202
202
|
voice.early ??= [];
|
|
@@ -358,7 +358,7 @@ function back(mix, t, seq, on) {
|
|
|
358
358
|
if (voice.parts !== null || voice.parted !== null)
|
|
359
359
|
mix.parters.add(voice);
|
|
360
360
|
mix.relinks++;
|
|
361
|
-
mix.
|
|
361
|
+
mix.lastPoses = new Store();
|
|
362
362
|
if (mix.restStamps !== null)
|
|
363
363
|
mix.restStamps = new Store();
|
|
364
364
|
unpull(mix);
|
|
@@ -401,7 +401,7 @@ function back(mix, t, seq, on) {
|
|
|
401
401
|
mix.pins.set(voice, voice.pinned);
|
|
402
402
|
}
|
|
403
403
|
refitAll(mix);
|
|
404
|
-
mix.due
|
|
404
|
+
mix.due.clear();
|
|
405
405
|
for (const voice of kept)
|
|
406
406
|
schedule(mix, voice);
|
|
407
407
|
mix.stir();
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Setting } from './types.js';
|
|
2
|
+
import type { Voice } from './voice.js';
|
|
3
|
+
/**
|
|
4
|
+
* A voice's `setting.keep`, one per voice: a setting is valid only during its call, so the state
|
|
5
|
+
* goes on the record of the subject being called for, `keepOn`, or on the voice before any is.
|
|
6
|
+
*/
|
|
7
|
+
export declare function keeping<I, O>(voice: Voice<I, O>): Setting['keep'];
|
|
8
|
+
/**
|
|
9
|
+
* A voice's setting. `keep` is made on first read: most patches keep no state, and a closure and
|
|
10
|
+
* its context per voice cost a one-subject tween voice about 100 bytes.
|
|
11
|
+
*/
|
|
12
|
+
export declare class VoiceSetting<I, O> implements Setting<unknown> {
|
|
13
|
+
host: unknown;
|
|
14
|
+
readonly send: (event: unknown) => void;
|
|
15
|
+
private readonly voice;
|
|
16
|
+
timestamp: number;
|
|
17
|
+
dt: number;
|
|
18
|
+
elapsed: number;
|
|
19
|
+
pass: number;
|
|
20
|
+
weight: number;
|
|
21
|
+
state: unknown;
|
|
22
|
+
/** The `Arg.MARK` a lane last filled `timestamp`, `elapsed` and `pass` under; 0 once anything else writes them. */
|
|
23
|
+
mark: number;
|
|
24
|
+
private kept;
|
|
25
|
+
constructor(host: unknown, send: (event: unknown) => void, voice: Voice<I, O>);
|
|
26
|
+
get keep(): Setting['keep'];
|
|
27
|
+
}
|
package/dist/setting.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { reading } from './reading.js';
|
|
2
|
+
/**
|
|
3
|
+
* A voice's `setting.keep`, one per voice: a setting is valid only during its call, so the state
|
|
4
|
+
* goes on the record of the subject being called for, `keepOn`, or on the voice before any is.
|
|
5
|
+
*/
|
|
6
|
+
export function keeping(voice) {
|
|
7
|
+
return function keep(owner, init) {
|
|
8
|
+
const held = voice.keepOn;
|
|
9
|
+
let kept = held === null ? voice.ownKept : held.kept;
|
|
10
|
+
if (kept === null) {
|
|
11
|
+
kept = new Map();
|
|
12
|
+
if (held === null)
|
|
13
|
+
voice.ownKept = kept;
|
|
14
|
+
else
|
|
15
|
+
held.kept = kept;
|
|
16
|
+
}
|
|
17
|
+
if (kept.has(owner))
|
|
18
|
+
return kept.get(owner);
|
|
19
|
+
const unkept = held?.unkept;
|
|
20
|
+
const made = unkept === undefined ? init() : unkept.shift();
|
|
21
|
+
if (unkept?.length === 0 && held !== null)
|
|
22
|
+
held.unkept = undefined;
|
|
23
|
+
kept.set(owner, made);
|
|
24
|
+
reading.kept++;
|
|
25
|
+
return made;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A voice's setting. `keep` is made on first read: most patches keep no state, and a closure and
|
|
30
|
+
* its context per voice cost a one-subject tween voice about 100 bytes.
|
|
31
|
+
*/
|
|
32
|
+
export class VoiceSetting {
|
|
33
|
+
host;
|
|
34
|
+
send;
|
|
35
|
+
voice;
|
|
36
|
+
timestamp = 0;
|
|
37
|
+
dt = 0;
|
|
38
|
+
elapsed = 0;
|
|
39
|
+
pass = 0;
|
|
40
|
+
weight = 0;
|
|
41
|
+
state = undefined;
|
|
42
|
+
/** The `Arg.MARK` a lane last filled `timestamp`, `elapsed` and `pass` under; 0 once anything else writes them. */
|
|
43
|
+
mark = 0;
|
|
44
|
+
kept = null;
|
|
45
|
+
constructor(host, send, voice) {
|
|
46
|
+
this.host = host;
|
|
47
|
+
this.send = send;
|
|
48
|
+
this.voice = voice;
|
|
49
|
+
}
|
|
50
|
+
get keep() {
|
|
51
|
+
if (this.kept === null)
|
|
52
|
+
this.kept = keeping(this.voice);
|
|
53
|
+
return this.kept;
|
|
54
|
+
}
|
|
55
|
+
}
|
package/dist/shared.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The package version, for a fact whose shape follows the code too closely to version by hand:
|
|
3
3
|
* copies of different releases keep apart. `test/copies.test.ts` holds it to `package.json`.
|
|
4
4
|
*/
|
|
5
|
-
export declare const release = "0.
|
|
5
|
+
export declare const release = "0.15.1";
|
|
6
6
|
/**
|
|
7
7
|
* A WeakMap every copy of blits loaded in one realm shares, so a fact one copy records about a
|
|
8
8
|
* patch or channel it made is read by another copy's mix. The name carries a version, bumped when
|
package/dist/shared.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The package version, for a fact whose shape follows the code too closely to version by hand:
|
|
3
3
|
* copies of different releases keep apart. `test/copies.test.ts` holds it to `package.json`.
|
|
4
4
|
*/
|
|
5
|
-
export const release = '0.
|
|
5
|
+
export const release = '0.15.1';
|
|
6
6
|
/**
|
|
7
7
|
* A WeakMap every copy of blits loaded in one realm shares, so a fact one copy records about a
|
|
8
8
|
* patch or channel it made is read by another copy's mix. The name carries a version, bumped when
|
package/dist/signals.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Setting, Signal } from './types.js';
|
|
1
|
+
import type { Band, Setting, Signal } from './types.js';
|
|
2
2
|
/** Whether a change to an input signal reaches `reading.inputs`, so a lane fill can see it. */
|
|
3
3
|
export declare const heard: (signal: object) => boolean;
|
|
4
4
|
/**
|
|
@@ -10,15 +10,24 @@ export declare function peak<I, H = unknown>(...signals: readonly Signal<I, H>[]
|
|
|
10
10
|
/** A blend member's share of its signal's read `k`: the members' stops sit evenly along 0..1. */
|
|
11
11
|
export declare function shareOf(k: number, i: number, stops: number): number;
|
|
12
12
|
/**
|
|
13
|
-
* Member `i` of `n`'s share of `by`, as `mix.blend` weighs it
|
|
14
|
-
* member's stop, the stops spaced evenly from 0 to 1. Weights a voice outside a blend as one of
|
|
15
|
-
*
|
|
13
|
+
* Member `i` of `n`'s share of `by`, as `mix.blend` weighs it. It is the hat of `by`'s read at the
|
|
14
|
+
* member's stop, the stops spaced evenly from 0 to 1. Weights a voice outside a blend as one of its
|
|
15
|
+
* members, such as one member played alone.
|
|
16
16
|
*
|
|
17
17
|
* @category signal
|
|
18
18
|
*/
|
|
19
19
|
export declare function share<I, H = unknown>(by: Signal<I, H>, i: number, n: number): Signal<I, H>;
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* The signal `input` returns, with `touch` to report a change.
|
|
22
|
+
*
|
|
23
|
+
* @category signal
|
|
24
|
+
*/
|
|
25
|
+
export interface Input<I, H = unknown> extends Signal<I, H> {
|
|
26
|
+
/** Reports a change to what the signal reads. */
|
|
27
|
+
touch(): void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Marks `read` as a signal driven from outside the clock. A host's own signal has to be one for
|
|
22
31
|
* `assess` and a history's `inputs` to treat it as one. Two uses:
|
|
23
32
|
*
|
|
24
33
|
* `input(read)` is an input of the host's own: a pointer, a volume, a value in a store. The host
|
|
@@ -32,54 +41,77 @@ export declare function share<I, H = unknown>(by: Signal<I, H>, i: number, n: nu
|
|
|
32
41
|
*
|
|
33
42
|
* @category signal
|
|
34
43
|
*/
|
|
35
|
-
export declare function input<I, H = unknown>(read: (subject: I, setting: Setting<void, H>) => number, of?: readonly Signal<I, H>[]):
|
|
36
|
-
touch(): void;
|
|
37
|
-
};
|
|
44
|
+
export declare function input<I, H = unknown>(read: (subject: I, setting: Setting<void, H>) => number, of?: readonly Signal<I, H>[]): Input<I, H>;
|
|
38
45
|
/**
|
|
39
|
-
*
|
|
40
|
-
* `level`.
|
|
46
|
+
* The signal `level` returns, with `set` to write it.
|
|
41
47
|
*
|
|
42
48
|
* @category signal
|
|
43
49
|
*/
|
|
44
|
-
export
|
|
50
|
+
export interface Level<I, H = unknown> extends Signal<I, H> {
|
|
51
|
+
/** Writes the level, reporting the change; writing the value it holds already does nothing. */
|
|
45
52
|
set(v: number): void;
|
|
46
|
-
}
|
|
53
|
+
}
|
|
47
54
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
55
|
+
* A signal the host writes. It is `input` over one number, with `set` reporting each change.
|
|
56
|
+
* klieg's `level`.
|
|
57
|
+
*
|
|
58
|
+
* @category signal
|
|
59
|
+
*/
|
|
60
|
+
export declare function level<I, H = unknown>(initial?: number): Level<I, H>;
|
|
61
|
+
/**
|
|
62
|
+
* What `slew` takes.
|
|
52
63
|
*
|
|
53
64
|
* @category signal
|
|
54
65
|
*/
|
|
55
|
-
export
|
|
66
|
+
export interface SlewOptions {
|
|
67
|
+
/** Ms per unit climbing; 0 follows at once. Default 0. */
|
|
56
68
|
riseMs?: number;
|
|
69
|
+
/** Ms per unit draining; 0 follows at once. Default 0. */
|
|
57
70
|
fallMs?: number;
|
|
71
|
+
/** Where a subject starts, unless `dt` is infinite. Default: on its input. */
|
|
58
72
|
from?: number;
|
|
59
|
-
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Follows its input at a rate limit, the package's linear decay primitive. No faster than `riseMs`
|
|
76
|
+
* per unit climbing or `fallMs` draining. The mix keeps its state per voice and subject, so two
|
|
77
|
+
* voices handed the same slew each follow on their own. A subject starts on its input, or at `from`
|
|
78
|
+
* unless `dt` is infinite.
|
|
79
|
+
*
|
|
80
|
+
* @category signal
|
|
81
|
+
*/
|
|
82
|
+
export declare function slew<I, H = unknown>(of: Signal<I, H>, { riseMs, fallMs, from }: SlewOptions): Signal<I, H>;
|
|
60
83
|
/**
|
|
61
|
-
*
|
|
62
|
-
* every equal stretch of time, `1 − exp(−gap / ms)`, so it reads the same however the frames that
|
|
63
|
-
* sample it are spaced while the input holds still. `riseMs` and `fallMs` are time constants: after
|
|
64
|
-
* one, 63% of the way is covered. 0 follows at once. Within `floor` of its input it lands on it, so a
|
|
65
|
-
* subject can reach rest; pass 0 to keep the curve exact. The mix keeps its state per voice and subject.
|
|
66
|
-
* A subject starts on its input, or at `from` unless `dt` is infinite.
|
|
84
|
+
* What `lag` takes.
|
|
67
85
|
*
|
|
68
86
|
* @category signal
|
|
69
87
|
*/
|
|
70
|
-
export
|
|
88
|
+
export interface LagOptions {
|
|
89
|
+
/** The time constant climbing, ms; 0 follows at once. Default 0. */
|
|
71
90
|
riseMs?: number;
|
|
91
|
+
/** The time constant draining, ms; 0 follows at once. Default 0. */
|
|
72
92
|
fallMs?: number;
|
|
93
|
+
/** Within this of its input it lands on it; 0 keeps the curve exact. Default 1e-6. */
|
|
73
94
|
floor?: number;
|
|
95
|
+
/** Where a subject starts, unless `dt` is infinite. Default: on its input. */
|
|
74
96
|
from?: number;
|
|
75
|
-
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Closes the same fraction of the distance to its input in every equal stretch of time. The
|
|
100
|
+
* exponential counterpart to `slew`: the fraction is `1 − exp(−gap / ms)`, so it reads the same
|
|
101
|
+
* however the frames that sample it are spaced while the input holds still. `riseMs` and `fallMs`
|
|
102
|
+
* are time constants: after one, 63% of the way is covered. 0 follows at once. Within `floor` of
|
|
103
|
+
* its input it lands on it, so a subject can reach rest; pass 0 to keep the curve exact. The mix
|
|
104
|
+
* keeps its state per voice and subject. A subject starts on its input, or at `from` unless `dt` is
|
|
105
|
+
* infinite.
|
|
106
|
+
*
|
|
107
|
+
* @category signal
|
|
108
|
+
*/
|
|
109
|
+
export declare function lag<I, H = unknown>(of: Signal<I, H>, { riseMs, fallMs, floor, from }: LagOptions): Signal<I, H>;
|
|
76
110
|
/**
|
|
77
|
-
*
|
|
78
|
-
* the two it holds whatever it last did, so an input resting on
|
|
111
|
+
* Passes or drops its input across a band, not an edge. The other half of the pair. It drops at
|
|
112
|
+
* `off`, passes at `on`, and between the two it holds whatever it last did, so an input resting on
|
|
113
|
+
* a threshold cannot chatter.
|
|
79
114
|
*
|
|
80
115
|
* @category signal
|
|
81
116
|
*/
|
|
82
|
-
export declare function gate<I, H = unknown>(of: Signal<I, H>, band:
|
|
83
|
-
on: number;
|
|
84
|
-
off: number;
|
|
85
|
-
} | number): Signal<I, H>;
|
|
117
|
+
export declare function gate<I, H = unknown>(of: Signal<I, H>, band: Band | number): Signal<I, H>;
|
package/dist/signals.js
CHANGED
|
@@ -33,9 +33,9 @@ export function shareOf(k, i, stops) {
|
|
|
33
33
|
return d >= 1 ? 0 : 1 - d;
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
|
-
* Member `i` of `n`'s share of `by`, as `mix.blend` weighs it
|
|
37
|
-
* member's stop, the stops spaced evenly from 0 to 1. Weights a voice outside a blend as one of
|
|
38
|
-
*
|
|
36
|
+
* Member `i` of `n`'s share of `by`, as `mix.blend` weighs it. It is the hat of `by`'s read at the
|
|
37
|
+
* member's stop, the stops spaced evenly from 0 to 1. Weights a voice outside a blend as one of its
|
|
38
|
+
* members, such as one member played alone.
|
|
39
39
|
*
|
|
40
40
|
* @category signal
|
|
41
41
|
*/
|
|
@@ -48,7 +48,7 @@ const touch = () => {
|
|
|
48
48
|
reading.inputs++;
|
|
49
49
|
};
|
|
50
50
|
/**
|
|
51
|
-
* Marks `read` as a signal driven from outside the clock
|
|
51
|
+
* Marks `read` as a signal driven from outside the clock. A host's own signal has to be one for
|
|
52
52
|
* `assess` and a history's `inputs` to treat it as one. Two uses:
|
|
53
53
|
*
|
|
54
54
|
* `input(read)` is an input of the host's own: a pointer, a volume, a value in a store. The host
|
|
@@ -69,8 +69,8 @@ export function input(read, of) {
|
|
|
69
69
|
return Object.assign(read, { input: true, touch });
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
72
|
-
* A signal the host writes
|
|
73
|
-
* `level`.
|
|
72
|
+
* A signal the host writes. It is `input` over one number, with `set` reporting each change.
|
|
73
|
+
* klieg's `level`.
|
|
74
74
|
*
|
|
75
75
|
* @category signal
|
|
76
76
|
*/
|
|
@@ -93,9 +93,9 @@ const firstSight = (target, from, setting) => from === undefined || !Number.isFi
|
|
|
93
93
|
? { value: target, seen: Number.NaN }
|
|
94
94
|
: { value: from, seen: setting.timestamp };
|
|
95
95
|
/**
|
|
96
|
-
*
|
|
97
|
-
* unit climbing or `fallMs` draining. The mix keeps its state per voice and subject, so two
|
|
98
|
-
* handed the same slew each follow on their own. A subject starts on its input, or at `from`
|
|
96
|
+
* Follows its input at a rate limit, the package's linear decay primitive. No faster than `riseMs`
|
|
97
|
+
* per unit climbing or `fallMs` draining. The mix keeps its state per voice and subject, so two
|
|
98
|
+
* voices handed the same slew each follow on their own. A subject starts on its input, or at `from`
|
|
99
99
|
* unless `dt` is infinite.
|
|
100
100
|
*
|
|
101
101
|
* @category signal
|
|
@@ -123,16 +123,17 @@ export function slew(of, { riseMs = 0, fallMs = 0, from }) {
|
|
|
123
123
|
return marked(read, [of]);
|
|
124
124
|
}
|
|
125
125
|
/**
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* sample it are spaced while the input holds still. `riseMs` and `fallMs`
|
|
129
|
-
* one, 63% of the way is covered. 0 follows at once. Within `floor` of
|
|
130
|
-
* subject can reach rest; pass 0 to keep the curve exact. The mix
|
|
131
|
-
* A subject starts on its input, or at `from` unless `dt` is
|
|
126
|
+
* Closes the same fraction of the distance to its input in every equal stretch of time. The
|
|
127
|
+
* exponential counterpart to `slew`: the fraction is `1 − exp(−gap / ms)`, so it reads the same
|
|
128
|
+
* however the frames that sample it are spaced while the input holds still. `riseMs` and `fallMs`
|
|
129
|
+
* are time constants: after one, 63% of the way is covered. 0 follows at once. Within `floor` of
|
|
130
|
+
* its input it lands on it, so a subject can reach rest; pass 0 to keep the curve exact. The mix
|
|
131
|
+
* keeps its state per voice and subject. A subject starts on its input, or at `from` unless `dt` is
|
|
132
|
+
* infinite.
|
|
132
133
|
*
|
|
133
134
|
* @category signal
|
|
134
135
|
*/
|
|
135
|
-
export function lag(of, { riseMs = 0, fallMs = 0, floor = 1e-6, from
|
|
136
|
+
export function lag(of, { riseMs = 0, fallMs = 0, floor = 1e-6, from }) {
|
|
136
137
|
const read = (subject, setting) => {
|
|
137
138
|
const target = of(subject, setting);
|
|
138
139
|
const held = setting.keep(read, () => firstSight(target, from, setting));
|
|
@@ -155,8 +156,9 @@ export function lag(of, { riseMs = 0, fallMs = 0, floor = 1e-6, from, }) {
|
|
|
155
156
|
return marked(read, [of]);
|
|
156
157
|
}
|
|
157
158
|
/**
|
|
158
|
-
*
|
|
159
|
-
* the two it holds whatever it last did, so an input resting on
|
|
159
|
+
* Passes or drops its input across a band, not an edge. The other half of the pair. It drops at
|
|
160
|
+
* `off`, passes at `on`, and between the two it holds whatever it last did, so an input resting on
|
|
161
|
+
* a threshold cannot chatter.
|
|
160
162
|
*
|
|
161
163
|
* @category signal
|
|
162
164
|
*/
|
package/dist/stack.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { Kit } from './types.js';
|
|
2
2
|
/**
|
|
3
|
-
* Folds deltas into one pose by a kit's arithmetic,
|
|
4
|
-
* gives for voices contributing these deltas at these weights. Each
|
|
5
|
-
* weight (default 1, held to 0..1) fades a delta toward rest, and the
|
|
6
|
-
* channel's bounds. A channel with no rest takes the last delta a mix's
|
|
7
|
-
* weight above 0, and stays undefined where none is.
|
|
3
|
+
* Folds deltas into one pose by a kit's arithmetic, with no mix and no clock. It folds them in
|
|
4
|
+
* order, and gives what a mix gives for voices contributing these deltas at these weights. Each
|
|
5
|
+
* channel starts at its rest, a weight (default 1, held to 0..1) fades a delta toward rest, and the
|
|
6
|
+
* pose is clamped to each channel's bounds. A channel with no rest takes the last delta a mix's
|
|
7
|
+
* default band switches on, any weight above 0, and stays undefined where none is.
|
|
8
8
|
*
|
|
9
9
|
* @category channel
|
|
10
10
|
*/
|
package/dist/stack.js
CHANGED
|
@@ -2,11 +2,11 @@ import { STOCK_BAND } from './channels.js';
|
|
|
2
2
|
import { copy, first } from './clone.js';
|
|
3
3
|
import { bound, merged } from './fold.js';
|
|
4
4
|
/**
|
|
5
|
-
* Folds deltas into one pose by a kit's arithmetic,
|
|
6
|
-
* gives for voices contributing these deltas at these weights. Each
|
|
7
|
-
* weight (default 1, held to 0..1) fades a delta toward rest, and the
|
|
8
|
-
* channel's bounds. A channel with no rest takes the last delta a mix's
|
|
9
|
-
* weight above 0, and stays undefined where none is.
|
|
5
|
+
* Folds deltas into one pose by a kit's arithmetic, with no mix and no clock. It folds them in
|
|
6
|
+
* order, and gives what a mix gives for voices contributing these deltas at these weights. Each
|
|
7
|
+
* channel starts at its rest, a weight (default 1, held to 0..1) fades a delta toward rest, and the
|
|
8
|
+
* pose is clamped to each channel's bounds. A channel with no rest takes the last delta a mix's
|
|
9
|
+
* default band switches on, any weight above 0, and stays undefined where none is.
|
|
10
10
|
*
|
|
11
11
|
* @category channel
|
|
12
12
|
*/
|
package/dist/standing.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { Cut } from './cut.js';
|
|
1
2
|
import type { Mixer } from './mixer.js';
|
|
2
|
-
import type {
|
|
3
|
+
import type { Transport } from './transport.js';
|
|
3
4
|
/**
|
|
4
5
|
* Throws unless a read back to mix time `t` is exact with no history: every voice plays as it was
|
|
5
6
|
* cued and reads the same whenever it is asked, and no mix on the transport has changed since `t`.
|
package/dist/standing.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { mirror } from './ahead.js';
|
|
1
2
|
import { ownBlends } from './blend.js';
|
|
2
3
|
import { relink } from './owner.js';
|
|
3
4
|
import { pin } from './place.js';
|
|
4
|
-
import {
|
|
5
|
+
import { recall, stateAt } from './project.js';
|
|
5
6
|
import { recount } from './roster.js';
|
|
6
7
|
/**
|
|
7
8
|
* Why a voice cannot be read at an earlier time from how it stands now, or undefined where it can:
|
|
@@ -28,7 +29,7 @@ function unfit(mix, voice) {
|
|
|
28
29
|
return 'it plays under an owner';
|
|
29
30
|
// A rest-less channel switches on across a band, by the weights its voice has passed through.
|
|
30
31
|
const steady = typeof spec.weight !== 'function' &&
|
|
31
|
-
spec.
|
|
32
|
+
spec.role === undefined &&
|
|
32
33
|
!((voice.fade.in ?? 0) > 0) &&
|
|
33
34
|
!((voice.fade.out ?? 0) > 0);
|
|
34
35
|
if (!steady && voice.slots.some((s) => mix.channels[s]?.rest === undefined))
|
package/dist/store.d.ts
CHANGED
|
@@ -33,3 +33,12 @@ export declare class Masked<K, V> extends Store<K, V> {
|
|
|
33
33
|
get(key: K): V | undefined;
|
|
34
34
|
delete(key: K): void;
|
|
35
35
|
}
|
|
36
|
+
/** A store that fills a missing entry from `make` on first ask. */
|
|
37
|
+
export declare class Filled<K, V> extends Store<K, V> {
|
|
38
|
+
private readonly make;
|
|
39
|
+
/** Keys deleted here, which are made afresh by whoever asks and never again by `make`. */
|
|
40
|
+
private gone;
|
|
41
|
+
constructor(make: (key: K) => V | undefined);
|
|
42
|
+
get(key: K): V | undefined;
|
|
43
|
+
delete(key: K): void;
|
|
44
|
+
}
|
package/dist/store.js
CHANGED
|
@@ -89,3 +89,27 @@ export class Masked extends Store {
|
|
|
89
89
|
const none = Symbol('none');
|
|
90
90
|
/** A Map's key equality, SameValueZero: NaN finds NaN. */
|
|
91
91
|
const same = (a, b) => a === b || Object.is(a, b);
|
|
92
|
+
/** A store that fills a missing entry from `make` on first ask. */
|
|
93
|
+
export class Filled extends Store {
|
|
94
|
+
make;
|
|
95
|
+
/** Keys deleted here, which are made afresh by whoever asks and never again by `make`. */
|
|
96
|
+
gone = null;
|
|
97
|
+
constructor(make) {
|
|
98
|
+
super();
|
|
99
|
+
this.make = make;
|
|
100
|
+
}
|
|
101
|
+
get(key) {
|
|
102
|
+
let v = super.get(key);
|
|
103
|
+
if (v === undefined && this.gone?.get(key) !== true) {
|
|
104
|
+
v = this.make(key);
|
|
105
|
+
if (v !== undefined)
|
|
106
|
+
super.set(key, v);
|
|
107
|
+
}
|
|
108
|
+
return v;
|
|
109
|
+
}
|
|
110
|
+
delete(key) {
|
|
111
|
+
super.delete(key);
|
|
112
|
+
this.gone ??= new Store();
|
|
113
|
+
this.gone.set(key, true);
|
|
114
|
+
}
|
|
115
|
+
}
|
package/dist/strays.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Mixer } from './mixer.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { Motions } from './motions.js';
|
|
3
|
+
import type { MotionOwner } from './stretch.js';
|
|
3
4
|
import type { Voice } from './voice.js';
|
|
4
5
|
/** Notes a motion patch that may hold state for a subject no voice playing it reaches. */
|
|
5
6
|
export declare function stray<I, O>(mix: Mixer<I, O>, motion: Motions<I>, subject: I): void;
|