@msb235/blits 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +196 -0
- package/README.md +22 -4
- package/dist/book.js +4 -4
- package/dist/chain.d.ts +1 -1
- package/dist/chain.js +57 -54
- package/dist/channels.d.ts +26 -5
- package/dist/channels.js +12 -8
- package/dist/clock.d.ts +8 -1
- package/dist/clock.js +14 -3
- package/dist/clone.d.ts +3 -0
- package/dist/clone.js +16 -1
- package/dist/closed.d.ts +1 -1
- package/dist/closed.js +3 -2
- package/dist/color.d.ts +0 -11
- package/dist/color.js +4 -24
- package/dist/columns.js +0 -1
- package/dist/copyout.d.ts +6 -0
- package/dist/copyout.js +38 -0
- package/dist/crowd.d.ts +7 -5
- package/dist/crowd.js +32 -18
- package/dist/cue.d.ts +3 -1
- package/dist/cue.js +33 -20
- package/dist/departed.d.ts +34 -0
- package/dist/departed.js +73 -0
- package/dist/easing.d.ts +5 -0
- package/dist/easing.js +31 -2
- package/dist/everyone.d.ts +56 -0
- package/dist/everyone.js +221 -0
- package/dist/fade.d.ts +8 -1
- package/dist/fade.js +36 -6
- package/dist/fill.d.ts +22 -13
- package/dist/fill.js +104 -41
- package/dist/fit.js +2 -1
- package/dist/fold.d.ts +37 -0
- package/dist/fold.js +213 -28
- package/dist/gather.d.ts +15 -9
- package/dist/gather.js +60 -25
- package/dist/gone.d.ts +32 -0
- package/dist/gone.js +144 -0
- package/dist/handle.d.ts +16 -5
- package/dist/handle.js +56 -6
- package/dist/held.d.ts +8 -5
- package/dist/held.js +56 -58
- package/dist/history.d.ts +17 -13
- package/dist/history.js +49 -28
- package/dist/hosts.js +57 -9
- package/dist/index.d.ts +9 -4
- package/dist/index.js +5 -2
- package/dist/keyfill.d.ts +7 -0
- package/dist/keyfill.js +124 -0
- package/dist/keyrows.d.ts +1 -0
- package/dist/keyrows.js +1 -1
- package/dist/lane.d.ts +32 -2
- package/dist/lane.js +5 -0
- package/dist/lanes.d.ts +32 -8
- package/dist/lanes.js +69 -37
- package/dist/leavings.d.ts +26 -0
- package/dist/leavings.js +70 -0
- package/dist/meet.js +14 -8
- package/dist/mixer.d.ts +43 -7
- package/dist/mixer.js +60 -11
- package/dist/motion.d.ts +2 -0
- package/dist/motion.js +4 -1
- package/dist/motions.d.ts +22 -15
- package/dist/motions.js +40 -34
- package/dist/move.js +31 -20
- package/dist/moved.d.ts +11 -0
- package/dist/moved.js +29 -0
- package/dist/origin.d.ts +19 -0
- package/dist/origin.js +68 -0
- package/dist/owed.d.ts +4 -4
- package/dist/owed.js +8 -8
- package/dist/owner.d.ts +1 -1
- package/dist/owner.js +2 -2
- package/dist/pace.d.ts +13 -5
- package/dist/pace.js +21 -8
- package/dist/pack.d.ts +3 -1
- package/dist/pack.js +15 -24
- package/dist/paging.d.ts +8 -2
- package/dist/paging.js +44 -4
- package/dist/patch.d.ts +14 -9
- package/dist/patch.js +83 -21
- package/dist/place.js +188 -30
- package/dist/project.d.ts +12 -1
- package/dist/project.js +101 -83
- package/dist/pull.d.ts +2 -0
- package/dist/pull.js +8 -0
- package/dist/qualify.js +10 -2
- package/dist/reading.d.ts +5 -0
- package/dist/reading.js +5 -0
- package/dist/record.d.ts +9 -0
- package/dist/record.js +42 -0
- package/dist/relink.d.ts +11 -5
- package/dist/relink.js +7 -5
- package/dist/restored.d.ts +41 -0
- package/dist/restored.js +91 -0
- package/dist/revive.d.ts +10 -3
- package/dist/revive.js +31 -23
- package/dist/roster.d.ts +11 -0
- package/dist/roster.js +46 -0
- package/dist/rotation.d.ts +29 -0
- package/dist/rotation.js +91 -0
- package/dist/rows.d.ts +5 -5
- package/dist/rows.js +5 -5
- package/dist/sample.d.ts +3 -2
- package/dist/sample.js +32 -15
- package/dist/scored.d.ts +57 -0
- package/dist/scored.js +196 -0
- package/dist/seek.js +97 -114
- package/dist/shared.d.ts +6 -0
- package/dist/shared.js +15 -0
- package/dist/signals.d.ts +24 -3
- package/dist/signals.js +50 -11
- package/dist/spans.js +7 -0
- package/dist/stack.d.ts +11 -0
- package/dist/stack.js +47 -0
- package/dist/standing.d.ts +10 -0
- package/dist/standing.js +79 -0
- package/dist/store.d.ts +3 -3
- package/dist/store.js +3 -3
- package/dist/strays.js +3 -0
- package/dist/tape.d.ts +8 -5
- package/dist/tape.js +21 -13
- package/dist/testing.d.ts +35 -0
- package/dist/testing.js +116 -0
- package/dist/touch.d.ts +6 -0
- package/dist/touch.js +28 -0
- package/dist/transport.d.ts +53 -6
- package/dist/transport.js +102 -20
- package/dist/turns.d.ts +18 -0
- package/dist/turns.js +72 -0
- package/dist/tweened.js +1 -1
- package/dist/types/channel.d.ts +46 -0
- package/dist/types/channel.js +1 -0
- package/dist/types/history.d.ts +139 -0
- package/dist/types/history.js +1 -0
- package/dist/types/mix.d.ts +336 -0
- package/dist/types/mix.js +1 -0
- package/dist/types/patch.d.ts +187 -0
- package/dist/types/patch.js +1 -0
- package/dist/types/place.d.ts +157 -0
- package/dist/types/place.js +1 -0
- package/dist/types/transport.d.ts +71 -0
- package/dist/types/transport.js +1 -0
- package/dist/types/voice.d.ts +323 -0
- package/dist/types/voice.js +1 -0
- package/dist/types.d.ts +7 -1162
- package/dist/unpage.d.ts +2 -2
- package/dist/unpage.js +55 -25
- package/dist/voice.d.ts +92 -22
- package/dist/voice.js +108 -43
- package/dist/wave.d.ts +42 -0
- package/dist/wave.js +62 -0
- package/dist/weigh.js +1 -1
- package/docs/schema.html +42 -36
- package/package.json +8 -3
package/dist/voice.js
CHANGED
|
@@ -3,7 +3,7 @@ import { curve } from './easing.js';
|
|
|
3
3
|
import { motionOf } from './motion.js';
|
|
4
4
|
import { Named } from './named.js';
|
|
5
5
|
import { childPlayed, Holding, mixTime, ownedElapsed, ownerPatch } from './owner.js';
|
|
6
|
-
import { builtOf,
|
|
6
|
+
import { builtOf, intosOf } from './patch.js';
|
|
7
7
|
import { reading } from './reading.js';
|
|
8
8
|
import { Store } from './store.js';
|
|
9
9
|
export const none = Object.freeze([]);
|
|
@@ -118,17 +118,32 @@ export class Voice {
|
|
|
118
118
|
holder = null;
|
|
119
119
|
/** Whether its channels run as lanes this frame, so the general fold passes it by. */
|
|
120
120
|
laned = false;
|
|
121
|
-
/**
|
|
121
|
+
/**
|
|
122
|
+
* How many times it has been sought or touched, so a delta read before either is not handed out
|
|
123
|
+
* after it.
|
|
124
|
+
*/
|
|
122
125
|
seeks = 0;
|
|
126
|
+
/** Whether the host has written to its handle, so it no longer plays as it was cued. */
|
|
127
|
+
written = false;
|
|
128
|
+
/** How many of `seeks` were the mix's `touch`, which moves no clock. */
|
|
129
|
+
touches = 0;
|
|
130
|
+
/** How many times its clock has jumped, which a booker counts hits again from. */
|
|
131
|
+
get jumps() {
|
|
132
|
+
return this.seeks - this.touches;
|
|
133
|
+
}
|
|
134
|
+
/** Seeks that rebuild state; a record stamped with fewer makes its state again before stepping. */
|
|
135
|
+
rebuilds = 0;
|
|
136
|
+
/** Whether its span's last fit jumped it to its end, which leaves it no time in that fit. */
|
|
137
|
+
skipped = false;
|
|
123
138
|
/** Whether its patch has kept state on a record through `setting.keep`, which makes it stateful. */
|
|
124
139
|
keeping = false;
|
|
125
140
|
/** Subjects fading out of this voice alone, by the ramp each started; null while none are. */
|
|
126
141
|
parts = null;
|
|
127
|
-
/** Subjects faded out of this voice, by the mix time each left at; null while none have. */
|
|
142
|
+
/** Subjects faded out of this voice, by the mix time and frame each left at; null while none have. */
|
|
128
143
|
parted = null;
|
|
129
144
|
/**
|
|
130
|
-
* Under history, the records of subjects that left this voice, by the mix time
|
|
131
|
-
* while a seek or a read back may reach them; null while none have.
|
|
145
|
+
* Under history, the records of subjects that left this voice, by the mix time and frame each
|
|
146
|
+
* left at, while a seek or a read back may reach them; null while none have.
|
|
132
147
|
*/
|
|
133
148
|
left = null;
|
|
134
149
|
ease;
|
|
@@ -146,8 +161,13 @@ export class Voice {
|
|
|
146
161
|
opened = Number.NaN;
|
|
147
162
|
/** Which of its entries in the mix's due queue is current; older ones are skipped when popped. */
|
|
148
163
|
dueToken = 0;
|
|
149
|
-
/**
|
|
164
|
+
/**
|
|
165
|
+
* Records whose `since` was still ahead when last worked out, which a later start, rate change
|
|
166
|
+
* or seek moves; null while none are.
|
|
167
|
+
*/
|
|
150
168
|
early = null;
|
|
169
|
+
/** The clocks it ran on before its current one, where a subject's origin may lie; null for none. */
|
|
170
|
+
clocks = null;
|
|
151
171
|
/** Reused for every call this voice makes, so it is valid only during the call. */
|
|
152
172
|
setting;
|
|
153
173
|
/** Every subject this voice has been asked about, so a handover knows when it is finished. */
|
|
@@ -157,8 +177,12 @@ export class Voice {
|
|
|
157
177
|
restedCount = 0;
|
|
158
178
|
/** The mix time it was cued at; -Infinity before the first sync. */
|
|
159
179
|
cuedAt = Number.NEGATIVE_INFINITY;
|
|
160
|
-
/** The
|
|
180
|
+
/** The frame it was cued in. */
|
|
181
|
+
cuedSeq = Number.NEGATIVE_INFINITY;
|
|
182
|
+
/** The mix time it left at, which a fade or seek given a time already passed puts behind now. */
|
|
161
183
|
doneAt = Number.POSITIVE_INFINITY;
|
|
184
|
+
/** The frame its leaving was decided in, which a seek or read back partitions by. */
|
|
185
|
+
doneSeq = Number.POSITIVE_INFINITY;
|
|
162
186
|
/** Under `history`, its controls after each change, oldest first. */
|
|
163
187
|
log = null;
|
|
164
188
|
/** Under `history`, its controls as `cue` left them, which a voice parked by a seek takes back. */
|
|
@@ -175,6 +199,8 @@ export class Voice {
|
|
|
175
199
|
placing = false;
|
|
176
200
|
/** What each member of a join last answered, kept for once its target has left. */
|
|
177
201
|
answers = null;
|
|
202
|
+
/** What each of its anchors' queries has read of each mix's gone voices (`place.ts`'s `Fold`). */
|
|
203
|
+
folds = null;
|
|
178
204
|
/** The record `setting.keep` writes to: the one its patch or signal is being called for. */
|
|
179
205
|
keepOn = null;
|
|
180
206
|
/** What `setting.keep` holds when called before any record is. */
|
|
@@ -185,6 +211,20 @@ export class Voice {
|
|
|
185
211
|
unreached = null;
|
|
186
212
|
/** By subject number, a bit set where `unreached` stands for the subject; null until one is. */
|
|
187
213
|
unreachedBits = null;
|
|
214
|
+
/** Whether one record stands for every subject: see `shares` in `everyone.ts`. */
|
|
215
|
+
sharing = false;
|
|
216
|
+
/** That record, null until a chain first asks and once the voice shares no more. */
|
|
217
|
+
everyone = null;
|
|
218
|
+
/** While sharing, by subject number: a bit where a chain has asked about the subject. */
|
|
219
|
+
sighted = null;
|
|
220
|
+
/** While sharing, by subject number: the weight last given the subject on the general path. */
|
|
221
|
+
weights = null;
|
|
222
|
+
/**
|
|
223
|
+
* While sharing a patch that is called, by subject number: when it was last called for the
|
|
224
|
+
* subject and at what `seeks`, side by side, and the delta that call gave.
|
|
225
|
+
*/
|
|
226
|
+
stamps = null;
|
|
227
|
+
deltas = null;
|
|
188
228
|
/** The handle `cue` returned, which `voices` hands back too. */
|
|
189
229
|
handle = null;
|
|
190
230
|
/** With a history store, the key of every subject it has a record of; null without one. */
|
|
@@ -199,8 +239,10 @@ export class Voice {
|
|
|
199
239
|
*/
|
|
200
240
|
finished = false;
|
|
201
241
|
playedAs = undefined;
|
|
202
|
-
/** The mix time `played` was settled at
|
|
242
|
+
/** The mix time `played` was settled at. */
|
|
203
243
|
playedAt = Number.NaN;
|
|
244
|
+
/** The frame `played` was settled in, so a seek back to before it can open it again. */
|
|
245
|
+
playedSeq = Number.NaN;
|
|
204
246
|
donePromise = null;
|
|
205
247
|
doneSettle = null;
|
|
206
248
|
playedPromise = null;
|
|
@@ -239,18 +281,19 @@ export class Voice {
|
|
|
239
281
|
* Its finite loop ended (true) or it left first (false), whichever comes first, noticed at mix
|
|
240
282
|
* time `at`: `played` resolves.
|
|
241
283
|
*/
|
|
242
|
-
play(played, at) {
|
|
284
|
+
play(played, at, seq) {
|
|
243
285
|
if (this.quiet || this.playedAs !== undefined)
|
|
244
286
|
return;
|
|
245
287
|
this.playedAs = played;
|
|
246
288
|
this.playedAt = at;
|
|
289
|
+
this.playedSeq = seq;
|
|
247
290
|
this.playedSettle?.(played);
|
|
248
291
|
if (played && this.owner !== null)
|
|
249
|
-
childPlayed(this.owner, at);
|
|
292
|
+
childPlayed(this.owner, at, seq);
|
|
250
293
|
}
|
|
251
|
-
/** How `played` settled, and the mix time it did; undefined while it has not. */
|
|
294
|
+
/** How `played` settled, and the mix time and frame it did; undefined while it has not. */
|
|
252
295
|
get settled() {
|
|
253
|
-
return { played: this.playedAs, at: this.playedAt };
|
|
296
|
+
return { played: this.playedAs, at: this.playedAt, seq: this.playedSeq };
|
|
254
297
|
}
|
|
255
298
|
/** Whether `played` settled true, which its owner counted. */
|
|
256
299
|
get passed() {
|
|
@@ -261,42 +304,50 @@ export class Voice {
|
|
|
261
304
|
return this.playedAs === false;
|
|
262
305
|
}
|
|
263
306
|
/**
|
|
264
|
-
* A seek back to
|
|
307
|
+
* A seek back to frame `seq`: `done` and `played`, where they settled after it, start over with
|
|
265
308
|
* fresh promises. True where `played` had settled true, which its owner counted.
|
|
266
309
|
*/
|
|
267
|
-
reopen(
|
|
310
|
+
reopen(seq) {
|
|
268
311
|
let unplayed = false;
|
|
269
|
-
if (this.playedAs !== undefined && !(this.
|
|
312
|
+
if (this.playedAs !== undefined && !(this.playedSeq <= seq)) {
|
|
270
313
|
unplayed = this.playedAs;
|
|
271
314
|
this.playedAs = undefined;
|
|
272
315
|
this.playedPromise = null;
|
|
273
316
|
this.playedSettle = null;
|
|
274
317
|
}
|
|
275
|
-
if (this.finished && !(this.
|
|
318
|
+
if (this.finished && !(this.doneSeq <= seq)) {
|
|
276
319
|
this.finished = false;
|
|
277
320
|
this.donePromise = null;
|
|
278
321
|
this.doneSettle = null;
|
|
279
322
|
}
|
|
280
323
|
return unplayed;
|
|
281
324
|
}
|
|
282
|
-
/**
|
|
283
|
-
|
|
284
|
-
* again. What it played since is forgotten, and `done` and `played` start over where they had
|
|
285
|
-
* settled.
|
|
286
|
-
*/
|
|
287
|
-
park() {
|
|
288
|
-
this.reopen(Number.NEGATIVE_INFINITY);
|
|
289
|
-
const c = this.first;
|
|
325
|
+
/** Takes on a set of controls: its clock, weight, fades and where its anchors put it. */
|
|
326
|
+
take(c) {
|
|
290
327
|
this.anchorNow = c.anchorNow;
|
|
291
328
|
this.anchorElapsed = c.anchorElapsed;
|
|
292
329
|
this.rate = c.rate;
|
|
293
330
|
this.ramp = c.ramp;
|
|
294
331
|
this.weight = c.weight;
|
|
295
332
|
this.out = c.out;
|
|
333
|
+
this.back = c.back;
|
|
296
334
|
this.start = c.start;
|
|
297
335
|
this.outAt = c.outAt;
|
|
298
336
|
this.outOver = c.outOver;
|
|
299
337
|
this.outSet = c.outSet;
|
|
338
|
+
this.rebuilds = c.rebuilds;
|
|
339
|
+
const clocks = this.clocks;
|
|
340
|
+
if (clocks !== null && clocks.length !== c.past)
|
|
341
|
+
this.clocks = c.past === 0 ? null : clocks.slice(0, c.past);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* A seek back to before its cue: out of the mix, as `cue` left it, until the mix plays the cue
|
|
345
|
+
* again. What it played since is forgotten, and `done` and `played` start over where they had
|
|
346
|
+
* settled.
|
|
347
|
+
*/
|
|
348
|
+
park() {
|
|
349
|
+
this.reopen(Number.NEGATIVE_INFINITY);
|
|
350
|
+
this.take(this.first);
|
|
300
351
|
this.log = null;
|
|
301
352
|
this.state = 'pending';
|
|
302
353
|
this.subjects = new Store();
|
|
@@ -314,13 +365,22 @@ export class Voice {
|
|
|
314
365
|
this.latest = 0;
|
|
315
366
|
this.restedCount = 0;
|
|
316
367
|
this.cuedAt = Number.NEGATIVE_INFINITY;
|
|
368
|
+
this.cuedSeq = Number.NEGATIVE_INFINITY;
|
|
317
369
|
this.doneAt = Number.POSITIVE_INFINITY;
|
|
370
|
+
this.doneSeq = Number.POSITIVE_INFINITY;
|
|
318
371
|
this.placing = false;
|
|
319
372
|
this.answers = null;
|
|
373
|
+
this.folds = null;
|
|
320
374
|
this.keepOn = null;
|
|
321
375
|
this.ownKept = null;
|
|
322
376
|
this.unreached = null;
|
|
323
377
|
this.unreachedBits = null;
|
|
378
|
+
this.sharing = false;
|
|
379
|
+
this.everyone = null;
|
|
380
|
+
this.sighted = null;
|
|
381
|
+
this.weights = null;
|
|
382
|
+
this.stamps = null;
|
|
383
|
+
this.deltas = null;
|
|
324
384
|
if (this.holding !== null)
|
|
325
385
|
this.holding = new Holding();
|
|
326
386
|
}
|
|
@@ -343,13 +403,13 @@ export class Voice {
|
|
|
343
403
|
: undefined;
|
|
344
404
|
this.ease = fade.ease === undefined ? undefined : curve(fade.ease);
|
|
345
405
|
this.passes = passesOf(spec.loop);
|
|
346
|
-
this.duration =
|
|
406
|
+
this.duration = patch.duration;
|
|
347
407
|
this.span =
|
|
348
408
|
this.duration > 0 && Number.isFinite(this.passes)
|
|
349
409
|
? this.duration * this.passes
|
|
350
410
|
: Number.POSITIVE_INFINITY;
|
|
351
411
|
this.motion = motionOf(patch);
|
|
352
|
-
const freezes = this.motion === undefined ?
|
|
412
|
+
const freezes = this.motion === undefined ? spec.freeze : undefined;
|
|
353
413
|
// A voice with no freeze of its own takes its owner's.
|
|
354
414
|
const inherits = freezes === undefined && this.motion === undefined && owner !== null;
|
|
355
415
|
this.freezesBefore = inherits
|
|
@@ -372,10 +432,11 @@ export class Voice {
|
|
|
372
432
|
const t = timeWith(this, elapsed);
|
|
373
433
|
return this.owner === null ? t : mixTime(this.owner, t);
|
|
374
434
|
}
|
|
375
|
-
/** Records this voice's controls as they stand, from mix time `at`. */
|
|
376
|
-
note(at, sync = false) {
|
|
435
|
+
/** Records this voice's controls as they stand, from mix time `at` in frame `seq`. */
|
|
436
|
+
note(at, seq, sync = false) {
|
|
377
437
|
this.log?.push({
|
|
378
438
|
at,
|
|
439
|
+
seq,
|
|
379
440
|
sync,
|
|
380
441
|
anchorNow: this.anchorNow,
|
|
381
442
|
anchorElapsed: this.anchorElapsed,
|
|
@@ -388,13 +449,17 @@ export class Voice {
|
|
|
388
449
|
outAt: this.outAt,
|
|
389
450
|
outOver: this.outOver,
|
|
390
451
|
outSet: this.outSet,
|
|
452
|
+
rebuilds: this.rebuilds,
|
|
453
|
+
past: this.clocks?.length ?? 0,
|
|
391
454
|
});
|
|
392
455
|
}
|
|
393
456
|
/**
|
|
394
457
|
* A copy for a projection: its own setting, which sends nothing, and its own per-subject records,
|
|
395
|
-
* filled from `fill`. With `controls` it takes those, as the voice stood at an earlier time.
|
|
458
|
+
* filled from `fill`. With `controls` it takes those, as the voice stood at an earlier time. With
|
|
459
|
+
* `share`, a voice keeping one record for every subject gives its copy a copy of that one, which
|
|
460
|
+
* a read ahead starts every subject from; `fill` then serves only a copy that shares no more.
|
|
396
461
|
*/
|
|
397
|
-
copy(fill, controls) {
|
|
462
|
+
copy(fill, controls, share = false) {
|
|
398
463
|
// A literal keeps the copy in fast mode, where `Object.assign` left it a dictionary that every
|
|
399
464
|
// read in a projection looked up by name.
|
|
400
465
|
const v = { __proto__: Voice.prototype, ...this };
|
|
@@ -408,22 +473,22 @@ export class Voice {
|
|
|
408
473
|
v.laned = false;
|
|
409
474
|
v.log = null;
|
|
410
475
|
v.early = null;
|
|
411
|
-
if (controls)
|
|
412
|
-
v.
|
|
413
|
-
|
|
414
|
-
v.
|
|
415
|
-
v.ramp = controls.ramp;
|
|
416
|
-
v.weight = controls.weight;
|
|
417
|
-
v.out = controls.out;
|
|
418
|
-
v.back = controls.back;
|
|
419
|
-
v.start = controls.start;
|
|
420
|
-
v.outAt = controls.outAt;
|
|
421
|
-
v.outOver = controls.outOver;
|
|
422
|
-
v.outSet = controls.outSet;
|
|
423
|
-
}
|
|
476
|
+
if (controls)
|
|
477
|
+
v.take(controls);
|
|
478
|
+
if (v.clocks === this.clocks && v.clocks !== null)
|
|
479
|
+
v.clocks = v.clocks.slice();
|
|
424
480
|
v.quiet = true;
|
|
425
481
|
v.unreached = null;
|
|
426
482
|
v.unreachedBits = null;
|
|
483
|
+
const all = share && this.sharing ? this.everyone : null;
|
|
484
|
+
v.sharing = all !== null;
|
|
485
|
+
// Its delta is the live voice's to write into, and a keys voice's is in the live scratch.
|
|
486
|
+
v.everyone =
|
|
487
|
+
all === null ? null : { ...all, delta: null, probed: Number.NaN, from: all.stepped };
|
|
488
|
+
v.sighted = null;
|
|
489
|
+
v.weights = null;
|
|
490
|
+
v.stamps = null;
|
|
491
|
+
v.deltas = null;
|
|
427
492
|
return v;
|
|
428
493
|
}
|
|
429
494
|
rateAt(now) {
|
package/dist/wave.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Kit, Patch } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The shape of one cycle of a `wave`.
|
|
4
|
+
*
|
|
5
|
+
* @category patch
|
|
6
|
+
*/
|
|
7
|
+
export type WaveShape = 'sine' | 'triangle' | 'saw' | 'square';
|
|
8
|
+
/**
|
|
9
|
+
* What `wave` takes besides its duration.
|
|
10
|
+
*
|
|
11
|
+
* @category patch
|
|
12
|
+
*/
|
|
13
|
+
export interface WaveOptions<O> {
|
|
14
|
+
/** Default 'sine'. */
|
|
15
|
+
shape?: WaveShape;
|
|
16
|
+
/** Whole or fractional cycles per pass of the patch's duration. Default 1. */
|
|
17
|
+
cycles?: number;
|
|
18
|
+
/** Where in its cycle the wave starts, 0..1. Default 0. */
|
|
19
|
+
phase?: number;
|
|
20
|
+
/** Peak swing per channel, either side of the channel's rest. Its keys are the patch's writes,
|
|
21
|
+
* and only a channel holding a number can take one. */
|
|
22
|
+
depth: {
|
|
23
|
+
[K in keyof O as NonNullable<O[K]> extends number ? K : never]?: number;
|
|
24
|
+
};
|
|
25
|
+
/** The channels this wave was written against, which `cue` checks a mix's kit against. Each
|
|
26
|
+
* channel swings around its rest here, so a `mul` channel pulses around 1; without it, around 0. */
|
|
27
|
+
kit?: Partial<Kit<O>>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The unit wave: -1..1 at `x` cycles, starting at 0 and rising (square: +1 for the first half).
|
|
31
|
+
*
|
|
32
|
+
* @category patch
|
|
33
|
+
*/
|
|
34
|
+
export declare function waveAt(shape: WaveShape, x: number): number;
|
|
35
|
+
/**
|
|
36
|
+
* A periodic swing on each channel `depth` names, around its rest: an LFO for a bob, a sway or a
|
|
37
|
+
* pulse. An `fn` patch that keeps its options on `patch.wave`, for an engine reading the wave
|
|
38
|
+
* rather than calling it.
|
|
39
|
+
*
|
|
40
|
+
* @category patch
|
|
41
|
+
*/
|
|
42
|
+
export declare function wave<I, O>(duration: number, opts: WaveOptions<O>): Patch<I, O, void>;
|
package/dist/wave.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { patch } from './patch.js';
|
|
2
|
+
/**
|
|
3
|
+
* The unit wave: -1..1 at `x` cycles, starting at 0 and rising (square: +1 for the first half).
|
|
4
|
+
*
|
|
5
|
+
* @category patch
|
|
6
|
+
*/
|
|
7
|
+
export function waveAt(shape, x) {
|
|
8
|
+
const u = x - Math.floor(x);
|
|
9
|
+
switch (shape) {
|
|
10
|
+
case 'sine':
|
|
11
|
+
return Math.sin(2 * Math.PI * u);
|
|
12
|
+
case 'triangle':
|
|
13
|
+
return u < 0.25 ? 4 * u : u < 0.75 ? 2 - 4 * u : 4 * u - 4;
|
|
14
|
+
case 'saw':
|
|
15
|
+
return u < 0.5 ? 2 * u : 2 * u - 2;
|
|
16
|
+
case 'square':
|
|
17
|
+
return u < 0.5 ? 1 : -1;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const plans = new WeakMap();
|
|
21
|
+
function planOf(opts) {
|
|
22
|
+
let plan = plans.get(opts);
|
|
23
|
+
if (plan === undefined) {
|
|
24
|
+
const depth = opts.depth;
|
|
25
|
+
const writes = Object.keys(depth);
|
|
26
|
+
plan = {
|
|
27
|
+
shape: opts.shape ?? 'sine',
|
|
28
|
+
cycles: opts.cycles ?? 1,
|
|
29
|
+
start: opts.phase ?? 0,
|
|
30
|
+
writes,
|
|
31
|
+
depths: writes.map((c) => depth[c]),
|
|
32
|
+
rests: writes.map((c) => {
|
|
33
|
+
const rest = opts.kit?.[c]?.rest;
|
|
34
|
+
return typeof rest === 'number' ? rest : 0;
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
plans.set(opts, plan);
|
|
38
|
+
}
|
|
39
|
+
return plan;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A periodic swing on each channel `depth` names, around its rest: an LFO for a bob, a sway or a
|
|
43
|
+
* pulse. An `fn` patch that keeps its options on `patch.wave`, for an engine reading the wave
|
|
44
|
+
* rather than calling it.
|
|
45
|
+
*
|
|
46
|
+
* @category patch
|
|
47
|
+
*/
|
|
48
|
+
export function wave(duration, opts) {
|
|
49
|
+
const own = planOf(opts);
|
|
50
|
+
const made = patch(duration,
|
|
51
|
+
// A copy of the patch carries this `at` with a `wave` of its own, which it is read by.
|
|
52
|
+
function at(phase) {
|
|
53
|
+
const plan = this.wave === opts ? own : planOf(this.wave);
|
|
54
|
+
const unit = waveAt(plan.shape, phase * plan.cycles + plan.start);
|
|
55
|
+
const out = {};
|
|
56
|
+
for (let i = 0; i < plan.writes.length; i++)
|
|
57
|
+
out[plan.writes[i]] =
|
|
58
|
+
plan.rests[i] + plan.depths[i] * unit;
|
|
59
|
+
return out;
|
|
60
|
+
}, { writes: own.writes, kit: opts.kit });
|
|
61
|
+
return { ...made, wave: opts };
|
|
62
|
+
}
|
package/dist/weigh.js
CHANGED
|
@@ -39,7 +39,7 @@ export function ownedBy(voice, subject) {
|
|
|
39
39
|
*/
|
|
40
40
|
export function ownerBase(owner, subject) {
|
|
41
41
|
const now = this.now;
|
|
42
|
-
const held = this.held(owner, subject,
|
|
42
|
+
const held = this.held(owner, subject, -1);
|
|
43
43
|
if (held.probed === this.frame)
|
|
44
44
|
return held.phase;
|
|
45
45
|
const kept = reading.kept;
|