@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
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The times a voice is known by on the mix clock: when its fade in begins (`start`), when it is
|
|
3
|
+
* fully in (`in`), when its last pass ends (`coast`), when its fade out begins (`out`), and when it
|
|
4
|
+
* is gone (`end`). A voice coasts when `played` resolves true, for its latest-staggered subject: at
|
|
5
|
+
* its `out` where it does not freeze, and where it starts showing its last frame where it does. A
|
|
6
|
+
* voice that loops for good, or fades before its last pass ends, never coasts.
|
|
7
|
+
*
|
|
8
|
+
* @category score
|
|
9
|
+
*/
|
|
10
|
+
export type Mark = 'start' | 'in' | 'coast' | 'out' | 'end';
|
|
11
|
+
/**
|
|
12
|
+
* Selects voices by what the plan knows of them, never by a channel's value, within the asking
|
|
13
|
+
* voice's own score unless it names another. Where several match,
|
|
14
|
+
* the resolver picks one: `last` cued (the default), `first` cued, `next` (the earliest whose mark
|
|
15
|
+
* is still to come), `earliest` or `latest` by the mark's time.
|
|
16
|
+
*
|
|
17
|
+
* @category score
|
|
18
|
+
*/
|
|
19
|
+
export interface Query {
|
|
20
|
+
/** The score to look in. Default: the asking voice's own. */
|
|
21
|
+
score?: string;
|
|
22
|
+
name?: string;
|
|
23
|
+
tag?: string;
|
|
24
|
+
/** A channel the voice's patch writes. */
|
|
25
|
+
writes?: string;
|
|
26
|
+
resolver?: 'last' | 'first' | 'next' | 'earliest' | 'latest';
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A time given by another voice: `mark` of the voice `of` selects, moved by `by` ms. `after` is
|
|
30
|
+
* sugar for that voice's `end`, `with` for its `start`, and `before` for its start less `by`. A
|
|
31
|
+
* string selects by name. `all` is the latest of its anchors, known once every one is; `any` the
|
|
32
|
+
* earliest, known once one has passed or every one is known.
|
|
33
|
+
*
|
|
34
|
+
* @category score
|
|
35
|
+
*/
|
|
36
|
+
export type Anchor = {
|
|
37
|
+
of: string | Query;
|
|
38
|
+
mark: Mark;
|
|
39
|
+
by?: number;
|
|
40
|
+
} | {
|
|
41
|
+
after: string | Query;
|
|
42
|
+
by?: number;
|
|
43
|
+
} | {
|
|
44
|
+
with: string | Query;
|
|
45
|
+
by?: number;
|
|
46
|
+
} | {
|
|
47
|
+
before: string | Query;
|
|
48
|
+
by?: number;
|
|
49
|
+
} | {
|
|
50
|
+
all: readonly Anchor[];
|
|
51
|
+
} | {
|
|
52
|
+
any: readonly Anchor[];
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Where a voice sits on the mix clock: at most one of `start` and `in`, and at most one of `out`
|
|
56
|
+
* and `end`, each a timestamp on the host's clock or an anchor to another voice. A voice whose
|
|
57
|
+
* anchor has no answer yet waits pending; one whose anchored mark is already past starts partway
|
|
58
|
+
* through, as playback does from the middle of a region.
|
|
59
|
+
*
|
|
60
|
+
* @category score
|
|
61
|
+
*/
|
|
62
|
+
export interface Placement {
|
|
63
|
+
start?: number | Anchor;
|
|
64
|
+
in?: number | Anchor;
|
|
65
|
+
out?: number | Anchor;
|
|
66
|
+
end?: number | Anchor;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* One mark as `marks` lists it: one of a voice's, or one the host announced on a score, which has a
|
|
70
|
+
* name and no voice.
|
|
71
|
+
*
|
|
72
|
+
* @category score
|
|
73
|
+
*/
|
|
74
|
+
export interface Marked {
|
|
75
|
+
/** On the host's clock. */
|
|
76
|
+
timestamp: number;
|
|
77
|
+
/** Which of a voice's this is; undefined for an announced mark. */
|
|
78
|
+
mark: Mark | undefined;
|
|
79
|
+
/** The voice it belongs to; undefined for an announced mark. */
|
|
80
|
+
voice: number | undefined;
|
|
81
|
+
score: string | undefined;
|
|
82
|
+
name: string | undefined;
|
|
83
|
+
tags: readonly string[];
|
|
84
|
+
/** The `name` of the mix the voice is in, or that announced the mark; undefined for none. */
|
|
85
|
+
mix: string | undefined;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* An event at a time on a voice's own clock, which `book` hands a host ahead of time. It plays once
|
|
89
|
+
* per pass, for the voice and not per subject, so `stagger` does not spread it.
|
|
90
|
+
*
|
|
91
|
+
* @category score
|
|
92
|
+
*/
|
|
93
|
+
export interface Hit<E = unknown> {
|
|
94
|
+
/** Voice ms into each pass: 0 up to the patch's `duration`, or any time from 0 for a patch with none. */
|
|
95
|
+
at: number;
|
|
96
|
+
event: E;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* One pass of one hit, as `book` takes it.
|
|
100
|
+
*
|
|
101
|
+
* @category score
|
|
102
|
+
*/
|
|
103
|
+
export interface BookedHit<E = unknown> {
|
|
104
|
+
/** On the host's clock. */
|
|
105
|
+
timestamp: number;
|
|
106
|
+
voice: number;
|
|
107
|
+
/** Which of the voice's `hits`, by index. */
|
|
108
|
+
hit: number;
|
|
109
|
+
/** Which pass, 0 first. */
|
|
110
|
+
pass: number;
|
|
111
|
+
event: E;
|
|
112
|
+
score: string | undefined;
|
|
113
|
+
name: string | undefined;
|
|
114
|
+
tags: readonly string[];
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* What `book` takes: an outside clock, how far ahead to book on it, and what to do with each item.
|
|
118
|
+
*
|
|
119
|
+
* @category score
|
|
120
|
+
*/
|
|
121
|
+
export interface BookOptions<E = unknown> {
|
|
122
|
+
/**
|
|
123
|
+
* The outside clock, in ms: `audio.currentTime * 1000`, `performance.now()`, or whatever the host
|
|
124
|
+
* schedules against. Read once a sync. The mix maps its host time onto it by an offset that folds
|
|
125
|
+
* in 5% of each frame's difference, and starts over from the clock's own reading on a jump past
|
|
126
|
+
* 50 ms, such as a suspended context or a hidden tab.
|
|
127
|
+
*/
|
|
128
|
+
clock: () => number;
|
|
129
|
+
/** How far ahead to book, host ms. It has to cover the longest gap between two syncs. */
|
|
130
|
+
ahead: number;
|
|
131
|
+
/** How far past an item first seen late may be and still be taken, host ms. */
|
|
132
|
+
late: number;
|
|
133
|
+
/**
|
|
134
|
+
* Called once per item: a mark as `marks` lists it, or a hit. `when` is on the outside clock;
|
|
135
|
+
* `lateBy` is how many host ms past the item was when first seen, which is then taken at the
|
|
136
|
+
* clock's now; it is 0 for one booked ahead. Return a `stop` to hear about a booking whose time moved by
|
|
137
|
+
* more than 1 ms or that went away (a seek, a rate or ramp on the voice or the mix, a fade, a
|
|
138
|
+
* `rebase`, an anchor's target moving, the voice leaving); the item is then booked again, at its
|
|
139
|
+
* new time, at the same sync.
|
|
140
|
+
*/
|
|
141
|
+
take(item: Marked | BookedHit<E>, when: number, lateBy: number): {
|
|
142
|
+
stop(): void;
|
|
143
|
+
} | undefined;
|
|
144
|
+
/** Book only the voices, and announced marks, carrying this tag. */
|
|
145
|
+
tag?: string;
|
|
146
|
+
/** Book only this score's voices and marks. */
|
|
147
|
+
score?: string;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* A running booker, returned by `book`.
|
|
151
|
+
*
|
|
152
|
+
* @category score
|
|
153
|
+
*/
|
|
154
|
+
export interface Booker {
|
|
155
|
+
/** Stops every booking still ahead, and books nothing more. */
|
|
156
|
+
stop(): void;
|
|
157
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Tape } from './history.js';
|
|
2
|
+
import type { Mix, MixOptions, Projection } from './mix.js';
|
|
3
|
+
import type { Marked } from './place.js';
|
|
4
|
+
/**
|
|
5
|
+
* How a transport is made: what history it keeps for every mix on it.
|
|
6
|
+
*
|
|
7
|
+
* @category mix
|
|
8
|
+
*/
|
|
9
|
+
export interface TransportOptions {
|
|
10
|
+
history?: MixOptions['history'];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Every mix on a transport read at another mix time, with nothing live moved: `of` gives one mix's
|
|
14
|
+
* reading. Valid until the transport is next synced or a mix on it cued.
|
|
15
|
+
*
|
|
16
|
+
* @category mix
|
|
17
|
+
*/
|
|
18
|
+
export interface TransportProjection {
|
|
19
|
+
readonly timestamp: number;
|
|
20
|
+
of<I, O, H>(mix: Mix<I, O, H>): Projection<I, O>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* One clock several mixes play on, each over its own kit: one sync, one rate, one seek and one
|
|
24
|
+
* tape for all of them, and a score that spans them, so an anchor in one mix waits on a voice in
|
|
25
|
+
* another by naming the score they share. A query naming no score stays in its own mix.
|
|
26
|
+
*
|
|
27
|
+
* @category mix
|
|
28
|
+
*/
|
|
29
|
+
export interface Transport {
|
|
30
|
+
/** The host reports the clock once a frame, after the frame's cues, as `Mix.sync` does. */
|
|
31
|
+
sync(timestamp: number): void;
|
|
32
|
+
/** As `Mix.rebase`, for every mix on it. */
|
|
33
|
+
rebase(): void;
|
|
34
|
+
/** As `Mix.rate`, multiplied into every voice of every mix on it. */
|
|
35
|
+
rate: number;
|
|
36
|
+
ramp(rate: number, over: number): void;
|
|
37
|
+
/**
|
|
38
|
+
* As `Mix.seek`, for every mix on it at once: back, each mix restores itself; forward, the one
|
|
39
|
+
* tape plays every mix's calls again in the order they were made, so an anchor across mixes
|
|
40
|
+
* answers as it did. A mix dropped after the moment sought is back on the transport.
|
|
41
|
+
*/
|
|
42
|
+
seek(time: number): void;
|
|
43
|
+
/**
|
|
44
|
+
* Loads from the history `store` what `seek(time)` and `project(time)` will need, where that
|
|
45
|
+
* reaches past memory. Without a store, or within memory, it loads nothing.
|
|
46
|
+
*/
|
|
47
|
+
prepare(time: number): Promise<void>;
|
|
48
|
+
readonly now: number;
|
|
49
|
+
readonly tape: Tape | undefined;
|
|
50
|
+
/** Puts a named mark on a score every mix on it sees. Throws without a `score`. */
|
|
51
|
+
announce(name: string, opts: {
|
|
52
|
+
at?: number;
|
|
53
|
+
score: string;
|
|
54
|
+
tags?: readonly string[];
|
|
55
|
+
}): void;
|
|
56
|
+
/** Every mark of every mix on it, and every mark announced on it, earliest first. */
|
|
57
|
+
marks(from: number, to: number): Marked[];
|
|
58
|
+
/** Every mix on it read at mix time `time`, together, so anchors across them answer. */
|
|
59
|
+
project(time: number): TransportProjection;
|
|
60
|
+
/** Any mix on it live. */
|
|
61
|
+
readonly live: boolean;
|
|
62
|
+
/** Every mix on it inert. */
|
|
63
|
+
readonly inert: boolean;
|
|
64
|
+
/** Calls `fn` when any mix on it needs frames again after a sync, once until the next sync. */
|
|
65
|
+
onWake(fn: () => void): () => void;
|
|
66
|
+
/**
|
|
67
|
+
* Takes a mix off: it is no longer synced and takes no more calls. With history, a seek back
|
|
68
|
+
* before the drop puts it back as it was then; without, it is let go.
|
|
69
|
+
*/
|
|
70
|
+
drop<I, O, H>(mix: Mix<I, O, H>): void;
|
|
71
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import type { Fit, Order, Strength } from '../fit.js';
|
|
2
|
+
import type { Motion, Value } from '../motion.js';
|
|
3
|
+
import type { Described } from './history.js';
|
|
4
|
+
import type { Doubt } from './mix.js';
|
|
5
|
+
import type { Easing, Patch, Signal } from './patch.js';
|
|
6
|
+
import type { Hit, Placement } from './place.js';
|
|
7
|
+
/**
|
|
8
|
+
* A voice's own ramps in and out, in ms, and the curve both take.
|
|
9
|
+
*
|
|
10
|
+
* @category blending
|
|
11
|
+
*/
|
|
12
|
+
export interface FadeSpec {
|
|
13
|
+
in?: number;
|
|
14
|
+
out?: number;
|
|
15
|
+
ease?: Easing;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* How a voice or owner held by a span may give way so the span keeps its budget, which the span's
|
|
19
|
+
* fit reads. Anything it does not allow, it will not do. Read only under a span.
|
|
20
|
+
*
|
|
21
|
+
* @category score
|
|
22
|
+
*/
|
|
23
|
+
export interface SpanHints {
|
|
24
|
+
/** How many times faster than its own rate it may play. Default 1: no faster. */
|
|
25
|
+
faster?: number;
|
|
26
|
+
/** How many times slower than its own rate it may play. Default 1: no slower. */
|
|
27
|
+
slower?: number;
|
|
28
|
+
/** Whether it may start before the one before it ends, where the span's order would not. */
|
|
29
|
+
overlap?: boolean;
|
|
30
|
+
/** Whether it may jump to its end instead of playing. A span held by a span is never skipped. */
|
|
31
|
+
ballast?: boolean;
|
|
32
|
+
/** How hard its own length holds against the span's budget. Default `weak`. */
|
|
33
|
+
priority?: Strength;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* What `cue` takes: a patch, and the clock, weight and reach it plays with.
|
|
37
|
+
*
|
|
38
|
+
* @category voice
|
|
39
|
+
*/
|
|
40
|
+
export interface VoiceSpec<I, O, H = unknown> extends SpanHints {
|
|
41
|
+
patch: Patch<I, O, unknown, H>;
|
|
42
|
+
/**
|
|
43
|
+
* What `history.revive` rebuilds this spec from, so a history `store` can page the voice out once
|
|
44
|
+
* it has left. A voice cued without it stays in memory for as long as history reaches it.
|
|
45
|
+
*/
|
|
46
|
+
as?: Described;
|
|
47
|
+
/**
|
|
48
|
+
* Which subjects this voice reaches. Default: all of them. The predicate is fixed at `cue`; it
|
|
49
|
+
* runs per subject the first time the mix sees that subject, and the answer is kept. Every
|
|
50
|
+
* voice's predicate meets every subject, so voices that each reach a known few cost the square
|
|
51
|
+
* of their number in time; name those with `subjects` instead. A no is kept as a bit by the
|
|
52
|
+
* number lanes give the subject, but with `lanes: false` as a map entry per voice per subject
|
|
53
|
+
* asked (about 37 MB for 1,000 such voices over 1,000 subjects).
|
|
54
|
+
*/
|
|
55
|
+
target?: (subject: I) => boolean;
|
|
56
|
+
/**
|
|
57
|
+
* The subjects this voice reaches, fixed at `cue` and matched by identity; a probe of any other
|
|
58
|
+
* never asks this voice. Takes the place of `target`, and a cue giving both is refused: a
|
|
59
|
+
* predicate over a fixed list is that list filtered, which the host can do before cueing.
|
|
60
|
+
*/
|
|
61
|
+
subjects?: readonly I[];
|
|
62
|
+
/**
|
|
63
|
+
* When the voice starts, in ms on the host's clock, the one it passes `sync`: a rAF timestamp and
|
|
64
|
+
* `performance.now()` share an origin, `Date.now()` does not. Default: the next sync.
|
|
65
|
+
*/
|
|
66
|
+
start?: number;
|
|
67
|
+
/** Playback rate. 1 is real time; 0 freezes. */
|
|
68
|
+
rate?: number;
|
|
69
|
+
/**
|
|
70
|
+
* true loops for good, false plays one pass, n plays n passes. A finite loop leaves when its
|
|
71
|
+
* passes are done for the latest-staggered subject it has seen — over `fade.out` where one is
|
|
72
|
+
* set, at once where none is — unless it freezes after.
|
|
73
|
+
*/
|
|
74
|
+
loop?: boolean | number;
|
|
75
|
+
/**
|
|
76
|
+
* Per-subject delay in voice ms, klieg's stagger grammar reduced to the one thing the mix needs.
|
|
77
|
+
* Like `target`, it runs once per subject on first sight, and the answer is kept.
|
|
78
|
+
*/
|
|
79
|
+
stagger?: (subject: I) => number;
|
|
80
|
+
/**
|
|
81
|
+
* Show a subject the first frame before it starts — while the voice is pending and while the
|
|
82
|
+
* subject waits out its `stagger` — the last frame of the last pass after a finite loop plays
|
|
83
|
+
* out, or both. A frozen subject's clock stands still: `at` is asked for the edge frame and `step`
|
|
84
|
+
* does not run, past one last step to the end of the last pass. `fade.in` counts from the first
|
|
85
|
+
* frame the voice shows. A voice freezing after stays, `frozen`, until `fade()` or an anchored
|
|
86
|
+
* `out` takes it out, so every one cued must be faded or it stays in the mix for good. Does
|
|
87
|
+
* nothing to a motion patch, which keeps its target already. Default: neither.
|
|
88
|
+
*/
|
|
89
|
+
freeze?: 'before' | 'after' | 'both';
|
|
90
|
+
/** Steady weight, or a signal read per subject per frame. Default 1. */
|
|
91
|
+
weight?: number | Signal<I, H>;
|
|
92
|
+
/** Ramp in and out, ms. Out applies on `fade()` and when a finite loop ends. */
|
|
93
|
+
fade?: FadeSpec;
|
|
94
|
+
/** Voices sharing a locus are alternatives: the mix folds them through each channel's `lerp`. */
|
|
95
|
+
locus?: string;
|
|
96
|
+
/** A `keys` voice whose first stop reads wherever this subject is now. */
|
|
97
|
+
from?: 'current';
|
|
98
|
+
/** Words a source attaches to this voice, so its events and its handle can be taken as a set. */
|
|
99
|
+
tags?: readonly string[];
|
|
100
|
+
/** What other voices call this one by. A label blits never reads. */
|
|
101
|
+
name?: string;
|
|
102
|
+
/**
|
|
103
|
+
* The plan this voice belongs to. Each source keeps its own, so two sources can use one name
|
|
104
|
+
* without meeting: a bare name in an anchor means a voice in the same score, and a query names
|
|
105
|
+
* `score` to reach into another. Default: the mix's one unnamed score.
|
|
106
|
+
*/
|
|
107
|
+
score?: string;
|
|
108
|
+
/** Where it sits relative to the clock or to other voices, in place of `start`. */
|
|
109
|
+
anchor?: Placement;
|
|
110
|
+
/**
|
|
111
|
+
* Events at times on this voice's clock, which `book` hands a host ahead of time. Patch-sent
|
|
112
|
+
* events are not known ahead, so they stay drain-only; these are the plan.
|
|
113
|
+
*/
|
|
114
|
+
hits?: readonly Hit[];
|
|
115
|
+
/**
|
|
116
|
+
* The owner this voice plays under, a handle `owns` returned. Its `start` and `anchor` are then on
|
|
117
|
+
* the owner's clock, in ms from when the owner starts, and default to where that clock is now; a
|
|
118
|
+
* bare name in an anchor means a sibling, another voice the owner holds. Its clock runs on the
|
|
119
|
+
* owner's, so the owner's rate, ramp and seeks move it, and its weight is multiplied by the
|
|
120
|
+
* owner's weight and fade. Without a `freeze` of its own it takes the owner's.
|
|
121
|
+
*/
|
|
122
|
+
owner?: Handle<I>;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* What `owns` takes: an owner has no patch, and plays only through the voices it holds.
|
|
126
|
+
*
|
|
127
|
+
* @category voice
|
|
128
|
+
*/
|
|
129
|
+
export interface OwnerSpec<I, H = unknown> extends SpanHints {
|
|
130
|
+
/**
|
|
131
|
+
* When the owner starts, on its own owner's clock: the host's for an owner on the mix, as a
|
|
132
|
+
* voice's `start` is. Default: now.
|
|
133
|
+
*/
|
|
134
|
+
start?: number;
|
|
135
|
+
/** Its clock's rate, multiplied into every child's own. Default 1. */
|
|
136
|
+
rate?: number;
|
|
137
|
+
/**
|
|
138
|
+
* Multiplied into every child's weight per subject, as the child's own fade is, before the child's
|
|
139
|
+
* locus folds it: a number, or a signal read per subject per frame. Default 1.
|
|
140
|
+
*/
|
|
141
|
+
weight?: number | Signal<I, H>;
|
|
142
|
+
/** One ramp in and out over every child, multiplied into their weights as `weight` is. */
|
|
143
|
+
fade?: FadeSpec;
|
|
144
|
+
/** The freeze every child without one of its own takes. */
|
|
145
|
+
freeze?: 'before' | 'after' | 'both';
|
|
146
|
+
/** Words a source attaches to it, as a voice's. */
|
|
147
|
+
tags?: readonly string[];
|
|
148
|
+
/** What other voices call it by, among its siblings. */
|
|
149
|
+
name?: string;
|
|
150
|
+
/** The plan it belongs to, as a voice's. */
|
|
151
|
+
score?: string;
|
|
152
|
+
/** Where it sits relative to its own owner's clock or to other voices, in place of `start`. */
|
|
153
|
+
anchor?: Placement;
|
|
154
|
+
/** The owner it plays under, so owners nest. */
|
|
155
|
+
owner?: Handle<I>;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* What `span` takes: an owner with a budget, which lays out the voices it holds in an order and
|
|
159
|
+
* fits them into the budget.
|
|
160
|
+
*
|
|
161
|
+
* @category score
|
|
162
|
+
*/
|
|
163
|
+
export interface SpanSpec<I, H = unknown> extends OwnerSpec<I, H> {
|
|
164
|
+
/** Its budget, ms on its own clock. Default: none, so its children only keep their order. */
|
|
165
|
+
duration?: number;
|
|
166
|
+
/** How hard the budget holds against its children's own lengths. Default `strong`. */
|
|
167
|
+
priority?: Strength;
|
|
168
|
+
/** How its children are laid out, in the order they were cued. Default `queue`. */
|
|
169
|
+
order?: Order;
|
|
170
|
+
/** How far through the one before a child starts under `stagger`, 0..1. Default 0.5. */
|
|
171
|
+
share?: number;
|
|
172
|
+
/**
|
|
173
|
+
* How the children are fitted once they are retimed toward the budget, faster or slower as
|
|
174
|
+
* their hints allow. Default `pipe(condense(), shed())`.
|
|
175
|
+
*/
|
|
176
|
+
fit?: Fit;
|
|
177
|
+
/**
|
|
178
|
+
* What happens where the fit leaves them too long for a span at least `strong`: `instant` jumps
|
|
179
|
+
* every child weaker than the span to its end at once, and `overrun` lets them run long.
|
|
180
|
+
* Default `instant`.
|
|
181
|
+
*/
|
|
182
|
+
spill?: 'instant' | 'overrun';
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* How a span's last fit came out.
|
|
186
|
+
*
|
|
187
|
+
* @category score
|
|
188
|
+
*/
|
|
189
|
+
export interface FitResult {
|
|
190
|
+
/** Its budget, ms on its own clock; Infinity for none. */
|
|
191
|
+
budget: number;
|
|
192
|
+
/** Where its children end, ms on its own clock from its start. */
|
|
193
|
+
length: number;
|
|
194
|
+
/** How far `length` runs past the budget, 0 where it does not. */
|
|
195
|
+
over: number;
|
|
196
|
+
/** How many children it jumps to their end. */
|
|
197
|
+
skipped: number;
|
|
198
|
+
/** Whether the fit failed and `spill` decided. */
|
|
199
|
+
fell: boolean;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* A span's handle: an owner's, and how its children were last fitted.
|
|
203
|
+
*
|
|
204
|
+
* @category score
|
|
205
|
+
*/
|
|
206
|
+
export interface SpanHandle<I = unknown> extends Handle<I> {
|
|
207
|
+
readonly result: FitResult;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* How a voice leaves when it is faded: the whole voice, or one subject.
|
|
211
|
+
*
|
|
212
|
+
* @category blending
|
|
213
|
+
*/
|
|
214
|
+
export type FadeOptions<I = unknown> = {
|
|
215
|
+
/** The ramp, ms. Defaults to the voice's own `fade.out`. */
|
|
216
|
+
over?: number;
|
|
217
|
+
/**
|
|
218
|
+
* When the fade begins. A mix time: ahead, the voice plays untouched until then and begins
|
|
219
|
+
* its fade exactly there, its `out` mark fixed from now, and `rise` before then takes it
|
|
220
|
+
* back with nothing changed; at or behind now, the fade began then and is partway. `'rest'`:
|
|
221
|
+
* leave per subject at the first frame that subject's contribution is at rest. Default now.
|
|
222
|
+
*/
|
|
223
|
+
at?: number | 'rest';
|
|
224
|
+
/** Ms after which the voice leaves whether or not it rested. */
|
|
225
|
+
deadline?: number;
|
|
226
|
+
subject?: never;
|
|
227
|
+
} | {
|
|
228
|
+
/**
|
|
229
|
+
* The one subject to fade out of this voice, which plays on for the rest. Once the ramp ends
|
|
230
|
+
* the voice forgets the subject and reaches it no more, until a motion patch's `to` or `push`
|
|
231
|
+
* or the mix's `drop` brings it back, met afresh: `from`, `target` and `stagger` asked again.
|
|
232
|
+
*/
|
|
233
|
+
subject: I;
|
|
234
|
+
/** The ramp, ms. Defaults to the voice's own `fade.out`; 0 takes the subject out at once. */
|
|
235
|
+
over?: number;
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* The live controls on one voice, returned by `cue`.
|
|
239
|
+
*
|
|
240
|
+
* @category voice
|
|
241
|
+
*/
|
|
242
|
+
export interface Handle<I = unknown> {
|
|
243
|
+
readonly id: number;
|
|
244
|
+
/** `frozen`: a voice freezing after has played every pass and shows its last frame until faded. */
|
|
245
|
+
readonly state: 'pending' | 'live' | 'frozen' | 'fading' | 'done';
|
|
246
|
+
/** The handle of the owner this voice plays under; undefined for one on the mix clock. */
|
|
247
|
+
readonly owner: Handle<I> | undefined;
|
|
248
|
+
/** Live. A write shows at the next probe. */
|
|
249
|
+
weight: number;
|
|
250
|
+
/**
|
|
251
|
+
* Playback rate now. Setting it changes speed at once; `ramp` eases into a new one. On a voice
|
|
252
|
+
* still pending, a rate above 0 applies from the voice's start, which stays where it is.
|
|
253
|
+
*/
|
|
254
|
+
rate: number;
|
|
255
|
+
/**
|
|
256
|
+
* Moves the rate to `rate` linearly over `over` mix ms, so a pause or a slow-motion eases in
|
|
257
|
+
* rather than snapping. The voice clock integrates the ramp, so its position stays continuous and
|
|
258
|
+
* its speed does too. A later `rate` write or `ramp` replaces it; `seek` keeps it.
|
|
259
|
+
*/
|
|
260
|
+
ramp(rate: number, over: number): void;
|
|
261
|
+
/**
|
|
262
|
+
* Moves this voice's clock, forward or back, and for an owner every clock it holds. By default
|
|
263
|
+
* each subject's state (a patch's `state`, what `setting.keep` holds) is made fresh and stepped
|
|
264
|
+
* again from the voice's start up to `elapsed` on its next probe; `state: 'keep'` leaves it where
|
|
265
|
+
* it was. Answers how sure the state now is: `exact` for a voice with none, or rebuilt under
|
|
266
|
+
* `stepMs` with no `maxDt`; `stepped` where it was caught up in one step or holds signal state;
|
|
267
|
+
* `held` where it was kept, or depends on host fields or an input weight the rebuild cannot know.
|
|
268
|
+
*/
|
|
269
|
+
seek(elapsed: number, opts?: SeekOptions): Doubt;
|
|
270
|
+
/**
|
|
271
|
+
* Fades the voice out, or one subject out of it, as `FadeOptions` says. A voice already fading or
|
|
272
|
+
* done is left as it is.
|
|
273
|
+
*/
|
|
274
|
+
fade(opts?: FadeOptions<I>): void;
|
|
275
|
+
/**
|
|
276
|
+
* Turns a fade out around: the voice climbs back from where its fade had got to, up the same
|
|
277
|
+
* curve, over `over` ms for the whole curve (default its `fade.in`, else its `fade.out`), and
|
|
278
|
+
* plays on as if never faded. A fade waiting for rest is taken back at once; a voice not fading
|
|
279
|
+
* is left as it is. A voice whose own end began the fade starts it again at its next frame.
|
|
280
|
+
*/
|
|
281
|
+
rise(opts?: {
|
|
282
|
+
over?: number;
|
|
283
|
+
}): void;
|
|
284
|
+
/**
|
|
285
|
+
* The weight this voice gave `subject` the last frame that subject was probed: after its fades
|
|
286
|
+
* and its weight signal, before a locus folds it with its alternatives. 0 for a subject it does
|
|
287
|
+
* not reach, has not started on and does not freeze before, has left at rest, or has never been
|
|
288
|
+
* probed for; 0 once done.
|
|
289
|
+
* Costs nothing until it is asked.
|
|
290
|
+
*/
|
|
291
|
+
weightOf(subject: I): number;
|
|
292
|
+
/**
|
|
293
|
+
* Heads `subject` for `target`, for a voice playing a `spring` or a `tween`: the patch's own `to`,
|
|
294
|
+
* reached without holding the patch. Throws for any other voice.
|
|
295
|
+
*/
|
|
296
|
+
to(subject: I, target: Value, at?: number): void;
|
|
297
|
+
/**
|
|
298
|
+
* Sets `subject` moving at `velocity`, units per second, for a voice playing a `spring` or a
|
|
299
|
+
* `glide`: the patch's own `push`. Throws for any other voice.
|
|
300
|
+
*/
|
|
301
|
+
push(subject: I, velocity: Value, at?: number): void;
|
|
302
|
+
/**
|
|
303
|
+
* Where `subject` is and how fast it moves, for a voice playing a motion patch: the patch's own
|
|
304
|
+
* `read`. Undefined for any other voice, and wherever the patch's `read` is.
|
|
305
|
+
*/
|
|
306
|
+
read(subject: I, at?: number): Motion<Value> | undefined;
|
|
307
|
+
/** Resolves when the voice has been removed from the mix, however that happened. */
|
|
308
|
+
readonly done: Promise<void>;
|
|
309
|
+
/**
|
|
310
|
+
* Resolves true when a finite loop's last pass ends, for the latest-staggered subject it has
|
|
311
|
+
* seen, and false if the voice leaves before that. Never rejects.
|
|
312
|
+
*/
|
|
313
|
+
readonly played: Promise<boolean>;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* What `Handle.seek` does with each subject's state: `rebuild` (the default) makes it fresh and
|
|
317
|
+
* steps it to the new position; `keep` leaves it as it was.
|
|
318
|
+
*
|
|
319
|
+
* @category voice
|
|
320
|
+
*/
|
|
321
|
+
export interface SeekOptions {
|
|
322
|
+
state?: 'rebuild' | 'keep';
|
|
323
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|