@msb235/blits 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/CHANGELOG.md +154 -0
  2. package/README.md +3 -3
  3. package/dist/ahead.d.ts +26 -0
  4. package/dist/ahead.js +264 -0
  5. package/dist/around.d.ts +11 -0
  6. package/dist/around.js +32 -0
  7. package/dist/bare.js +15 -7
  8. package/dist/blank.d.ts +10 -0
  9. package/dist/blank.js +26 -0
  10. package/dist/blend.d.ts +2 -1
  11. package/dist/blend.js +1 -6
  12. package/dist/bound.d.ts +70 -0
  13. package/dist/bound.js +351 -0
  14. package/dist/chain.d.ts +2 -1
  15. package/dist/chain.js +7 -5
  16. package/dist/changes.d.ts +24 -0
  17. package/dist/changes.js +189 -0
  18. package/dist/channels.d.ts +39 -13
  19. package/dist/channels.js +14 -5
  20. package/dist/color.d.ts +12 -10
  21. package/dist/color.js +25 -25
  22. package/dist/columns.js +7 -3
  23. package/dist/contribution.d.ts +30 -0
  24. package/dist/contribution.js +374 -0
  25. package/dist/copyout.d.ts +10 -0
  26. package/dist/copyout.js +69 -24
  27. package/dist/crowd.d.ts +8 -2
  28. package/dist/crowd.js +4 -5
  29. package/dist/cue.d.ts +8 -1
  30. package/dist/cue.js +39 -13
  31. package/dist/cut.d.ts +8 -0
  32. package/dist/cut.js +4 -0
  33. package/dist/drop.d.ts +9 -0
  34. package/dist/drop.js +84 -0
  35. package/dist/due.d.ts +24 -5
  36. package/dist/due.js +113 -33
  37. package/dist/easing.d.ts +4 -4
  38. package/dist/easing.js +3 -3
  39. package/dist/everyone.d.ts +3 -2
  40. package/dist/everyone.js +3 -3
  41. package/dist/fade.d.ts +2 -1
  42. package/dist/fade.js +2 -1
  43. package/dist/fill.d.ts +3 -2
  44. package/dist/fill.js +51 -19
  45. package/dist/fit.d.ts +44 -26
  46. package/dist/fit.js +10 -9
  47. package/dist/fold.d.ts +4 -37
  48. package/dist/fold.js +5 -513
  49. package/dist/gather.d.ts +12 -7
  50. package/dist/gather.js +179 -44
  51. package/dist/gone.js +2 -2
  52. package/dist/grid.d.ts +47 -0
  53. package/dist/grid.js +247 -0
  54. package/dist/handle.d.ts +2 -0
  55. package/dist/handle.js +14 -8
  56. package/dist/held.d.ts +2 -1
  57. package/dist/history.d.ts +6 -5
  58. package/dist/history.js +7 -9
  59. package/dist/hosts.js +9 -15
  60. package/dist/index.d.ts +5 -4
  61. package/dist/keyfill.d.ts +1 -1
  62. package/dist/keyfill.js +5 -3
  63. package/dist/keyrows.d.ts +12 -0
  64. package/dist/keyrows.js +99 -12
  65. package/dist/lane.d.ts +36 -6
  66. package/dist/lane.js +32 -1
  67. package/dist/lanes.d.ts +23 -8
  68. package/dist/lanes.js +29 -8
  69. package/dist/leavings.d.ts +2 -2
  70. package/dist/leavings.js +1 -1
  71. package/dist/lives.d.ts +47 -0
  72. package/dist/lives.js +180 -0
  73. package/dist/meet.d.ts +2 -2
  74. package/dist/meet.js +90 -4
  75. package/dist/mixer.d.ts +54 -36
  76. package/dist/mixer.js +53 -171
  77. package/dist/motion.d.ts +14 -118
  78. package/dist/motion.js +16 -8
  79. package/dist/motions.d.ts +62 -155
  80. package/dist/motions.js +56 -370
  81. package/dist/moved.d.ts +1 -1
  82. package/dist/moved.js +16 -7
  83. package/dist/named.d.ts +0 -1
  84. package/dist/named.js +20 -2
  85. package/dist/numbers.d.ts +2 -0
  86. package/dist/numbers.js +4 -0
  87. package/dist/owed.d.ts +2 -0
  88. package/dist/owed.js +4 -0
  89. package/dist/pack.d.ts +2 -1
  90. package/dist/pack.js +2 -3
  91. package/dist/patch.d.ts +7 -3
  92. package/dist/patch.js +6 -2
  93. package/dist/places.d.ts +53 -0
  94. package/dist/places.js +171 -0
  95. package/dist/plot.d.ts +12 -0
  96. package/dist/plot.js +52 -0
  97. package/dist/project.d.ts +4 -4
  98. package/dist/project.js +9 -212
  99. package/dist/pull.js +11 -8
  100. package/dist/qualify.js +84 -21
  101. package/dist/reading.d.ts +6 -0
  102. package/dist/reading.js +5 -0
  103. package/dist/record.d.ts +5 -1
  104. package/dist/record.js +3 -2
  105. package/dist/relink.d.ts +1 -1
  106. package/dist/restored.d.ts +2 -2
  107. package/dist/restored.js +1 -1
  108. package/dist/rests.d.ts +9 -0
  109. package/dist/rests.js +76 -0
  110. package/dist/revive.d.ts +3 -2
  111. package/dist/revive.js +2 -2
  112. package/dist/{locus.d.ts → role.d.ts} +10 -9
  113. package/dist/{locus.js → role.js} +3 -3
  114. package/dist/roles.d.ts +10 -0
  115. package/dist/roles.js +158 -0
  116. package/dist/roster.js +3 -3
  117. package/dist/rotation.d.ts +1 -1
  118. package/dist/rotation.js +1 -1
  119. package/dist/rows.js +1 -1
  120. package/dist/sample.d.ts +2 -2
  121. package/dist/sample.js +33 -7
  122. package/dist/seek.js +5 -5
  123. package/dist/setting.d.ts +27 -0
  124. package/dist/setting.js +55 -0
  125. package/dist/shared.d.ts +1 -1
  126. package/dist/shared.js +1 -1
  127. package/dist/signals.d.ts +64 -32
  128. package/dist/signals.js +20 -18
  129. package/dist/stack.d.ts +5 -5
  130. package/dist/stack.js +5 -5
  131. package/dist/standing.d.ts +2 -1
  132. package/dist/standing.js +3 -2
  133. package/dist/store.d.ts +9 -0
  134. package/dist/store.js +24 -0
  135. package/dist/strays.d.ts +2 -1
  136. package/dist/strays.js +20 -13
  137. package/dist/stretch.d.ts +112 -0
  138. package/dist/stretch.js +9 -0
  139. package/dist/subject.d.ts +142 -0
  140. package/dist/subject.js +1 -0
  141. package/dist/tape.d.ts +9 -5
  142. package/dist/tape.js +5 -1
  143. package/dist/then.d.ts +9 -0
  144. package/dist/then.js +57 -0
  145. package/dist/ticker.d.ts +4 -4
  146. package/dist/transport.d.ts +0 -8
  147. package/dist/transport.js +0 -4
  148. package/dist/turns.d.ts +4 -3
  149. package/dist/turns.js +4 -3
  150. package/dist/types/arc.d.ts +12 -11
  151. package/dist/types/channel.d.ts +12 -8
  152. package/dist/types/history.d.ts +35 -19
  153. package/dist/types/mix.d.ts +222 -163
  154. package/dist/types/motion.d.ts +151 -0
  155. package/dist/types/motion.js +1 -0
  156. package/dist/types/patch.d.ts +67 -34
  157. package/dist/types/place.d.ts +51 -36
  158. package/dist/types/transport.d.ts +20 -18
  159. package/dist/types/voice.d.ts +136 -70
  160. package/dist/types/watch.d.ts +88 -40
  161. package/dist/types.d.ts +1 -0
  162. package/dist/voice.d.ts +7 -143
  163. package/dist/voice.js +28 -79
  164. package/dist/warn.d.ts +2 -0
  165. package/dist/warn.js +1 -1
  166. package/dist/watch.d.ts +2 -2
  167. package/dist/watch.js +5 -3
  168. package/dist/wave.d.ts +4 -3
  169. package/dist/wave.js +3 -2
  170. package/dist/weigh.d.ts +7 -1
  171. package/dist/weigh.js +27 -0
  172. package/docs/schema.html +212 -34
  173. package/package.json +2 -2
@@ -0,0 +1,151 @@
1
+ import type { Easing, Patch } from './patch.js';
2
+ /**
3
+ * A number, or one number per axis.
4
+ *
5
+ * @category patch
6
+ */
7
+ export type Value = number | readonly number[];
8
+ /**
9
+ * One value for every subject, or one per subject.
10
+ *
11
+ * @category patch
12
+ */
13
+ export type PerSubject<I, V> = V | ((subject: I) => V);
14
+ /**
15
+ * Where a subject is and how fast it is moving. At one moment of voice time.
16
+ *
17
+ * @category patch
18
+ */
19
+ export interface Motion<V extends Value = number> {
20
+ value: V;
21
+ /** How fast `value` is changing, in its units per second. */
22
+ velocity: V;
23
+ }
24
+ /**
25
+ * A patch whose motion is a closed form per subject. It lands in the same place at any frame rate,
26
+ * and its changes mid-flight start from where the subject is and how fast it moves.
27
+ *
28
+ * @category patch
29
+ */
30
+ export interface Moving<I, O, V extends Value> extends Patch<I, O, void> {
31
+ /**
32
+ * Where `subject` is and how fast it moves at voice time `at`. `at` defaults to the mix's latest
33
+ * frame, counting every change due by then. With no time given, undefined until a frame of its
34
+ * voice has met the subject, while the subject is still inside its stagger, and once that voice
35
+ * is gone. At any time, undefined for a subject the patch has never met or changed, or that the
36
+ * mix dropped.
37
+ */
38
+ read(subject: I, at?: number): Motion<V> | undefined;
39
+ /**
40
+ * Sets `subject` moving at `velocity`, units per second, from voice time `at`. `at` defaults to
41
+ * the mix's latest frame; for a subject no frame of its voice has met yet, or still inside its
42
+ * stagger, its first read, after any change with a time due by then. A subject faded out of the
43
+ * voice comes back at the latest frame too, however long it is before it is next read.
44
+ */
45
+ push(subject: I, velocity: V, at?: number): void;
46
+ /**
47
+ * Puts `subject` at `value` from voice time `at`, keeping its velocity. `at` defaults as `push`'s
48
+ * does. A spring or tween heads for its target from there, a glide coasts on from there.
49
+ */
50
+ set(subject: I, value: V, at?: number): void;
51
+ }
52
+ /**
53
+ * What `spring` and `glide` both take.
54
+ *
55
+ * @category patch
56
+ */
57
+ export interface MotionOptions<I, V extends Value> {
58
+ /** Units per second each subject starts moving at. Default 0. */
59
+ velocity?: PerSubject<I, V>;
60
+ /**
61
+ * How near and slow a subject must be to land exactly where it heads. Within this distance of
62
+ * where it heads, and this slow, a subject lands there exactly, so a mix can see it at rest.
63
+ * Default 1e-4; 0 keeps the curve exact.
64
+ */
65
+ settle?: number;
66
+ }
67
+ /**
68
+ * What `spring` takes.
69
+ *
70
+ * @category patch
71
+ */
72
+ export interface SpringOptions<I, V extends Value> extends MotionOptions<I, V> {
73
+ to: PerSubject<I, V>;
74
+ /** Where each subject starts. Default: `to`, at rest. */
75
+ from?: PerSubject<I, V>;
76
+ /** How hard the spring pulls toward its target, per second squared. Default 170. */
77
+ stiffness?: number;
78
+ /**
79
+ * How fast the spring's motion dies away, per second. Default 26, just short of critical at the
80
+ * default stiffness.
81
+ */
82
+ damping?: number;
83
+ mass?: number;
84
+ }
85
+ /**
86
+ * What `glide` takes.
87
+ *
88
+ * @category patch
89
+ */
90
+ export interface GlideOptions<I, V extends Value> extends MotionOptions<I, V> {
91
+ /** Where each subject starts. */
92
+ from: PerSubject<I, V>;
93
+ /** The friction's time constant, ms. Default 325, a touch scroll's. */
94
+ ms?: number;
95
+ /** The least and greatest value a coast comes to rest at, per axis. Default none. */
96
+ bounds?: PerSubject<I, readonly [min: V, max: V]>;
97
+ /** The spring back's, per second squared, with `bounds`. Default 170, as a spring's. */
98
+ stiffness?: number;
99
+ }
100
+ /**
101
+ * What `tween` takes.
102
+ *
103
+ * @category patch
104
+ */
105
+ export interface TweenOptions<I, V extends Value> {
106
+ /** Where each subject starts. */
107
+ from: PerSubject<I, V>;
108
+ /** Where each subject ends. */
109
+ to: PerSubject<I, V>;
110
+ /** How long a stretch takes, ms. Asked per subject each time one of its stretches starts. */
111
+ ms: PerSubject<I, number>;
112
+ /** The curve from `from` to `to`. Default `'ease'`, as CSS's. */
113
+ ease?: Easing;
114
+ }
115
+ /**
116
+ * The patch `spring` returns, a motion that can be retargeted.
117
+ *
118
+ * @category patch
119
+ */
120
+ export interface Spring<I, O, V extends Value> extends Moving<I, O, V> {
121
+ /**
122
+ * Heads `subject` for `target` from voice time `at`, keeping its velocity. `at` is by default the
123
+ * mix's latest frame, or for a subject no frame of its voice has met yet, or still inside its
124
+ * stagger, its first read, after any change with a time due by then. A subject faded out of the
125
+ * voice comes back at the latest frame too, however long it is before it is next read.
126
+ */
127
+ to(subject: I, target: V, at?: number): void;
128
+ }
129
+ /**
130
+ * The patch `glide` returns, a motion that reports its bounds.
131
+ *
132
+ * @category patch
133
+ */
134
+ export interface Glide<I, O, V extends Value> extends Moving<I, O, V> {
135
+ /** `subject`'s bounds, undefined for a glide without them. */
136
+ bounds(subject: I): readonly [min: V, max: V] | undefined;
137
+ }
138
+ /**
139
+ * The patch `tween` returns, a motion that can be retargeted, with no `push`.
140
+ *
141
+ * @category patch
142
+ */
143
+ export interface Tween<I, O, V extends Value> extends Omit<Moving<I, O, V>, 'push'> {
144
+ /**
145
+ * Heads `subject` for `target` from voice time `at`, over a full `ms` from where it is. `at` is
146
+ * by default the mix's latest frame, or for a subject no frame of its voice has met yet, or still
147
+ * inside its stagger, its first read, after any change with a time due by then. A subject faded
148
+ * out of the voice comes back at the latest frame too, however long it is before it is next read.
149
+ */
150
+ to(subject: I, target: V, at?: number): void;
151
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,7 +1,7 @@
1
1
  import type { WaveOptions } from '../wave.js';
2
2
  import type { Kit } from './channel.js';
3
3
  /**
4
- * A curve on 0..1, as data where it can be: CSS's names, a `cubic-bezier`, or `steps`, which a
4
+ * A curve on 0..1, as data where it can be. CSS's names, a `cubic-bezier`, or `steps`, which a
5
5
  * WAAPI or GPU engine can read. The function form runs on the CPU engine only.
6
6
  *
7
7
  * @category patch
@@ -25,37 +25,38 @@ export interface Keyframe<O> {
25
25
  }
26
26
  /**
27
27
  * What a patch may read and did not compute, for one subject this frame. The mix reuses the object,
28
- * so it is valid only during the call it is handed to.
28
+ * so it is valid only during the call it is handed to, and read-only: a write would reach whatever
29
+ * the mix calls next.
29
30
  *
30
31
  * @category state
31
32
  */
32
33
  export interface Setting<S = void, H = unknown> {
33
34
  /**
34
- * The mix clock at this frame: the host's timestamp less any time `rebase` took out, run at the
35
+ * The mix clock at this frame. The host's timestamp less any time `rebase` took out, run at the
35
36
  * mix's `rate`. Identical for every probe in the frame.
36
37
  */
37
- timestamp: number;
38
+ readonly timestamp: number;
38
39
  /**
39
- * The gap this subject is catching up by: milliseconds since it last advanced, which is the gap
40
+ * The gap this subject is catching up by, in milliseconds since it last advanced. That is the gap
40
41
  * since the previous sync only for a subject sampled every frame. Infinity under reduced motion;
41
- * no more than `maxDt` where the mix sets one. Inside a `step` under `stepMs`, it is `stepMs`, and
42
- * `timestamp` is the end of that interval. A lane samples a subject for one frame after its last
43
- * probe. A read by `project` is one sample, so its gap is not the gap a frame of play has.
42
+ * no more than `maxDt` where the mix sets one. Inside a `step` under `stepMs`, it is `stepMs`,
43
+ * and `timestamp` is the end of that interval. A lane samples a subject for one frame after its
44
+ * last probe. A read by `project` is one sample, so its gap is not the gap a frame of play has.
44
45
  */
45
- dt: number;
46
+ readonly dt: number;
46
47
  /**
47
48
  * Milliseconds this voice has been playing, rate applied. Below 0 only for a voice with no end
48
49
  * cued backward, which plays into the passes before its first.
49
50
  */
50
- elapsed: number;
51
+ readonly elapsed: number;
51
52
  /** Which pass this is, 0 first; below 0 where `elapsed` is. */
52
- pass: number;
53
- /** This voice's weight for this subject this frame, after fades, signals and any locus. */
54
- weight: number;
53
+ readonly pass: number;
54
+ /** This voice's weight for this subject this frame, after fades, signals and any role. */
55
+ readonly weight: number;
55
56
  /** This subject's state, when the patch declares one. */
56
- state: S;
57
- /** Anything the host adds for its own patches: the mix's `host`, typed as its `H`. */
58
- host: H;
57
+ readonly state: S;
58
+ /** Anything the host adds for its own patches. The mix's `host`, typed as its `H`. */
59
+ readonly host: H;
59
60
  /**
60
61
  * The state `owner` keeps for this voice and this subject, made by `init` on first ask. The mix
61
62
  * holds it, so a read at another time can copy it instead of moving it. A stateful signal keeps
@@ -91,33 +92,51 @@ export interface Sent<I, E = unknown> {
91
92
  event: E;
92
93
  }
93
94
  /**
94
- * What a `'motion'` patch is made of, as data an engine can read: the kind of motion and its
95
+ * What a `'motion'` patch is made of, as data an engine can read. The kind of motion and its
95
96
  * constants. Each subject's start, target and starting velocity stay on the patch, since they may
96
97
  * be functions of the subject.
97
98
  *
98
99
  * @category patch
99
100
  */
100
- export type MotionSpec = {
101
+ export type MotionSpec = SpringSpec | GlideSpec | TweenSpec;
102
+ /**
103
+ * A spring's constants, as `MotionSpec` gives them.
104
+ *
105
+ * @category patch
106
+ */
107
+ export interface SpringSpec {
101
108
  readonly kind: 'spring';
102
- /** Per second squared. */
109
+ /** How hard the spring pulls toward its target, per second squared. */
103
110
  readonly stiffness: number;
104
- /** Per second. */
111
+ /** How fast the spring's motion dies away, per second. */
105
112
  readonly damping: number;
106
113
  readonly mass: number;
107
114
  readonly settle: number;
108
- } | {
115
+ }
116
+ /**
117
+ * A glide's constants, as `MotionSpec` gives them.
118
+ *
119
+ * @category patch
120
+ */
121
+ export interface GlideSpec {
109
122
  readonly kind: 'glide';
110
123
  /** The friction's time constant, ms. */
111
124
  readonly ms: number;
112
125
  readonly settle: number;
113
126
  /** The spring back's, per second squared; only on a glide with bounds. */
114
127
  readonly stiffness?: number;
115
- } | {
128
+ }
129
+ /**
130
+ * A tween's constants, as `MotionSpec` gives them.
131
+ *
132
+ * @category patch
133
+ */
134
+ export interface TweenSpec {
116
135
  readonly kind: 'tween';
117
- /** How long a stretch takes; undefined where it varies by subject, kept on the patch then. */
136
+ /** How long a stretch takes. Undefined where it varies by subject, kept on the patch then. */
118
137
  readonly ms: number | undefined;
119
138
  readonly ease: Easing;
120
- };
139
+ }
121
140
  /**
122
141
  * A pure function of phase and a subject that returns a delta. Optionally stateful.
123
142
  *
@@ -125,7 +144,7 @@ export type MotionSpec = {
125
144
  */
126
145
  export interface Patch<I, O, S = void, H = unknown> {
127
146
  /**
128
- * Which authoring form built it: `'fn'` from `patch`, `'keys'` from `keys`, `'motion'` from
147
+ * Which authoring form built it. `'fn'` from `patch`, `'keys'` from `keys`, `'motion'` from
129
148
  * `spring`, `glide` or `tween`. An engine declares which forms it runs.
130
149
  */
131
150
  readonly form: 'fn' | 'keys' | 'motion';
@@ -146,20 +165,20 @@ export interface Patch<I, O, S = void, H = unknown> {
146
165
  readonly reads?: readonly string[];
147
166
  /**
148
167
  * `phase` is 0..1 across one pass, wrapping. Not asked for a subject its voice gives no weight, unless the voice is fading to rest;
149
- * `step` still runs. A `keys` patch's stops are not read there either, unless its voice is in a locus.
168
+ * `step` still runs. A `keys` patch's stops are not read there either, unless its voice is in a role.
150
169
  */
151
170
  at(phase: number, subject: I, setting: Setting<S, H>): Partial<O>;
152
171
  /** Per-subject state, created on the first frame this patch sees a subject. */
153
172
  state?(subject: I): S;
154
173
  /**
155
- * Advances state once per subject per sampled frame, by the whole gap since it last advanced; or,
156
- * where the mix sets `stepMs`, once per whole interval of that length.
174
+ * Advances state once per subject per sampled frame. It advances by the whole gap since it last
175
+ * advanced; or, where the mix sets `stepMs`, once per whole interval of that length.
157
176
  */
158
177
  step?(state: S, dt: number, subject: I, setting: Setting<S, H>): void;
159
178
  /** Present when the patch was authored as keyframes, so an engine that reads data can. */
160
179
  readonly keys?: readonly Keyframe<O>[];
161
180
  /**
162
- * Present on a `keys` patch that was given them: what `keys` took besides its stops, each as
181
+ * What `keys` took besides its stops, on a `keys` patch that was given them. Each is as
163
182
  * `KeysOptions` describes it. They are read off the patch, so a copy that changes one, as
164
183
  * `{ ...p, ease: 'linear' }` does, plays by its own.
165
184
  */
@@ -167,9 +186,12 @@ export interface Patch<I, O, S = void, H = unknown> {
167
186
  easeBy?(channel: keyof O): Easing | undefined;
168
187
  delayBy?(channel: keyof O): number;
169
188
  lerpBy?(channel: keyof O): ((a: never, b: never, u: number) => unknown) | undefined;
170
- /** Present on a `wave` patch: what `wave` took, which a copy may change as it may a `keys` field. */
189
+ /** What `wave` took, present on a `wave` patch. A copy may change it as it may a `keys` field. */
171
190
  readonly wave?: WaveOptions<O>;
172
- /** Present on a `'motion'` patch: its kind and constants, for an engine that reads data. */
191
+ /**
192
+ * A `'motion'` patch's kind and constants, for an engine that reads data. Absent on any other
193
+ * patch.
194
+ */
173
195
  readonly motion?: MotionSpec;
174
196
  /**
175
197
  * A copy of `state` that shares nothing with it, for a read at another time. Default
@@ -178,7 +200,7 @@ export interface Patch<I, O, S = void, H = unknown> {
178
200
  */
179
201
  clone?(state: S): S;
180
202
  /**
181
- * `state` as data that survives `structuredClone`, for a history `store` to keep; `unpack` makes
203
+ * `state` as data that survives `structuredClone`, for a history `store` to keep. `unpack` makes
182
204
  * a state from it again. With a store, a patch with `state` or `step` needs both, or `cue`
183
205
  * refuses it.
184
206
  */
@@ -192,6 +214,17 @@ export interface Patch<I, O, S = void, H = unknown> {
192
214
  *
193
215
  * @category signal
194
216
  */
195
- export type Signal<I, H = unknown> = ((subject: I, setting: Setting<void, H>) => number) & {
217
+ export interface Signal<I, H = unknown> {
218
+ (subject: I, setting: Setting<void, H>): number;
196
219
  readonly input?: boolean;
197
- };
220
+ }
221
+ /**
222
+ * Two thresholds that switch something on and off. On at `on` and off at `off`, holding it as it
223
+ * was between.
224
+ *
225
+ * @category signal
226
+ */
227
+ export interface Band {
228
+ on: number;
229
+ off: number;
230
+ }
@@ -1,24 +1,25 @@
1
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.
2
+ * One of the five times a voice is known by on the mix clock. They are when its fade in begins
3
+ * (`start`), when it is fully in (`in`), when its last pass ends (`coast`), when its fade out
4
+ * begins (`out`), and when it is gone (`end`). A voice coasts when `played` resolves true, for its
5
+ * latest-staggered subject: at its `out` where it does not freeze, and where it starts showing its
6
+ * last frame where it does. A voice that loops for good, or fades before its last pass ends, never
7
+ * coasts.
7
8
  *
8
9
  * @category score
9
10
  */
10
11
  export type Mark = 'start' | 'in' | 'coast' | 'out' | 'end';
11
12
  /**
12
- * A mark by name: one of a voice's own five, or one it places inside itself with `marks`.
13
+ * A mark by name. It is one of a voice's own five, or one it places inside itself with `marks`.
13
14
  *
14
15
  * @category score
15
16
  */
16
17
  export type MarkName = Mark | (string & {});
17
18
  /**
18
- * Selects voices by what the plan knows of them, never by a channel's value, within the asking
19
- * voice's own score unless it names another. Where several match,
20
- * the resolver picks one: `last` cued (the default), `first` cued, `next` (the earliest whose mark
21
- * is still to come), `earliest` or `latest` by the mark's time.
19
+ * Selects voices by what the plan knows of them, never by a channel's value. It looks within the
20
+ * asking voice's own score unless it names another. Where several match, the resolver picks one:
21
+ * `last` cued (the default), `first` cued, `next` (the earliest whose mark is still to come),
22
+ * `earliest` or `latest` by the mark's time.
22
23
  *
23
24
  * @category score
24
25
  */
@@ -32,8 +33,8 @@ export interface Query {
32
33
  resolver?: 'last' | 'first' | 'next' | 'earliest' | 'latest';
33
34
  }
34
35
  /**
35
- * A time given by another voice: `mark` of the voice `of` selects, moved by `by` ms, where `mark`
36
- * is one of its five or one it places inside itself with `marks`. `after` is
36
+ * A time given by another voice. It is `mark` of the voice `of` selects, moved by `by` ms, where
37
+ * `mark` is one of its five or one it places inside itself with `marks`. `after` is
37
38
  * sugar for that voice's `end`, `with` for its `start`, and `before` for its start less `by`. A
38
39
  * string selects by name. `all` is the latest of its anchors, known once every one is; `any` the
39
40
  * earliest, known once one has passed or every one is known.
@@ -59,12 +60,12 @@ export type Anchor = {
59
60
  any: readonly Anchor[];
60
61
  };
61
62
  /**
62
- * Where a voice sits on the mix clock: at most one of `start` and `in`, and at most one of `out`
63
- * and `end`, each a timestamp on the host's clock or an anchor to another voice. A voice whose
64
- * anchor has no answer yet waits pending; one whose anchored mark is already past starts partway
65
- * through, as playback does from the middle of a region. A fade out begins no earlier than the
66
- * voice starts: an `end` that leaves less room than `fade.out` shortens the fade to fit, and one
67
- * before the start makes the voice an instant, which starts and ends at its start and shows
63
+ * Where a voice sits on the mix clock. It sets at most one of `start` and `in`, and at most one of
64
+ * `out` and `end`, each a timestamp on the host's clock or an anchor to another voice. A voice
65
+ * whose anchor has no answer yet waits pending; one whose anchored mark is already past starts
66
+ * partway through, as playback does from the middle of a region. A fade out begins no earlier than
67
+ * the voice starts: an `end` that leaves less room than `fade.out` shortens the fade to fit, and
68
+ * one before the start makes the voice an instant, which starts and ends at its start and shows
68
69
  * nothing.
69
70
  *
70
71
  * @category score
@@ -76,32 +77,38 @@ export interface Placement {
76
77
  end?: number | Anchor;
77
78
  }
78
79
  /**
79
- * One mark as `marks` lists it: one of a voice's, or one the host announced on a score, which has a
80
- * name and no voice.
80
+ * One mark as `marks` lists it. It is one of a voice's, or one the host announced on a score,
81
+ * which has a name and no voice.
81
82
  *
82
83
  * @category score
83
84
  */
84
85
  export interface Marked {
85
86
  /** On the host's clock. */
86
87
  timestamp: number;
87
- /** Which of a voice's this is, one of its five or one it placed inside itself; undefined for an announced mark. */
88
+ /**
89
+ * Which of a voice's marks this is. It is one of its five or one it placed inside itself;
90
+ * undefined for an announced mark.
91
+ */
88
92
  mark: MarkName | undefined;
89
93
  /** The voice it belongs to; undefined for an announced mark. */
90
94
  voice: number | undefined;
91
95
  score: string | undefined;
92
96
  name: string | undefined;
93
97
  tags: readonly string[];
94
- /** The `name` of the mix the voice is in, or that announced the mark; undefined for none. */
98
+ /** The `name` of the mix the voice is in, or that announced the mark. Undefined for none. */
95
99
  mix: string | undefined;
96
100
  }
97
101
  /**
98
- * An event at a time on a voice's own clock, which `book` hands a host ahead of time. It plays once
102
+ * An event at a time on a voice's own clock. `book` hands it to a host ahead of time. It plays once
99
103
  * per pass, for the voice and not per subject, so `stagger` does not spread it.
100
104
  *
101
105
  * @category score
102
106
  */
103
107
  export interface Hit<E = unknown> {
104
- /** Voice ms into each pass: 0 up to the patch's `duration`, or any time from 0 for a patch with none. */
108
+ /**
109
+ * Voice ms into each pass. It runs from 0 up to the patch's `duration`, or any time from 0 for a
110
+ * patch with none.
111
+ */
105
112
  at: number;
106
113
  event: E;
107
114
  }
@@ -126,38 +133,46 @@ export interface BookedHit<E = unknown, I = unknown> {
126
133
  subjects: readonly I[] | undefined;
127
134
  }
128
135
  /**
129
- * What `book` takes: an outside clock, how far ahead to book on it, and what to do with each item.
136
+ * What `book` takes. It names an outside clock, how far ahead to book on it, and what to do with
137
+ * each item.
130
138
  *
131
139
  * @category score
132
140
  */
133
141
  export interface BookOptions<E = unknown, I = unknown> {
134
142
  /**
135
- * The outside clock, in ms: `audio.currentTime * 1000`, `performance.now()`, or whatever the host
136
- * schedules against. Read once a sync. The mix maps its host time onto it by an offset that folds
137
- * in 5% of each frame's difference, and starts over from the clock's own reading on a jump past
138
- * 50 ms, such as a suspended context or a hidden tab.
143
+ * The outside clock, in ms. It is `audio.currentTime * 1000`, `performance.now()`, or whatever
144
+ * the host schedules against. Read once a sync. The mix maps its host time onto it by an offset
145
+ * that folds in 5% of each frame's difference, and starts over from the clock's own reading on a
146
+ * jump past 50 ms, such as a suspended context or a hidden tab.
139
147
  */
140
148
  clock: () => number;
141
149
  /** How far ahead to book, host ms. It has to cover the longest gap between two syncs. */
142
150
  ahead: number;
143
- /** How far past an item first seen late may be and still be taken, host ms. */
151
+ /** How late an item may be when first seen and still be taken, host ms. */
144
152
  late: number;
145
153
  /**
146
- * Called once per item: a mark as `marks` lists it, or a hit. `when` is on the outside clock;
154
+ * Called once per item, a mark as `marks` lists it or a hit. `when` is on the outside clock;
147
155
  * `lateBy` is how many host ms past the item was when first seen, which is then taken at the
148
156
  * clock's now; it is 0 for one booked ahead. Return a `cancel` to hear about a booking whose time moved by
149
157
  * more than 1 ms or that went away (a seek, a rate or ramp on the voice or the mix, a fade, a
150
158
  * `rebase`, an anchor's target moving, the voice leaving); the item is then booked again, at its
151
159
  * new time, at the same sync.
152
160
  */
153
- take(item: Marked | BookedHit<E, I>, when: number, lateBy: number): {
154
- cancel(): void;
155
- } | undefined;
161
+ take(item: Marked | BookedHit<E, I>, when: number, lateBy: number): Taken | undefined;
156
162
  /** Book only the voices, and announced marks, carrying this tag. */
157
163
  tag?: string;
158
164
  /** Book only this score's voices and marks. */
159
165
  score?: string;
160
166
  }
167
+ /**
168
+ * What `BookOptions.take` may return for a booking it took.
169
+ *
170
+ * @category score
171
+ */
172
+ export interface Taken {
173
+ /** Called when the booking's time moved by more than 1 ms, or it went away. */
174
+ cancel(): void;
175
+ }
161
176
  /**
162
177
  * A running booker, returned by `book`.
163
178
  *
@@ -167,8 +182,8 @@ export interface Booker {
167
182
  /** Cancels every booking still ahead, and books nothing more. */
168
183
  cancel(): void;
169
184
  /**
170
- * Where host `timestamp` falls on the outside clock, by the offset as the last sync left it;
171
- * NaN before the first sync.
185
+ * Where host `timestamp` falls on the outside clock. It goes by the offset as the last sync left
186
+ * it; NaN before the first sync.
172
187
  */
173
188
  at(timestamp: number): number;
174
189
  }
@@ -1,8 +1,8 @@
1
1
  import type { Tape } from './history.js';
2
- import type { Mix, MixOptions, Projection } from './mix.js';
2
+ import type { AnnounceOptions, Mix, MixOptions, Projection } from './mix.js';
3
3
  import type { Marked } from './place.js';
4
4
  /**
5
- * How a transport is made: what history it keeps for every mix on it.
5
+ * How a transport is made. It says what history the transport keeps for every mix on it.
6
6
  *
7
7
  * @category mix
8
8
  */
@@ -10,8 +10,8 @@ export interface TransportOptions {
10
10
  history?: MixOptions['history'];
11
11
  }
12
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.
13
+ * Every mix on a transport read at another mix time, with nothing live moved. `of` gives one
14
+ * mix's reading. Valid until the transport is next synced or a mix on it cued.
15
15
  *
16
16
  * @category mix
17
17
  */
@@ -20,8 +20,8 @@ export interface TransportProjection {
20
20
  of<I, O, H>(mix: Mix<I, O, H>): Projection<I, O>;
21
21
  }
22
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
23
+ * One clock several mixes play on, each over its own kit. It gives them one sync, one rate, one
24
+ * seek and one tape, and a score that spans them, so an anchor in one mix waits on a voice in
25
25
  * another by naming the score they share. A query naming no score stays in its own mix.
26
26
  *
27
27
  * @category mix
@@ -35,7 +35,7 @@ export interface Transport {
35
35
  rate: number;
36
36
  ramp(rate: number, over: number): void;
37
37
  /**
38
- * As `Mix.seek`, for every mix on it at once: back, each mix restores itself; forward, the one
38
+ * As `Mix.seek`, for every mix on it at once. Back, each mix restores itself; forward, the one
39
39
  * tape plays every mix's calls again in the order they were made, so an anchor across mixes
40
40
  * answers as it did. A mix dropped after the moment sought is back on the transport.
41
41
  */
@@ -43,25 +43,24 @@ export interface Transport {
43
43
  readonly frame: number;
44
44
  }): void;
45
45
  /**
46
- * Loads from the history `store` what `seek(time)` and `project(time)` will need, where that
47
- * reaches past memory. Without a store, or within memory, it loads nothing.
46
+ * Loads from the history `store` what a seek or projection to `time` will need. That is, what
47
+ * `seek(time)` and `project(time)` need where it reaches past memory. Without a store, or within
48
+ * memory, it loads nothing.
48
49
  */
49
50
  prepare(time: number): Promise<void>;
50
51
  readonly now: number;
51
- /** As `Mix.seq`: the number of the frame being played, the same for every mix on it. */
52
+ /** As `Mix.seq`, the number of the frame being played. It is the same for every mix on it. */
52
53
  readonly seq: number;
53
54
  readonly tape: Tape | undefined;
54
55
  /** Puts a named mark on a score every mix on it sees. Throws without a `score`. */
55
- announce(name: string, opts: {
56
- at?: number;
56
+ announce(name: string, opts: AnnounceOptions & {
57
57
  score: string;
58
- tags?: readonly string[];
59
58
  }): void;
60
59
  /** Every mark of every mix on it, and every mark announced on it, earliest first. */
61
60
  marks(from: number, to: number): Marked[];
62
61
  /**
63
- * Every mix on it read at mix time `at`, or at the frame `{ frame }` names, together, so anchors
64
- * across them answer.
62
+ * Every mix on it read together at another time. The time is mix time `at`, or the frame
63
+ * `{ frame }` names, and reading them together lets anchors across them answer.
65
64
  */
66
65
  project(at: number | {
67
66
  readonly frame: number;
@@ -70,11 +69,14 @@ export interface Transport {
70
69
  readonly live: boolean;
71
70
  /** Every mix on it inert. */
72
71
  readonly inert: boolean;
73
- /** Calls `fn` when any mix on it needs frames again after a sync, once until the next sync. */
72
+ /**
73
+ * Calls `fn` when any mix on it needs frames again after a sync. It fires once until the next
74
+ * sync.
75
+ */
74
76
  onWake(fn: () => void): () => void;
75
77
  /**
76
- * Takes a mix off: it is no longer synced and takes no more calls. With history, a seek back
77
- * before the drop puts it back as it was then; without, it is let go.
78
+ * Takes a mix off the transport. It is no longer synced and takes no more calls. With history, a
79
+ * seek back before the drop puts it back as it was then; without, it is let go.
78
80
  */
79
81
  drop<I, O, H>(mix: Mix<I, O, H>): void;
80
82
  }