@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,3 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SDK_LICENSES,
|
|
3
|
+
__publicField,
|
|
4
|
+
kitSampleDefaults,
|
|
5
|
+
sampleBankFromManifest,
|
|
6
|
+
splitTier
|
|
7
|
+
} from "./chunk-JV5XXCQE.js";
|
|
8
|
+
|
|
1
9
|
// src/falloff.ts
|
|
2
10
|
var DISTANCE_CURVES = {
|
|
3
11
|
/** The game's `sfx`: `vol / (1 + d² × 0.004)`, cutoff `/ (1 + d × 0.01)`, silent below 0.01 (jogo L62091–62092, L62101). */
|
|
@@ -289,6 +297,20 @@ var voice_groups_default = {
|
|
|
289
297
|
sources: [
|
|
290
298
|
"sdk: the crackles of every fire share four voices"
|
|
291
299
|
]
|
|
300
|
+
},
|
|
301
|
+
debris_knock: {
|
|
302
|
+
maxConcurrent: 3,
|
|
303
|
+
cooldown: 0.04,
|
|
304
|
+
sources: [
|
|
305
|
+
"sdk: forty parts coming loose in one blast are a few knocks, not forty (room log: thunk x34 in under a second when a molotov broke)"
|
|
306
|
+
]
|
|
307
|
+
},
|
|
308
|
+
sizzle: {
|
|
309
|
+
maxConcurrent: 1,
|
|
310
|
+
cooldown: 0.5,
|
|
311
|
+
sources: [
|
|
312
|
+
"sdk: every melting part of a burning bin is one sizzle at a time (room log: hiss x34 in 1.6 s on a plastic bin)"
|
|
313
|
+
]
|
|
292
314
|
}
|
|
293
315
|
};
|
|
294
316
|
|
|
@@ -380,12 +402,48 @@ function mergeRecords(base, patch) {
|
|
|
380
402
|
}
|
|
381
403
|
return merged;
|
|
382
404
|
}
|
|
405
|
+
var trimmed = (refs, alias) => refs.filter((ref) => alias.only === void 0 || ref.url.includes(alias.only)).map((ref) => ({
|
|
406
|
+
...ref,
|
|
407
|
+
...alias.offset === void 0 ? {} : { offset: alias.offset },
|
|
408
|
+
...alias.duration === void 0 ? {} : { duration: alias.duration }
|
|
409
|
+
}));
|
|
410
|
+
function aliasSample(alias, file) {
|
|
411
|
+
const close = trimmed(file.close, alias);
|
|
412
|
+
if (close.length === 0) return void 0;
|
|
413
|
+
const { tiers: _tiers, fallback: _fallback, choke: _choke, ...rest } = file;
|
|
414
|
+
return {
|
|
415
|
+
...rest,
|
|
416
|
+
id: alias.id,
|
|
417
|
+
close,
|
|
418
|
+
...file.far ? { far: trimmed(file.far, alias) } : {},
|
|
419
|
+
...alias.loop === void 0 ? {} : { loop: alias.loop },
|
|
420
|
+
...alias.baseFrequency === void 0 ? {} : { baseFrequency: alias.baseFrequency },
|
|
421
|
+
...alias.gain === void 0 ? {} : { gain: alias.gain },
|
|
422
|
+
...alias.pitch === void 0 ? {} : { pitch: alias.pitch },
|
|
423
|
+
...alias.falloff ? { falloff: alias.falloff } : {},
|
|
424
|
+
fallback: alias.id,
|
|
425
|
+
sources: [...file.sources, `alias: ${alias.id} \u2192 ${alias.file}`]
|
|
426
|
+
};
|
|
427
|
+
}
|
|
383
428
|
function createSoundRegistry(banks = []) {
|
|
384
429
|
const sounds = /* @__PURE__ */ new Map();
|
|
385
430
|
const loops = /* @__PURE__ */ new Map();
|
|
386
431
|
const sets = /* @__PURE__ */ new Map();
|
|
387
432
|
const samples = /* @__PURE__ */ new Map();
|
|
388
433
|
const owners = /* @__PURE__ */ new Map();
|
|
434
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
435
|
+
const derived = /* @__PURE__ */ new Map();
|
|
436
|
+
const resolveAlias = (id) => {
|
|
437
|
+
const alias = aliases.get(id);
|
|
438
|
+
if (!alias) return void 0;
|
|
439
|
+
const cached = derived.get(id);
|
|
440
|
+
if (cached) return cached;
|
|
441
|
+
const file = samples.get(alias.file);
|
|
442
|
+
if (!file) return void 0;
|
|
443
|
+
const sample = aliasSample(alias, file);
|
|
444
|
+
if (sample) derived.set(id, sample);
|
|
445
|
+
return sample;
|
|
446
|
+
};
|
|
389
447
|
const registry = {
|
|
390
448
|
register(bank) {
|
|
391
449
|
for (const sound of bank.sounds ?? []) {
|
|
@@ -405,6 +463,11 @@ function createSoundRegistry(banks = []) {
|
|
|
405
463
|
samples.set(sample.id, sample);
|
|
406
464
|
owners.set(sample.id, bank.id);
|
|
407
465
|
}
|
|
466
|
+
for (const alias of bank.sampleAliases ?? []) {
|
|
467
|
+
aliases.set(alias.id, alias);
|
|
468
|
+
if (!owners.has(alias.id)) owners.set(alias.id, bank.id);
|
|
469
|
+
}
|
|
470
|
+
derived.clear();
|
|
408
471
|
},
|
|
409
472
|
patch(id, patch) {
|
|
410
473
|
const sound = sounds.get(id);
|
|
@@ -413,22 +476,31 @@ function createSoundRegistry(banks = []) {
|
|
|
413
476
|
if (loop) loops.set(id, mergeRecords(loop, patch));
|
|
414
477
|
const sample = samples.get(id);
|
|
415
478
|
if (sample) samples.set(id, mergeRecords(sample, patch));
|
|
479
|
+
derived.clear();
|
|
416
480
|
},
|
|
417
481
|
remove(id) {
|
|
418
482
|
sounds.delete(id);
|
|
419
483
|
loops.delete(id);
|
|
420
484
|
sets.delete(id);
|
|
421
485
|
samples.delete(id);
|
|
486
|
+
aliases.delete(id);
|
|
422
487
|
owners.delete(id);
|
|
488
|
+
derived.clear();
|
|
489
|
+
},
|
|
490
|
+
removeSample(id) {
|
|
491
|
+
samples.delete(id);
|
|
492
|
+
aliases.delete(id);
|
|
493
|
+
if (!sounds.has(id) && !loops.has(id) && !sets.has(id)) owners.delete(id);
|
|
494
|
+
derived.clear();
|
|
423
495
|
},
|
|
424
496
|
sound: (id) => sounds.get(id),
|
|
425
497
|
loop: (id) => loops.get(id),
|
|
426
498
|
set: (id) => sets.get(id),
|
|
427
|
-
sample: (id) => samples.get(id),
|
|
499
|
+
sample: (id) => samples.get(id) ?? resolveAlias(id),
|
|
428
500
|
soundIds: () => [...sounds.keys()],
|
|
429
501
|
setIds: () => [...sets.keys()],
|
|
430
502
|
loopIds: () => [...loops.keys()],
|
|
431
|
-
sampleIds: () => [...samples.keys()],
|
|
503
|
+
sampleIds: () => [...samples.keys(), ...[...aliases.keys()].filter((id) => !samples.has(id) && resolveAlias(id) !== void 0)],
|
|
432
504
|
bankOf: (id) => owners.get(id)
|
|
433
505
|
};
|
|
434
506
|
for (const bank of banks) registry.register(bank);
|
|
@@ -1071,7 +1143,16 @@ function planSample(sound, input) {
|
|
|
1071
1143
|
const index = pickTake(refs.length, input.memory?.get(key), input.random);
|
|
1072
1144
|
input.memory?.set(key, index);
|
|
1073
1145
|
const ref = refs[index];
|
|
1074
|
-
layers.push({
|
|
1146
|
+
layers.push({
|
|
1147
|
+
role,
|
|
1148
|
+
url: ref.url,
|
|
1149
|
+
take: index,
|
|
1150
|
+
gain: gain * (ref.gain ?? 1) * level,
|
|
1151
|
+
rate,
|
|
1152
|
+
at,
|
|
1153
|
+
...ref.offset === void 0 ? {} : { offset: ref.offset },
|
|
1154
|
+
...ref.duration === void 0 ? {} : { duration: ref.duration }
|
|
1155
|
+
});
|
|
1075
1156
|
};
|
|
1076
1157
|
take("close", close, gains.close, 0);
|
|
1077
1158
|
take("far", far, gains.far, 0);
|
|
@@ -1100,6 +1181,8 @@ function planSample(sound, input) {
|
|
|
1100
1181
|
var DEFAULT_LOOP_CROSSFADE = 0.25;
|
|
1101
1182
|
var LOOKAHEAD = 1.5;
|
|
1102
1183
|
var VOLUME_SMOOTHING = 0.05;
|
|
1184
|
+
var RATE_SMOOTHING = 0.04;
|
|
1185
|
+
var RATE_RANGE = [0.25, 4];
|
|
1103
1186
|
function loopCrossfade(sound) {
|
|
1104
1187
|
if (!sound.loop) return void 0;
|
|
1105
1188
|
return sound.loop === true ? DEFAULT_LOOP_CROSSFADE : Math.max(0, sound.loop.crossfade ?? DEFAULT_LOOP_CROSSFADE);
|
|
@@ -1111,6 +1194,7 @@ var ramp2 = (param, direction, at, seconds) => {
|
|
|
1111
1194
|
param.setValueAtTime(value(0), at);
|
|
1112
1195
|
for (let step = 1; step <= CROSSFADE_STEPS; step++) param.linearRampToValueAtTime(value(step / CROSSFADE_STEPS), at + seconds * step / CROSSFADE_STEPS);
|
|
1113
1196
|
};
|
|
1197
|
+
var loopRate = (sound, frequency) => sound.baseFrequency && sound.baseFrequency > 0 && frequency > 0 ? Math.max(RATE_RANGE[0], Math.min(RATE_RANGE[1], frequency / sound.baseFrequency)) : 1;
|
|
1114
1198
|
function createSampleLoopHandle(sound, host, volume = 0) {
|
|
1115
1199
|
const crossfade = loopCrossfade(sound) ?? DEFAULT_LOOP_CROSSFADE;
|
|
1116
1200
|
let level = volume;
|
|
@@ -1120,13 +1204,17 @@ function createSampleLoopHandle(sound, host, volume = 0) {
|
|
|
1120
1204
|
let segments = [];
|
|
1121
1205
|
let last;
|
|
1122
1206
|
let timer;
|
|
1207
|
+
let panner;
|
|
1208
|
+
let rate = 1;
|
|
1209
|
+
let position;
|
|
1123
1210
|
const entry = {
|
|
1124
1211
|
get created() {
|
|
1125
1212
|
return master !== void 0;
|
|
1126
1213
|
},
|
|
1127
1214
|
rewire() {
|
|
1128
|
-
master
|
|
1129
|
-
|
|
1215
|
+
const out = panner ?? master;
|
|
1216
|
+
out?.disconnect();
|
|
1217
|
+
out?.connect(host.output(sound.bus));
|
|
1130
1218
|
},
|
|
1131
1219
|
stop() {
|
|
1132
1220
|
stopped = true;
|
|
@@ -1143,23 +1231,29 @@ function createSampleLoopHandle(sound, host, volume = 0) {
|
|
|
1143
1231
|
segments = [];
|
|
1144
1232
|
master?.disconnect();
|
|
1145
1233
|
master = void 0;
|
|
1234
|
+
panner?.disconnect();
|
|
1235
|
+
panner = void 0;
|
|
1146
1236
|
fallback?.stop();
|
|
1147
1237
|
fallback = void 0;
|
|
1148
1238
|
host.unregister(entry);
|
|
1149
1239
|
}
|
|
1150
1240
|
};
|
|
1151
|
-
const
|
|
1241
|
+
const nextTake = () => {
|
|
1152
1242
|
const takes = sound.close;
|
|
1153
1243
|
const take = pickTake(takes.length, last, host.random);
|
|
1154
1244
|
last = take;
|
|
1155
1245
|
const ref = takes[take];
|
|
1156
|
-
|
|
1246
|
+
const buffer = ref ? host.buffer(ref.url) : void 0;
|
|
1247
|
+
return ref && buffer ? { buffer, ref } : void 0;
|
|
1157
1248
|
};
|
|
1158
1249
|
const schedule = (context, output, at, first) => {
|
|
1159
|
-
const
|
|
1160
|
-
if (!
|
|
1250
|
+
const next = nextTake();
|
|
1251
|
+
if (!next) return void 0;
|
|
1252
|
+
const { buffer, ref } = next;
|
|
1253
|
+
const offset = Math.max(0, Math.min(ref.offset ?? 0, buffer.duration));
|
|
1161
1254
|
const source = context.createBufferSource();
|
|
1162
1255
|
source.buffer = buffer;
|
|
1256
|
+
source.playbackRate.value = rate;
|
|
1163
1257
|
const gain = context.createGain();
|
|
1164
1258
|
source.connect(gain);
|
|
1165
1259
|
gain.connect(output);
|
|
@@ -1167,15 +1261,15 @@ function createSampleLoopHandle(sound, host, volume = 0) {
|
|
|
1167
1261
|
if (buffer.duration < 2 * crossfade || sound.close.length === 1) {
|
|
1168
1262
|
source.loop = true;
|
|
1169
1263
|
if (!first) ramp2(gain.gain, "in", at, Math.max(1e-3, fade));
|
|
1170
|
-
source.start(at);
|
|
1264
|
+
source.start(at, offset);
|
|
1171
1265
|
segments.push({ source, gain, end: Number.POSITIVE_INFINITY });
|
|
1172
1266
|
return void 0;
|
|
1173
1267
|
}
|
|
1174
1268
|
if (first) gain.gain.setValueAtTime(1, at);
|
|
1175
1269
|
else ramp2(gain.gain, "in", at, fade);
|
|
1176
|
-
const end3 = at + buffer.duration;
|
|
1270
|
+
const end3 = at + (buffer.duration - offset) / rate;
|
|
1177
1271
|
ramp2(gain.gain, "out", end3 - fade, fade);
|
|
1178
|
-
source.start(at);
|
|
1272
|
+
source.start(at, offset);
|
|
1179
1273
|
source.stop(end3);
|
|
1180
1274
|
segments.push({ source, gain, end: end3 });
|
|
1181
1275
|
source.onended = () => {
|
|
@@ -1196,14 +1290,26 @@ function createSampleLoopHandle(sound, host, volume = 0) {
|
|
|
1196
1290
|
pump(context, output, next, false);
|
|
1197
1291
|
}, wait);
|
|
1198
1292
|
};
|
|
1199
|
-
const
|
|
1293
|
+
const spatial = () => {
|
|
1294
|
+
if (!position || !host.listener) return 1;
|
|
1295
|
+
return falloffGain(sound.falloff ?? DEFAULT_SAMPLE_FALLOFF, 1, listenerDistance(host.listener(), position, host.distance));
|
|
1296
|
+
};
|
|
1297
|
+
const fileLevel = () => level * (sound.gain ?? 1) * spatial();
|
|
1298
|
+
const place = (context) => {
|
|
1299
|
+
if (panner && position && host.listener) panner.pan.setTargetAtTime(panFor(host.listener(), position), context.currentTime, VOLUME_SMOOTHING);
|
|
1300
|
+
};
|
|
1200
1301
|
const startFiles = () => {
|
|
1201
1302
|
if (stopped || master || !host.isReady(sound)) return master !== void 0;
|
|
1202
1303
|
const context = host.ready();
|
|
1203
1304
|
if (!context) return false;
|
|
1204
1305
|
master = context.createGain();
|
|
1205
1306
|
master.gain.setValueAtTime(fileLevel(), context.currentTime);
|
|
1206
|
-
|
|
1307
|
+
if (sound.pan !== false && position && typeof context.createStereoPanner === "function") {
|
|
1308
|
+
panner = context.createStereoPanner();
|
|
1309
|
+
if (host.listener) panner.pan.value = panFor(host.listener(), position);
|
|
1310
|
+
master.connect(panner);
|
|
1311
|
+
panner.connect(host.output(sound.bus));
|
|
1312
|
+
} else master.connect(host.output(sound.bus));
|
|
1207
1313
|
host.register(entry);
|
|
1208
1314
|
pump(context, master, context.currentTime, true);
|
|
1209
1315
|
if (fallback) {
|
|
@@ -1229,9 +1335,15 @@ function createSampleLoopHandle(sound, host, volume = 0) {
|
|
|
1229
1335
|
set(next) {
|
|
1230
1336
|
if (stopped) return;
|
|
1231
1337
|
if (next.volume !== void 0) level = host.muted(sound.bus) ? 0 : Math.max(0, next.volume);
|
|
1338
|
+
if (next.position) position = next.position;
|
|
1339
|
+
if (next.frequency !== void 0 && sound.baseFrequency) rate = loopRate(sound, next.frequency);
|
|
1232
1340
|
if (level > 0) ensure();
|
|
1233
1341
|
const context = host.ready();
|
|
1234
|
-
if (master && context)
|
|
1342
|
+
if (master && context) {
|
|
1343
|
+
master.gain.setTargetAtTime(fileLevel(), context.currentTime, VOLUME_SMOOTHING);
|
|
1344
|
+
place(context);
|
|
1345
|
+
if (next.frequency !== void 0 && sound.baseFrequency) for (const segment of segments) segment.source.playbackRate.setTargetAtTime(rate, context.currentTime, RATE_SMOOTHING);
|
|
1346
|
+
}
|
|
1235
1347
|
fallback?.set(next.volume === void 0 ? next : { ...next, volume: level });
|
|
1236
1348
|
},
|
|
1237
1349
|
stop: entry.stop
|
|
@@ -1859,6 +1971,7 @@ function createSampleStore(loader = fetchLoader()) {
|
|
|
1859
1971
|
}
|
|
1860
1972
|
|
|
1861
1973
|
// src/webaudio/realize-sample.ts
|
|
1974
|
+
var TRIM_FADE = 0.04;
|
|
1862
1975
|
function realizeSample(plan, target) {
|
|
1863
1976
|
const context = target.context;
|
|
1864
1977
|
let head = target.output;
|
|
@@ -1889,7 +2002,17 @@ function realizeSample(plan, target) {
|
|
|
1889
2002
|
const gain = gainNode(context, layer.gain);
|
|
1890
2003
|
source.connect(gain);
|
|
1891
2004
|
gain.connect(head);
|
|
1892
|
-
|
|
2005
|
+
const at = target.time + layer.at;
|
|
2006
|
+
const offset = Math.max(0, Math.min(layer.offset ?? 0, buffer.duration));
|
|
2007
|
+
if (layer.duration === void 0) source.start(at, offset);
|
|
2008
|
+
else {
|
|
2009
|
+
const duration = Math.max(0, Math.min(layer.duration, buffer.duration - offset));
|
|
2010
|
+
const end3 = at + duration / layer.rate;
|
|
2011
|
+
const fade = Math.min(TRIM_FADE, (end3 - at) / 4);
|
|
2012
|
+
gain.gain.setValueAtTime(layer.gain, end3 - fade);
|
|
2013
|
+
gain.gain.linearRampToValueAtTime(0, end3);
|
|
2014
|
+
source.start(at, offset, duration);
|
|
2015
|
+
}
|
|
1893
2016
|
sources.push(source);
|
|
1894
2017
|
}
|
|
1895
2018
|
const realized = voiceOf(sources);
|
|
@@ -1909,7 +2032,11 @@ function realizeSample(plan, target) {
|
|
|
1909
2032
|
}
|
|
1910
2033
|
function sampleLength(plan, seconds) {
|
|
1911
2034
|
let length = 0;
|
|
1912
|
-
for (const layer of plan.layers)
|
|
2035
|
+
for (const layer of plan.layers) {
|
|
2036
|
+
const file = seconds(layer.url) ?? 0;
|
|
2037
|
+
const played = layer.duration === void 0 ? file - (layer.offset ?? 0) : Math.min(layer.duration, file - (layer.offset ?? 0));
|
|
2038
|
+
length = Math.max(length, layer.at + Math.max(0, played) / layer.rate);
|
|
2039
|
+
}
|
|
1913
2040
|
return length;
|
|
1914
2041
|
}
|
|
1915
2042
|
|
|
@@ -2118,6 +2245,7 @@ function createAudioEngine(options = {}) {
|
|
|
2118
2245
|
const set = registry.set(id);
|
|
2119
2246
|
return set ? chooser.pick(set, random) : { id, rate: 1 };
|
|
2120
2247
|
};
|
|
2248
|
+
const wanted = /* @__PURE__ */ new Set();
|
|
2121
2249
|
const loadSounds = (sounds) => {
|
|
2122
2250
|
const audio = ready();
|
|
2123
2251
|
if (!audio) return Promise.resolve({ loaded: [], failed: sounds.flatMap(sampleUrls).map((url2) => ({ url: url2, error: "no audio context" })) });
|
|
@@ -2242,13 +2370,20 @@ function createAudioEngine(options = {}) {
|
|
|
2242
2370
|
};
|
|
2243
2371
|
return {
|
|
2244
2372
|
registry,
|
|
2245
|
-
register: (bank) =>
|
|
2373
|
+
register: (bank) => {
|
|
2374
|
+
registry.register(bank);
|
|
2375
|
+
if (wanted.size === 0) return;
|
|
2376
|
+
const now = [...wanted].map((id) => registry.sample(id)).filter((sample) => sample !== void 0);
|
|
2377
|
+
for (const sample of now) wanted.delete(sample.id);
|
|
2378
|
+
if (now.length > 0) void loadSounds(now).catch(() => void 0);
|
|
2379
|
+
},
|
|
2246
2380
|
plan: (id, playOptions = {}) => planWith(id, playOptions, createRng(playOptions.seed ?? seed)),
|
|
2247
2381
|
planSample(id, playOptions = {}) {
|
|
2248
2382
|
const sample = registry.sample(id);
|
|
2249
2383
|
return sample ? planSample(sample, sampleInput(playOptions, createRng(playOptions.seed ?? seed), false)) : null;
|
|
2250
2384
|
},
|
|
2251
2385
|
loadSamples(ids) {
|
|
2386
|
+
for (const id of ids ?? []) if (!registry.sample(id)) wanted.add(id);
|
|
2252
2387
|
const chosen = (ids ?? registry.sampleIds()).map((id) => registry.sample(id)).filter((sample) => sample !== void 0);
|
|
2253
2388
|
return loadSounds(chosen);
|
|
2254
2389
|
},
|
|
@@ -2298,7 +2433,9 @@ function createAudioEngine(options = {}) {
|
|
|
2298
2433
|
random: engineRandom,
|
|
2299
2434
|
register: loopHost.register,
|
|
2300
2435
|
unregister: loopHost.unregister,
|
|
2301
|
-
muted: (bus) => busSettings.get(bus)?.muted === true
|
|
2436
|
+
muted: (bus) => busSettings.get(bus)?.muted === true,
|
|
2437
|
+
listener: () => listener,
|
|
2438
|
+
...options.distance ? { distance: options.distance } : {}
|
|
2302
2439
|
},
|
|
2303
2440
|
loopOptions.volume
|
|
2304
2441
|
);
|
|
@@ -3599,141 +3736,67 @@ async function recordOutput(engine, seconds, act) {
|
|
|
3599
3736
|
return new Blob(chunks, { type: recorder.mimeType || "audio/webm" });
|
|
3600
3737
|
}
|
|
3601
3738
|
|
|
3602
|
-
// src/
|
|
3603
|
-
var
|
|
3604
|
-
var
|
|
3605
|
-
var
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
return { id, layer, take };
|
|
3612
|
-
}
|
|
3613
|
-
function splitTier(id) {
|
|
3614
|
-
const match = /^(.*)_(light|medium|heavy)$/.exec(id);
|
|
3615
|
-
return match ? { base: match[1], tier: match[2] } : { base: id };
|
|
3616
|
-
}
|
|
3617
|
-
var refsOf = (entries2, baseUrl) => (entries2 ?? []).map((entry) => ({ url: `${baseUrl}${entry.file}` }));
|
|
3618
|
-
function sampleBankFromManifest(manifest, options) {
|
|
3619
|
-
const baseUrl = options.baseUrl ?? "";
|
|
3620
|
-
const samples = [];
|
|
3621
|
-
const tiersOf = /* @__PURE__ */ new Map();
|
|
3622
|
-
for (const sound of manifest.sounds) {
|
|
3623
|
-
const { base, tier } = splitTier(sound.id);
|
|
3624
|
-
if (tier) tiersOf.set(base, [...tiersOf.get(base) ?? [], sound]);
|
|
3625
|
-
}
|
|
3626
|
-
const bases = /* @__PURE__ */ new Map();
|
|
3627
|
-
for (const sound of manifest.sounds) {
|
|
3628
|
-
if (!splitTier(sound.id).tier) bases.set(sound.id, sound);
|
|
3629
|
-
}
|
|
3630
|
-
for (const [base, tiers] of tiersOf) {
|
|
3631
|
-
if (!bases.has(base)) bases.set(base, { id: base, category: tiers[0]?.category ?? "", layers: { close: tiers[0]?.layers.close ?? [] } });
|
|
3632
|
-
}
|
|
3633
|
-
for (const sound of bases.values()) {
|
|
3634
|
-
const numbers = options.sounds?.[sound.id] ?? options.defaults?.(sound);
|
|
3635
|
-
const close = refsOf(sound.layers.close, baseUrl);
|
|
3636
|
-
if (!numbers || close.length === 0) continue;
|
|
3637
|
-
const tiers = (tiersOf.get(sound.id) ?? []).map((tier) => {
|
|
3638
|
-
const name = splitTier(tier.id).tier;
|
|
3639
|
-
const tierFar = refsOf(tier.layers.far, baseUrl);
|
|
3640
|
-
return { name, from: SFX_TIERS[name] ?? 0, close: refsOf(tier.layers.close, baseUrl), ...tierFar.length > 0 ? { far: tierFar } : {} };
|
|
3641
|
-
}).sort((a, b) => a.from - b.from);
|
|
3642
|
-
const far = refsOf(sound.layers.far, baseUrl);
|
|
3643
|
-
const indoor = refsOf(sound.layers.tail_in, baseUrl);
|
|
3644
|
-
const outdoor = refsOf(sound.layers.tail_out, baseUrl);
|
|
3645
|
-
const files = [sound, ...tiersOf.get(sound.id) ?? []].flatMap((entry) => Object.values(entry.layers).flatMap((entries2) => entries2 ?? []));
|
|
3646
|
-
samples.push({
|
|
3647
|
-
id: sound.id,
|
|
3648
|
-
bus: numbers.bus,
|
|
3649
|
-
close,
|
|
3650
|
-
...far.length > 0 ? { far } : {},
|
|
3651
|
-
...tiers.length > 0 ? { tiers } : {},
|
|
3652
|
-
...numbers.crossover ? { crossover: numbers.crossover } : {},
|
|
3653
|
-
...indoor.length > 0 || outdoor.length > 0 ? { tail: { ...indoor.length > 0 ? { indoor } : {}, ...outdoor.length > 0 ? { outdoor } : {}, ...numbers.tailGain === void 0 ? {} : { gain: numbers.tailGain } } } : {},
|
|
3654
|
-
...numbers.pitch === void 0 ? {} : { pitch: numbers.pitch },
|
|
3655
|
-
...numbers.gain === void 0 ? {} : { gain: numbers.gain },
|
|
3656
|
-
...numbers.falloff ? { falloff: numbers.falloff } : {},
|
|
3657
|
-
...numbers.cutoffK === void 0 ? {} : { cutoffK: numbers.cutoffK },
|
|
3658
|
-
...numbers.group ? { group: numbers.group } : {},
|
|
3659
|
-
...numbers.priority === void 0 ? {} : { priority: numbers.priority },
|
|
3660
|
-
...numbers.fallback ? { fallback: numbers.fallback } : {},
|
|
3661
|
-
sources: files.map((file) => `${file.file}: ${file.source} ${file.author} ${file.license}`)
|
|
3662
|
-
});
|
|
3739
|
+
// src/local-pack.ts
|
|
3740
|
+
var LOCAL_PACK_LICENSES = ["CC0", "CC-BY", "unknown", "proprietary"];
|
|
3741
|
+
var LOCAL_PACK_PREFERENCES = ["pack", "sdk"];
|
|
3742
|
+
var LocalSoundPackError = class extends Error {
|
|
3743
|
+
constructor(problems) {
|
|
3744
|
+
super(`invalid local sound pack: ${problems.join("; ")}`);
|
|
3745
|
+
__publicField(this, "problems");
|
|
3746
|
+
this.name = "LocalSoundPackError";
|
|
3747
|
+
this.problems = problems;
|
|
3663
3748
|
}
|
|
3664
|
-
return { id: options.id, samples };
|
|
3665
|
-
}
|
|
3666
|
-
|
|
3667
|
-
// src/kit-samples.ts
|
|
3668
|
-
var KIT_CATEGORY_BUS = {
|
|
3669
|
-
armas: "weapons",
|
|
3670
|
-
impactos: "world",
|
|
3671
|
-
"explosoes-fogo": "world",
|
|
3672
|
-
personagem: "world",
|
|
3673
|
-
veiculos: "world",
|
|
3674
|
-
"itens-portas": "world",
|
|
3675
|
-
ambiente: "ambience"
|
|
3676
3749
|
};
|
|
3677
|
-
var
|
|
3678
|
-
var
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3750
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3751
|
+
var isLicense = (value) => LOCAL_PACK_LICENSES.includes(value);
|
|
3752
|
+
var isBus = (value) => BUS_IDS.includes(value);
|
|
3753
|
+
function entryProblems(id, entry) {
|
|
3754
|
+
if (!isRecord(entry)) return [`${id}: not an object`];
|
|
3755
|
+
const problems = [];
|
|
3756
|
+
const files = entry.files;
|
|
3757
|
+
if (!Array.isArray(files) || files.length === 0 || !files.every((file) => typeof file === "string" && file.length > 0)) problems.push(`${id}: files must be a non-empty list of paths`);
|
|
3758
|
+
if (!isLicense(entry.license)) problems.push(`${id}: license must be one of ${LOCAL_PACK_LICENSES.join(", ")}`);
|
|
3759
|
+
if (entry.prefer !== void 0 && !LOCAL_PACK_PREFERENCES.includes(entry.prefer)) problems.push(`${id}: prefer must be pack or sdk`);
|
|
3760
|
+
if (entry.bus !== void 0 && !isBus(entry.bus)) problems.push(`${id}: unknown bus ${String(entry.bus)}`);
|
|
3761
|
+
if (entry.gain !== void 0 && (typeof entry.gain !== "number" || entry.gain < 0)) problems.push(`${id}: gain must be a number \u2265 0`);
|
|
3762
|
+
if (entry.score !== void 0 && (typeof entry.score !== "number" || entry.score < 0 || entry.score > 10)) problems.push(`${id}: score must be 0\u201310`);
|
|
3763
|
+
return problems;
|
|
3764
|
+
}
|
|
3765
|
+
function parseLocalSoundPack(value) {
|
|
3766
|
+
if (!isRecord(value)) throw new LocalSoundPackError(["the pack is not an object"]);
|
|
3767
|
+
const problems = [];
|
|
3768
|
+
if (value.version !== 1) problems.push("version must be 1");
|
|
3769
|
+
if (value.baseUrl !== void 0 && typeof value.baseUrl !== "string") problems.push("baseUrl must be a string");
|
|
3770
|
+
if (!isRecord(value.sounds)) problems.push("sounds must be an object of id \u2192 entry");
|
|
3771
|
+
else for (const [id, entry] of Object.entries(value.sounds)) problems.push(...entryProblems(id, entry));
|
|
3772
|
+
if (problems.length > 0) throw new LocalSoundPackError(problems);
|
|
3773
|
+
return value;
|
|
3774
|
+
}
|
|
3775
|
+
var isShippableLicense = (license) => SDK_LICENSES.includes(license);
|
|
3776
|
+
var CATALOG = new Map([...SFX_CATALOG, ...SFX_IMPACTS].map((entry) => [entry.id, entry]));
|
|
3777
|
+
var busOf = (id, entry) => {
|
|
3778
|
+
if (entry.bus) return entry.bus;
|
|
3779
|
+
const category = CATALOG.get(id)?.category ?? "";
|
|
3780
|
+
return kitSampleDefaults({ id, category })?.bus ?? "world";
|
|
3688
3781
|
};
|
|
3689
|
-
function
|
|
3690
|
-
const
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
id: options.id ?? "kit_samples",
|
|
3706
|
-
baseUrl: options.baseUrl ?? "",
|
|
3707
|
-
defaults: kitSampleDefaults
|
|
3782
|
+
function localPackSamples(pack, options = {}) {
|
|
3783
|
+
const baseUrl = options.baseUrl ?? pack.baseUrl ?? "";
|
|
3784
|
+
return Object.entries(pack.sounds).map(([id, entry]) => {
|
|
3785
|
+
const current = CATALOG.get(id)?.current;
|
|
3786
|
+
const isLoop = /_loop(_|$)/.test(id);
|
|
3787
|
+
return {
|
|
3788
|
+
id,
|
|
3789
|
+
bus: busOf(id, entry),
|
|
3790
|
+
close: entry.files.map((file) => ({ url: `${baseUrl}${file}` })),
|
|
3791
|
+
pitch: isLoop ? 0 : 0.04,
|
|
3792
|
+
...isLoop ? { loop: true } : {},
|
|
3793
|
+
...entry.gain === void 0 ? {} : { gain: entry.gain },
|
|
3794
|
+
...current ? { fallback: current } : {},
|
|
3795
|
+
license: entry.license,
|
|
3796
|
+
sources: entry.files.map((file) => `local: ${file} ${entry.license}`)
|
|
3797
|
+
};
|
|
3708
3798
|
});
|
|
3709
3799
|
}
|
|
3710
|
-
var isFileUrl = (url2) => {
|
|
3711
|
-
const page = globalThis.location?.href;
|
|
3712
|
-
try {
|
|
3713
|
-
return new URL(url2, page).protocol === "file:";
|
|
3714
|
-
} catch {
|
|
3715
|
-
return false;
|
|
3716
|
-
}
|
|
3717
|
-
};
|
|
3718
|
-
var fetchJson = async (url2) => {
|
|
3719
|
-
if (isFileUrl(url2)) throw new Error(`${url2}: file:// is not fetched`);
|
|
3720
|
-
const response = await fetch(url2);
|
|
3721
|
-
if (!response.ok) throw new Error(`${url2}: ${response.status}`);
|
|
3722
|
-
return await response.json();
|
|
3723
|
-
};
|
|
3724
|
-
async function loadKitSamples(engine, options = {}) {
|
|
3725
|
-
const baseUrl = options.baseUrl ?? "";
|
|
3726
|
-
let manifest;
|
|
3727
|
-
try {
|
|
3728
|
-
manifest = await (options.fetchManifest ?? fetchJson)(`${baseUrl}manifest.json`);
|
|
3729
|
-
} catch {
|
|
3730
|
-
return null;
|
|
3731
|
-
}
|
|
3732
|
-
const bank = kitSampleBank(manifest, options);
|
|
3733
|
-
engine.register(bank);
|
|
3734
|
-
if (options.preload && engine.loadSamples) void engine.loadSamples(options.preload).catch(() => void 0);
|
|
3735
|
-
return bank;
|
|
3736
|
-
}
|
|
3737
3800
|
|
|
3738
3801
|
// src/user-samples.ts
|
|
3739
3802
|
var USER_SAMPLES_BANK = "user_samples";
|
|
@@ -3863,9 +3926,9 @@ var PT = {
|
|
|
3863
3926
|
strengths: { light: "leve", medium: "m\xE9dio", heavy: "forte" },
|
|
3864
3927
|
states: { file: "A", synth: "S", missing: "F" },
|
|
3865
3928
|
criteria: { C1: "C1 Sincronia", C2: "C2 Certo p/ a\xE7\xE3o", C3: "C3 Dist\xE2ncia", C4: "C4 Posi\xE7\xE3o", C5: "C5 Varia\xE7\xE3o", C6: "C6 Volume", C7: "C7 Intensidade", C8: "C8 Cauda", C9: "C9 Rajada", C10: "C10 Escuta" },
|
|
3866
|
-
metrics: { source: "1 \xB7 Fonte do que tocou", chosen: "1 \xB7 Escolhido", matrix: "2 \xB7 Matriz", last: "\xDAltimo tocado", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Prefer\xEAncias", state: "5 \xB7 Medi\xE7\xE3o", count: "1 \xB7 Cat\xE1logo" },
|
|
3929
|
+
metrics: { source: "1 \xB7 Fonte do que tocou", chosen: "1 \xB7 Escolhido", matrix: "2 \xB7 Matriz", last: "\xDAltimo tocado", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Prefer\xEAncias", state: "5 \xB7 Medi\xE7\xE3o", count: "1 \xB7 Cat\xE1logo", unlicensed: "1 \xB7 Arquivo sem licen\xE7a" },
|
|
3867
3930
|
run: { idle: "parada", measuring: "medindo\u2026", done: "pronta", failed: "falhou", recording: "gravando\u2026", recorded: "grava\xE7\xE3o baixada" },
|
|
3868
|
-
words: { none: "\u2014", hidden: "? (revele)", prefers: "prefere", approved: "aprovado pelo dono" },
|
|
3931
|
+
words: { none: "\u2014", hidden: "? (revele)", prefers: "prefere", approved: "aprovado pelo dono", local_file: "arquivo do pacote local", sdk_file: "grava\xE7\xE3o do SDK", synth: "s\xEDntese do SDK" },
|
|
3869
3932
|
sources: { sdk: "SDK", user: "seu som", synth: "sintetizado" },
|
|
3870
3933
|
probe: "Fonte do som",
|
|
3871
3934
|
wall: "Parede (oclus\xE3o)",
|
|
@@ -3936,9 +3999,9 @@ var EN2 = {
|
|
|
3936
3999
|
environments: { indoor: "indoor", outdoor: "outdoor" },
|
|
3937
4000
|
strengths: { light: "light", medium: "medium", heavy: "heavy" },
|
|
3938
4001
|
criteria: { C1: "C1 Sync", C2: "C2 Right sound", C3: "C3 Distance", C4: "C4 Position", C5: "C5 Variation", C6: "C6 Level", C7: "C7 Strength", C8: "C8 Tail", C9: "C9 Burst", C10: "C10 Listening" },
|
|
3939
|
-
metrics: { source: "1 \xB7 Source of what played", chosen: "1 \xB7 Chosen", matrix: "2 \xB7 Matrix", last: "Last played", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Preferences", state: "5 \xB7 Measurement", count: "1 \xB7 Catalogue" },
|
|
4002
|
+
metrics: { source: "1 \xB7 Source of what played", chosen: "1 \xB7 Chosen", matrix: "2 \xB7 Matrix", last: "Last played", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Preferences", state: "5 \xB7 Measurement", count: "1 \xB7 Catalogue", unlicensed: "1 \xB7 File without licence" },
|
|
3940
4003
|
run: { idle: "idle", measuring: "measuring\u2026", done: "done", failed: "failed", recording: "recording\u2026", recorded: "recording downloaded" },
|
|
3941
|
-
words: { none: "\u2014", hidden: "? (reveal)", prefers: "prefers", approved: "approved by the owner" },
|
|
4004
|
+
words: { none: "\u2014", hidden: "? (reveal)", prefers: "prefers", approved: "approved by the owner", local_file: "local pack file", sdk_file: "SDK recording", synth: "SDK synthesis" },
|
|
3942
4005
|
sources: { sdk: "SDK", user: "your sound", synth: "synthesized" },
|
|
3943
4006
|
probe: "Sound source",
|
|
3944
4007
|
wall: "Wall (occlusion)",
|
|
@@ -4146,6 +4209,18 @@ function createSoundCheckModule(options = {}) {
|
|
|
4146
4209
|
const count = (state) => states.filter((each) => each === state).length;
|
|
4147
4210
|
return `${text.states.file} ${count("file")} \xB7 ${text.states.synth} ${count("synth")} \xB7 ${text.states.missing} ${count("missing")}`;
|
|
4148
4211
|
};
|
|
4212
|
+
const sourceOf2 = (id) => {
|
|
4213
|
+
const sample = registry().sample(id);
|
|
4214
|
+
if (!sample) return text.words.synth;
|
|
4215
|
+
return sample.sources.some((source) => source.startsWith("local:")) ? text.words.local_file : text.words.sdk_file;
|
|
4216
|
+
};
|
|
4217
|
+
const unlicensed = () => {
|
|
4218
|
+
const ids = registry().sampleIds().filter((id) => {
|
|
4219
|
+
const license = registry().sample(id)?.license;
|
|
4220
|
+
return license !== void 0 && !isShippableLicense(license);
|
|
4221
|
+
});
|
|
4222
|
+
return ids.length === 0 ? text.words.none : `${ids.length}: ${ids.join(", ")}`;
|
|
4223
|
+
};
|
|
4149
4224
|
const strikeId = () => impactSoundId(chosen.material, chosen.blow);
|
|
4150
4225
|
const lastLine = () => {
|
|
4151
4226
|
const last = log.at(-1);
|
|
@@ -4162,7 +4237,8 @@ function createSoundCheckModule(options = {}) {
|
|
|
4162
4237
|
const metrics = () => [
|
|
4163
4238
|
{ id: "source", name: text.metrics.source, read: sourceLine },
|
|
4164
4239
|
{ id: "count", name: text.metrics.count, read: counts },
|
|
4165
|
-
{ id: "
|
|
4240
|
+
{ id: "unlicensed", name: text.metrics.unlicensed, read: unlicensed },
|
|
4241
|
+
{ id: "chosen", name: text.metrics.chosen, read: () => `${label(chosen.sound)}${registry().sample(chosen.sound) ? ` (${engine.sampleStatus(chosen.sound)})` : ""} \xB7 ${sourceOf2(chosen.sound)}` },
|
|
4166
4242
|
{ id: "matrix", name: text.metrics.matrix, read: () => `${strikeId()} \xB7 ${text.states[stateOf(strikeId())]}${pairOf(strikeId()).a ? ` \xB7 A=${pairOf(strikeId()).a}` : ""}` },
|
|
4167
4243
|
{ id: "ab", name: text.metrics.ab, read: () => `A ${pairOf(chosen.sound).a ?? text.words.none} \xB7 B ${pairOf(chosen.sound).b ?? text.words.none}` },
|
|
4168
4244
|
{ id: "blind_state", name: text.metrics.blind, read: () => !blind ? text.words.none : blind.revealed ? `X = ${blind.side}` : text.words.hidden },
|
|
@@ -4405,6 +4481,7 @@ export {
|
|
|
4405
4481
|
CALIBRATION_LOOP_SOUND,
|
|
4406
4482
|
isCalibrationUrl,
|
|
4407
4483
|
calibrationLoader,
|
|
4484
|
+
aliasSample,
|
|
4408
4485
|
createSoundRegistry,
|
|
4409
4486
|
MIX_PROFILES,
|
|
4410
4487
|
DEFAULT_MIX,
|
|
@@ -4423,12 +4500,14 @@ export {
|
|
|
4423
4500
|
loopCrossfade,
|
|
4424
4501
|
CROSSFADE_STEPS,
|
|
4425
4502
|
equalPowerIn,
|
|
4503
|
+
loopRate,
|
|
4426
4504
|
realize,
|
|
4427
4505
|
retunePlan,
|
|
4428
4506
|
createSetPicker,
|
|
4429
4507
|
fetchLoader,
|
|
4430
4508
|
inlineLoader,
|
|
4431
4509
|
createSampleStore,
|
|
4510
|
+
TRIM_FADE,
|
|
4432
4511
|
realizeSample,
|
|
4433
4512
|
sampleLength,
|
|
4434
4513
|
limiterCurve2 as limiterCurve,
|
|
@@ -4454,24 +4533,18 @@ export {
|
|
|
4454
4533
|
impactSoundId,
|
|
4455
4534
|
SFX_IMPACTS,
|
|
4456
4535
|
sfxState,
|
|
4457
|
-
SDK_LICENSES,
|
|
4458
|
-
SFX_LAYERS,
|
|
4459
|
-
SFX_TIERS,
|
|
4460
|
-
parseSfxName,
|
|
4461
|
-
splitTier,
|
|
4462
|
-
sampleBankFromManifest,
|
|
4463
|
-
KIT_CATEGORY_BUS,
|
|
4464
|
-
KIT_SAMPLE_ALIASES,
|
|
4465
|
-
kitSampleDefaults,
|
|
4466
|
-
withAliases,
|
|
4467
|
-
kitSampleBank,
|
|
4468
|
-
loadKitSamples,
|
|
4469
4536
|
USER_SAMPLES_BANK,
|
|
4470
4537
|
KIT_SAMPLES_BANK,
|
|
4471
4538
|
USER_SOUND_PREFIX,
|
|
4472
4539
|
soundSourceOf,
|
|
4473
4540
|
userSampleBank,
|
|
4474
4541
|
loadUserSamples,
|
|
4542
|
+
LOCAL_PACK_LICENSES,
|
|
4543
|
+
LOCAL_PACK_PREFERENCES,
|
|
4544
|
+
LocalSoundPackError,
|
|
4545
|
+
parseLocalSoundPack,
|
|
4546
|
+
isShippableLicense,
|
|
4547
|
+
localPackSamples,
|
|
4475
4548
|
GAME_SFX_CLASSES,
|
|
4476
4549
|
GAME_SFX_FALLBACK,
|
|
4477
4550
|
noiseClassRecipe,
|
|
@@ -4487,4 +4560,4 @@ export {
|
|
|
4487
4560
|
CALIBRATION_CATEGORY,
|
|
4488
4561
|
createSoundCheckModule
|
|
4489
4562
|
};
|
|
4490
|
-
//# sourceMappingURL=chunk-
|
|
4563
|
+
//# sourceMappingURL=chunk-UUWKSG4J.js.map
|