@adatechnology/game-audio 0.7.0 → 0.9.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/README.md +69 -1
- package/assets/sfx/CREDITOS.md +2 -2
- package/assets/sfx/manifest.json +48 -0
- package/dist/bank-Dsj1VAht.d.ts +391 -0
- package/dist/chunk-JV5XXCQE.js +180 -0
- package/dist/chunk-JV5XXCQE.js.map +1 -0
- package/dist/{chunk-BXUGSOPY.js → chunk-UUWKSG4J.js} +240 -167
- package/dist/chunk-UUWKSG4J.js.map +1 -0
- package/dist/fitted.d.ts +89 -0
- package/dist/fitted.js +139 -0
- package/dist/fitted.js.map +1 -0
- package/dist/index.d.ts +138 -3
- package/dist/index.global.js +642 -200
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +258 -20
- package/dist/index.js.map +1 -1
- package/dist/{locale-CJfDpWnI.d.ts → locale-YHyJwN2P.d.ts} +108 -440
- package/dist/testing.d.ts +5 -4
- package/dist/testing.js +2 -1
- package/package.json +6 -2
- package/dist/chunk-BXUGSOPY.js.map +0 -1
|
@@ -1,340 +1,119 @@
|
|
|
1
|
+
import { B as BusId, q as SampleEnvironment, p as SampleCrossover, F as Falloff, c as SampleSound, t as SampleTier, h as BuildOrder, C as Curve, b as SoundRecipe, S as SoundRegistry, a as SoundBank } from './bank-Dsj1VAht.js';
|
|
1
2
|
import { Vec3, DeferredQueue, TestableModule } from '@adatechnology/game-contracts';
|
|
2
3
|
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
declare const BUS_IDS: readonly ["weapons", "voices", "world", "ambience", "weather", "ui"];
|
|
8
|
-
type BusId = (typeof BUS_IDS)[number];
|
|
9
|
-
/** A named number: from `PlayOptions.params` or the recipe's `vars`, times `scale`, plus `add`. */
|
|
10
|
-
type ParamRef = {
|
|
11
|
-
readonly param: string;
|
|
12
|
-
readonly scale?: number;
|
|
13
|
-
readonly add?: number;
|
|
14
|
-
};
|
|
15
|
-
/** A number, a `[min, max]` drawn uniformly (`min + random × (max − min)`), or a named number. */
|
|
16
|
-
type Range = number | readonly [min: number, max: number] | ParamRef;
|
|
17
|
-
/** Seconds from the layer start: a range, the layer `'duration'`, or `'0.6d'` (0.6 × the layer duration). */
|
|
18
|
-
type Time = Range | 'duration' | `${number}d`;
|
|
19
|
-
type Curve = 'linear' | 'exp';
|
|
20
|
-
/**
|
|
21
|
-
* How an AudioParam moves:
|
|
22
|
-
* - `{ set }` assigns `.value`;
|
|
23
|
-
* - `{ set, to, curve, over }` assigns `.value`, then ramps to `to` at `over`;
|
|
24
|
-
* - `{ from }` calls `setValueAtTime(from)` at the start; with `to`, `curve` and `over` it then ramps to `to` (`'from'` is the value drawn for `from`: the art scene ramps a tone back to its own start when it gives no end).
|
|
25
|
-
*/
|
|
26
|
-
type Automation = {
|
|
27
|
-
readonly set: Range;
|
|
28
|
-
readonly to?: Range | 'from';
|
|
29
|
-
readonly curve?: Curve;
|
|
30
|
-
readonly over?: Time;
|
|
31
|
-
} | {
|
|
32
|
-
readonly from: Range;
|
|
33
|
-
readonly to?: Range | 'from';
|
|
34
|
-
readonly curve?: Curve;
|
|
35
|
-
readonly over?: Time;
|
|
36
|
-
};
|
|
37
|
-
/**
|
|
38
|
-
* One gain point: time (seconds, or `'0.6d'`), value and how it is reached (`set` = `setValueAtTime`, or a ramp). The value is multiplied by the
|
|
39
|
-
* layer level (volume, distance and layer gain) except when the fourth item is `'fixed'` (the floor a ramp falls to, such as 0.001).
|
|
40
|
-
*/
|
|
41
|
-
type EnvelopePoint = readonly [time: number | `${number}d`, value: number, curve: 'set' | Curve] | readonly [time: number | `${number}d`, value: number, curve: 'set' | Curve, fixed: 'fixed'];
|
|
42
|
-
type Envelope = readonly EnvelopePoint[];
|
|
43
|
-
type FilterSpec = {
|
|
44
|
-
readonly type: BiquadFilterType;
|
|
45
|
-
readonly frequency: Automation;
|
|
46
|
-
readonly q?: Range;
|
|
47
|
-
/** The BiquadFilter gain (shelf and peaking types). */
|
|
48
|
-
readonly gain?: Range;
|
|
49
|
-
/** A gain node after the filter, for a parallel bank where each band has its own level (the game's scream formants). */
|
|
50
|
-
readonly level?: Range;
|
|
51
|
-
};
|
|
52
|
-
type FilterBank = {
|
|
53
|
-
readonly mode: 'serial' | 'parallel';
|
|
54
|
-
readonly bank: readonly FilterSpec[];
|
|
55
|
-
};
|
|
56
|
-
/** An LFO. `depth` is absolute, or a factor of the source start frequency. With `base`, gain modulation goes through its own gain stage (the game rotor). */
|
|
57
|
-
type Modulator = {
|
|
58
|
-
readonly target: 'gain' | 'frequency';
|
|
59
|
-
/** Left out, the oscillator keeps its default (sine) and no type is set. */
|
|
60
|
-
readonly wave?: OscillatorType;
|
|
61
|
-
readonly rate: Range;
|
|
62
|
-
readonly depth: Range | {
|
|
63
|
-
readonly scaleOf: 'frequency';
|
|
64
|
-
readonly factor: number;
|
|
65
|
-
};
|
|
66
|
-
readonly base?: number;
|
|
67
|
-
};
|
|
68
|
-
/**
|
|
69
|
-
* Noise from the engine's seeded buffer. `offset` is where playback starts in it: `'random'` (random × `offsetScale`, default 1), `'fit'`
|
|
70
|
-
* (random × (buffer length − duration)) or seconds. `loop` sets the source to loop (the art scene sets it on every noise source).
|
|
71
|
-
*/
|
|
72
|
-
type NoiseSource = {
|
|
73
|
-
readonly kind: 'noise';
|
|
74
|
-
readonly offset?: 'random' | 'fit' | number;
|
|
75
|
-
readonly offsetScale?: number;
|
|
76
|
-
readonly loop?: boolean;
|
|
77
|
-
};
|
|
78
|
-
type OscSource = {
|
|
79
|
-
readonly kind: 'osc';
|
|
80
|
-
readonly wave: OscillatorType;
|
|
81
|
-
readonly frequency: Automation;
|
|
82
|
-
};
|
|
83
|
-
/** The art scene's `voice`: an oscillator with vibrato through formant bands, plus a band of breath noise, summed and boosted. */
|
|
84
|
-
type FormantVoiceSource = {
|
|
85
|
-
readonly kind: 'formant_voice';
|
|
86
|
-
readonly wave: OscillatorType;
|
|
87
|
-
readonly frequency: Automation;
|
|
88
|
-
/** Vibrato rate, and depth as a factor of the start frequency. */
|
|
89
|
-
readonly vibrato: {
|
|
90
|
-
readonly rate: Range;
|
|
91
|
-
readonly depth: number;
|
|
92
|
-
};
|
|
93
|
-
readonly formants: readonly {
|
|
94
|
-
readonly frequency: Range;
|
|
95
|
-
readonly q: number;
|
|
96
|
-
}[];
|
|
97
|
-
readonly breath: {
|
|
98
|
-
readonly frequency: Range;
|
|
99
|
-
readonly q: number;
|
|
100
|
-
readonly gain: Range;
|
|
101
|
-
};
|
|
102
|
-
readonly mix: number;
|
|
103
|
-
};
|
|
104
|
-
type LayerSource = NoiseSource | OscSource | FormantVoiceSource;
|
|
105
|
-
type Layer = {
|
|
106
|
-
/** Start, seconds after the sound starts. */
|
|
107
|
-
readonly at?: Range;
|
|
108
|
-
/** Overrides the recipe duration for this layer. */
|
|
109
|
-
readonly duration?: Range;
|
|
110
|
-
/** Seconds the source keeps running after the duration (the `+ 0.05` of the team routines). Default: the recipe's, else 0.05. */
|
|
111
|
-
readonly tail?: number;
|
|
112
|
-
/** The layer played `count` times, `spacing` seconds apart (the game's animal calls). */
|
|
113
|
-
readonly repeat?: {
|
|
114
|
-
readonly count: number;
|
|
115
|
-
readonly spacing: number;
|
|
116
|
-
};
|
|
117
|
-
/** Layer level before distance. Default 1. */
|
|
118
|
-
readonly gain?: Range;
|
|
119
|
-
/** Send to the reverb, 0..1 or more (the art scene uses up to 1.2). */
|
|
120
|
-
readonly wet?: number;
|
|
121
|
-
readonly source: LayerSource;
|
|
122
|
-
readonly filters?: FilterBank;
|
|
123
|
-
readonly modulators?: readonly Modulator[];
|
|
124
|
-
readonly envelope: Envelope;
|
|
4
|
+
/** Where the ears are. `yaw` turns around y like a three.js camera: the right ear points at `(cos yaw, 0, −sin yaw)`. */
|
|
5
|
+
type Listener = {
|
|
6
|
+
readonly position: Vec3;
|
|
7
|
+
readonly yaw: number;
|
|
125
8
|
};
|
|
9
|
+
type DistanceMode = 'xz' | '3d';
|
|
10
|
+
declare const DEFAULT_LISTENER: Listener;
|
|
11
|
+
/** The art scene clamps the pan to ±0.85 and never divides by less than 2 m (cena L1319). */
|
|
12
|
+
declare const PAN_LIMIT = 0.85;
|
|
13
|
+
declare const PAN_MIN_DISTANCE = 2;
|
|
14
|
+
/** Distance from the listener: on the ground (`xz`, the teams' choice) or in 3D. */
|
|
15
|
+
declare function listenerDistance(listener: Listener, position: Vec3, mode?: DistanceMode): number;
|
|
16
|
+
/** The art scene's `panFor`: the side the sound is on, −0.85 (left) to 0.85 (right). No HRTF, for cost. */
|
|
17
|
+
declare function panFor(listener: Listener, position: Vec3): number;
|
|
18
|
+
|
|
126
19
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
20
|
+
* Sounds made of recorded files (`.ogg`), as data. A `SampleSound` lists the takes of each layer: `close` (the sound as heard near, the only one
|
|
21
|
+
* required), `far` (the same event heard from far away: a muffled bang with its echo) and the tail of the place it happens in (`indoor` / `outdoor`).
|
|
22
|
+
* `planSample` decides, from a seeded stream, which take plays (round-robin: never the same take twice in a row), the pitch (± a fraction), how the
|
|
23
|
+
* near and far layers cross over with the distance, the level, the pan and the distance lowpass. It is pure, so it runs in Node and in tests; the
|
|
24
|
+
* WebAudio layer (`realizeSample`) plays the plan from decoded buffers.
|
|
132
25
|
*/
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
26
|
+
|
|
27
|
+
declare const SAMPLE_ENVIRONMENTS: readonly ["indoor", "outdoor"];
|
|
28
|
+
/** The role of a layer in a plan. */
|
|
29
|
+
type SampleLayerRole = 'close' | 'far' | 'tail';
|
|
30
|
+
declare const DEFAULT_SAMPLE_FALLOFF: Falloff;
|
|
31
|
+
declare const DEFAULT_CROSSOVER: SampleCrossover;
|
|
32
|
+
declare const DEFAULT_SAMPLE_PITCH = 0.04;
|
|
33
|
+
declare const DEFAULT_TAIL_GAIN = 0.6;
|
|
34
|
+
declare const DEFAULT_SAMPLE_CUTOFF_K = 0.01;
|
|
35
|
+
/** The open lowpass: at or above it the realizer leaves the filter out. */
|
|
36
|
+
declare const OPEN_CUTOFF = 20000;
|
|
37
|
+
/** A layer quieter than this is left out of the plan. */
|
|
38
|
+
declare const LAYER_FLOOR = 0.001;
|
|
39
|
+
/** One file to play: which take, at what level (already times the sound level), rate and start. */
|
|
40
|
+
type PlannedSampleLayer = {
|
|
41
|
+
readonly role: SampleLayerRole;
|
|
42
|
+
readonly url: string;
|
|
43
|
+
/** Index of the take in its list. */
|
|
44
|
+
readonly take: number;
|
|
45
|
+
readonly gain: number;
|
|
46
|
+
readonly rate: number;
|
|
47
|
+
readonly at: number;
|
|
48
|
+
/** Seconds into the file (the take's trim). */
|
|
49
|
+
readonly offset?: number;
|
|
50
|
+
/** Seconds of the file played (the take's trim). */
|
|
51
|
+
readonly duration?: number;
|
|
146
52
|
};
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
* matches the trace of the team code node for node:
|
|
150
|
-
* - `layered` (default): the art scene's `sNoise`, `sTone` and `voice`; every layer has its own output stage (distance gain, pan, reverb send);
|
|
151
|
-
* - `burst`: the game's `sfx` (jogo L62089);
|
|
152
|
-
* - `scream`: the game's `grito` (L62128);
|
|
153
|
-
* - `groan`: the game's `voz` (L62143);
|
|
154
|
-
* - `boom`: the game's `boom` (L68278);
|
|
155
|
-
* - `static`: the game's `chiado` (L69998);
|
|
156
|
-
* - `chord`: the game's `buzina` (L70272);
|
|
157
|
-
* - `calls`: the game's `bichoSom` (L66625);
|
|
158
|
-
* - `siren`: the art scene's `siren` (L1369);
|
|
159
|
-
* - `weapon`: the weapon audio of the kit (`weapons-three`): per layer a filtered noise burst or an oscillator, then its own gain, chained to the bus.
|
|
160
|
-
* Every order but `layered` puts the level into the envelope and connects straight to the bus.
|
|
161
|
-
*/
|
|
162
|
-
declare const BUILD_ORDERS: readonly ["layered", "burst", "scream", "groan", "boom", "static", "chord", "calls", "siren", "weapon"];
|
|
163
|
-
type BuildOrder = (typeof BUILD_ORDERS)[number];
|
|
164
|
-
type SoundRecipe = {
|
|
53
|
+
type SamplePlan = {
|
|
54
|
+
readonly kind: 'sample';
|
|
165
55
|
readonly id: string;
|
|
166
56
|
readonly bus: BusId;
|
|
167
|
-
readonly
|
|
168
|
-
|
|
169
|
-
readonly
|
|
170
|
-
|
|
171
|
-
readonly
|
|
172
|
-
|
|
173
|
-
readonly
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
57
|
+
readonly level: number;
|
|
58
|
+
readonly distance: number;
|
|
59
|
+
readonly pan?: number;
|
|
60
|
+
/** Lowpass cutoff in Hz (`OPEN_CUTOFF` = no filter). */
|
|
61
|
+
readonly cutoff: number;
|
|
62
|
+
/** Playback rate of every layer (the pitch drawn for this play). */
|
|
63
|
+
readonly rate: number;
|
|
64
|
+
readonly environment: SampleEnvironment;
|
|
65
|
+
/** The tier played (`undefined` without tiers or intensity). */
|
|
66
|
+
readonly tier?: string;
|
|
67
|
+
/** 0 = all near, 1 = all far. */
|
|
68
|
+
readonly farMix: number;
|
|
69
|
+
readonly layers: readonly PlannedSampleLayer[];
|
|
70
|
+
readonly priority: number;
|
|
177
71
|
readonly group?: string;
|
|
178
|
-
/** Limiter priority; default from the bus (weapons > voices > world > ambience). */
|
|
179
|
-
readonly priority?: number;
|
|
180
|
-
/**
|
|
181
|
-
* The team routine creates nodes before it checks the level (the game's `bichoSom` creates its gain and filter first): a silent sound is kept as
|
|
182
|
-
* a plan with `silent: true` so the realizer repeats those nodes. Off by default.
|
|
183
|
-
*/
|
|
184
|
-
readonly keepSilent?: boolean;
|
|
185
|
-
/** Where the numbers come from: `"jogo:L62128"`, `"cena:L1342"`, or `"sdk"` for values the kit chose. */
|
|
186
|
-
readonly sources: readonly string[];
|
|
187
72
|
};
|
|
188
|
-
/**
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
readonly
|
|
197
|
-
readonly order?: LoopOrder;
|
|
198
|
-
/** An oscillator loop may leave the frequency out: it starts at the default and `set({ frequency })` glides it (the game's motor). */
|
|
199
|
-
readonly source: (NoiseSource & {
|
|
200
|
-
readonly loop: true;
|
|
201
|
-
}) | {
|
|
202
|
-
readonly kind: 'osc';
|
|
203
|
-
readonly wave: OscillatorType;
|
|
204
|
-
readonly frequency?: Automation;
|
|
205
|
-
readonly loop: true;
|
|
206
|
-
};
|
|
207
|
-
readonly filters?: FilterBank;
|
|
208
|
-
readonly modulators?: readonly Modulator[];
|
|
209
|
-
/** `setTargetAtTime` time constants (jogo L62125–62126: 0.15 for the volume, 0.08 for the frequency). */
|
|
210
|
-
readonly smoothing?: {
|
|
211
|
-
readonly volume: number;
|
|
212
|
-
readonly frequency: number;
|
|
213
|
-
};
|
|
214
|
-
/** Nodes are created the first time the volume reaches this (jogo L62112: 0.002). */
|
|
215
|
-
readonly startAbove?: number;
|
|
216
|
-
/** Volume the gain starts at when the loop opens (`chain_loop`). */
|
|
73
|
+
/** The last take each sound layer played (`<id>/<role>` → index), so the next play never repeats it. Keep one per engine or channel. */
|
|
74
|
+
type SampleMemory = Map<string, number>;
|
|
75
|
+
type SamplePlanInput = {
|
|
76
|
+
readonly random: () => number;
|
|
77
|
+
readonly listener?: Listener;
|
|
78
|
+
readonly distanceMode?: DistanceMode;
|
|
79
|
+
readonly position?: Vec3;
|
|
80
|
+
/** Metres; overrides `position` for the distance (not for the pan). */
|
|
81
|
+
readonly distance?: number;
|
|
217
82
|
readonly volume?: number;
|
|
218
|
-
/**
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
readonly
|
|
83
|
+
/** Default `outdoor`. */
|
|
84
|
+
readonly environment?: SampleEnvironment;
|
|
85
|
+
/** 0 (clear) to 1 (behind a wall): lowers the level and closes the lowpass. */
|
|
86
|
+
readonly occlusion?: number;
|
|
87
|
+
/** Round-robin memory; without it each plan is drawn on its own (and may repeat). */
|
|
88
|
+
readonly memory?: SampleMemory;
|
|
89
|
+
/** Limiter priority when the sound has none. */
|
|
90
|
+
readonly priority?: number;
|
|
91
|
+
/** 0 (light) to 1 (heavy): picks the tier (see `SampleTier`). */
|
|
92
|
+
readonly intensity?: number;
|
|
226
93
|
};
|
|
227
94
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
95
|
+
* Round-robin without repeat: a take drawn among all but the last one played. With one take it is always 0; without `last` any take may come.
|
|
96
|
+
* One random number per call.
|
|
230
97
|
*/
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
readonly
|
|
237
|
-
|
|
238
|
-
readonly repeat?: boolean;
|
|
239
|
-
};
|
|
240
|
-
type SoundBank = {
|
|
241
|
-
readonly id: string;
|
|
242
|
-
readonly sounds?: readonly SoundRecipe[];
|
|
243
|
-
readonly loops?: readonly LoopRecipe[];
|
|
244
|
-
readonly sets?: readonly SoundSet[];
|
|
245
|
-
/** Sounds played from recorded files (see `sample.ts`). A sample and a recipe may share an id: the sample plays once its files are loaded. */
|
|
246
|
-
readonly samples?: readonly SampleSound[];
|
|
247
|
-
};
|
|
248
|
-
/** One take: a file and its own trim (linear gain, default 1). */
|
|
249
|
-
type SampleRef = {
|
|
250
|
-
readonly url: string;
|
|
251
|
-
readonly gain?: number;
|
|
252
|
-
};
|
|
253
|
-
/** Where a sound happens: a closed room rings short and dense, the open field long and thin. */
|
|
254
|
-
type SampleEnvironment = 'indoor' | 'outdoor';
|
|
255
|
-
/** Where the near take hands over to the far one: all near up to `from` metres, all far from `to`, an equal-power crossfade between. */
|
|
256
|
-
type SampleCrossover = {
|
|
257
|
-
readonly from: number;
|
|
258
|
-
readonly to: number;
|
|
259
|
-
};
|
|
260
|
-
type SampleTail = {
|
|
261
|
-
readonly indoor?: readonly SampleRef[];
|
|
262
|
-
readonly outdoor?: readonly SampleRef[];
|
|
263
|
-
/** Level of the tail against the dry take (default 0.6). */
|
|
264
|
-
readonly gain?: number;
|
|
265
|
-
/** Seconds after the start (default 0: the tail file carries its own pre-delay). */
|
|
266
|
-
readonly at?: number;
|
|
98
|
+
declare function pickTake(count: number, last: number | undefined, random: () => number): number;
|
|
99
|
+
/** 0 at or below `from`, 1 at or beyond `to`, linear between. */
|
|
100
|
+
declare function farMixAt(crossover: SampleCrossover, distance: number): number;
|
|
101
|
+
/** Equal-power gains of the near and far layers for a far mix (so the crossover has no dip in loudness). */
|
|
102
|
+
declare function crossGains(farMix: number): {
|
|
103
|
+
readonly close: number;
|
|
104
|
+
readonly far: number;
|
|
267
105
|
};
|
|
106
|
+
/** The distance lowpass, closed further behind a wall (an occluded sound loses its highs first). */
|
|
107
|
+
declare function sampleCutoff(cutoffK: number, distance: number, occlusion?: number): number;
|
|
108
|
+
/** Every file a sound may play (to load before its first play). */
|
|
109
|
+
declare function sampleUrls(sound: SampleSound): string[];
|
|
110
|
+
/** The tier for an intensity: the last whose `from` is at or below it. */
|
|
111
|
+
declare function tierFor(sound: SampleSound, intensity: number | undefined): SampleTier | undefined;
|
|
268
112
|
/**
|
|
269
|
-
*
|
|
270
|
-
*
|
|
113
|
+
* The plan of one play, or `null` when the sound is too far to be heard. Random numbers, in order: the pitch, the near take, the far take, the
|
|
114
|
+
* tail take (each drawn only when that layer has more than zero takes and is heard).
|
|
271
115
|
*/
|
|
272
|
-
|
|
273
|
-
readonly name: string;
|
|
274
|
-
readonly from: number;
|
|
275
|
-
readonly close: readonly SampleRef[];
|
|
276
|
-
readonly far?: readonly SampleRef[];
|
|
277
|
-
};
|
|
278
|
-
type SampleSound = {
|
|
279
|
-
readonly id: string;
|
|
280
|
-
readonly bus: BusId;
|
|
281
|
-
/** The takes heard near; at least one (the criteria ask four for a sound heard all the time). */
|
|
282
|
-
readonly close: readonly SampleRef[];
|
|
283
|
-
/** The takes heard far; without them the near take plays at every distance (muffled by the lowpass). */
|
|
284
|
-
readonly far?: readonly SampleRef[];
|
|
285
|
-
/** Takes by strength (light, medium, heavy), in rising `from`; without `intensity` the near takes above play. */
|
|
286
|
-
readonly tiers?: readonly SampleTier[];
|
|
287
|
-
/** Default `{ from: 30, to: 80 }`. */
|
|
288
|
-
readonly crossover?: SampleCrossover;
|
|
289
|
-
readonly tail?: SampleTail;
|
|
290
|
-
/** ± fraction of the playback rate drawn per play (default 0.04: ±4 %, inside the 3–5 % of the criteria). 0 plays every take at its pitch. */
|
|
291
|
-
readonly pitch?: number;
|
|
292
|
-
/** Level of the sound (default 1). */
|
|
293
|
-
readonly gain?: number;
|
|
294
|
-
/** Default `{ model: 'inverse_square', k: 0.002, minGain: 0.002 }`: a recorded take already sounds near or far, so the curve is gentler than a recipe's. */
|
|
295
|
-
readonly falloff?: Falloff;
|
|
296
|
-
/** The lowpass cutoff is `20000 / (1 + d × cutoffK)` Hz (default 0.01: 10 kHz at 100 m). 0 turns the distance lowpass off. */
|
|
297
|
-
readonly cutoffK?: number;
|
|
298
|
-
/** Stereo pan from the listener (default true). */
|
|
299
|
-
readonly pan?: boolean;
|
|
300
|
-
readonly group?: string;
|
|
301
|
-
readonly priority?: number;
|
|
302
|
-
/**
|
|
303
|
-
* At most `voices` plays of this sound ring at once: a new one fades the oldest out in `fade` seconds (default 0.03) at its own start. Rapid fire
|
|
304
|
-
* then stays shot by shot instead of a wall of overlapping takes (criterion C9). Without it every play rings to its end.
|
|
305
|
-
*/
|
|
306
|
-
readonly choke?: {
|
|
307
|
-
readonly voices: number;
|
|
308
|
-
readonly fade?: number;
|
|
309
|
-
};
|
|
310
|
-
/**
|
|
311
|
-
* A continuous sound (fire, rain, an engine idling) that `engine.loop(id)` plays: the near takes chained without a seam, each crossed into the next
|
|
312
|
-
* in `crossfade` seconds (default 0.25, equal power), never the same take twice in a row. While the files load, the recipe loop of `fallback`
|
|
313
|
-
* (or of the same id) plays. `play(id)` still plays one take as a one-shot.
|
|
314
|
-
*/
|
|
315
|
-
readonly loop?: boolean | {
|
|
316
|
-
readonly crossfade?: number;
|
|
317
|
-
};
|
|
318
|
-
/** A recipe id the engine plays while the files are not loaded yet (or failed): the synthesized sound stays as the fallback. */
|
|
319
|
-
readonly fallback?: string;
|
|
320
|
-
/** Where each file came from: `"freesound:123456 autor CC0"`, or `"sdk"` for files the kit made. */
|
|
321
|
-
readonly sources: readonly string[];
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
/** Where the ears are. `yaw` turns around y like a three.js camera: the right ear points at `(cos yaw, 0, −sin yaw)`. */
|
|
325
|
-
type Listener = {
|
|
326
|
-
readonly position: Vec3;
|
|
327
|
-
readonly yaw: number;
|
|
328
|
-
};
|
|
329
|
-
type DistanceMode = 'xz' | '3d';
|
|
330
|
-
declare const DEFAULT_LISTENER: Listener;
|
|
331
|
-
/** The art scene clamps the pan to ±0.85 and never divides by less than 2 m (cena L1319). */
|
|
332
|
-
declare const PAN_LIMIT = 0.85;
|
|
333
|
-
declare const PAN_MIN_DISTANCE = 2;
|
|
334
|
-
/** Distance from the listener: on the ground (`xz`, the teams' choice) or in 3D. */
|
|
335
|
-
declare function listenerDistance(listener: Listener, position: Vec3, mode?: DistanceMode): number;
|
|
336
|
-
/** The art scene's `panFor`: the side the sound is on, −0.85 (left) to 0.85 (right). No HRTF, for cost. */
|
|
337
|
-
declare function panFor(listener: Listener, position: Vec3): number;
|
|
116
|
+
declare function planSample(sound: SampleSound, input: SamplePlanInput): SamplePlan | null;
|
|
338
117
|
|
|
339
118
|
/** How an AudioParam moves, with every number resolved and every time in seconds from the layer start. */
|
|
340
119
|
type PlannedAutomation = {
|
|
@@ -448,101 +227,6 @@ type PlanInput = {
|
|
|
448
227
|
*/
|
|
449
228
|
declare function planSound(recipe: SoundRecipe, input?: PlanInput): SoundPlan | null;
|
|
450
229
|
|
|
451
|
-
/**
|
|
452
|
-
* Sounds made of recorded files (`.ogg`), as data. A `SampleSound` lists the takes of each layer: `close` (the sound as heard near, the only one
|
|
453
|
-
* required), `far` (the same event heard from far away: a muffled bang with its echo) and the tail of the place it happens in (`indoor` / `outdoor`).
|
|
454
|
-
* `planSample` decides, from a seeded stream, which take plays (round-robin: never the same take twice in a row), the pitch (± a fraction), how the
|
|
455
|
-
* near and far layers cross over with the distance, the level, the pan and the distance lowpass. It is pure, so it runs in Node and in tests; the
|
|
456
|
-
* WebAudio layer (`realizeSample`) plays the plan from decoded buffers.
|
|
457
|
-
*/
|
|
458
|
-
|
|
459
|
-
declare const SAMPLE_ENVIRONMENTS: readonly ["indoor", "outdoor"];
|
|
460
|
-
/** The role of a layer in a plan. */
|
|
461
|
-
type SampleLayerRole = 'close' | 'far' | 'tail';
|
|
462
|
-
declare const DEFAULT_SAMPLE_FALLOFF: Falloff;
|
|
463
|
-
declare const DEFAULT_CROSSOVER: SampleCrossover;
|
|
464
|
-
declare const DEFAULT_SAMPLE_PITCH = 0.04;
|
|
465
|
-
declare const DEFAULT_TAIL_GAIN = 0.6;
|
|
466
|
-
declare const DEFAULT_SAMPLE_CUTOFF_K = 0.01;
|
|
467
|
-
/** The open lowpass: at or above it the realizer leaves the filter out. */
|
|
468
|
-
declare const OPEN_CUTOFF = 20000;
|
|
469
|
-
/** A layer quieter than this is left out of the plan. */
|
|
470
|
-
declare const LAYER_FLOOR = 0.001;
|
|
471
|
-
/** One file to play: which take, at what level (already times the sound level), rate and start. */
|
|
472
|
-
type PlannedSampleLayer = {
|
|
473
|
-
readonly role: SampleLayerRole;
|
|
474
|
-
readonly url: string;
|
|
475
|
-
/** Index of the take in its list. */
|
|
476
|
-
readonly take: number;
|
|
477
|
-
readonly gain: number;
|
|
478
|
-
readonly rate: number;
|
|
479
|
-
readonly at: number;
|
|
480
|
-
};
|
|
481
|
-
type SamplePlan = {
|
|
482
|
-
readonly kind: 'sample';
|
|
483
|
-
readonly id: string;
|
|
484
|
-
readonly bus: BusId;
|
|
485
|
-
readonly level: number;
|
|
486
|
-
readonly distance: number;
|
|
487
|
-
readonly pan?: number;
|
|
488
|
-
/** Lowpass cutoff in Hz (`OPEN_CUTOFF` = no filter). */
|
|
489
|
-
readonly cutoff: number;
|
|
490
|
-
/** Playback rate of every layer (the pitch drawn for this play). */
|
|
491
|
-
readonly rate: number;
|
|
492
|
-
readonly environment: SampleEnvironment;
|
|
493
|
-
/** The tier played (`undefined` without tiers or intensity). */
|
|
494
|
-
readonly tier?: string;
|
|
495
|
-
/** 0 = all near, 1 = all far. */
|
|
496
|
-
readonly farMix: number;
|
|
497
|
-
readonly layers: readonly PlannedSampleLayer[];
|
|
498
|
-
readonly priority: number;
|
|
499
|
-
readonly group?: string;
|
|
500
|
-
};
|
|
501
|
-
/** The last take each sound layer played (`<id>/<role>` → index), so the next play never repeats it. Keep one per engine or channel. */
|
|
502
|
-
type SampleMemory = Map<string, number>;
|
|
503
|
-
type SamplePlanInput = {
|
|
504
|
-
readonly random: () => number;
|
|
505
|
-
readonly listener?: Listener;
|
|
506
|
-
readonly distanceMode?: DistanceMode;
|
|
507
|
-
readonly position?: Vec3;
|
|
508
|
-
/** Metres; overrides `position` for the distance (not for the pan). */
|
|
509
|
-
readonly distance?: number;
|
|
510
|
-
readonly volume?: number;
|
|
511
|
-
/** Default `outdoor`. */
|
|
512
|
-
readonly environment?: SampleEnvironment;
|
|
513
|
-
/** 0 (clear) to 1 (behind a wall): lowers the level and closes the lowpass. */
|
|
514
|
-
readonly occlusion?: number;
|
|
515
|
-
/** Round-robin memory; without it each plan is drawn on its own (and may repeat). */
|
|
516
|
-
readonly memory?: SampleMemory;
|
|
517
|
-
/** Limiter priority when the sound has none. */
|
|
518
|
-
readonly priority?: number;
|
|
519
|
-
/** 0 (light) to 1 (heavy): picks the tier (see `SampleTier`). */
|
|
520
|
-
readonly intensity?: number;
|
|
521
|
-
};
|
|
522
|
-
/**
|
|
523
|
-
* Round-robin without repeat: a take drawn among all but the last one played. With one take it is always 0; without `last` any take may come.
|
|
524
|
-
* One random number per call.
|
|
525
|
-
*/
|
|
526
|
-
declare function pickTake(count: number, last: number | undefined, random: () => number): number;
|
|
527
|
-
/** 0 at or below `from`, 1 at or beyond `to`, linear between. */
|
|
528
|
-
declare function farMixAt(crossover: SampleCrossover, distance: number): number;
|
|
529
|
-
/** Equal-power gains of the near and far layers for a far mix (so the crossover has no dip in loudness). */
|
|
530
|
-
declare function crossGains(farMix: number): {
|
|
531
|
-
readonly close: number;
|
|
532
|
-
readonly far: number;
|
|
533
|
-
};
|
|
534
|
-
/** The distance lowpass, closed further behind a wall (an occluded sound loses its highs first). */
|
|
535
|
-
declare function sampleCutoff(cutoffK: number, distance: number, occlusion?: number): number;
|
|
536
|
-
/** Every file a sound may play (to load before its first play). */
|
|
537
|
-
declare function sampleUrls(sound: SampleSound): string[];
|
|
538
|
-
/** The tier for an intensity: the last whose `from` is at or below it. */
|
|
539
|
-
declare function tierFor(sound: SampleSound, intensity: number | undefined): SampleTier | undefined;
|
|
540
|
-
/**
|
|
541
|
-
* The plan of one play, or `null` when the sound is too far to be heard. Random numbers, in order: the pitch, the near take, the far take, the
|
|
542
|
-
* tail take (each drawn only when that layer has more than zero takes and is heard).
|
|
543
|
-
*/
|
|
544
|
-
declare function planSample(sound: SampleSound, input: SamplePlanInput): SamplePlan | null;
|
|
545
|
-
|
|
546
230
|
/**
|
|
547
231
|
* Decoded sample buffers by url. Files load once (concurrent asks share the same promise), decode on the engine's context and stay until `clear`.
|
|
548
232
|
* The bytes come from a `SampleLoader`: `fetch` by default, or anything else (a single-file page passes the files inlined as base64).
|
|
@@ -624,29 +308,6 @@ declare function resolveMix(mix: string | MixProfile, profiles?: Readonly<Record
|
|
|
624
308
|
/** The gain a bus plays at: 0 when muted, its gain (default 1) otherwise. */
|
|
625
309
|
declare function busGain(setting: BusSetting | undefined): number;
|
|
626
310
|
|
|
627
|
-
type DeepPartial<TValue> = TValue extends readonly unknown[] ? TValue : TValue extends object ? {
|
|
628
|
-
readonly [Key in keyof TValue]?: DeepPartial<TValue[Key]>;
|
|
629
|
-
} : TValue;
|
|
630
|
-
/** Every sound and loop the engine knows, by id. Banks register in order; a later bank replaces an earlier recipe with the same id. */
|
|
631
|
-
type SoundRegistry = {
|
|
632
|
-
register(bank: SoundBank): void;
|
|
633
|
-
/** Merged into the recipe by id (objects merge, arrays such as `layers` are replaced); an unknown id is ignored. */
|
|
634
|
-
patch(id: string, patch: DeepPartial<SoundRecipe> | DeepPartial<LoopRecipe> | DeepPartial<SampleSound>): void;
|
|
635
|
-
remove(id: string): void;
|
|
636
|
-
sound(id: string): SoundRecipe | undefined;
|
|
637
|
-
loop(id: string): LoopRecipe | undefined;
|
|
638
|
-
/** The set an id names (`SoundBank.sets`), if any; a recipe with the same id wins in `play`. */
|
|
639
|
-
set(id: string): SoundSet | undefined;
|
|
640
|
-
sample(id: string): SampleSound | undefined;
|
|
641
|
-
soundIds(): string[];
|
|
642
|
-
setIds(): string[];
|
|
643
|
-
loopIds(): string[];
|
|
644
|
-
sampleIds(): string[];
|
|
645
|
-
/** Which bank each id came from. */
|
|
646
|
-
bankOf(id: string): string | undefined;
|
|
647
|
-
};
|
|
648
|
-
declare function createSoundRegistry(banks?: readonly SoundBank[]): SoundRegistry;
|
|
649
|
-
|
|
650
311
|
/**
|
|
651
312
|
* Rules for a group of voices (`undead_voice`...). A request passes when every rule passes:
|
|
652
313
|
* - `maxConcurrent`: at most this many of the group play at once (`steal` replaces the group's oldest instead of refusing);
|
|
@@ -859,7 +520,10 @@ type AudioEngine = {
|
|
|
859
520
|
plan(id: string, options?: PlayOptions): SoundPlan | null;
|
|
860
521
|
/** Pure: the plan a sample sound would play with (no round-robin memory), from `options.seed` or the engine seed. */
|
|
861
522
|
planSample(id: string, options?: PlayOptions): SamplePlan | null;
|
|
862
|
-
/**
|
|
523
|
+
/**
|
|
524
|
+
* Loads the files of these sample sounds (default all registered). Creates the context; resolves when every file is decoded or failed. An id named
|
|
525
|
+
* here that has no files yet (its manifest not registered) loads as soon as a bank that resolves it registers.
|
|
526
|
+
*/
|
|
863
527
|
loadSamples(ids?: readonly string[]): Promise<SampleLoadReport>;
|
|
864
528
|
/** `ready` when every file of the sound is decoded. */
|
|
865
529
|
sampleStatus(id: string): SampleStatus;
|
|
@@ -1124,6 +788,10 @@ type UserSoundPick = {
|
|
|
1124
788
|
/** 0–10: how well the files fit the sound (rate, clipping, band). */
|
|
1125
789
|
readonly score: number;
|
|
1126
790
|
readonly loop?: boolean;
|
|
791
|
+
/** Who made the files, when the pack is not the list's `author`. */
|
|
792
|
+
readonly author?: string;
|
|
793
|
+
/** Their licence, when not the list's `license`. */
|
|
794
|
+
readonly license?: string;
|
|
1127
795
|
};
|
|
1128
796
|
type UserSoundPicks = {
|
|
1129
797
|
readonly version: 1;
|
|
@@ -1247,4 +915,4 @@ type AudioBenchText = {
|
|
|
1247
915
|
};
|
|
1248
916
|
declare const audioBenchTextOf: (locale: string) => AudioBenchText;
|
|
1249
917
|
|
|
1250
|
-
export {
|
|
918
|
+
export { SDK_LICENSES as $, type AudioEngine as A, BENCH_BANK as B, CRITERIA as C, type DistanceMode as D, DEFAULT_TAIL_GAIN as E, LAYER_FLOOR as F, type LoadUserSamplesOptions as G, type LoopSet as H, MIX_PROFILES as I, type MeasureOptions as J, KIT_SAMPLES_BANK as K, type LoopEntry as L, type MixProfile as M, PAN_MIN_DISTANCE as N, OPEN_CUTOFF as O, PAN_LIMIT as P, type PlanInput as Q, type PlannedAutomation as R, type SampleLoader as S, type PlannedEnvelopePoint as T, type PlannedFilter as U, type PlannedLayer as V, type PlannedModulator as W, type PlannedSampleLayer as X, type PlannedSource as Y, type PlayOptions as Z, SAMPLE_ENVIRONMENTS as _, type SfxManifest as a, measureCriteria as a$, SFX_BLOWS as a0, SFX_CATALOG as a1, SFX_CATEGORIES as a2, SFX_IMPACTS as a3, SFX_LAYERS as a4, SFX_MATERIALS as a5, SFX_TIERS as a6, type SampleBankOptions as a7, type SampleLayerRole as a8, type SampleLoadReport as a9, type UserSoundPicks as aA, type UserSoundRole as aB, VOICE_GROUPS as aC, type VoiceDecision as aD, type VoiceGroup as aE, type VoiceHandle as aF, type VoiceManager as aG, type VoiceManagerOptions as aH, type VoiceRefusal as aI, type VoiceRequest as aJ, type VoiceStartEvent as aK, type VoiceStats as aL, audioBenchTextOf as aM, busGain as aN, busPriority as aO, createAudioEngine as aP, createAudioTestModule as aQ, createSampleStore as aR, createVoiceManager as aS, crossGains as aT, farMixAt as aU, fetchLoader as aV, impactSoundId as aW, inlineLoader as aX, limiterCurve as aY, listenerDistance as aZ, loadUserSamples as a_, type SampleMemory as aa, type SampleOptions as ab, type SamplePlanInput as ac, type SampleStatus as ad, type SampleStore as ae, type SdkLicense as af, type SfxBlow as ag, type SfxCategory as ah, type SfxEntry as ai, type SfxFileEntry as aj, type SfxLayer as ak, type SfxManifestLike as al, type SfxManifestSound as am, type SfxMaterial as an, type SfxPriority as ao, type SfxState as ap, type SoundSource as aq, type StartQueueOptions as ar, USER_SAMPLES_BANK as as, USER_SOUND_PREFIX as at, type UserSampleBankOptions as au, type UserSampleBankResult as av, type UserSfxFile as aw, type UserSfxManifest as ax, type UserSfxSound as ay, type UserSoundPick as az, type SampleDefaults as b, panFor as b0, parseSfxName as b1, pickTake as b2, planSample as b3, planSound as b4, recordOutput as b5, resolveMix as b6, sampleBankFromManifest as b7, sampleCutoff as b8, sampleUrls as b9, sfxState as ba, soundSourceOf as bb, splitTier as bc, tierFor as bd, userSampleBank as be, type SoundPlan as c, type SamplePlan as d, type AudioLoopHandle as e, type Listener as f, type ActionCheck as g, type AudioBenchText as h, type AudioChannel as i, type AudioEngineOptions as j, type AudioScenarioLike as k, type AudioStats as l, type AudioTestModule as m, type AudioTestModuleOptions as n, BUS_PRIORITY as o, type BusSetting as p, CRITERIA_TARGETS as q, type CriterionId as r, type CriterionResult as s, DEFAULT_CROSSOVER as t, DEFAULT_LISTENER as u, DEFAULT_MAX_VOICES as v, DEFAULT_MIX as w, DEFAULT_SAMPLE_CUTOFF_K as x, DEFAULT_SAMPLE_FALLOFF as y, DEFAULT_SAMPLE_PITCH as z };
|
package/dist/testing.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { ag as SfxBlow, an as SfxMaterial, ap as SfxState, r as CriterionId, aq as SoundSource, k as AudioScenarioLike, A as AudioEngine, s as CriterionResult, aK as VoiceStartEvent, aF as VoiceHandle, S as SampleLoader, ai as SfxEntry, g as ActionCheck } from './locale-YHyJwN2P.js';
|
|
2
|
+
export { h as AudioBenchText, m as AudioTestModule, n as AudioTestModuleOptions, B as BENCH_BANK, aM as audioBenchTextOf, aQ as createAudioTestModule } from './locale-YHyJwN2P.js';
|
|
3
3
|
import { TestableModule } from '@adatechnology/game-contracts';
|
|
4
|
+
import { q as SampleEnvironment, a as SoundBank } from './bank-Dsj1VAht.js';
|
|
4
5
|
|
|
5
6
|
type Strength = 'light' | 'medium' | 'heavy';
|
|
6
7
|
type SoundCheckText = {
|
|
@@ -15,9 +16,9 @@ type SoundCheckText = {
|
|
|
15
16
|
readonly strengths: Readonly<Record<Strength, string>>;
|
|
16
17
|
readonly states: Readonly<Record<SfxState, string>>;
|
|
17
18
|
readonly criteria: Readonly<Record<CriterionId, string>>;
|
|
18
|
-
readonly metrics: Readonly<Record<'source' | 'chosen' | 'matrix' | 'last' | 'ab' | 'blind' | 'verdicts' | 'state' | 'count', string>>;
|
|
19
|
+
readonly metrics: Readonly<Record<'source' | 'chosen' | 'matrix' | 'last' | 'ab' | 'blind' | 'verdicts' | 'state' | 'count' | 'unlicensed', string>>;
|
|
19
20
|
readonly run: Readonly<Record<'idle' | 'measuring' | 'done' | 'failed' | 'recording' | 'recorded', string>>;
|
|
20
|
-
readonly words: Readonly<Record<'none' | 'hidden' | 'prefers' | 'approved', string>>;
|
|
21
|
+
readonly words: Readonly<Record<'none' | 'hidden' | 'prefers' | 'approved' | 'local_file' | 'sdk_file' | 'synth', string>>;
|
|
21
22
|
/** Where the voice came from: the kit's file, the owner's file, the synthesized recipe. */
|
|
22
23
|
readonly sources: Readonly<Record<SoundSource, string>>;
|
|
23
24
|
readonly probe: string;
|