reframe-video 0.6.32 → 0.6.34

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/cli.js CHANGED
@@ -425,6 +425,125 @@ var EASE_TABLE = {
425
425
  springStiff: springEase(210, 26, 0)
426
426
  };
427
427
  var EASE_NAMES = Object.keys(EASE_TABLE);
428
+ function resolveEase(ease) {
429
+ if (ease === void 0) return EASE_TABLE.linear;
430
+ if (typeof ease === "string") {
431
+ const fn = EASE_TABLE[ease];
432
+ if (!fn) throw new Error(`unknown ease "${ease}" \u2014 valid: ${Object.keys(EASE_TABLE).join(", ")}`);
433
+ return fn;
434
+ }
435
+ if ("spring" in ease) {
436
+ const { stiffness = 100, damping = 10, velocity = 0 } = ease.spring;
437
+ return springEase(stiffness, damping, velocity);
438
+ }
439
+ return cubicBezierEase(...ease.cubicBezier);
440
+ }
441
+ function cubicBezierEase(x1, y1, x2, y2) {
442
+ const bez = (a, b) => (t) => 3 * a * t * (1 - t) ** 2 + 3 * b * t * t * (1 - t) + t ** 3;
443
+ const bx = bez(x1, x2);
444
+ const by = bez(y1, y2);
445
+ const dbx = (t) => 3 * x1 * (1 - t) * (1 - 3 * t) + 3 * x2 * t * (2 - 3 * t) + 3 * t * t;
446
+ return (u) => {
447
+ if (u <= 0) return 0;
448
+ if (u >= 1) return 1;
449
+ let t = u;
450
+ for (let i = 0; i < 8; i++) {
451
+ const err = bx(t) - u;
452
+ if (Math.abs(err) < 1e-6) return by(t);
453
+ const d = dbx(t);
454
+ if (Math.abs(d) < 1e-6) break;
455
+ t -= err / d;
456
+ }
457
+ let lo = 0;
458
+ let hi = 1;
459
+ t = u;
460
+ while (hi - lo > 1e-6) {
461
+ if (bx(t) < u) lo = t;
462
+ else hi = t;
463
+ t = (lo + hi) / 2;
464
+ }
465
+ return by(t);
466
+ };
467
+ }
468
+ var HEX_COLOR = /^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
469
+ function isColor(v) {
470
+ return typeof v === "string" && HEX_COLOR.test(v);
471
+ }
472
+ function parseColor(hex) {
473
+ let h = hex.slice(1);
474
+ if (h.length <= 4) h = [...h].map((c) => c + c).join("");
475
+ const n = parseInt(h.padEnd(8, "f"), 16);
476
+ return [n >>> 24 & 255, n >>> 16 & 255, n >>> 8 & 255, n & 255];
477
+ }
478
+ function formatColor([r, g, b, a]) {
479
+ const hex = (v) => Math.round(Math.max(0, Math.min(255, v))).toString(16).padStart(2, "0");
480
+ return a >= 255 ? `#${hex(r)}${hex(g)}${hex(b)}` : `#${hex(r)}${hex(g)}${hex(b)}${hex(a)}`;
481
+ }
482
+ function lerpValue(from, to, u) {
483
+ if (typeof from === "number" && typeof to === "number") {
484
+ return from + (to - from) * u;
485
+ }
486
+ if (isColor(from) && isColor(to)) {
487
+ const a = parseColor(from);
488
+ const b = parseColor(to);
489
+ return formatColor([
490
+ a[0] + (b[0] - a[0]) * u,
491
+ a[1] + (b[1] - a[1]) * u,
492
+ a[2] + (b[2] - a[2]) * u,
493
+ a[3] + (b[3] - a[3]) * u
494
+ ]);
495
+ }
496
+ if (looksLikePath(from) && looksLikePath(to)) {
497
+ const a = tokenizePath(from);
498
+ const b = tokenizePath(to);
499
+ if (a && b && morphCompatible(a, b)) return morphPath(a, b, u);
500
+ return u < 0.5 ? from : to;
501
+ }
502
+ return to;
503
+ }
504
+ var PATH_BODY = /^[\sMmLlHhVvCcSsQqTtAaZz0-9.,eE+-]+$/;
505
+ function looksLikePath(v) {
506
+ return typeof v === "string" && /^\s*[Mm]/.test(v) && PATH_BODY.test(v);
507
+ }
508
+ var PATH_TOKEN = /([MmLlHhVvCcSsQqTtAaZz])|(-?(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?)/g;
509
+ function tokenizePath(d) {
510
+ const out = [];
511
+ let cur = null;
512
+ let m;
513
+ PATH_TOKEN.lastIndex = 0;
514
+ while (m = PATH_TOKEN.exec(d)) {
515
+ if (m[1]) out.push(cur = { cmd: m[1], nums: [] });
516
+ else if (m[2]) {
517
+ if (!cur) return null;
518
+ cur.nums.push(parseFloat(m[2]));
519
+ }
520
+ }
521
+ return out.length ? out : null;
522
+ }
523
+ function morphCompatible(a, b) {
524
+ if (a.length !== b.length) return false;
525
+ for (let i = 0; i < a.length; i++) {
526
+ const ca = a[i];
527
+ const cb = b[i];
528
+ if (ca.cmd !== cb.cmd || ca.nums.length !== cb.nums.length) return false;
529
+ if (ca.cmd === "A" || ca.cmd === "a") return false;
530
+ }
531
+ return true;
532
+ }
533
+ var fmtNum = (v) => {
534
+ const r = Number(v.toFixed(3));
535
+ return Object.is(r, -0) ? "0" : String(r);
536
+ };
537
+ function morphPath(a, b, u) {
538
+ let s = "";
539
+ for (let i = 0; i < a.length; i++) {
540
+ const an = a[i].nums;
541
+ const bn = b[i].nums;
542
+ s += (i ? " " : "") + a[i].cmd;
543
+ for (let j = 0; j < an.length; j++) s += " " + fmtNum(an[j] + (bn[j] - an[j]) * u);
544
+ }
545
+ return s;
546
+ }
428
547
 
429
548
  // ../core/src/validate.ts
430
549
  var EASE_SET = new Set(EASE_NAMES);
@@ -1025,6 +1144,258 @@ function formatComposeReport(report) {
1025
1144
  return lines.join("\n");
1026
1145
  }
1027
1146
 
1147
+ // ../core/src/behaviors.ts
1148
+ function sampleBehavior(b, t) {
1149
+ switch (b.name) {
1150
+ case "oscillate": {
1151
+ const { amplitude, frequency, phase = 0 } = b.params;
1152
+ return amplitude * Math.sin(2 * Math.PI * frequency * t + phase);
1153
+ }
1154
+ case "wiggle": {
1155
+ const { amplitude, frequency, seed } = b.params;
1156
+ return amplitude * valueNoise(t * frequency, seed);
1157
+ }
1158
+ }
1159
+ }
1160
+ function valueNoise(x, seed) {
1161
+ const i = Math.floor(x);
1162
+ const f = x - i;
1163
+ const u = f * f * (3 - 2 * f);
1164
+ const a = hash01(i, seed) * 2 - 1;
1165
+ const b = hash01(i + 1, seed) * 2 - 1;
1166
+ return a + (b - a) * u;
1167
+ }
1168
+ function hash01(n, seed) {
1169
+ let h = n * 374761393 + seed * 668265263 | 0;
1170
+ h = h ^ h >>> 13 | 0;
1171
+ h = Math.imul(h, 1274126177);
1172
+ h = (h ^ h >>> 16) >>> 0;
1173
+ return h / 4294967295;
1174
+ }
1175
+
1176
+ // ../core/src/evaluate.ts
1177
+ var IDENTITY = [1, 0, 0, 1, 0, 0];
1178
+ function multiply(m, n) {
1179
+ return [
1180
+ m[0] * n[0] + m[2] * n[1],
1181
+ m[1] * n[0] + m[3] * n[1],
1182
+ m[0] * n[2] + m[2] * n[3],
1183
+ m[1] * n[2] + m[3] * n[3],
1184
+ m[0] * n[4] + m[2] * n[5] + m[4],
1185
+ m[1] * n[4] + m[3] * n[5] + m[5]
1186
+ ];
1187
+ }
1188
+ var DEG = Math.PI / 180;
1189
+ function localMatrix(x, y, rotationDeg, scale, scaleX = 1, scaleY = 1, skewXDeg = 0, skewYDeg = 0) {
1190
+ const r = rotationDeg * Math.PI / 180;
1191
+ if (scaleX === 1 && scaleY === 1 && skewXDeg === 0 && skewYDeg === 0) {
1192
+ const cos = Math.cos(r) * scale;
1193
+ const sin = Math.sin(r) * scale;
1194
+ return [cos, sin, -sin, cos, x, y];
1195
+ }
1196
+ const c = Math.cos(r);
1197
+ const s = Math.sin(r);
1198
+ const tx = Math.tan(skewXDeg * Math.PI / 180);
1199
+ const ty = Math.tan(skewYDeg * Math.PI / 180);
1200
+ const R = [c, s, -s, c, 0, 0];
1201
+ const K = [1, ty, tx, 1, 0, 0];
1202
+ const S = [scale * scaleX, 0, 0, scale * scaleY, 0, 0];
1203
+ const m = multiply(R, multiply(K, S));
1204
+ return [m[0], m[1], m[2], m[3], x, y];
1205
+ }
1206
+ function behaviorEnvelope(b, t) {
1207
+ const from = b.from ?? Number.NEGATIVE_INFINITY;
1208
+ const until = b.until ?? Number.POSITIVE_INFINITY;
1209
+ if (t < from || t > until) return 0;
1210
+ const ramp = b.ramp ?? 0.2;
1211
+ let envelope = 1;
1212
+ if (Number.isFinite(from) && ramp > 0) envelope = Math.min(envelope, (t - from) / ramp);
1213
+ if (Number.isFinite(until) && ramp > 0) envelope = Math.min(envelope, (until - t) / ramp);
1214
+ return Math.max(0, Math.min(1, envelope));
1215
+ }
1216
+ function sampleProp(compiled, t, target, prop, fallback) {
1217
+ let value = compiled.initialValues.get(`${target}.${prop}`) ?? fallback;
1218
+ let segStart = Number.NEGATIVE_INFINITY;
1219
+ const segs = compiled.segments.get(`${target}.${prop}`);
1220
+ if (segs) {
1221
+ let active;
1222
+ for (const seg of segs) {
1223
+ if (seg.t0 <= t) active = seg;
1224
+ else break;
1225
+ }
1226
+ if (active) {
1227
+ segStart = active.t0;
1228
+ if (t >= active.t1) {
1229
+ value = active.to;
1230
+ } else {
1231
+ const u = resolveEase(active.ease)((t - active.t0) / (active.t1 - active.t0));
1232
+ value = lerpValue(active.from, active.to, u);
1233
+ }
1234
+ }
1235
+ }
1236
+ if (prop === "x" || prop === "y" || prop === "rotation") {
1237
+ const drivers = compiled.motionPaths.get(target);
1238
+ if (drivers) {
1239
+ let active;
1240
+ for (const d of drivers) {
1241
+ if (d.t0 <= t) active = d;
1242
+ else break;
1243
+ }
1244
+ if (active && active.t0 >= segStart && (prop !== "rotation" || active.autoRotate) && active.points.length > 0) {
1245
+ const span = active.t1 - active.t0;
1246
+ const u = span <= 0 ? 1 : resolveEase(active.ease)(Math.max(0, Math.min(1, (t - active.t0) / span)));
1247
+ if (prop === "x") value = pathPoint(active.points, active.closed, u, active.curviness)[0];
1248
+ else if (prop === "y") value = pathPoint(active.points, active.closed, u, active.curviness)[1];
1249
+ else value = pathTangentAngle(active.points, active.closed, u, active.curviness) + active.rotateOffset;
1250
+ }
1251
+ }
1252
+ }
1253
+ for (const b of compiled.ir.behaviors ?? []) {
1254
+ if (b.target === target && b.prop === prop && typeof value === "number") {
1255
+ const envelope = behaviorEnvelope(b, t);
1256
+ if (envelope > 0) value = value + envelope * sampleBehavior(b.behavior, t);
1257
+ }
1258
+ }
1259
+ return value;
1260
+ }
1261
+ function nodeParentMatrix(compiled, id, t) {
1262
+ const num2 = (target, prop, fallback) => {
1263
+ const v = sampleProp(compiled, t, target, prop, fallback);
1264
+ return typeof v === "number" ? v : fallback;
1265
+ };
1266
+ let result = null;
1267
+ const walk = (node, parent) => {
1268
+ if (node.id === id) {
1269
+ result = parent;
1270
+ return true;
1271
+ }
1272
+ if (node.type === "group") {
1273
+ const m = multiply(
1274
+ parent,
1275
+ localMatrix(
1276
+ num2(node.id, "x", node.props.x),
1277
+ num2(node.id, "y", node.props.y),
1278
+ num2(node.id, "rotation", node.props.rotation ?? 0),
1279
+ num2(node.id, "scale", node.props.scale ?? 1),
1280
+ num2(node.id, "scaleX", node.props.scaleX ?? 1),
1281
+ num2(node.id, "scaleY", node.props.scaleY ?? 1),
1282
+ num2(node.id, "skewX", node.props.skewX ?? 0),
1283
+ num2(node.id, "skewY", node.props.skewY ?? 0)
1284
+ )
1285
+ );
1286
+ for (const child of node.children) if (walk(child, m)) return true;
1287
+ }
1288
+ return false;
1289
+ };
1290
+ for (const node of compiled.ir.nodes) if (walk(node, IDENTITY)) break;
1291
+ return result;
1292
+ }
1293
+
1294
+ // ../core/src/autoFoley.ts
1295
+ var V_MIN = 360;
1296
+ var V_STOP = 60;
1297
+ var V_DECEL = 520;
1298
+ var V_MAX = 2600;
1299
+ var MIN_DUR = 0.1;
1300
+ var num = (c, t, id, prop, fb) => {
1301
+ const v = sampleProp(c, t, id, prop, fb);
1302
+ return typeof v === "number" ? v : fb;
1303
+ };
1304
+ function nodeSize(node) {
1305
+ const p = node.props;
1306
+ return Math.max(p.width ?? 0, p.height ?? 0, (p.radius ?? 0) * 2, p.fontSize ?? 0, 0);
1307
+ }
1308
+ var FAMILY = { whoosh: "move", swish: "move", thud: "hit", knock: "hit", pop: "pop" };
1309
+ var DEDUP_DT = 0.09;
1310
+ function autoFoley(compiled, opts = {}) {
1311
+ const master = opts.gain ?? 0.5;
1312
+ const sens = opts.sensitivity ?? 1;
1313
+ const wantWhoosh = opts.whoosh !== false;
1314
+ const wantImpact = opts.impact !== false;
1315
+ const wantPop = opts.pop !== false;
1316
+ const wantPan = opts.pan !== false;
1317
+ const vMin = V_MIN / sens, vStop = V_STOP, vDecel = V_DECEL / sens;
1318
+ const fps = compiled.ir.fps ?? 30;
1319
+ const N = Math.max(1, Math.ceil(compiled.duration * fps));
1320
+ const W = compiled.ir.size.width || 1920;
1321
+ const ids = opts.nodes ?? [...compiled.nodeById.keys()];
1322
+ const cands = [];
1323
+ const panOf = (x) => wantPan ? Math.max(-1, Math.min(1, x / W * 2 - 1)) : 0;
1324
+ const loud = (v) => Math.max(0.2, Math.min(1, (v - vMin) / (V_MAX - vMin)));
1325
+ for (const id of ids) {
1326
+ const node = compiled.nodeById.get(id);
1327
+ if (!node || node.type === "line") continue;
1328
+ const size = nodeSize(node);
1329
+ const xs = [], ys = [], ss = [], os = [];
1330
+ for (let i2 = 0; i2 <= N; i2++) {
1331
+ const t = i2 / fps;
1332
+ xs.push(num(compiled, t, id, "x", node.props.x ?? 0));
1333
+ ys.push(num(compiled, t, id, "y", node.props.y ?? 0));
1334
+ ss.push(num(compiled, t, id, "scale", node.props.scale ?? 1));
1335
+ os.push(num(compiled, t, id, "opacity", node.props.opacity ?? 1));
1336
+ }
1337
+ const speed = (i2) => i2 <= 0 ? 0 : Math.hypot(xs[i2] - xs[i2 - 1], ys[i2] - ys[i2 - 1]) * fps;
1338
+ const worldX = (frame) => {
1339
+ const m = nodeParentMatrix(compiled, id, frame / fps);
1340
+ return m ? m[0] * xs[frame] + m[2] * ys[frame] + m[4] : xs[frame];
1341
+ };
1342
+ let i = 1;
1343
+ while (i <= N) {
1344
+ if (speed(i) <= vMin) {
1345
+ i++;
1346
+ continue;
1347
+ }
1348
+ const a = i;
1349
+ let peak = i, peakV = speed(i);
1350
+ while (i <= N && speed(i) > vStop) {
1351
+ const s = speed(i);
1352
+ if (s > peakV) {
1353
+ peakV = s;
1354
+ peak = i;
1355
+ }
1356
+ i++;
1357
+ }
1358
+ const b = i - 1;
1359
+ const durS = (b - a + 1) / fps;
1360
+ const visible = os[peak] > 0.1;
1361
+ if (peakV > vMin && durS >= MIN_DUR && visible) {
1362
+ if (wantWhoosh) {
1363
+ const quickFlick = durS < 0.25;
1364
+ cands.push({ t: peak / fps, sfx: quickFlick ? "swish" : "whoosh", gain: master * loud(peakV), pan: panOf(worldX(peak)), rank: peakV });
1365
+ }
1366
+ const stopped = b >= N || speed(b + 1) < vStop && speed(Math.min(N, b + 2)) < vStop;
1367
+ const wxb = worldX(b);
1368
+ const landsOnScreen = wxb >= 0 && wxb <= W && os[b] > 0.1;
1369
+ if (wantImpact && peakV > vDecel && stopped && landsOnScreen && b < N) {
1370
+ cands.push({ t: (b + 1) / fps, sfx: size > 220 ? "thud" : "knock", gain: master * loud(peakV), pan: panOf(worldX(b)), rank: peakV * 1.1 });
1371
+ }
1372
+ }
1373
+ }
1374
+ if (wantPop && ss[0] < 0.25) {
1375
+ for (let k = 1; k <= N; k++) {
1376
+ if (ss[k - 1] < 0.5 && ss[k] >= 0.5 && os[k] > 0.05) {
1377
+ cands.push({ t: k / fps, sfx: "pop", gain: master * 0.7, pan: panOf(worldX(k)), rank: 600 });
1378
+ break;
1379
+ }
1380
+ }
1381
+ }
1382
+ }
1383
+ cands.sort((p, q) => q.rank - p.rank);
1384
+ const kept = [];
1385
+ for (const c of cands) {
1386
+ const fam = FAMILY[c.sfx] ?? c.sfx;
1387
+ if (kept.some((k) => (FAMILY[k.sfx] ?? k.sfx) === fam && Math.abs(k.t - c.t) < DEDUP_DT)) continue;
1388
+ kept.push(c);
1389
+ }
1390
+ const max = opts.maxCues ?? 32;
1391
+ return kept.slice(0, max).map((c) => ({
1392
+ at: Number(c.t.toFixed(3)),
1393
+ sfx: c.sfx,
1394
+ gain: Number(c.gain.toFixed(3)),
1395
+ ...c.pan !== 0 ? { pan: Number(c.pan.toFixed(3)) } : {}
1396
+ }));
1397
+ }
1398
+
1028
1399
  // ../core/src/presets.ts
1029
1400
  var SET = 1 / 120;
1030
1401
 
@@ -1097,11 +1468,13 @@ function resolveAudioPlan(compiled) {
1097
1468
  const warnings = [];
1098
1469
  const duration = compiled.duration;
1099
1470
  const clipAudio = collectClipAudio(compiled.ir, duration, warnings);
1100
- if (!audio || !audio.bgm && (audio.cues ?? []).length === 0) {
1471
+ const autoCues = audio?.autoFoley ? autoFoley(compiled, audio.autoFoley === true ? {} : audio.autoFoley) : [];
1472
+ const manualCues = [...audio?.cues ?? [], ...autoCues];
1473
+ if (!audio || !audio.bgm && manualCues.length === 0) {
1101
1474
  return clipAudio.length === 0 ? null : { duration, bgm: null, cues: [], duckWindows: [], clipAudio, warnings };
1102
1475
  }
1103
1476
  const cues = [];
1104
- for (const [index, cue] of (audio.cues ?? []).entries()) {
1477
+ for (const [index, cue] of manualCues.entries()) {
1105
1478
  let anchor;
1106
1479
  if (typeof cue.at === "number") {
1107
1480
  anchor = cue.at;
@@ -1232,9 +1605,6 @@ function resolveCompositionAudioPlan(comp) {
1232
1605
  };
1233
1606
  }
1234
1607
 
1235
- // ../core/src/evaluate.ts
1236
- var DEG = Math.PI / 180;
1237
-
1238
1608
  // ../core/src/assets.ts
1239
1609
  function collectSrcs(ir, type) {
1240
1610
  const srcs = /* @__PURE__ */ new Set();
@@ -1311,14 +1681,14 @@ function encodeWavMono16(samples, sampleRate = SAMPLE_RATE) {
1311
1681
  }
1312
1682
 
1313
1683
  // ../render-cli/src/audio/synth.ts
1314
- function hash01(n, seed) {
1684
+ function hash012(n, seed) {
1315
1685
  let h = n * 374761393 + seed * 668265263 | 0;
1316
1686
  h = h ^ h >>> 13 | 0;
1317
1687
  h = Math.imul(h, 1274126177);
1318
1688
  h = (h ^ h >>> 16) >>> 0;
1319
1689
  return h / 4294967295;
1320
1690
  }
1321
- var noise = (n, seed) => hash01(n, seed) * 2 - 1;
1691
+ var noise = (n, seed) => hash012(n, seed) * 2 - 1;
1322
1692
  var TAU = Math.PI * 2;
1323
1693
  var expDecay = (t, dur, k = 5) => Math.exp(-k * t / dur);
1324
1694
  var square = (ph) => (Math.sin(ph) + 0.33 * Math.sin(3 * ph) + 0.2 * Math.sin(5 * ph)) / 1.4;
@@ -1562,7 +1932,7 @@ function sparkle(seed, pitch) {
1562
1932
  const on = u * steps.length - g;
1563
1933
  if (on > 0 && on < 3) {
1564
1934
  const ge = Math.exp(-on * 1.8);
1565
- s += Math.sin(TAU * base * steps[g] * t + hash01(g, seed) * TAU) * ge;
1935
+ s += Math.sin(TAU * base * steps[g] * t + hash012(g, seed) * TAU) * ge;
1566
1936
  }
1567
1937
  }
1568
1938
  out[i] = s / 2.4 * Math.sin(Math.PI * u) ** 0.5 * 0.5;
@@ -1589,9 +1959,9 @@ function shimmer(seed, pitch) {
1589
1959
  const dur = 0.9;
1590
1960
  const { out, n } = buffer(dur);
1591
1961
  const partials = Array.from({ length: 5 }, (_, p) => ({
1592
- freq: (2e3 + hash01(p, seed + 7) * 2e3) * pitch,
1593
- am: 0.5 + hash01(p, seed + 8) * 1.5,
1594
- phase: hash01(p, seed + 9) * TAU
1962
+ freq: (2e3 + hash012(p, seed + 7) * 2e3) * pitch,
1963
+ am: 0.5 + hash012(p, seed + 8) * 1.5,
1964
+ phase: hash012(p, seed + 9) * TAU
1595
1965
  }));
1596
1966
  for (let i = 0; i < n; i++) {
1597
1967
  const t = i / SAMPLE_RATE, u = t / dur;
@@ -1652,8 +2022,8 @@ function glitch(seed, pitch) {
1652
2022
  for (let i = 0; i < n; i++) {
1653
2023
  const t = i / SAMPLE_RATE, u = t / dur;
1654
2024
  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));
2025
+ const on = hash012(c, seed) > 0.4 ? 1 : 0;
2026
+ const freq = 400 * pitch * (1 + Math.floor(hash012(c, seed + 1) * 6));
1657
2027
  phase += TAU * freq / SAMPLE_RATE;
1658
2028
  const crush = Math.round(square(phase) * 4) / 4;
1659
2029
  out[i] = (crush * 0.7 + noise(i, seed + c) * 0.3) * on * (1 - u * 0.3) * 0.55;
@@ -1847,8 +2217,8 @@ function synthSfx(name, params = {}) {
1847
2217
  function pad(freqs, duration, seed, opts) {
1848
2218
  const { out, n } = buffer(duration);
1849
2219
  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 }
2220
+ { freq: f * (1 + (hash012(v, seed + 3) - 0.5) * 4e-3), am: opts.amBase + hash012(v, seed + 4) * 0.08, phase: hash012(v, seed + 5) * TAU },
2221
+ { freq: f * (1 - (hash012(v, seed + 6) - 0.5) * 4e-3), am: opts.amBase + hash012(v, seed + 7) * 0.08, phase: hash012(v, seed + 8) * TAU }
1852
2222
  ]);
1853
2223
  for (let i = 0; i < n; i++) {
1854
2224
  const t = i / SAMPLE_RATE;
@@ -1887,8 +2257,8 @@ function synthTension(duration, seed = 0) {
1887
2257
  const drift = 1 + 0.03 * (t / Math.max(1e-3, duration));
1888
2258
  let s = 0;
1889
2259
  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);
2260
+ const f = base[v] * drift * (1 + (hash012(v, seed) - 0.5) * 6e-3);
2261
+ s += Math.sin(TAU * f * t + hash012(v, seed + 1) * TAU);
1892
2262
  }
1893
2263
  const swell = 0.6 + 0.4 * Math.sin(TAU * 0.08 * t);
1894
2264
  out[i] = s / base.length * swell * 0.6;
@@ -439,12 +439,12 @@ function validateComposition(comp) {
439
439
  if (problems.length > 0) throw new SceneValidationError(problems);
440
440
  }
441
441
 
442
- // ../core/src/presets.ts
443
- var SET = 1 / 120;
444
-
445
442
  // ../core/src/evaluate.ts
446
443
  var DEG = Math.PI / 180;
447
444
 
445
+ // ../core/src/presets.ts
446
+ var SET = 1 / 120;
447
+
448
448
  // ../render-cli/src/loadScene.ts
449
449
  var HERE = dirname(fileURLToPath(import.meta.url));
450
450
  var CORE_ENTRY = true ? resolve(HERE, "index.js") : resolve(HERE, "..", "..", "core", "src", "index.ts");
package/dist/compile.js CHANGED
@@ -414,12 +414,12 @@ function validateScene(ir) {
414
414
  if (problems.length > 0) throw new SceneValidationError(problems);
415
415
  }
416
416
 
417
- // ../core/src/presets.ts
418
- var SET = 1 / 120;
419
-
420
417
  // ../core/src/evaluate.ts
421
418
  var DEG = Math.PI / 180;
422
419
 
420
+ // ../core/src/presets.ts
421
+ var SET = 1 / 120;
422
+
423
423
  // ../render-cli/src/loadScene.ts
424
424
  var HERE = dirname(fileURLToPath(import.meta.url));
425
425
  var CORE_ENTRY = true ? resolve(HERE, "index.js") : resolve(HERE, "..", "..", "core", "src", "index.ts");
package/dist/diff.js CHANGED
@@ -770,12 +770,12 @@ function validateComposition(comp) {
770
770
  if (problems.length > 0) throw new SceneValidationError(problems);
771
771
  }
772
772
 
773
- // ../core/src/presets.ts
774
- var SET = 1 / 120;
775
-
776
773
  // ../core/src/evaluate.ts
777
774
  var DEG = Math.PI / 180;
778
775
 
776
+ // ../core/src/presets.ts
777
+ var SET = 1 / 120;
778
+
779
779
  // ../core/src/assets.ts
780
780
  function collectSrcs(ir, type) {
781
781
  const srcs = /* @__PURE__ */ new Set();
package/dist/frame.js CHANGED
@@ -797,12 +797,12 @@ function validateComposition(comp) {
797
797
  if (problems.length > 0) throw new SceneValidationError(problems);
798
798
  }
799
799
 
800
- // ../core/src/presets.ts
801
- var SET = 1 / 120;
802
-
803
800
  // ../core/src/evaluate.ts
804
801
  var DEG = Math.PI / 180;
805
802
 
803
+ // ../core/src/presets.ts
804
+ var SET = 1 / 120;
805
+
806
806
  // ../core/src/assets.ts
807
807
  function collectSrcs(ir, type) {
808
808
  const srcs = /* @__PURE__ */ new Set();