reframe-video 0.6.27 → 0.6.29
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/assets/sfx/LICENSE.md +4 -2
- package/dist/bin.js +205 -5
- package/dist/cli.js +205 -5
- package/dist/compile-api.js +13 -1
- package/dist/compile.js +13 -1
- package/dist/diff.js +13 -1
- package/dist/frame.js +13 -1
- package/dist/index.js +28 -2
- package/dist/labels.js +13 -1
- package/dist/types/ir.d.ts +5 -4
- package/guides/edsl-guide.md +13 -4
- package/package.json +1 -1
package/assets/sfx/LICENSE.md
CHANGED
|
@@ -14,5 +14,7 @@ Verified against each asset page's license field on 2026-06-11.
|
|
|
14
14
|
| bgm-song21.mp3 | [Mysterious Ambience (song21)](https://opengameart.org/content/mysterious-ambience-song21) | cynicmusic (pixelsphere.org) | multi-licensed; used under its CC0 option |
|
|
15
15
|
|
|
16
16
|
CC0 requires no attribution; this file records provenance anyway.
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
These files are loaded only by an explicit `file:` cue (e.g.
|
|
18
|
+
`{ sfx: undefined, file: "whoosh.wav" }`). A bare `sfx:` name always uses the
|
|
19
|
+
procedural synthesizer (so its pitch/auto-variation applies) — it is no longer
|
|
20
|
+
auto-overridden by a same-named `.wav` here.
|
package/dist/bin.js
CHANGED
|
@@ -17,6 +17,7 @@ var init_ir = __esm({
|
|
|
17
17
|
SFX_NAMES = [
|
|
18
18
|
"whoosh",
|
|
19
19
|
"swish",
|
|
20
|
+
"swoosh",
|
|
20
21
|
"rise",
|
|
21
22
|
"riser",
|
|
22
23
|
"warp",
|
|
@@ -28,6 +29,7 @@ var init_ir = __esm({
|
|
|
28
29
|
"thud",
|
|
29
30
|
"boom",
|
|
30
31
|
"knock",
|
|
32
|
+
"sub",
|
|
31
33
|
"chime",
|
|
32
34
|
"ding",
|
|
33
35
|
"coin",
|
|
@@ -35,7 +37,17 @@ var init_ir = __esm({
|
|
|
35
37
|
"shimmer",
|
|
36
38
|
"success",
|
|
37
39
|
"zap",
|
|
38
|
-
"error"
|
|
40
|
+
"error",
|
|
41
|
+
"glitch",
|
|
42
|
+
"static",
|
|
43
|
+
"scan",
|
|
44
|
+
"powerup",
|
|
45
|
+
"powerdown",
|
|
46
|
+
"snare",
|
|
47
|
+
"hat",
|
|
48
|
+
"bubble",
|
|
49
|
+
"notify",
|
|
50
|
+
"camera"
|
|
39
51
|
];
|
|
40
52
|
BGM_SYNTHS = ["ambient-pad", "lofi", "pulse", "tension", "uplift"];
|
|
41
53
|
DEFAULT_TO_DURATION = 0.5;
|
|
@@ -1473,6 +1485,7 @@ var init_audio = __esm({
|
|
|
1473
1485
|
// transition
|
|
1474
1486
|
whoosh: 0.35,
|
|
1475
1487
|
swish: 0.32,
|
|
1488
|
+
swoosh: 0.35,
|
|
1476
1489
|
rise: 0.5,
|
|
1477
1490
|
riser: 0.85,
|
|
1478
1491
|
warp: 0.5,
|
|
@@ -1486,6 +1499,7 @@ var init_audio = __esm({
|
|
|
1486
1499
|
thud: 0.25,
|
|
1487
1500
|
boom: 0.6,
|
|
1488
1501
|
knock: 0.14,
|
|
1502
|
+
sub: 0.7,
|
|
1489
1503
|
// positive
|
|
1490
1504
|
chime: 0.7,
|
|
1491
1505
|
ding: 0.5,
|
|
@@ -1495,7 +1509,19 @@ var init_audio = __esm({
|
|
|
1495
1509
|
success: 0.6,
|
|
1496
1510
|
// alert
|
|
1497
1511
|
zap: 0.22,
|
|
1498
|
-
error: 0.4
|
|
1512
|
+
error: 0.4,
|
|
1513
|
+
// tech
|
|
1514
|
+
glitch: 0.3,
|
|
1515
|
+
static: 0.18,
|
|
1516
|
+
scan: 0.45,
|
|
1517
|
+
powerup: 0.4,
|
|
1518
|
+
powerdown: 0.5,
|
|
1519
|
+
// rhythm / foley
|
|
1520
|
+
snare: 0.18,
|
|
1521
|
+
hat: 0.05,
|
|
1522
|
+
bubble: 0.16,
|
|
1523
|
+
notify: 0.45,
|
|
1524
|
+
camera: 0.18
|
|
1499
1525
|
};
|
|
1500
1526
|
FILE_CUE_DURATION = 0.4;
|
|
1501
1527
|
}
|
|
@@ -2097,6 +2123,170 @@ function error(_seed, pitch) {
|
|
|
2097
2123
|
}
|
|
2098
2124
|
return out;
|
|
2099
2125
|
}
|
|
2126
|
+
function swoosh(seed, pitch) {
|
|
2127
|
+
const dur2 = 0.35;
|
|
2128
|
+
const { out, n } = buffer(dur2);
|
|
2129
|
+
let lp = 0, lp2 = 0;
|
|
2130
|
+
for (let i = 0; i < n; i++) {
|
|
2131
|
+
const t = i / SAMPLE_RATE, u = t / dur2;
|
|
2132
|
+
const center = 300 * pitch * Math.pow(7.3, u);
|
|
2133
|
+
const alpha = Math.min(1, TAU * center / SAMPLE_RATE);
|
|
2134
|
+
lp += alpha * (noise(i, seed) - lp);
|
|
2135
|
+
lp2 += alpha * 0.5 * (lp - lp2);
|
|
2136
|
+
const env = Math.sin(Math.PI * u) ** 0.9;
|
|
2137
|
+
out[i] = (lp - lp2) * env * 2.4;
|
|
2138
|
+
}
|
|
2139
|
+
return out;
|
|
2140
|
+
}
|
|
2141
|
+
function glitch(seed, pitch) {
|
|
2142
|
+
const dur2 = 0.3;
|
|
2143
|
+
const { out, n } = buffer(dur2);
|
|
2144
|
+
const cell = Math.round(SAMPLE_RATE * 0.012);
|
|
2145
|
+
let phase = 0;
|
|
2146
|
+
for (let i = 0; i < n; i++) {
|
|
2147
|
+
const t = i / SAMPLE_RATE, u = t / dur2;
|
|
2148
|
+
const c = Math.floor(i / cell);
|
|
2149
|
+
const on = hash01(c, seed) > 0.4 ? 1 : 0;
|
|
2150
|
+
const freq = 400 * pitch * (1 + Math.floor(hash01(c, seed + 1) * 6));
|
|
2151
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
2152
|
+
const crush = Math.round(square(phase) * 4) / 4;
|
|
2153
|
+
out[i] = (crush * 0.7 + noise(i, seed + c) * 0.3) * on * (1 - u * 0.3) * 0.55;
|
|
2154
|
+
}
|
|
2155
|
+
return out;
|
|
2156
|
+
}
|
|
2157
|
+
function staticHit(seed, pitch) {
|
|
2158
|
+
const dur2 = 0.18;
|
|
2159
|
+
const { out, n } = buffer(dur2);
|
|
2160
|
+
let lp = 0;
|
|
2161
|
+
const alpha = Math.min(0.8, TAU * 3e3 * pitch / SAMPLE_RATE);
|
|
2162
|
+
for (let i = 0; i < n; i++) {
|
|
2163
|
+
const t = i / SAMPLE_RATE, u = t / dur2;
|
|
2164
|
+
lp += alpha * (noise(i, seed) - lp);
|
|
2165
|
+
const env = Math.min(1, u * 30) * expDecay(t, dur2, 5);
|
|
2166
|
+
out[i] = (noise(i, seed) - lp) * env * 1.4;
|
|
2167
|
+
}
|
|
2168
|
+
return out;
|
|
2169
|
+
}
|
|
2170
|
+
function scan(seed, pitch) {
|
|
2171
|
+
const dur2 = 0.45;
|
|
2172
|
+
const { out, n } = buffer(dur2);
|
|
2173
|
+
let phase = 0;
|
|
2174
|
+
for (let i = 0; i < n; i++) {
|
|
2175
|
+
const t = i / SAMPLE_RATE, u = t / dur2;
|
|
2176
|
+
const step = Math.floor(u * 6) / 6;
|
|
2177
|
+
const freq = 500 * pitch * Math.pow(3, step);
|
|
2178
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
2179
|
+
const cell = u * 6 % 1;
|
|
2180
|
+
const env = Math.min(1, cell * 12) * Math.min(1, (1 - cell) * 4) * 0.7;
|
|
2181
|
+
out[i] = square(phase) * env * 0.5;
|
|
2182
|
+
}
|
|
2183
|
+
return out;
|
|
2184
|
+
}
|
|
2185
|
+
function powerup(seed, pitch) {
|
|
2186
|
+
const dur2 = 0.4;
|
|
2187
|
+
const { out, n } = buffer(dur2);
|
|
2188
|
+
const notes = [392, 523, 659, 784, 1046].map((f) => f * pitch);
|
|
2189
|
+
let phase = 0;
|
|
2190
|
+
for (let i = 0; i < n; i++) {
|
|
2191
|
+
const t = i / SAMPLE_RATE, u = t / dur2;
|
|
2192
|
+
const idx = Math.min(notes.length - 1, Math.floor(u * notes.length));
|
|
2193
|
+
phase += TAU * notes[idx] / SAMPLE_RATE;
|
|
2194
|
+
const local = u * notes.length - idx;
|
|
2195
|
+
const env = Math.min(1, local * 14) * Math.min(1, (1 - Math.min(1, local)) * 4 + 0.3);
|
|
2196
|
+
out[i] = (Math.sin(phase) + 0.25 * Math.sin(2 * phase)) * env * 0.45;
|
|
2197
|
+
}
|
|
2198
|
+
return out;
|
|
2199
|
+
}
|
|
2200
|
+
function powerdown(seed, pitch) {
|
|
2201
|
+
const dur2 = 0.5;
|
|
2202
|
+
const { out, n } = buffer(dur2);
|
|
2203
|
+
let phase = 0;
|
|
2204
|
+
for (let i = 0; i < n; i++) {
|
|
2205
|
+
const t = i / SAMPLE_RATE, u = t / dur2;
|
|
2206
|
+
const freq = 700 * pitch * Math.pow(0.18, u);
|
|
2207
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
2208
|
+
const env = (1 - u) ** 0.8;
|
|
2209
|
+
out[i] = (square(phase) * 0.7 + Math.sin(phase) * 0.3) * env * 0.5;
|
|
2210
|
+
}
|
|
2211
|
+
return out;
|
|
2212
|
+
}
|
|
2213
|
+
function sub(seed, pitch) {
|
|
2214
|
+
const dur2 = 0.7;
|
|
2215
|
+
const { out, n } = buffer(dur2);
|
|
2216
|
+
let phase = 0;
|
|
2217
|
+
for (let i = 0; i < n; i++) {
|
|
2218
|
+
const t = i / SAMPLE_RATE;
|
|
2219
|
+
const freq = 80 * pitch * Math.pow(0.45, t / 0.4);
|
|
2220
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
2221
|
+
const click2 = t < 4e-3 ? noise(i, seed) * 0.4 : 0;
|
|
2222
|
+
out[i] = (Math.sin(phase) + click2) * expDecay(t, dur2, 3) * 0.95;
|
|
2223
|
+
}
|
|
2224
|
+
return out;
|
|
2225
|
+
}
|
|
2226
|
+
function snare(seed, pitch) {
|
|
2227
|
+
const dur2 = 0.18;
|
|
2228
|
+
const { out, n } = buffer(dur2);
|
|
2229
|
+
let phase = 0;
|
|
2230
|
+
for (let i = 0; i < n; i++) {
|
|
2231
|
+
const t = i / SAMPLE_RATE;
|
|
2232
|
+
phase += TAU * 180 * pitch / SAMPLE_RATE;
|
|
2233
|
+
const body = Math.sin(phase) * 0.5 * expDecay(t, dur2, 16);
|
|
2234
|
+
const rattle = noise(i, seed) * expDecay(t, dur2, 7);
|
|
2235
|
+
out[i] = (body + rattle * 0.8) * 0.7;
|
|
2236
|
+
}
|
|
2237
|
+
return out;
|
|
2238
|
+
}
|
|
2239
|
+
function hat(seed, pitch) {
|
|
2240
|
+
const dur2 = 0.05;
|
|
2241
|
+
const { out, n } = buffer(dur2);
|
|
2242
|
+
let lp = 0;
|
|
2243
|
+
const alpha = Math.min(0.85, TAU * 2500 * pitch / SAMPLE_RATE);
|
|
2244
|
+
for (let i = 0; i < n; i++) {
|
|
2245
|
+
const t = i / SAMPLE_RATE;
|
|
2246
|
+
lp += alpha * (noise(i, seed) - lp);
|
|
2247
|
+
out[i] = (noise(i, seed) - lp) * expDecay(t, dur2, 14) * 0.9;
|
|
2248
|
+
}
|
|
2249
|
+
return out;
|
|
2250
|
+
}
|
|
2251
|
+
function bubble(seed, pitch) {
|
|
2252
|
+
const dur2 = 0.16;
|
|
2253
|
+
const { out, n } = buffer(dur2);
|
|
2254
|
+
let phase = 0;
|
|
2255
|
+
for (let i = 0; i < n; i++) {
|
|
2256
|
+
const t = i / SAMPLE_RATE, u = t / dur2;
|
|
2257
|
+
const freq = 400 * pitch * Math.pow(3, u);
|
|
2258
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
2259
|
+
const env = Math.sin(Math.PI * u) ** 1.1;
|
|
2260
|
+
out[i] = Math.sin(phase) * env * 0.6;
|
|
2261
|
+
}
|
|
2262
|
+
return out;
|
|
2263
|
+
}
|
|
2264
|
+
function notify(seed, pitch) {
|
|
2265
|
+
const dur2 = 0.45;
|
|
2266
|
+
const { out, n } = buffer(dur2);
|
|
2267
|
+
const f0 = 880 * pitch;
|
|
2268
|
+
for (let i = 0; i < n; i++) {
|
|
2269
|
+
const t = i / SAMPLE_RATE;
|
|
2270
|
+
const a = Math.sin(TAU * f0 * t) * expDecay(t, dur2, 5);
|
|
2271
|
+
const b = t > 0.09 ? Math.sin(TAU * f0 * 1.5 * t) * expDecay(t - 0.09, dur2, 4.5) : 0;
|
|
2272
|
+
out[i] = (a * 0.55 + b * 0.6) * 0.55;
|
|
2273
|
+
}
|
|
2274
|
+
return out;
|
|
2275
|
+
}
|
|
2276
|
+
function camera(seed, pitch) {
|
|
2277
|
+
const dur2 = 0.18;
|
|
2278
|
+
const { out, n } = buffer(dur2);
|
|
2279
|
+
let lp = 0;
|
|
2280
|
+
for (let i = 0; i < n; i++) {
|
|
2281
|
+
const t = i / SAMPLE_RATE;
|
|
2282
|
+
lp += 0.45 * (noise(i, seed) - lp);
|
|
2283
|
+
const k1 = t < 0.02 ? expDecay(t, 0.02, 6) : 0;
|
|
2284
|
+
const k2 = t > 0.08 && t < 0.12 ? expDecay(t - 0.08, 0.04, 6) : 0;
|
|
2285
|
+
const sine = Math.sin(TAU * 2200 * pitch * t);
|
|
2286
|
+
out[i] = (lp * 0.7 + sine * 0.3) * (k1 + k2) * 1.3;
|
|
2287
|
+
}
|
|
2288
|
+
return out;
|
|
2289
|
+
}
|
|
2100
2290
|
function synthSfx(name, params = {}) {
|
|
2101
2291
|
const seed = params.seed ?? 0;
|
|
2102
2292
|
const pitch = (params.pitch ?? 1) * seedPitch(seed);
|
|
@@ -2183,6 +2373,7 @@ var init_synth = __esm({
|
|
|
2183
2373
|
RECIPES = {
|
|
2184
2374
|
whoosh,
|
|
2185
2375
|
swish,
|
|
2376
|
+
swoosh,
|
|
2186
2377
|
rise,
|
|
2187
2378
|
riser,
|
|
2188
2379
|
warp,
|
|
@@ -2194,6 +2385,7 @@ var init_synth = __esm({
|
|
|
2194
2385
|
thud,
|
|
2195
2386
|
boom,
|
|
2196
2387
|
knock,
|
|
2388
|
+
sub,
|
|
2197
2389
|
chime,
|
|
2198
2390
|
ding,
|
|
2199
2391
|
coin,
|
|
@@ -2201,7 +2393,17 @@ var init_synth = __esm({
|
|
|
2201
2393
|
shimmer,
|
|
2202
2394
|
success,
|
|
2203
2395
|
zap,
|
|
2204
|
-
error
|
|
2396
|
+
error,
|
|
2397
|
+
glitch,
|
|
2398
|
+
static: staticHit,
|
|
2399
|
+
scan,
|
|
2400
|
+
powerup,
|
|
2401
|
+
powerdown,
|
|
2402
|
+
snare,
|
|
2403
|
+
hat,
|
|
2404
|
+
bubble,
|
|
2405
|
+
notify,
|
|
2406
|
+
camera
|
|
2205
2407
|
};
|
|
2206
2408
|
BGM_RECIPES = {
|
|
2207
2409
|
"ambient-pad": synthAmbientPad,
|
|
@@ -2250,8 +2452,6 @@ async function resolveCueFile(cue, sceneDir) {
|
|
|
2250
2452
|
`audio cue file "${p}" not found (tried absolute, scene-relative, assets/sfx/)`
|
|
2251
2453
|
);
|
|
2252
2454
|
}
|
|
2253
|
-
const vendored = join(VENDORED, `${cue.source.name}.wav`);
|
|
2254
|
-
if (existsSync2(vendored)) return vendored;
|
|
2255
2455
|
const { name, params } = cue.source;
|
|
2256
2456
|
return writeCached(`${name}-${fnv1a(JSON.stringify(params))}`, () => synthSfx(name, params));
|
|
2257
2457
|
}
|
package/dist/cli.js
CHANGED
|
@@ -9,6 +9,7 @@ import { basename, dirname as dirname7, join as join9, resolve as resolve6 } fro
|
|
|
9
9
|
var SFX_NAMES = [
|
|
10
10
|
"whoosh",
|
|
11
11
|
"swish",
|
|
12
|
+
"swoosh",
|
|
12
13
|
"rise",
|
|
13
14
|
"riser",
|
|
14
15
|
"warp",
|
|
@@ -20,6 +21,7 @@ var SFX_NAMES = [
|
|
|
20
21
|
"thud",
|
|
21
22
|
"boom",
|
|
22
23
|
"knock",
|
|
24
|
+
"sub",
|
|
23
25
|
"chime",
|
|
24
26
|
"ding",
|
|
25
27
|
"coin",
|
|
@@ -27,7 +29,17 @@ var SFX_NAMES = [
|
|
|
27
29
|
"shimmer",
|
|
28
30
|
"success",
|
|
29
31
|
"zap",
|
|
30
|
-
"error"
|
|
32
|
+
"error",
|
|
33
|
+
"glitch",
|
|
34
|
+
"static",
|
|
35
|
+
"scan",
|
|
36
|
+
"powerup",
|
|
37
|
+
"powerdown",
|
|
38
|
+
"snare",
|
|
39
|
+
"hat",
|
|
40
|
+
"bubble",
|
|
41
|
+
"notify",
|
|
42
|
+
"camera"
|
|
31
43
|
];
|
|
32
44
|
var BGM_SYNTHS = ["ambient-pad", "lofi", "pulse", "tension", "uplift"];
|
|
33
45
|
var DEFAULT_CROSSFADE = 0.5;
|
|
@@ -1021,6 +1033,7 @@ var SFX_DURATION = {
|
|
|
1021
1033
|
// transition
|
|
1022
1034
|
whoosh: 0.35,
|
|
1023
1035
|
swish: 0.32,
|
|
1036
|
+
swoosh: 0.35,
|
|
1024
1037
|
rise: 0.5,
|
|
1025
1038
|
riser: 0.85,
|
|
1026
1039
|
warp: 0.5,
|
|
@@ -1034,6 +1047,7 @@ var SFX_DURATION = {
|
|
|
1034
1047
|
thud: 0.25,
|
|
1035
1048
|
boom: 0.6,
|
|
1036
1049
|
knock: 0.14,
|
|
1050
|
+
sub: 0.7,
|
|
1037
1051
|
// positive
|
|
1038
1052
|
chime: 0.7,
|
|
1039
1053
|
ding: 0.5,
|
|
@@ -1043,7 +1057,19 @@ var SFX_DURATION = {
|
|
|
1043
1057
|
success: 0.6,
|
|
1044
1058
|
// alert
|
|
1045
1059
|
zap: 0.22,
|
|
1046
|
-
error: 0.4
|
|
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
|
|
1047
1073
|
};
|
|
1048
1074
|
var FILE_CUE_DURATION = 0.4;
|
|
1049
1075
|
function collectClipAudio(ir, duration, warnings) {
|
|
@@ -1603,9 +1629,174 @@ function error(_seed, pitch) {
|
|
|
1603
1629
|
}
|
|
1604
1630
|
return out;
|
|
1605
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);
|
|
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;
|
|
1723
|
+
for (let i = 0; i < n; i++) {
|
|
1724
|
+
const t = i / SAMPLE_RATE;
|
|
1725
|
+
const freq = 80 * pitch * Math.pow(0.45, t / 0.4);
|
|
1726
|
+
phase += TAU * freq / SAMPLE_RATE;
|
|
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;
|
|
1793
|
+
}
|
|
1794
|
+
return out;
|
|
1795
|
+
}
|
|
1606
1796
|
var RECIPES = {
|
|
1607
1797
|
whoosh,
|
|
1608
1798
|
swish,
|
|
1799
|
+
swoosh,
|
|
1609
1800
|
rise,
|
|
1610
1801
|
riser,
|
|
1611
1802
|
warp,
|
|
@@ -1617,6 +1808,7 @@ var RECIPES = {
|
|
|
1617
1808
|
thud,
|
|
1618
1809
|
boom,
|
|
1619
1810
|
knock,
|
|
1811
|
+
sub,
|
|
1620
1812
|
chime,
|
|
1621
1813
|
ding,
|
|
1622
1814
|
coin,
|
|
@@ -1624,7 +1816,17 @@ var RECIPES = {
|
|
|
1624
1816
|
shimmer,
|
|
1625
1817
|
success,
|
|
1626
1818
|
zap,
|
|
1627
|
-
error
|
|
1819
|
+
error,
|
|
1820
|
+
glitch,
|
|
1821
|
+
static: staticHit,
|
|
1822
|
+
scan,
|
|
1823
|
+
powerup,
|
|
1824
|
+
powerdown,
|
|
1825
|
+
snare,
|
|
1826
|
+
hat,
|
|
1827
|
+
bubble,
|
|
1828
|
+
notify,
|
|
1829
|
+
camera
|
|
1628
1830
|
};
|
|
1629
1831
|
function synthSfx(name, params = {}) {
|
|
1630
1832
|
const seed = params.seed ?? 0;
|
|
@@ -1742,8 +1944,6 @@ async function resolveCueFile(cue, sceneDir) {
|
|
|
1742
1944
|
`audio cue file "${p}" not found (tried absolute, scene-relative, assets/sfx/)`
|
|
1743
1945
|
);
|
|
1744
1946
|
}
|
|
1745
|
-
const vendored = join(VENDORED, `${cue.source.name}.wav`);
|
|
1746
|
-
if (existsSync(vendored)) return vendored;
|
|
1747
1947
|
const { name, params } = cue.source;
|
|
1748
1948
|
return writeCached(`${name}-${fnv1a(JSON.stringify(params))}`, () => synthSfx(name, params));
|
|
1749
1949
|
}
|
package/dist/compile-api.js
CHANGED
|
@@ -8,6 +8,7 @@ import { fileURLToPath } from "node:url";
|
|
|
8
8
|
var SFX_NAMES = [
|
|
9
9
|
"whoosh",
|
|
10
10
|
"swish",
|
|
11
|
+
"swoosh",
|
|
11
12
|
"rise",
|
|
12
13
|
"riser",
|
|
13
14
|
"warp",
|
|
@@ -19,6 +20,7 @@ var SFX_NAMES = [
|
|
|
19
20
|
"thud",
|
|
20
21
|
"boom",
|
|
21
22
|
"knock",
|
|
23
|
+
"sub",
|
|
22
24
|
"chime",
|
|
23
25
|
"ding",
|
|
24
26
|
"coin",
|
|
@@ -26,7 +28,17 @@ var SFX_NAMES = [
|
|
|
26
28
|
"shimmer",
|
|
27
29
|
"success",
|
|
28
30
|
"zap",
|
|
29
|
-
"error"
|
|
31
|
+
"error",
|
|
32
|
+
"glitch",
|
|
33
|
+
"static",
|
|
34
|
+
"scan",
|
|
35
|
+
"powerup",
|
|
36
|
+
"powerdown",
|
|
37
|
+
"snare",
|
|
38
|
+
"hat",
|
|
39
|
+
"bubble",
|
|
40
|
+
"notify",
|
|
41
|
+
"camera"
|
|
30
42
|
];
|
|
31
43
|
var BGM_SYNTHS = ["ambient-pad", "lofi", "pulse", "tension", "uplift"];
|
|
32
44
|
|
package/dist/compile.js
CHANGED
|
@@ -13,6 +13,7 @@ import { fileURLToPath } from "node:url";
|
|
|
13
13
|
var SFX_NAMES = [
|
|
14
14
|
"whoosh",
|
|
15
15
|
"swish",
|
|
16
|
+
"swoosh",
|
|
16
17
|
"rise",
|
|
17
18
|
"riser",
|
|
18
19
|
"warp",
|
|
@@ -24,6 +25,7 @@ var SFX_NAMES = [
|
|
|
24
25
|
"thud",
|
|
25
26
|
"boom",
|
|
26
27
|
"knock",
|
|
28
|
+
"sub",
|
|
27
29
|
"chime",
|
|
28
30
|
"ding",
|
|
29
31
|
"coin",
|
|
@@ -31,7 +33,17 @@ var SFX_NAMES = [
|
|
|
31
33
|
"shimmer",
|
|
32
34
|
"success",
|
|
33
35
|
"zap",
|
|
34
|
-
"error"
|
|
36
|
+
"error",
|
|
37
|
+
"glitch",
|
|
38
|
+
"static",
|
|
39
|
+
"scan",
|
|
40
|
+
"powerup",
|
|
41
|
+
"powerdown",
|
|
42
|
+
"snare",
|
|
43
|
+
"hat",
|
|
44
|
+
"bubble",
|
|
45
|
+
"notify",
|
|
46
|
+
"camera"
|
|
35
47
|
];
|
|
36
48
|
var BGM_SYNTHS = ["ambient-pad", "lofi", "pulse", "tension", "uplift"];
|
|
37
49
|
|
package/dist/diff.js
CHANGED
|
@@ -16,6 +16,7 @@ import { fileURLToPath } from "node:url";
|
|
|
16
16
|
var SFX_NAMES = [
|
|
17
17
|
"whoosh",
|
|
18
18
|
"swish",
|
|
19
|
+
"swoosh",
|
|
19
20
|
"rise",
|
|
20
21
|
"riser",
|
|
21
22
|
"warp",
|
|
@@ -27,6 +28,7 @@ var SFX_NAMES = [
|
|
|
27
28
|
"thud",
|
|
28
29
|
"boom",
|
|
29
30
|
"knock",
|
|
31
|
+
"sub",
|
|
30
32
|
"chime",
|
|
31
33
|
"ding",
|
|
32
34
|
"coin",
|
|
@@ -34,7 +36,17 @@ var SFX_NAMES = [
|
|
|
34
36
|
"shimmer",
|
|
35
37
|
"success",
|
|
36
38
|
"zap",
|
|
37
|
-
"error"
|
|
39
|
+
"error",
|
|
40
|
+
"glitch",
|
|
41
|
+
"static",
|
|
42
|
+
"scan",
|
|
43
|
+
"powerup",
|
|
44
|
+
"powerdown",
|
|
45
|
+
"snare",
|
|
46
|
+
"hat",
|
|
47
|
+
"bubble",
|
|
48
|
+
"notify",
|
|
49
|
+
"camera"
|
|
38
50
|
];
|
|
39
51
|
var BGM_SYNTHS = ["ambient-pad", "lofi", "pulse", "tension", "uplift"];
|
|
40
52
|
var DEFAULT_TO_DURATION = 0.5;
|
package/dist/frame.js
CHANGED
|
@@ -43,6 +43,7 @@ import { extname, isAbsolute, resolve } from "node:path";
|
|
|
43
43
|
var SFX_NAMES = [
|
|
44
44
|
"whoosh",
|
|
45
45
|
"swish",
|
|
46
|
+
"swoosh",
|
|
46
47
|
"rise",
|
|
47
48
|
"riser",
|
|
48
49
|
"warp",
|
|
@@ -54,6 +55,7 @@ var SFX_NAMES = [
|
|
|
54
55
|
"thud",
|
|
55
56
|
"boom",
|
|
56
57
|
"knock",
|
|
58
|
+
"sub",
|
|
57
59
|
"chime",
|
|
58
60
|
"ding",
|
|
59
61
|
"coin",
|
|
@@ -61,7 +63,17 @@ var SFX_NAMES = [
|
|
|
61
63
|
"shimmer",
|
|
62
64
|
"success",
|
|
63
65
|
"zap",
|
|
64
|
-
"error"
|
|
66
|
+
"error",
|
|
67
|
+
"glitch",
|
|
68
|
+
"static",
|
|
69
|
+
"scan",
|
|
70
|
+
"powerup",
|
|
71
|
+
"powerdown",
|
|
72
|
+
"snare",
|
|
73
|
+
"hat",
|
|
74
|
+
"bubble",
|
|
75
|
+
"notify",
|
|
76
|
+
"camera"
|
|
65
77
|
];
|
|
66
78
|
var BGM_SYNTHS = ["ambient-pad", "lofi", "pulse", "tension", "uplift"];
|
|
67
79
|
var DEFAULT_TO_DURATION = 0.5;
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
var SFX_NAMES = [
|
|
3
3
|
"whoosh",
|
|
4
4
|
"swish",
|
|
5
|
+
"swoosh",
|
|
5
6
|
"rise",
|
|
6
7
|
"riser",
|
|
7
8
|
"warp",
|
|
@@ -13,6 +14,7 @@ var SFX_NAMES = [
|
|
|
13
14
|
"thud",
|
|
14
15
|
"boom",
|
|
15
16
|
"knock",
|
|
17
|
+
"sub",
|
|
16
18
|
"chime",
|
|
17
19
|
"ding",
|
|
18
20
|
"coin",
|
|
@@ -20,7 +22,17 @@ var SFX_NAMES = [
|
|
|
20
22
|
"shimmer",
|
|
21
23
|
"success",
|
|
22
24
|
"zap",
|
|
23
|
-
"error"
|
|
25
|
+
"error",
|
|
26
|
+
"glitch",
|
|
27
|
+
"static",
|
|
28
|
+
"scan",
|
|
29
|
+
"powerup",
|
|
30
|
+
"powerdown",
|
|
31
|
+
"snare",
|
|
32
|
+
"hat",
|
|
33
|
+
"bubble",
|
|
34
|
+
"notify",
|
|
35
|
+
"camera"
|
|
24
36
|
];
|
|
25
37
|
var BGM_SYNTHS = ["ambient-pad", "lofi", "pulse", "tension", "uplift"];
|
|
26
38
|
var DEFAULT_CROSSFADE = 0.5;
|
|
@@ -2919,6 +2931,7 @@ var SFX_DURATION = {
|
|
|
2919
2931
|
// transition
|
|
2920
2932
|
whoosh: 0.35,
|
|
2921
2933
|
swish: 0.32,
|
|
2934
|
+
swoosh: 0.35,
|
|
2922
2935
|
rise: 0.5,
|
|
2923
2936
|
riser: 0.85,
|
|
2924
2937
|
warp: 0.5,
|
|
@@ -2932,6 +2945,7 @@ var SFX_DURATION = {
|
|
|
2932
2945
|
thud: 0.25,
|
|
2933
2946
|
boom: 0.6,
|
|
2934
2947
|
knock: 0.14,
|
|
2948
|
+
sub: 0.7,
|
|
2935
2949
|
// positive
|
|
2936
2950
|
chime: 0.7,
|
|
2937
2951
|
ding: 0.5,
|
|
@@ -2941,7 +2955,19 @@ var SFX_DURATION = {
|
|
|
2941
2955
|
success: 0.6,
|
|
2942
2956
|
// alert
|
|
2943
2957
|
zap: 0.22,
|
|
2944
|
-
error: 0.4
|
|
2958
|
+
error: 0.4,
|
|
2959
|
+
// tech
|
|
2960
|
+
glitch: 0.3,
|
|
2961
|
+
static: 0.18,
|
|
2962
|
+
scan: 0.45,
|
|
2963
|
+
powerup: 0.4,
|
|
2964
|
+
powerdown: 0.5,
|
|
2965
|
+
// rhythm / foley
|
|
2966
|
+
snare: 0.18,
|
|
2967
|
+
hat: 0.05,
|
|
2968
|
+
bubble: 0.16,
|
|
2969
|
+
notify: 0.45,
|
|
2970
|
+
camera: 0.18
|
|
2945
2971
|
};
|
|
2946
2972
|
var FILE_CUE_DURATION = 0.4;
|
|
2947
2973
|
function collectClipAudio(ir, duration, warnings) {
|
package/dist/labels.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
var SFX_NAMES = [
|
|
5
5
|
"whoosh",
|
|
6
6
|
"swish",
|
|
7
|
+
"swoosh",
|
|
7
8
|
"rise",
|
|
8
9
|
"riser",
|
|
9
10
|
"warp",
|
|
@@ -15,6 +16,7 @@ var SFX_NAMES = [
|
|
|
15
16
|
"thud",
|
|
16
17
|
"boom",
|
|
17
18
|
"knock",
|
|
19
|
+
"sub",
|
|
18
20
|
"chime",
|
|
19
21
|
"ding",
|
|
20
22
|
"coin",
|
|
@@ -22,7 +24,17 @@ var SFX_NAMES = [
|
|
|
22
24
|
"shimmer",
|
|
23
25
|
"success",
|
|
24
26
|
"zap",
|
|
25
|
-
"error"
|
|
27
|
+
"error",
|
|
28
|
+
"glitch",
|
|
29
|
+
"static",
|
|
30
|
+
"scan",
|
|
31
|
+
"powerup",
|
|
32
|
+
"powerdown",
|
|
33
|
+
"snare",
|
|
34
|
+
"hat",
|
|
35
|
+
"bubble",
|
|
36
|
+
"notify",
|
|
37
|
+
"camera"
|
|
26
38
|
];
|
|
27
39
|
var BGM_SYNTHS = ["ambient-pad", "lofi", "pulse", "tension", "uplift"];
|
|
28
40
|
var DEFAULT_TO_DURATION = 0.5;
|
package/dist/types/ir.d.ts
CHANGED
|
@@ -415,13 +415,14 @@ export interface BehaviorIR {
|
|
|
415
415
|
/**
|
|
416
416
|
* The procedural sfx palette — the single source of truth (the type, validation,
|
|
417
417
|
* and the render-cli synth recipes all key off this). Grouped by use:
|
|
418
|
-
* transition: whoosh swish rise riser warp · ui: tick click blip pop select
|
|
419
|
-
* impact: thud boom knock · positive: chime ding coin sparkle shimmer success
|
|
420
|
-
* alert: zap error
|
|
418
|
+
* transition: whoosh swish swoosh rise riser warp · ui: tick click blip pop select
|
|
419
|
+
* impact: thud boom knock sub · positive: chime ding coin sparkle shimmer success
|
|
420
|
+
* alert: zap error · tech: glitch static scan powerup powerdown
|
|
421
|
+
* rhythm: snare hat · foley: bubble notify camera
|
|
421
422
|
* Every cue's pitch/texture varies with its `seed` (auto-seeded by cue order), so
|
|
422
423
|
* repeated cues sound different; `params.pitch` is an explicit multiplier.
|
|
423
424
|
*/
|
|
424
|
-
export declare const SFX_NAMES: readonly ["whoosh", "swish", "rise", "riser", "warp", "tick", "click", "blip", "pop", "select", "thud", "boom", "knock", "chime", "ding", "coin", "sparkle", "shimmer", "success", "zap", "error"];
|
|
425
|
+
export declare const SFX_NAMES: readonly ["whoosh", "swish", "swoosh", "rise", "riser", "warp", "tick", "click", "blip", "pop", "select", "thud", "boom", "knock", "sub", "chime", "ding", "coin", "sparkle", "shimmer", "success", "zap", "error", "glitch", "static", "scan", "powerup", "powerdown", "snare", "hat", "bubble", "notify", "camera"];
|
|
425
426
|
export type SfxName = (typeof SFX_NAMES)[number];
|
|
426
427
|
/** Synthesized background-music beds (license-free). */
|
|
427
428
|
export declare const BGM_SYNTHS: readonly ["ambient-pad", "lofi", "pulse", "tension", "uplift"];
|
package/guides/edsl-guide.md
CHANGED
|
@@ -562,11 +562,14 @@ audio: {
|
|
|
562
562
|
|
|
563
563
|
| group | names |
|
|
564
564
|
| --- | --- |
|
|
565
|
-
| transition | `whoosh` `swish` `rise` `riser` `warp` |
|
|
565
|
+
| transition | `whoosh` `swish` `swoosh` `rise` `riser` `warp` |
|
|
566
566
|
| ui | `tick` `click` `blip` `pop` `select` |
|
|
567
|
-
| impact | `thud` `boom` `knock` |
|
|
567
|
+
| impact | `thud` `boom` `knock` `sub` |
|
|
568
568
|
| positive | `chime` `ding` `coin` `sparkle` `shimmer` `success` |
|
|
569
569
|
| alert | `zap` `error` |
|
|
570
|
+
| tech | `glitch` `static` `scan` `powerup` `powerdown` |
|
|
571
|
+
| rhythm | `snare` `hat` |
|
|
572
|
+
| foley | `bubble` `notify` `camera` |
|
|
570
573
|
|
|
571
574
|
**Variation — repeats don't sound the same.** Each cue's `seed` shifts the sound's
|
|
572
575
|
PITCH (a musical step) and texture, and it **defaults to the cue's order**, so a run of
|
|
@@ -578,8 +581,14 @@ up). `params.gainDb` trims a single hit.
|
|
|
578
581
|
**bgm beds** (`bgm.synth`): `ambient-pad` `lofi` `pulse` `tension` `uplift` — or
|
|
579
582
|
`bgm.file` for your own. **Mixing**: any cue takes `fadeIn`/`fadeOut` (seconds) and `pan`
|
|
580
583
|
(-1 left … 0 centre … +1 right). A `video` clip's audio takes `fadeIn` and `pan` too
|
|
581
|
-
(clip fade-out isn't supported yet). The bed auto-ducks under cues (`bgm.duck`).
|
|
582
|
-
|
|
584
|
+
(clip fade-out isn't supported yet). The bed auto-ducks under cues (`bgm.duck`).
|
|
585
|
+
|
|
586
|
+
**Recorded samples** are a separate layer from the synth palette: use a `file:` cue to
|
|
587
|
+
play a CC0 file from `assets/sfx/` — keyboard typing (`keypress-*.wav`, also driven by
|
|
588
|
+
`textTypeCues`), `footstep_*`, and the Kenney UI pack (`click_*`/`confirmation_*`/
|
|
589
|
+
`select_*`/…). A bare `sfx:` name always synthesizes (so it pitch-varies); pass
|
|
590
|
+
`file: "whoosh.wav"` to play the recorded version instead. Audition the procedural set
|
|
591
|
+
with `examples/scenes/sfx-showcase.ts` and the samples with `sample-showcase.ts`.
|
|
583
592
|
|
|
584
593
|
## Rules
|
|
585
594
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reframe-video",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.29",
|
|
4
4
|
"description": "Declarative motion graphics that AI can write and humans can tweak — human edits survive AI regeneration. Deterministic mp4 renders from a plain-data scene format.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"motion-graphics",
|