reframe-video 0.6.26 → 0.6.28
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/dist/bin.js +588 -48
- package/dist/cli.js +590 -47
- package/dist/compile-api.js +42 -1
- package/dist/compile.js +42 -1
- package/dist/diff.js +40 -1
- package/dist/frame.js +40 -1
- package/dist/index.js +89 -6
- package/dist/labels.js +40 -1
- package/dist/types/audio.d.ts +2 -2
- package/dist/types/ir.d.ts +22 -4
- package/guides/edsl-guide.md +25 -6
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -6,6 +6,42 @@ import { tmpdir as tmpdir6 } from "node:os";
|
|
|
6
6
|
import { basename, dirname as dirname7, join as join9, resolve as resolve6 } from "node:path";
|
|
7
7
|
|
|
8
8
|
// ../core/src/ir.ts
|
|
9
|
+
var SFX_NAMES = [
|
|
10
|
+
"whoosh",
|
|
11
|
+
"swish",
|
|
12
|
+
"swoosh",
|
|
13
|
+
"rise",
|
|
14
|
+
"riser",
|
|
15
|
+
"warp",
|
|
16
|
+
"tick",
|
|
17
|
+
"click",
|
|
18
|
+
"blip",
|
|
19
|
+
"pop",
|
|
20
|
+
"select",
|
|
21
|
+
"thud",
|
|
22
|
+
"boom",
|
|
23
|
+
"knock",
|
|
24
|
+
"sub",
|
|
25
|
+
"chime",
|
|
26
|
+
"ding",
|
|
27
|
+
"coin",
|
|
28
|
+
"sparkle",
|
|
29
|
+
"shimmer",
|
|
30
|
+
"success",
|
|
31
|
+
"zap",
|
|
32
|
+
"error",
|
|
33
|
+
"glitch",
|
|
34
|
+
"static",
|
|
35
|
+
"scan",
|
|
36
|
+
"powerup",
|
|
37
|
+
"powerdown",
|
|
38
|
+
"snare",
|
|
39
|
+
"hat",
|
|
40
|
+
"bubble",
|
|
41
|
+
"notify",
|
|
42
|
+
"camera"
|
|
43
|
+
];
|
|
44
|
+
var BGM_SYNTHS = ["ambient-pad", "lofi", "pulse", "tension", "uplift"];
|
|
9
45
|
var DEFAULT_CROSSFADE = 0.5;
|
|
10
46
|
var DEFAULT_TO_DURATION = 0.5;
|
|
11
47
|
var DEFAULT_TWEEN_DURATION = 0.5;
|
|
@@ -656,7 +692,6 @@ function validateScene(ir) {
|
|
|
656
692
|
}
|
|
657
693
|
}
|
|
658
694
|
}
|
|
659
|
-
const SFX_NAMES = ["whoosh", "pop", "tick", "rise", "shimmer", "thud"];
|
|
660
695
|
for (const [i, cue] of (ir.audio?.cues ?? []).entries()) {
|
|
661
696
|
if (typeof cue.at === "string" && !labels.has(cue.at)) {
|
|
662
697
|
problems.push(
|
|
@@ -692,6 +727,10 @@ function validateScene(ir) {
|
|
|
692
727
|
if (ir.audio?.bgm?.file !== void 0 && ir.audio.bgm.synth !== void 0) {
|
|
693
728
|
problems.push('audio.bgm: use either "file" or "synth", not both');
|
|
694
729
|
}
|
|
730
|
+
const bgmSynth = ir.audio?.bgm?.synth;
|
|
731
|
+
if (bgmSynth !== void 0 && !BGM_SYNTHS.includes(bgmSynth)) {
|
|
732
|
+
problems.push(`audio.bgm.synth: unknown synth "${bgmSynth}" \u2014 valid: ${BGM_SYNTHS.join(", ")}`);
|
|
733
|
+
}
|
|
695
734
|
if (problems.length > 0) throw new SceneValidationError(problems);
|
|
696
735
|
}
|
|
697
736
|
var TRANSITIONS = ["cut", "crossfade"];
|
|
@@ -991,12 +1030,46 @@ var SET = 1 / 120;
|
|
|
991
1030
|
|
|
992
1031
|
// ../core/src/audio.ts
|
|
993
1032
|
var SFX_DURATION = {
|
|
1033
|
+
// transition
|
|
994
1034
|
whoosh: 0.35,
|
|
995
|
-
|
|
996
|
-
|
|
1035
|
+
swish: 0.32,
|
|
1036
|
+
swoosh: 0.35,
|
|
997
1037
|
rise: 0.5,
|
|
1038
|
+
riser: 0.85,
|
|
1039
|
+
warp: 0.5,
|
|
1040
|
+
// ui
|
|
1041
|
+
tick: 0.03,
|
|
1042
|
+
click: 0.05,
|
|
1043
|
+
blip: 0.1,
|
|
1044
|
+
pop: 0.12,
|
|
1045
|
+
select: 0.18,
|
|
1046
|
+
// impact
|
|
1047
|
+
thud: 0.25,
|
|
1048
|
+
boom: 0.6,
|
|
1049
|
+
knock: 0.14,
|
|
1050
|
+
sub: 0.7,
|
|
1051
|
+
// positive
|
|
1052
|
+
chime: 0.7,
|
|
1053
|
+
ding: 0.5,
|
|
1054
|
+
coin: 0.3,
|
|
1055
|
+
sparkle: 0.6,
|
|
998
1056
|
shimmer: 0.9,
|
|
999
|
-
|
|
1057
|
+
success: 0.6,
|
|
1058
|
+
// alert
|
|
1059
|
+
zap: 0.22,
|
|
1060
|
+
error: 0.4,
|
|
1061
|
+
// tech
|
|
1062
|
+
glitch: 0.3,
|
|
1063
|
+
static: 0.18,
|
|
1064
|
+
scan: 0.45,
|
|
1065
|
+
powerup: 0.4,
|
|
1066
|
+
powerdown: 0.5,
|
|
1067
|
+
// rhythm / foley
|
|
1068
|
+
snare: 0.18,
|
|
1069
|
+
hat: 0.05,
|
|
1070
|
+
bubble: 0.16,
|
|
1071
|
+
notify: 0.45,
|
|
1072
|
+
camera: 0.18
|
|
1000
1073
|
};
|
|
1001
1074
|
var FILE_CUE_DURATION = 0.4;
|
|
1002
1075
|
function collectClipAudio(ir, duration, warnings) {
|
|
@@ -1056,7 +1129,11 @@ function resolveAudioPlan(compiled) {
|
|
|
1056
1129
|
fadeIn: cue.fadeIn ?? 0,
|
|
1057
1130
|
fadeOut: cue.fadeOut ?? 0,
|
|
1058
1131
|
pan: cue.pan ?? 0,
|
|
1059
|
-
source: cue.sfx ?
|
|
1132
|
+
source: cue.sfx ? (
|
|
1133
|
+
// auto-vary: default the seed to the cue's order so repeated sfx differ
|
|
1134
|
+
// (pitch/texture); an explicit params.seed always wins.
|
|
1135
|
+
{ kind: "sfx", name: cue.sfx, params: { seed: index, ...cue.params } }
|
|
1136
|
+
) : { kind: "file", path: cue.file }
|
|
1060
1137
|
});
|
|
1061
1138
|
}
|
|
1062
1139
|
cues.sort((a, b) => a.t - b.t);
|
|
@@ -1136,7 +1213,11 @@ function resolveCompositionAudioPlan(comp) {
|
|
|
1136
1213
|
fadeIn: cue.fadeIn ?? 0,
|
|
1137
1214
|
fadeOut: cue.fadeOut ?? 0,
|
|
1138
1215
|
pan: cue.pan ?? 0,
|
|
1139
|
-
source: cue.sfx ?
|
|
1216
|
+
source: cue.sfx ? (
|
|
1217
|
+
// auto-vary: default the seed to the cue's order so repeated sfx differ
|
|
1218
|
+
// (pitch/texture); an explicit params.seed always wins.
|
|
1219
|
+
{ kind: "sfx", name: cue.sfx, params: { seed: index, ...cue.params } }
|
|
1220
|
+
) : { kind: "file", path: cue.file }
|
|
1140
1221
|
});
|
|
1141
1222
|
}
|
|
1142
1223
|
if (!audio?.bgm && cues.length === 0 && clipAudio.length === 0) return null;
|
|
@@ -1240,19 +1321,23 @@ function hash01(n, seed) {
|
|
|
1240
1321
|
var noise = (n, seed) => hash01(n, seed) * 2 - 1;
|
|
1241
1322
|
var TAU = Math.PI * 2;
|
|
1242
1323
|
var expDecay = (t, dur, k = 5) => Math.exp(-k * t / dur);
|
|
1324
|
+
var square = (ph) => (Math.sin(ph) + 0.33 * Math.sin(3 * ph) + 0.2 * Math.sin(5 * ph)) / 1.4;
|
|
1325
|
+
var PITCH_STEPS = [0, 2, 4, 7, 9, 12, 5, -3, 16, -5];
|
|
1326
|
+
function seedPitch(seed) {
|
|
1327
|
+
const i = (Math.round(seed) % PITCH_STEPS.length + PITCH_STEPS.length) % PITCH_STEPS.length;
|
|
1328
|
+
return Math.pow(2, PITCH_STEPS[i] / 12);
|
|
1329
|
+
}
|
|
1243
1330
|
function buffer(duration) {
|
|
1244
1331
|
const n = Math.round(duration * SAMPLE_RATE);
|
|
1245
1332
|
return { out: new Float32Array(n), n };
|
|
1246
1333
|
}
|
|
1247
|
-
function whoosh(seed) {
|
|
1334
|
+
function whoosh(seed, pitch) {
|
|
1248
1335
|
const dur = 0.35;
|
|
1249
1336
|
const { out, n } = buffer(dur);
|
|
1250
|
-
let lp = 0;
|
|
1251
|
-
let lp2 = 0;
|
|
1337
|
+
let lp = 0, lp2 = 0;
|
|
1252
1338
|
for (let i = 0; i < n; i++) {
|
|
1253
|
-
const t = i / SAMPLE_RATE;
|
|
1254
|
-
const
|
|
1255
|
-
const center = 1200 * Math.pow(300 / 1200, u);
|
|
1339
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1340
|
+
const center = 1200 * pitch * Math.pow(0.25, u);
|
|
1256
1341
|
const alpha = Math.min(1, TAU * center / SAMPLE_RATE);
|
|
1257
1342
|
lp += alpha * (noise(i, seed) - lp);
|
|
1258
1343
|
lp2 += alpha * 0.5 * (lp - lp2);
|
|
@@ -1261,110 +1346,568 @@ function whoosh(seed) {
|
|
|
1261
1346
|
}
|
|
1262
1347
|
return out;
|
|
1263
1348
|
}
|
|
1264
|
-
function
|
|
1349
|
+
function swish(seed, pitch) {
|
|
1350
|
+
const dur = 0.32;
|
|
1351
|
+
const { out, n } = buffer(dur);
|
|
1352
|
+
let lp = 0, lp2 = 0;
|
|
1353
|
+
for (let i = 0; i < n; i++) {
|
|
1354
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1355
|
+
const center = 2600 * pitch * Math.pow(0.2, u);
|
|
1356
|
+
const alpha = Math.min(1, TAU * center / SAMPLE_RATE);
|
|
1357
|
+
lp += alpha * (noise(i, seed) - lp);
|
|
1358
|
+
lp2 += alpha * 0.5 * (lp - lp2);
|
|
1359
|
+
const env = u < 0.15 ? u / 0.15 : expDecay(t - 0.15 * dur, dur * 0.85, 5);
|
|
1360
|
+
out[i] = (lp - lp2) * env * 2.4;
|
|
1361
|
+
}
|
|
1362
|
+
return out;
|
|
1363
|
+
}
|
|
1364
|
+
function rise(_seed, pitch) {
|
|
1365
|
+
const dur = 0.5;
|
|
1366
|
+
const { out, n } = buffer(dur);
|
|
1367
|
+
let phase = 0;
|
|
1368
|
+
for (let i = 0; i < n; i++) {
|
|
1369
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1370
|
+
const freq = 220 * pitch * Math.pow(4, u);
|
|
1371
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
1372
|
+
const env = Math.sin(Math.PI * Math.min(1, u * 1.05)) ** 1.5;
|
|
1373
|
+
out[i] = (Math.sin(phase) + 0.3 * Math.sin(2 * phase)) * env * 0.45;
|
|
1374
|
+
}
|
|
1375
|
+
return out;
|
|
1376
|
+
}
|
|
1377
|
+
function riser(seed, pitch) {
|
|
1378
|
+
const dur = 0.85;
|
|
1379
|
+
const { out, n } = buffer(dur);
|
|
1380
|
+
let lp = 0, phase = 0;
|
|
1381
|
+
for (let i = 0; i < n; i++) {
|
|
1382
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1383
|
+
const center = 200 * pitch * Math.pow(12, u);
|
|
1384
|
+
const alpha = Math.min(1, TAU * center / SAMPLE_RATE);
|
|
1385
|
+
lp += alpha * (noise(i, seed) - lp);
|
|
1386
|
+
const freq = 120 * pitch * Math.pow(6, u);
|
|
1387
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
1388
|
+
const env = Math.pow(u, 1.6);
|
|
1389
|
+
out[i] = (lp * 1.6 + Math.sin(phase) * 0.5) * env * 0.9;
|
|
1390
|
+
}
|
|
1391
|
+
return out;
|
|
1392
|
+
}
|
|
1393
|
+
function warp(_seed, pitch) {
|
|
1394
|
+
const dur = 0.5;
|
|
1395
|
+
const { out, n } = buffer(dur);
|
|
1396
|
+
let phase = 0;
|
|
1397
|
+
for (let i = 0; i < n; i++) {
|
|
1398
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1399
|
+
const bend = Math.sin(Math.PI * u);
|
|
1400
|
+
const vib = 1 + 0.4 * Math.sin(TAU * 18 * t);
|
|
1401
|
+
const freq = 300 * pitch * (1 + 2.5 * bend) * vib;
|
|
1402
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
1403
|
+
const env = Math.sin(Math.PI * u) ** 0.8;
|
|
1404
|
+
out[i] = square(phase) * env * 0.5;
|
|
1405
|
+
}
|
|
1406
|
+
return out;
|
|
1407
|
+
}
|
|
1408
|
+
function tick(seed, pitch) {
|
|
1409
|
+
const dur = 0.03;
|
|
1410
|
+
const { out, n } = buffer(dur);
|
|
1411
|
+
for (let i = 0; i < n; i++) {
|
|
1412
|
+
const t = i / SAMPLE_RATE;
|
|
1413
|
+
const sine = t < 4e-3 ? Math.sin(TAU * 4e3 * pitch * t) : 0;
|
|
1414
|
+
out[i] = (sine * 0.6 + noise(i, seed) * 0.35) * expDecay(t, dur, 8);
|
|
1415
|
+
}
|
|
1416
|
+
return out;
|
|
1417
|
+
}
|
|
1418
|
+
function click(seed, pitch) {
|
|
1419
|
+
const dur = 0.05;
|
|
1420
|
+
const { out, n } = buffer(dur);
|
|
1421
|
+
let lp = 0;
|
|
1422
|
+
for (let i = 0; i < n; i++) {
|
|
1423
|
+
const t = i / SAMPLE_RATE;
|
|
1424
|
+
lp += 0.5 * (noise(i, seed) - lp);
|
|
1425
|
+
const sine = Math.sin(TAU * 1500 * pitch * t);
|
|
1426
|
+
out[i] = (sine * 0.5 + lp * 0.6) * expDecay(t, dur, 11);
|
|
1427
|
+
}
|
|
1428
|
+
return out;
|
|
1429
|
+
}
|
|
1430
|
+
function blip(_seed, pitch) {
|
|
1431
|
+
const dur = 0.1;
|
|
1432
|
+
const { out, n } = buffer(dur);
|
|
1433
|
+
let phase = 0;
|
|
1434
|
+
for (let i = 0; i < n; i++) {
|
|
1435
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1436
|
+
phase += TAU * 880 * pitch / SAMPLE_RATE;
|
|
1437
|
+
const env = Math.min(1, u * 12) * Math.min(1, (1 - u) * 6);
|
|
1438
|
+
out[i] = square(phase) * env * 0.5;
|
|
1439
|
+
}
|
|
1440
|
+
return out;
|
|
1441
|
+
}
|
|
1442
|
+
function pop(seed, pitch) {
|
|
1265
1443
|
const dur = 0.12;
|
|
1266
1444
|
const { out, n } = buffer(dur);
|
|
1267
1445
|
let phase = 0;
|
|
1268
1446
|
for (let i = 0; i < n; i++) {
|
|
1269
1447
|
const t = i / SAMPLE_RATE;
|
|
1270
|
-
const freq = 600 * Math.pow(
|
|
1448
|
+
const freq = 600 * pitch * Math.pow(0.25, t / 0.08);
|
|
1271
1449
|
phase += TAU * freq / SAMPLE_RATE;
|
|
1272
1450
|
const transient = t < 2e-3 ? noise(i, seed) * 0.5 : 0;
|
|
1273
1451
|
out[i] = (Math.sin(phase) + transient) * expDecay(t, dur, 6) * 0.8;
|
|
1274
1452
|
}
|
|
1275
1453
|
return out;
|
|
1276
1454
|
}
|
|
1277
|
-
function
|
|
1278
|
-
const dur = 0.
|
|
1455
|
+
function select(_seed, pitch) {
|
|
1456
|
+
const dur = 0.18;
|
|
1457
|
+
const { out, n } = buffer(dur);
|
|
1458
|
+
let phase = 0;
|
|
1459
|
+
for (let i = 0; i < n; i++) {
|
|
1460
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1461
|
+
const freq = (t < 0.08 ? 620 : 930) * pitch;
|
|
1462
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
1463
|
+
const env = Math.min(1, u * 16) * Math.min(1, (1 - u) * 5);
|
|
1464
|
+
out[i] = (Math.sin(phase) + 0.25 * Math.sin(2 * phase)) * env * 0.5;
|
|
1465
|
+
}
|
|
1466
|
+
return out;
|
|
1467
|
+
}
|
|
1468
|
+
function thud(seed, pitch) {
|
|
1469
|
+
const dur = 0.25;
|
|
1279
1470
|
const { out, n } = buffer(dur);
|
|
1471
|
+
let phase = 0, lp = 0;
|
|
1280
1472
|
for (let i = 0; i < n; i++) {
|
|
1281
1473
|
const t = i / SAMPLE_RATE;
|
|
1282
|
-
const
|
|
1283
|
-
|
|
1474
|
+
const freq = 90 * pitch * Math.pow(0.5, t / 0.15);
|
|
1475
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
1476
|
+
lp += 0.02 * (noise(i, seed) - lp);
|
|
1477
|
+
const attack = t < 0.01 ? lp * 3 : 0;
|
|
1478
|
+
out[i] = (Math.sin(phase) * 0.9 + attack) * expDecay(t, dur, 5);
|
|
1284
1479
|
}
|
|
1285
1480
|
return out;
|
|
1286
1481
|
}
|
|
1287
|
-
function
|
|
1482
|
+
function boom(seed, pitch) {
|
|
1483
|
+
const dur = 0.6;
|
|
1484
|
+
const { out, n } = buffer(dur);
|
|
1485
|
+
let phase = 0, lp = 0;
|
|
1486
|
+
for (let i = 0; i < n; i++) {
|
|
1487
|
+
const t = i / SAMPLE_RATE;
|
|
1488
|
+
const freq = 70 * pitch * Math.pow(0.5, t / 0.3);
|
|
1489
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
1490
|
+
lp += 0.06 * (noise(i, seed) - lp);
|
|
1491
|
+
const body = t < 0.06 ? lp * 2.5 * (1 - t / 0.06) : 0;
|
|
1492
|
+
out[i] = (Math.sin(phase) * 1 + body) * expDecay(t, dur, 3.2);
|
|
1493
|
+
}
|
|
1494
|
+
return out;
|
|
1495
|
+
}
|
|
1496
|
+
function knock(seed, pitch) {
|
|
1497
|
+
const dur = 0.14;
|
|
1498
|
+
const { out, n } = buffer(dur);
|
|
1499
|
+
let phase = 0, lp = 0;
|
|
1500
|
+
for (let i = 0; i < n; i++) {
|
|
1501
|
+
const t = i / SAMPLE_RATE;
|
|
1502
|
+
const freq = 220 * pitch * Math.pow(0.7, t / 0.05);
|
|
1503
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
1504
|
+
lp += 0.3 * (noise(i, seed) - lp);
|
|
1505
|
+
const tap = t < 5e-3 ? lp : 0;
|
|
1506
|
+
out[i] = (Math.sin(phase) * 0.8 + tap * 0.6) * expDecay(t, dur, 9);
|
|
1507
|
+
}
|
|
1508
|
+
return out;
|
|
1509
|
+
}
|
|
1510
|
+
function chime(seed, pitch) {
|
|
1511
|
+
const dur = 0.7;
|
|
1512
|
+
const { out, n } = buffer(dur);
|
|
1513
|
+
const f0 = 800 * pitch;
|
|
1514
|
+
const partials = [
|
|
1515
|
+
{ f: f0, a: 1, k: 4 },
|
|
1516
|
+
{ f: f0 * 2.76, a: 0.5, k: 5.5 },
|
|
1517
|
+
{ f: f0 * 5.4, a: 0.28, k: 7 },
|
|
1518
|
+
{ f: f0 * 8.9, a: 0.13, k: 9 }
|
|
1519
|
+
];
|
|
1520
|
+
for (let i = 0; i < n; i++) {
|
|
1521
|
+
const t = i / SAMPLE_RATE;
|
|
1522
|
+
let s = 0;
|
|
1523
|
+
for (const p of partials) s += Math.sin(TAU * p.f * t) * p.a * expDecay(t, dur, p.k);
|
|
1524
|
+
const strike = t < 3e-3 ? noise(i, seed) * 0.3 : 0;
|
|
1525
|
+
out[i] = (s / 1.9 + strike) * 0.6;
|
|
1526
|
+
}
|
|
1527
|
+
return out;
|
|
1528
|
+
}
|
|
1529
|
+
function ding(_seed, pitch) {
|
|
1288
1530
|
const dur = 0.5;
|
|
1289
1531
|
const { out, n } = buffer(dur);
|
|
1290
|
-
|
|
1532
|
+
const f0 = 1200 * pitch;
|
|
1291
1533
|
for (let i = 0; i < n; i++) {
|
|
1292
1534
|
const t = i / SAMPLE_RATE;
|
|
1293
|
-
const
|
|
1294
|
-
|
|
1535
|
+
const s = Math.sin(TAU * f0 * t) + 0.4 * Math.sin(TAU * f0 * 2 * t) + 0.2 * Math.sin(TAU * f0 * 3.01 * t);
|
|
1536
|
+
out[i] = s / 1.6 * expDecay(t, dur, 4.5) * 0.6;
|
|
1537
|
+
}
|
|
1538
|
+
return out;
|
|
1539
|
+
}
|
|
1540
|
+
function coin(_seed, pitch) {
|
|
1541
|
+
const dur = 0.3;
|
|
1542
|
+
const { out, n } = buffer(dur);
|
|
1543
|
+
let phase = 0;
|
|
1544
|
+
for (let i = 0; i < n; i++) {
|
|
1545
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1546
|
+
const freq = (t < 0.06 ? 988 : 1319) * pitch;
|
|
1295
1547
|
phase += TAU * freq / SAMPLE_RATE;
|
|
1296
|
-
const env = Math.
|
|
1297
|
-
out[i] = (
|
|
1548
|
+
const env = Math.min(1, u * 30) * expDecay(Math.max(0, t - 0.06), dur, 3.5);
|
|
1549
|
+
out[i] = square(phase) * env * 0.55;
|
|
1298
1550
|
}
|
|
1299
1551
|
return out;
|
|
1300
1552
|
}
|
|
1301
|
-
function
|
|
1553
|
+
function sparkle(seed, pitch) {
|
|
1554
|
+
const dur = 0.6;
|
|
1555
|
+
const { out, n } = buffer(dur);
|
|
1556
|
+
const steps = [1, 1.5, 2, 3, 4, 5, 6];
|
|
1557
|
+
const base = 1200 * pitch;
|
|
1558
|
+
for (let i = 0; i < n; i++) {
|
|
1559
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1560
|
+
let s = 0;
|
|
1561
|
+
for (let g = 0; g < steps.length; g++) {
|
|
1562
|
+
const on = u * steps.length - g;
|
|
1563
|
+
if (on > 0 && on < 3) {
|
|
1564
|
+
const ge = Math.exp(-on * 1.8);
|
|
1565
|
+
s += Math.sin(TAU * base * steps[g] * t + hash01(g, seed) * TAU) * ge;
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
out[i] = s / 2.4 * Math.sin(Math.PI * u) ** 0.5 * 0.5;
|
|
1569
|
+
}
|
|
1570
|
+
return out;
|
|
1571
|
+
}
|
|
1572
|
+
function success(_seed, pitch) {
|
|
1573
|
+
const dur = 0.6;
|
|
1574
|
+
const { out, n } = buffer(dur);
|
|
1575
|
+
const notes = [523.25, 659.25, 783.99].map((f) => f * pitch);
|
|
1576
|
+
let phase = 0, cur = 0;
|
|
1577
|
+
for (let i = 0; i < n; i++) {
|
|
1578
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1579
|
+
const idx = Math.min(notes.length - 1, Math.floor(u * 3.2));
|
|
1580
|
+
if (idx !== cur) cur = idx;
|
|
1581
|
+
phase += TAU * notes[cur] / SAMPLE_RATE;
|
|
1582
|
+
const local = u * 3.2 - idx;
|
|
1583
|
+
const env = Math.min(1, local * 12) * Math.min(1, (1 - Math.min(1, local)) * 4 + 0.2);
|
|
1584
|
+
out[i] = (Math.sin(phase) + 0.3 * Math.sin(2 * phase)) * env * 0.42;
|
|
1585
|
+
}
|
|
1586
|
+
return out;
|
|
1587
|
+
}
|
|
1588
|
+
function shimmer(seed, pitch) {
|
|
1302
1589
|
const dur = 0.9;
|
|
1303
1590
|
const { out, n } = buffer(dur);
|
|
1304
1591
|
const partials = Array.from({ length: 5 }, (_, p) => ({
|
|
1305
|
-
freq: 2e3 + hash01(p, seed + 7) * 2e3,
|
|
1592
|
+
freq: (2e3 + hash01(p, seed + 7) * 2e3) * pitch,
|
|
1306
1593
|
am: 0.5 + hash01(p, seed + 8) * 1.5,
|
|
1307
1594
|
phase: hash01(p, seed + 9) * TAU
|
|
1308
1595
|
}));
|
|
1309
1596
|
for (let i = 0; i < n; i++) {
|
|
1310
|
-
const t = i / SAMPLE_RATE;
|
|
1311
|
-
const u = t / dur;
|
|
1597
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1312
1598
|
const env = Math.sin(Math.PI * u) ** 1.2;
|
|
1313
1599
|
let s = 0;
|
|
1314
|
-
for (const part of partials)
|
|
1315
|
-
s += Math.sin(TAU * part.freq * t + part.phase) * (0.6 + 0.4 * Math.sin(TAU * part.am * t));
|
|
1316
|
-
}
|
|
1600
|
+
for (const part of partials) s += Math.sin(TAU * part.freq * t + part.phase) * (0.6 + 0.4 * Math.sin(TAU * part.am * t));
|
|
1317
1601
|
out[i] = s / 5 * env * 0.5;
|
|
1318
1602
|
}
|
|
1319
1603
|
return out;
|
|
1320
1604
|
}
|
|
1321
|
-
function
|
|
1322
|
-
const dur = 0.
|
|
1605
|
+
function zap(seed, pitch) {
|
|
1606
|
+
const dur = 0.22;
|
|
1607
|
+
const { out, n } = buffer(dur);
|
|
1608
|
+
let phase = 0;
|
|
1609
|
+
for (let i = 0; i < n; i++) {
|
|
1610
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1611
|
+
const freq = 1600 * pitch * Math.pow(0.12, u);
|
|
1612
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
1613
|
+
const grit = noise(i, seed) * 0.25;
|
|
1614
|
+
out[i] = (square(phase) + grit) * expDecay(t, dur, 4.5) * 0.5;
|
|
1615
|
+
}
|
|
1616
|
+
return out;
|
|
1617
|
+
}
|
|
1618
|
+
function error(_seed, pitch) {
|
|
1619
|
+
const dur = 0.4;
|
|
1323
1620
|
const { out, n } = buffer(dur);
|
|
1324
1621
|
let phase = 0;
|
|
1622
|
+
for (let i = 0; i < n; i++) {
|
|
1623
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1624
|
+
const freq = (t < 0.16 ? 311 : 233) * pitch;
|
|
1625
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
1626
|
+
const seg = t < 0.16 ? u / 0.4 : (u - 0.4) / 0.6;
|
|
1627
|
+
const env = Math.min(1, seg * 18) * Math.min(1, (1 - seg) * 6);
|
|
1628
|
+
out[i] = square(phase) * env * 0.5;
|
|
1629
|
+
}
|
|
1630
|
+
return out;
|
|
1631
|
+
}
|
|
1632
|
+
function swoosh(seed, pitch) {
|
|
1633
|
+
const dur = 0.35;
|
|
1634
|
+
const { out, n } = buffer(dur);
|
|
1635
|
+
let lp = 0, lp2 = 0;
|
|
1636
|
+
for (let i = 0; i < n; i++) {
|
|
1637
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1638
|
+
const center = 300 * pitch * Math.pow(7.3, u);
|
|
1639
|
+
const alpha = Math.min(1, TAU * center / SAMPLE_RATE);
|
|
1640
|
+
lp += alpha * (noise(i, seed) - lp);
|
|
1641
|
+
lp2 += alpha * 0.5 * (lp - lp2);
|
|
1642
|
+
const env = Math.sin(Math.PI * u) ** 0.9;
|
|
1643
|
+
out[i] = (lp - lp2) * env * 2.4;
|
|
1644
|
+
}
|
|
1645
|
+
return out;
|
|
1646
|
+
}
|
|
1647
|
+
function glitch(seed, pitch) {
|
|
1648
|
+
const dur = 0.3;
|
|
1649
|
+
const { out, n } = buffer(dur);
|
|
1650
|
+
const cell = Math.round(SAMPLE_RATE * 0.012);
|
|
1651
|
+
let phase = 0;
|
|
1652
|
+
for (let i = 0; i < n; i++) {
|
|
1653
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1654
|
+
const c = Math.floor(i / cell);
|
|
1655
|
+
const on = hash01(c, seed) > 0.4 ? 1 : 0;
|
|
1656
|
+
const freq = 400 * pitch * (1 + Math.floor(hash01(c, seed + 1) * 6));
|
|
1657
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
1658
|
+
const crush = Math.round(square(phase) * 4) / 4;
|
|
1659
|
+
out[i] = (crush * 0.7 + noise(i, seed + c) * 0.3) * on * (1 - u * 0.3) * 0.55;
|
|
1660
|
+
}
|
|
1661
|
+
return out;
|
|
1662
|
+
}
|
|
1663
|
+
function staticHit(seed, pitch) {
|
|
1664
|
+
const dur = 0.18;
|
|
1665
|
+
const { out, n } = buffer(dur);
|
|
1325
1666
|
let lp = 0;
|
|
1667
|
+
const alpha = Math.min(0.8, TAU * 3e3 * pitch / SAMPLE_RATE);
|
|
1668
|
+
for (let i = 0; i < n; i++) {
|
|
1669
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1670
|
+
lp += alpha * (noise(i, seed) - lp);
|
|
1671
|
+
const env = Math.min(1, u * 30) * expDecay(t, dur, 5);
|
|
1672
|
+
out[i] = (noise(i, seed) - lp) * env * 1.4;
|
|
1673
|
+
}
|
|
1674
|
+
return out;
|
|
1675
|
+
}
|
|
1676
|
+
function scan(seed, pitch) {
|
|
1677
|
+
const dur = 0.45;
|
|
1678
|
+
const { out, n } = buffer(dur);
|
|
1679
|
+
let phase = 0;
|
|
1680
|
+
for (let i = 0; i < n; i++) {
|
|
1681
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1682
|
+
const step = Math.floor(u * 6) / 6;
|
|
1683
|
+
const freq = 500 * pitch * Math.pow(3, step);
|
|
1684
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
1685
|
+
const cell = u * 6 % 1;
|
|
1686
|
+
const env = Math.min(1, cell * 12) * Math.min(1, (1 - cell) * 4) * 0.7;
|
|
1687
|
+
out[i] = square(phase) * env * 0.5;
|
|
1688
|
+
}
|
|
1689
|
+
return out;
|
|
1690
|
+
}
|
|
1691
|
+
function powerup(seed, pitch) {
|
|
1692
|
+
const dur = 0.4;
|
|
1693
|
+
const { out, n } = buffer(dur);
|
|
1694
|
+
const notes = [392, 523, 659, 784, 1046].map((f) => f * pitch);
|
|
1695
|
+
let phase = 0;
|
|
1696
|
+
for (let i = 0; i < n; i++) {
|
|
1697
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1698
|
+
const idx = Math.min(notes.length - 1, Math.floor(u * notes.length));
|
|
1699
|
+
phase += TAU * notes[idx] / SAMPLE_RATE;
|
|
1700
|
+
const local = u * notes.length - idx;
|
|
1701
|
+
const env = Math.min(1, local * 14) * Math.min(1, (1 - Math.min(1, local)) * 4 + 0.3);
|
|
1702
|
+
out[i] = (Math.sin(phase) + 0.25 * Math.sin(2 * phase)) * env * 0.45;
|
|
1703
|
+
}
|
|
1704
|
+
return out;
|
|
1705
|
+
}
|
|
1706
|
+
function powerdown(seed, pitch) {
|
|
1707
|
+
const dur = 0.5;
|
|
1708
|
+
const { out, n } = buffer(dur);
|
|
1709
|
+
let phase = 0;
|
|
1710
|
+
for (let i = 0; i < n; i++) {
|
|
1711
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1712
|
+
const freq = 700 * pitch * Math.pow(0.18, u);
|
|
1713
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
1714
|
+
const env = (1 - u) ** 0.8;
|
|
1715
|
+
out[i] = (square(phase) * 0.7 + Math.sin(phase) * 0.3) * env * 0.5;
|
|
1716
|
+
}
|
|
1717
|
+
return out;
|
|
1718
|
+
}
|
|
1719
|
+
function sub(seed, pitch) {
|
|
1720
|
+
const dur = 0.7;
|
|
1721
|
+
const { out, n } = buffer(dur);
|
|
1722
|
+
let phase = 0;
|
|
1326
1723
|
for (let i = 0; i < n; i++) {
|
|
1327
1724
|
const t = i / SAMPLE_RATE;
|
|
1328
|
-
const freq =
|
|
1725
|
+
const freq = 80 * pitch * Math.pow(0.45, t / 0.4);
|
|
1329
1726
|
phase += TAU * freq / SAMPLE_RATE;
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1727
|
+
const click2 = t < 4e-3 ? noise(i, seed) * 0.4 : 0;
|
|
1728
|
+
out[i] = (Math.sin(phase) + click2) * expDecay(t, dur, 3) * 0.95;
|
|
1729
|
+
}
|
|
1730
|
+
return out;
|
|
1731
|
+
}
|
|
1732
|
+
function snare(seed, pitch) {
|
|
1733
|
+
const dur = 0.18;
|
|
1734
|
+
const { out, n } = buffer(dur);
|
|
1735
|
+
let phase = 0;
|
|
1736
|
+
for (let i = 0; i < n; i++) {
|
|
1737
|
+
const t = i / SAMPLE_RATE;
|
|
1738
|
+
phase += TAU * 180 * pitch / SAMPLE_RATE;
|
|
1739
|
+
const body = Math.sin(phase) * 0.5 * expDecay(t, dur, 16);
|
|
1740
|
+
const rattle = noise(i, seed) * expDecay(t, dur, 7);
|
|
1741
|
+
out[i] = (body + rattle * 0.8) * 0.7;
|
|
1742
|
+
}
|
|
1743
|
+
return out;
|
|
1744
|
+
}
|
|
1745
|
+
function hat(seed, pitch) {
|
|
1746
|
+
const dur = 0.05;
|
|
1747
|
+
const { out, n } = buffer(dur);
|
|
1748
|
+
let lp = 0;
|
|
1749
|
+
const alpha = Math.min(0.85, TAU * 2500 * pitch / SAMPLE_RATE);
|
|
1750
|
+
for (let i = 0; i < n; i++) {
|
|
1751
|
+
const t = i / SAMPLE_RATE;
|
|
1752
|
+
lp += alpha * (noise(i, seed) - lp);
|
|
1753
|
+
out[i] = (noise(i, seed) - lp) * expDecay(t, dur, 14) * 0.9;
|
|
1754
|
+
}
|
|
1755
|
+
return out;
|
|
1756
|
+
}
|
|
1757
|
+
function bubble(seed, pitch) {
|
|
1758
|
+
const dur = 0.16;
|
|
1759
|
+
const { out, n } = buffer(dur);
|
|
1760
|
+
let phase = 0;
|
|
1761
|
+
for (let i = 0; i < n; i++) {
|
|
1762
|
+
const t = i / SAMPLE_RATE, u = t / dur;
|
|
1763
|
+
const freq = 400 * pitch * Math.pow(3, u);
|
|
1764
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
1765
|
+
const env = Math.sin(Math.PI * u) ** 1.1;
|
|
1766
|
+
out[i] = Math.sin(phase) * env * 0.6;
|
|
1767
|
+
}
|
|
1768
|
+
return out;
|
|
1769
|
+
}
|
|
1770
|
+
function notify(seed, pitch) {
|
|
1771
|
+
const dur = 0.45;
|
|
1772
|
+
const { out, n } = buffer(dur);
|
|
1773
|
+
const f0 = 880 * pitch;
|
|
1774
|
+
for (let i = 0; i < n; i++) {
|
|
1775
|
+
const t = i / SAMPLE_RATE;
|
|
1776
|
+
const a = Math.sin(TAU * f0 * t) * expDecay(t, dur, 5);
|
|
1777
|
+
const b = t > 0.09 ? Math.sin(TAU * f0 * 1.5 * t) * expDecay(t - 0.09, dur, 4.5) : 0;
|
|
1778
|
+
out[i] = (a * 0.55 + b * 0.6) * 0.55;
|
|
1779
|
+
}
|
|
1780
|
+
return out;
|
|
1781
|
+
}
|
|
1782
|
+
function camera(seed, pitch) {
|
|
1783
|
+
const dur = 0.18;
|
|
1784
|
+
const { out, n } = buffer(dur);
|
|
1785
|
+
let lp = 0;
|
|
1786
|
+
for (let i = 0; i < n; i++) {
|
|
1787
|
+
const t = i / SAMPLE_RATE;
|
|
1788
|
+
lp += 0.45 * (noise(i, seed) - lp);
|
|
1789
|
+
const k1 = t < 0.02 ? expDecay(t, 0.02, 6) : 0;
|
|
1790
|
+
const k2 = t > 0.08 && t < 0.12 ? expDecay(t - 0.08, 0.04, 6) : 0;
|
|
1791
|
+
const sine = Math.sin(TAU * 2200 * pitch * t);
|
|
1792
|
+
out[i] = (lp * 0.7 + sine * 0.3) * (k1 + k2) * 1.3;
|
|
1333
1793
|
}
|
|
1334
1794
|
return out;
|
|
1335
1795
|
}
|
|
1336
1796
|
var RECIPES = {
|
|
1337
1797
|
whoosh,
|
|
1338
|
-
|
|
1339
|
-
|
|
1798
|
+
swish,
|
|
1799
|
+
swoosh,
|
|
1340
1800
|
rise,
|
|
1801
|
+
riser,
|
|
1802
|
+
warp,
|
|
1803
|
+
tick,
|
|
1804
|
+
click,
|
|
1805
|
+
blip,
|
|
1806
|
+
pop,
|
|
1807
|
+
select,
|
|
1808
|
+
thud,
|
|
1809
|
+
boom,
|
|
1810
|
+
knock,
|
|
1811
|
+
sub,
|
|
1812
|
+
chime,
|
|
1813
|
+
ding,
|
|
1814
|
+
coin,
|
|
1815
|
+
sparkle,
|
|
1341
1816
|
shimmer,
|
|
1342
|
-
|
|
1817
|
+
success,
|
|
1818
|
+
zap,
|
|
1819
|
+
error,
|
|
1820
|
+
glitch,
|
|
1821
|
+
static: staticHit,
|
|
1822
|
+
scan,
|
|
1823
|
+
powerup,
|
|
1824
|
+
powerdown,
|
|
1825
|
+
snare,
|
|
1826
|
+
hat,
|
|
1827
|
+
bubble,
|
|
1828
|
+
notify,
|
|
1829
|
+
camera
|
|
1343
1830
|
};
|
|
1344
1831
|
function synthSfx(name, params = {}) {
|
|
1345
|
-
const
|
|
1832
|
+
const seed = params.seed ?? 0;
|
|
1833
|
+
const pitch = (params.pitch ?? 1) * seedPitch(seed);
|
|
1834
|
+
const samples = RECIPES[name](seed, pitch);
|
|
1346
1835
|
if (params.gainDb) {
|
|
1347
1836
|
const g = Math.pow(10, params.gainDb / 20);
|
|
1348
1837
|
for (let i = 0; i < samples.length; i++) samples[i] *= g;
|
|
1349
1838
|
}
|
|
1839
|
+
let peak = 0;
|
|
1840
|
+
for (let i = 0; i < samples.length; i++) peak = Math.max(peak, Math.abs(samples[i]));
|
|
1841
|
+
if (peak > 0.95) {
|
|
1842
|
+
const g = 0.95 / peak;
|
|
1843
|
+
for (let i = 0; i < samples.length; i++) samples[i] *= g;
|
|
1844
|
+
}
|
|
1350
1845
|
return samples;
|
|
1351
1846
|
}
|
|
1352
|
-
function
|
|
1847
|
+
function pad(freqs, duration, seed, opts) {
|
|
1353
1848
|
const { out, n } = buffer(duration);
|
|
1354
|
-
const voices =
|
|
1355
|
-
{ freq: f * (1 + (hash01(v, seed + 3) - 0.5) * 4e-3), am:
|
|
1356
|
-
{ freq: f * (1 - (hash01(v, seed + 6) - 0.5) * 4e-3), am:
|
|
1849
|
+
const voices = freqs.flatMap((f, v) => [
|
|
1850
|
+
{ freq: f * (1 + (hash01(v, seed + 3) - 0.5) * 4e-3), am: opts.amBase + hash01(v, seed + 4) * 0.08, phase: hash01(v, seed + 5) * TAU },
|
|
1851
|
+
{ freq: f * (1 - (hash01(v, seed + 6) - 0.5) * 4e-3), am: opts.amBase + hash01(v, seed + 7) * 0.08, phase: hash01(v, seed + 8) * TAU }
|
|
1357
1852
|
]);
|
|
1358
1853
|
for (let i = 0; i < n; i++) {
|
|
1359
1854
|
const t = i / SAMPLE_RATE;
|
|
1360
1855
|
let s = 0;
|
|
1361
1856
|
for (const voice of voices) {
|
|
1362
1857
|
s += Math.sin(TAU * voice.freq * t + voice.phase) * (0.75 + 0.25 * Math.sin(TAU * voice.am * t));
|
|
1858
|
+
if (opts.bright > 0) s += opts.bright * Math.sin(TAU * voice.freq * 2 * t + voice.phase);
|
|
1859
|
+
}
|
|
1860
|
+
out[i] = s / voices.length * opts.gain;
|
|
1861
|
+
}
|
|
1862
|
+
return out;
|
|
1863
|
+
}
|
|
1864
|
+
function synthAmbientPad(duration, seed = 0) {
|
|
1865
|
+
return pad([110, 165, 220], duration, seed, { amBase: 0.05, bright: 0, gain: 0.7 });
|
|
1866
|
+
}
|
|
1867
|
+
function synthLofi(duration, seed = 0) {
|
|
1868
|
+
return pad([130.81, 164.81, 196, 246.94], duration, seed, { amBase: 0.04, bright: 0.04, gain: 0.62 });
|
|
1869
|
+
}
|
|
1870
|
+
function synthPulse(duration, _seed = 0) {
|
|
1871
|
+
const { out, n } = buffer(duration);
|
|
1872
|
+
const beat2 = 2.2;
|
|
1873
|
+
for (let i = 0; i < n; i++) {
|
|
1874
|
+
const t = i / SAMPLE_RATE;
|
|
1875
|
+
const ph = t * beat2 % 1;
|
|
1876
|
+
const gate = Math.exp(-ph * 5) * 0.9 + 0.1;
|
|
1877
|
+
const s = Math.sin(TAU * 82 * t) + 0.6 * Math.sin(TAU * 123 * t) + 0.3 * Math.sin(TAU * 246 * t);
|
|
1878
|
+
out[i] = s / 1.9 * gate * 0.6;
|
|
1879
|
+
}
|
|
1880
|
+
return out;
|
|
1881
|
+
}
|
|
1882
|
+
function synthTension(duration, seed = 0) {
|
|
1883
|
+
const { out, n } = buffer(duration);
|
|
1884
|
+
const base = [98, 104, 110];
|
|
1885
|
+
for (let i = 0; i < n; i++) {
|
|
1886
|
+
const t = i / SAMPLE_RATE;
|
|
1887
|
+
const drift = 1 + 0.03 * (t / Math.max(1e-3, duration));
|
|
1888
|
+
let s = 0;
|
|
1889
|
+
for (let v = 0; v < base.length; v++) {
|
|
1890
|
+
const f = base[v] * drift * (1 + (hash01(v, seed) - 0.5) * 6e-3);
|
|
1891
|
+
s += Math.sin(TAU * f * t + hash01(v, seed + 1) * TAU);
|
|
1363
1892
|
}
|
|
1364
|
-
|
|
1893
|
+
const swell = 0.6 + 0.4 * Math.sin(TAU * 0.08 * t);
|
|
1894
|
+
out[i] = s / base.length * swell * 0.6;
|
|
1365
1895
|
}
|
|
1366
1896
|
return out;
|
|
1367
1897
|
}
|
|
1898
|
+
function synthUplift(duration, seed = 0) {
|
|
1899
|
+
return pad([196, 246.94, 293.66, 392], duration, seed, { amBase: 0.07, bright: 0.1, gain: 0.6 });
|
|
1900
|
+
}
|
|
1901
|
+
var BGM_RECIPES = {
|
|
1902
|
+
"ambient-pad": synthAmbientPad,
|
|
1903
|
+
lofi: synthLofi,
|
|
1904
|
+
pulse: synthPulse,
|
|
1905
|
+
tension: synthTension,
|
|
1906
|
+
uplift: synthUplift
|
|
1907
|
+
};
|
|
1908
|
+
function synthBgm(name, duration, seed = 0) {
|
|
1909
|
+
return BGM_RECIPES[name](duration, seed);
|
|
1910
|
+
}
|
|
1368
1911
|
|
|
1369
1912
|
// ../render-cli/src/audio/sfx.ts
|
|
1370
1913
|
var ROOT = true ? resolve(dirname(fileURLToPath(import.meta.url)), "..") : resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "..");
|
|
@@ -1414,7 +1957,7 @@ async function resolveBgmFile(source, duration, sceneDir) {
|
|
|
1414
1957
|
}
|
|
1415
1958
|
throw new Error(`bgm file "${p}" not found`);
|
|
1416
1959
|
}
|
|
1417
|
-
return writeCached(
|
|
1960
|
+
return writeCached(`${source.name}-${duration.toFixed(2)}`, () => synthBgm(source.name, duration));
|
|
1418
1961
|
}
|
|
1419
1962
|
|
|
1420
1963
|
// ../render-cli/src/audio/clip.ts
|