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/bin.js CHANGED
@@ -409,7 +409,119 @@ function easeOutBounce(u) {
409
409
  if (u < 2.5 / d1) return n1 * (u -= 2.25 / d1) * u + 0.9375;
410
410
  return n1 * (u -= 2.625 / d1) * u + 0.984375;
411
411
  }
412
- var BACK_C1, BACK_C2, BACK_C3, ELASTIC_C4, ELASTIC_C5, EASE_TABLE, EASE_NAMES;
412
+ function resolveEase(ease) {
413
+ if (ease === void 0) return EASE_TABLE.linear;
414
+ if (typeof ease === "string") {
415
+ const fn = EASE_TABLE[ease];
416
+ if (!fn) throw new Error(`unknown ease "${ease}" \u2014 valid: ${Object.keys(EASE_TABLE).join(", ")}`);
417
+ return fn;
418
+ }
419
+ if ("spring" in ease) {
420
+ const { stiffness = 100, damping = 10, velocity = 0 } = ease.spring;
421
+ return springEase(stiffness, damping, velocity);
422
+ }
423
+ return cubicBezierEase(...ease.cubicBezier);
424
+ }
425
+ function cubicBezierEase(x1, y1, x2, y2) {
426
+ const bez = (a, b) => (t) => 3 * a * t * (1 - t) ** 2 + 3 * b * t * t * (1 - t) + t ** 3;
427
+ const bx = bez(x1, x2);
428
+ const by = bez(y1, y2);
429
+ const dbx = (t) => 3 * x1 * (1 - t) * (1 - 3 * t) + 3 * x2 * t * (2 - 3 * t) + 3 * t * t;
430
+ return (u) => {
431
+ if (u <= 0) return 0;
432
+ if (u >= 1) return 1;
433
+ let t = u;
434
+ for (let i = 0; i < 8; i++) {
435
+ const err = bx(t) - u;
436
+ if (Math.abs(err) < 1e-6) return by(t);
437
+ const d = dbx(t);
438
+ if (Math.abs(d) < 1e-6) break;
439
+ t -= err / d;
440
+ }
441
+ let lo = 0;
442
+ let hi = 1;
443
+ t = u;
444
+ while (hi - lo > 1e-6) {
445
+ if (bx(t) < u) lo = t;
446
+ else hi = t;
447
+ t = (lo + hi) / 2;
448
+ }
449
+ return by(t);
450
+ };
451
+ }
452
+ function isColor(v) {
453
+ return typeof v === "string" && HEX_COLOR.test(v);
454
+ }
455
+ function parseColor(hex) {
456
+ let h = hex.slice(1);
457
+ if (h.length <= 4) h = [...h].map((c) => c + c).join("");
458
+ const n = parseInt(h.padEnd(8, "f"), 16);
459
+ return [n >>> 24 & 255, n >>> 16 & 255, n >>> 8 & 255, n & 255];
460
+ }
461
+ function formatColor([r, g, b, a]) {
462
+ const hex = (v) => Math.round(Math.max(0, Math.min(255, v))).toString(16).padStart(2, "0");
463
+ return a >= 255 ? `#${hex(r)}${hex(g)}${hex(b)}` : `#${hex(r)}${hex(g)}${hex(b)}${hex(a)}`;
464
+ }
465
+ function lerpValue(from, to, u) {
466
+ if (typeof from === "number" && typeof to === "number") {
467
+ return from + (to - from) * u;
468
+ }
469
+ if (isColor(from) && isColor(to)) {
470
+ const a = parseColor(from);
471
+ const b = parseColor(to);
472
+ return formatColor([
473
+ a[0] + (b[0] - a[0]) * u,
474
+ a[1] + (b[1] - a[1]) * u,
475
+ a[2] + (b[2] - a[2]) * u,
476
+ a[3] + (b[3] - a[3]) * u
477
+ ]);
478
+ }
479
+ if (looksLikePath(from) && looksLikePath(to)) {
480
+ const a = tokenizePath(from);
481
+ const b = tokenizePath(to);
482
+ if (a && b && morphCompatible(a, b)) return morphPath(a, b, u);
483
+ return u < 0.5 ? from : to;
484
+ }
485
+ return to;
486
+ }
487
+ function looksLikePath(v) {
488
+ return typeof v === "string" && /^\s*[Mm]/.test(v) && PATH_BODY.test(v);
489
+ }
490
+ function tokenizePath(d) {
491
+ const out = [];
492
+ let cur = null;
493
+ let m;
494
+ PATH_TOKEN.lastIndex = 0;
495
+ while (m = PATH_TOKEN.exec(d)) {
496
+ if (m[1]) out.push(cur = { cmd: m[1], nums: [] });
497
+ else if (m[2]) {
498
+ if (!cur) return null;
499
+ cur.nums.push(parseFloat(m[2]));
500
+ }
501
+ }
502
+ return out.length ? out : null;
503
+ }
504
+ function morphCompatible(a, b) {
505
+ if (a.length !== b.length) return false;
506
+ for (let i = 0; i < a.length; i++) {
507
+ const ca = a[i];
508
+ const cb = b[i];
509
+ if (ca.cmd !== cb.cmd || ca.nums.length !== cb.nums.length) return false;
510
+ if (ca.cmd === "A" || ca.cmd === "a") return false;
511
+ }
512
+ return true;
513
+ }
514
+ function morphPath(a, b, u) {
515
+ let s = "";
516
+ for (let i = 0; i < a.length; i++) {
517
+ const an = a[i].nums;
518
+ const bn = b[i].nums;
519
+ s += (i ? " " : "") + a[i].cmd;
520
+ for (let j = 0; j < an.length; j++) s += " " + fmtNum(an[j] + (bn[j] - an[j]) * u);
521
+ }
522
+ return s;
523
+ }
524
+ var BACK_C1, BACK_C2, BACK_C3, ELASTIC_C4, ELASTIC_C5, EASE_TABLE, EASE_NAMES, HEX_COLOR, PATH_BODY, PATH_TOKEN, fmtNum;
413
525
  var init_interpolate = __esm({
414
526
  "../core/src/interpolate.ts"() {
415
527
  "use strict";
@@ -451,6 +563,13 @@ var init_interpolate = __esm({
451
563
  springStiff: springEase(210, 26, 0)
452
564
  };
453
565
  EASE_NAMES = Object.keys(EASE_TABLE);
566
+ HEX_COLOR = /^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
567
+ PATH_BODY = /^[\sMmLlHhVvCcSsQqTtAaZz0-9.,eE+-]+$/;
568
+ PATH_TOKEN = /([MmLlHhVvCcSsQqTtAaZz])|(-?(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?)/g;
569
+ fmtNum = (v) => {
570
+ const r = Number(v.toFixed(3));
571
+ return Object.is(r, -0) ? "0" : String(r);
572
+ };
454
573
  }
455
574
  });
456
575
 
@@ -1102,6 +1221,40 @@ var init_camera = __esm({
1102
1221
  }
1103
1222
  });
1104
1223
 
1224
+ // ../core/src/behaviors.ts
1225
+ function sampleBehavior(b, t) {
1226
+ switch (b.name) {
1227
+ case "oscillate": {
1228
+ const { amplitude, frequency, phase = 0 } = b.params;
1229
+ return amplitude * Math.sin(2 * Math.PI * frequency * t + phase);
1230
+ }
1231
+ case "wiggle": {
1232
+ const { amplitude, frequency, seed } = b.params;
1233
+ return amplitude * valueNoise(t * frequency, seed);
1234
+ }
1235
+ }
1236
+ }
1237
+ function valueNoise(x, seed) {
1238
+ const i = Math.floor(x);
1239
+ const f = x - i;
1240
+ const u = f * f * (3 - 2 * f);
1241
+ const a = hash01(i, seed) * 2 - 1;
1242
+ const b = hash01(i + 1, seed) * 2 - 1;
1243
+ return a + (b - a) * u;
1244
+ }
1245
+ function hash01(n, seed) {
1246
+ let h = n * 374761393 + seed * 668265263 | 0;
1247
+ h = h ^ h >>> 13 | 0;
1248
+ h = Math.imul(h, 1274126177);
1249
+ h = (h ^ h >>> 16) >>> 0;
1250
+ return h / 4294967295;
1251
+ }
1252
+ var init_behaviors = __esm({
1253
+ "../core/src/behaviors.ts"() {
1254
+ "use strict";
1255
+ }
1256
+ });
1257
+
1105
1258
  // ../core/src/gradient.ts
1106
1259
  var init_gradient = __esm({
1107
1260
  "../core/src/gradient.ts"() {
@@ -1109,6 +1262,247 @@ var init_gradient = __esm({
1109
1262
  }
1110
1263
  });
1111
1264
 
1265
+ // ../core/src/evaluate.ts
1266
+ function multiply(m, n) {
1267
+ return [
1268
+ m[0] * n[0] + m[2] * n[1],
1269
+ m[1] * n[0] + m[3] * n[1],
1270
+ m[0] * n[2] + m[2] * n[3],
1271
+ m[1] * n[2] + m[3] * n[3],
1272
+ m[0] * n[4] + m[2] * n[5] + m[4],
1273
+ m[1] * n[4] + m[3] * n[5] + m[5]
1274
+ ];
1275
+ }
1276
+ function localMatrix(x, y, rotationDeg, scale, scaleX = 1, scaleY = 1, skewXDeg = 0, skewYDeg = 0) {
1277
+ const r = rotationDeg * Math.PI / 180;
1278
+ if (scaleX === 1 && scaleY === 1 && skewXDeg === 0 && skewYDeg === 0) {
1279
+ const cos = Math.cos(r) * scale;
1280
+ const sin = Math.sin(r) * scale;
1281
+ return [cos, sin, -sin, cos, x, y];
1282
+ }
1283
+ const c = Math.cos(r);
1284
+ const s = Math.sin(r);
1285
+ const tx = Math.tan(skewXDeg * Math.PI / 180);
1286
+ const ty = Math.tan(skewYDeg * Math.PI / 180);
1287
+ const R = [c, s, -s, c, 0, 0];
1288
+ const K = [1, ty, tx, 1, 0, 0];
1289
+ const S = [scale * scaleX, 0, 0, scale * scaleY, 0, 0];
1290
+ const m = multiply(R, multiply(K, S));
1291
+ return [m[0], m[1], m[2], m[3], x, y];
1292
+ }
1293
+ function behaviorEnvelope(b, t) {
1294
+ const from = b.from ?? Number.NEGATIVE_INFINITY;
1295
+ const until = b.until ?? Number.POSITIVE_INFINITY;
1296
+ if (t < from || t > until) return 0;
1297
+ const ramp = b.ramp ?? 0.2;
1298
+ let envelope = 1;
1299
+ if (Number.isFinite(from) && ramp > 0) envelope = Math.min(envelope, (t - from) / ramp);
1300
+ if (Number.isFinite(until) && ramp > 0) envelope = Math.min(envelope, (until - t) / ramp);
1301
+ return Math.max(0, Math.min(1, envelope));
1302
+ }
1303
+ function sampleProp(compiled, t, target, prop, fallback) {
1304
+ let value = compiled.initialValues.get(`${target}.${prop}`) ?? fallback;
1305
+ let segStart = Number.NEGATIVE_INFINITY;
1306
+ const segs = compiled.segments.get(`${target}.${prop}`);
1307
+ if (segs) {
1308
+ let active;
1309
+ for (const seg of segs) {
1310
+ if (seg.t0 <= t) active = seg;
1311
+ else break;
1312
+ }
1313
+ if (active) {
1314
+ segStart = active.t0;
1315
+ if (t >= active.t1) {
1316
+ value = active.to;
1317
+ } else {
1318
+ const u = resolveEase(active.ease)((t - active.t0) / (active.t1 - active.t0));
1319
+ value = lerpValue(active.from, active.to, u);
1320
+ }
1321
+ }
1322
+ }
1323
+ if (prop === "x" || prop === "y" || prop === "rotation") {
1324
+ const drivers = compiled.motionPaths.get(target);
1325
+ if (drivers) {
1326
+ let active;
1327
+ for (const d of drivers) {
1328
+ if (d.t0 <= t) active = d;
1329
+ else break;
1330
+ }
1331
+ if (active && active.t0 >= segStart && (prop !== "rotation" || active.autoRotate) && active.points.length > 0) {
1332
+ const span = active.t1 - active.t0;
1333
+ const u = span <= 0 ? 1 : resolveEase(active.ease)(Math.max(0, Math.min(1, (t - active.t0) / span)));
1334
+ if (prop === "x") value = pathPoint(active.points, active.closed, u, active.curviness)[0];
1335
+ else if (prop === "y") value = pathPoint(active.points, active.closed, u, active.curviness)[1];
1336
+ else value = pathTangentAngle(active.points, active.closed, u, active.curviness) + active.rotateOffset;
1337
+ }
1338
+ }
1339
+ }
1340
+ for (const b of compiled.ir.behaviors ?? []) {
1341
+ if (b.target === target && b.prop === prop && typeof value === "number") {
1342
+ const envelope = behaviorEnvelope(b, t);
1343
+ if (envelope > 0) value = value + envelope * sampleBehavior(b.behavior, t);
1344
+ }
1345
+ }
1346
+ return value;
1347
+ }
1348
+ function nodeParentMatrix(compiled, id, t) {
1349
+ const num2 = (target, prop, fallback) => {
1350
+ const v = sampleProp(compiled, t, target, prop, fallback);
1351
+ return typeof v === "number" ? v : fallback;
1352
+ };
1353
+ let result = null;
1354
+ const walk = (node, parent) => {
1355
+ if (node.id === id) {
1356
+ result = parent;
1357
+ return true;
1358
+ }
1359
+ if (node.type === "group") {
1360
+ const m = multiply(
1361
+ parent,
1362
+ localMatrix(
1363
+ num2(node.id, "x", node.props.x),
1364
+ num2(node.id, "y", node.props.y),
1365
+ num2(node.id, "rotation", node.props.rotation ?? 0),
1366
+ num2(node.id, "scale", node.props.scale ?? 1),
1367
+ num2(node.id, "scaleX", node.props.scaleX ?? 1),
1368
+ num2(node.id, "scaleY", node.props.scaleY ?? 1),
1369
+ num2(node.id, "skewX", node.props.skewX ?? 0),
1370
+ num2(node.id, "skewY", node.props.skewY ?? 0)
1371
+ )
1372
+ );
1373
+ for (const child of node.children) if (walk(child, m)) return true;
1374
+ }
1375
+ return false;
1376
+ };
1377
+ for (const node of compiled.ir.nodes) if (walk(node, IDENTITY)) break;
1378
+ return result;
1379
+ }
1380
+ var IDENTITY, DEG;
1381
+ var init_evaluate = __esm({
1382
+ "../core/src/evaluate.ts"() {
1383
+ "use strict";
1384
+ init_behaviors();
1385
+ init_camera();
1386
+ init_gradient();
1387
+ init_interpolate();
1388
+ init_path();
1389
+ IDENTITY = [1, 0, 0, 1, 0, 0];
1390
+ DEG = Math.PI / 180;
1391
+ }
1392
+ });
1393
+
1394
+ // ../core/src/autoFoley.ts
1395
+ function nodeSize(node) {
1396
+ const p = node.props;
1397
+ return Math.max(p.width ?? 0, p.height ?? 0, (p.radius ?? 0) * 2, p.fontSize ?? 0, 0);
1398
+ }
1399
+ function autoFoley(compiled, opts = {}) {
1400
+ const master = opts.gain ?? 0.5;
1401
+ const sens = opts.sensitivity ?? 1;
1402
+ const wantWhoosh = opts.whoosh !== false;
1403
+ const wantImpact = opts.impact !== false;
1404
+ const wantPop = opts.pop !== false;
1405
+ const wantPan = opts.pan !== false;
1406
+ const vMin = V_MIN / sens, vStop = V_STOP, vDecel = V_DECEL / sens;
1407
+ const fps = compiled.ir.fps ?? 30;
1408
+ const N = Math.max(1, Math.ceil(compiled.duration * fps));
1409
+ const W = compiled.ir.size.width || 1920;
1410
+ const ids = opts.nodes ?? [...compiled.nodeById.keys()];
1411
+ const cands = [];
1412
+ const panOf = (x) => wantPan ? Math.max(-1, Math.min(1, x / W * 2 - 1)) : 0;
1413
+ const loud = (v) => Math.max(0.2, Math.min(1, (v - vMin) / (V_MAX - vMin)));
1414
+ for (const id of ids) {
1415
+ const node = compiled.nodeById.get(id);
1416
+ if (!node || node.type === "line") continue;
1417
+ const size = nodeSize(node);
1418
+ const xs = [], ys = [], ss = [], os = [];
1419
+ for (let i2 = 0; i2 <= N; i2++) {
1420
+ const t = i2 / fps;
1421
+ xs.push(num(compiled, t, id, "x", node.props.x ?? 0));
1422
+ ys.push(num(compiled, t, id, "y", node.props.y ?? 0));
1423
+ ss.push(num(compiled, t, id, "scale", node.props.scale ?? 1));
1424
+ os.push(num(compiled, t, id, "opacity", node.props.opacity ?? 1));
1425
+ }
1426
+ const speed = (i2) => i2 <= 0 ? 0 : Math.hypot(xs[i2] - xs[i2 - 1], ys[i2] - ys[i2 - 1]) * fps;
1427
+ const worldX = (frame) => {
1428
+ const m = nodeParentMatrix(compiled, id, frame / fps);
1429
+ return m ? m[0] * xs[frame] + m[2] * ys[frame] + m[4] : xs[frame];
1430
+ };
1431
+ let i = 1;
1432
+ while (i <= N) {
1433
+ if (speed(i) <= vMin) {
1434
+ i++;
1435
+ continue;
1436
+ }
1437
+ const a = i;
1438
+ let peak = i, peakV = speed(i);
1439
+ while (i <= N && speed(i) > vStop) {
1440
+ const s = speed(i);
1441
+ if (s > peakV) {
1442
+ peakV = s;
1443
+ peak = i;
1444
+ }
1445
+ i++;
1446
+ }
1447
+ const b = i - 1;
1448
+ const durS = (b - a + 1) / fps;
1449
+ const visible = os[peak] > 0.1;
1450
+ if (peakV > vMin && durS >= MIN_DUR && visible) {
1451
+ if (wantWhoosh) {
1452
+ const quickFlick = durS < 0.25;
1453
+ cands.push({ t: peak / fps, sfx: quickFlick ? "swish" : "whoosh", gain: master * loud(peakV), pan: panOf(worldX(peak)), rank: peakV });
1454
+ }
1455
+ const stopped = b >= N || speed(b + 1) < vStop && speed(Math.min(N, b + 2)) < vStop;
1456
+ const wxb = worldX(b);
1457
+ const landsOnScreen = wxb >= 0 && wxb <= W && os[b] > 0.1;
1458
+ if (wantImpact && peakV > vDecel && stopped && landsOnScreen && b < N) {
1459
+ cands.push({ t: (b + 1) / fps, sfx: size > 220 ? "thud" : "knock", gain: master * loud(peakV), pan: panOf(worldX(b)), rank: peakV * 1.1 });
1460
+ }
1461
+ }
1462
+ }
1463
+ if (wantPop && ss[0] < 0.25) {
1464
+ for (let k = 1; k <= N; k++) {
1465
+ if (ss[k - 1] < 0.5 && ss[k] >= 0.5 && os[k] > 0.05) {
1466
+ cands.push({ t: k / fps, sfx: "pop", gain: master * 0.7, pan: panOf(worldX(k)), rank: 600 });
1467
+ break;
1468
+ }
1469
+ }
1470
+ }
1471
+ }
1472
+ cands.sort((p, q) => q.rank - p.rank);
1473
+ const kept = [];
1474
+ for (const c of cands) {
1475
+ const fam = FAMILY[c.sfx] ?? c.sfx;
1476
+ if (kept.some((k) => (FAMILY[k.sfx] ?? k.sfx) === fam && Math.abs(k.t - c.t) < DEDUP_DT)) continue;
1477
+ kept.push(c);
1478
+ }
1479
+ const max = opts.maxCues ?? 32;
1480
+ return kept.slice(0, max).map((c) => ({
1481
+ at: Number(c.t.toFixed(3)),
1482
+ sfx: c.sfx,
1483
+ gain: Number(c.gain.toFixed(3)),
1484
+ ...c.pan !== 0 ? { pan: Number(c.pan.toFixed(3)) } : {}
1485
+ }));
1486
+ }
1487
+ var V_MIN, V_STOP, V_DECEL, V_MAX, MIN_DUR, num, FAMILY, DEDUP_DT;
1488
+ var init_autoFoley = __esm({
1489
+ "../core/src/autoFoley.ts"() {
1490
+ "use strict";
1491
+ init_evaluate();
1492
+ V_MIN = 360;
1493
+ V_STOP = 60;
1494
+ V_DECEL = 520;
1495
+ V_MAX = 2600;
1496
+ MIN_DUR = 0.1;
1497
+ num = (c, t, id, prop, fb) => {
1498
+ const v = sampleProp(c, t, id, prop, fb);
1499
+ return typeof v === "number" ? v : fb;
1500
+ };
1501
+ FAMILY = { whoosh: "move", swish: "move", thud: "hit", knock: "hit", pop: "pop" };
1502
+ DEDUP_DT = 0.09;
1503
+ }
1504
+ });
1505
+
1112
1506
  // ../core/src/effects.ts
1113
1507
  var init_effects = __esm({
1114
1508
  "../core/src/effects.ts"() {
@@ -1403,11 +1797,13 @@ function resolveAudioPlan(compiled) {
1403
1797
  const warnings = [];
1404
1798
  const duration = compiled.duration;
1405
1799
  const clipAudio = collectClipAudio(compiled.ir, duration, warnings);
1406
- if (!audio || !audio.bgm && (audio.cues ?? []).length === 0) {
1800
+ const autoCues = audio?.autoFoley ? autoFoley(compiled, audio.autoFoley === true ? {} : audio.autoFoley) : [];
1801
+ const manualCues = [...audio?.cues ?? [], ...autoCues];
1802
+ if (!audio || !audio.bgm && manualCues.length === 0) {
1407
1803
  return clipAudio.length === 0 ? null : { duration, bgm: null, cues: [], duckWindows: [], clipAudio, warnings };
1408
1804
  }
1409
1805
  const cues = [];
1410
- for (const [index, cue] of (audio.cues ?? []).entries()) {
1806
+ for (const [index, cue] of manualCues.entries()) {
1411
1807
  let anchor;
1412
1808
  if (typeof cue.at === "number") {
1413
1809
  anchor = cue.at;
@@ -1481,6 +1877,7 @@ var SFX_DURATION, FILE_CUE_DURATION;
1481
1877
  var init_audio = __esm({
1482
1878
  "../core/src/audio.ts"() {
1483
1879
  "use strict";
1880
+ init_autoFoley();
1484
1881
  SFX_DURATION = {
1485
1882
  // transition
1486
1883
  whoosh: 0.35,
@@ -1527,27 +1924,6 @@ var init_audio = __esm({
1527
1924
  }
1528
1925
  });
1529
1926
 
1530
- // ../core/src/behaviors.ts
1531
- var init_behaviors = __esm({
1532
- "../core/src/behaviors.ts"() {
1533
- "use strict";
1534
- }
1535
- });
1536
-
1537
- // ../core/src/evaluate.ts
1538
- var DEG;
1539
- var init_evaluate = __esm({
1540
- "../core/src/evaluate.ts"() {
1541
- "use strict";
1542
- init_behaviors();
1543
- init_camera();
1544
- init_gradient();
1545
- init_interpolate();
1546
- init_path();
1547
- DEG = Math.PI / 180;
1548
- }
1549
- });
1550
-
1551
1927
  // ../core/src/assets.ts
1552
1928
  function collectSrcs(ir, type) {
1553
1929
  const srcs = /* @__PURE__ */ new Set();
@@ -1611,6 +1987,7 @@ var init_src = __esm({
1611
1987
  init_compile();
1612
1988
  init_path();
1613
1989
  init_camera();
1990
+ init_autoFoley();
1614
1991
  init_gradient();
1615
1992
  init_effects();
1616
1993
  init_layout();
@@ -1810,7 +2187,7 @@ var init_wav = __esm({
1810
2187
  });
1811
2188
 
1812
2189
  // ../render-cli/src/audio/synth.ts
1813
- function hash01(n, seed) {
2190
+ function hash012(n, seed) {
1814
2191
  let h = n * 374761393 + seed * 668265263 | 0;
1815
2192
  h = h ^ h >>> 13 | 0;
1816
2193
  h = Math.imul(h, 1274126177);
@@ -2056,7 +2433,7 @@ function sparkle(seed, pitch) {
2056
2433
  const on = u * steps.length - g;
2057
2434
  if (on > 0 && on < 3) {
2058
2435
  const ge = Math.exp(-on * 1.8);
2059
- s += Math.sin(TAU * base * steps[g] * t + hash01(g, seed) * TAU) * ge;
2436
+ s += Math.sin(TAU * base * steps[g] * t + hash012(g, seed) * TAU) * ge;
2060
2437
  }
2061
2438
  }
2062
2439
  out[i] = s / 2.4 * Math.sin(Math.PI * u) ** 0.5 * 0.5;
@@ -2083,9 +2460,9 @@ function shimmer(seed, pitch) {
2083
2460
  const dur2 = 0.9;
2084
2461
  const { out, n } = buffer(dur2);
2085
2462
  const partials = Array.from({ length: 5 }, (_, p) => ({
2086
- freq: (2e3 + hash01(p, seed + 7) * 2e3) * pitch,
2087
- am: 0.5 + hash01(p, seed + 8) * 1.5,
2088
- phase: hash01(p, seed + 9) * TAU
2463
+ freq: (2e3 + hash012(p, seed + 7) * 2e3) * pitch,
2464
+ am: 0.5 + hash012(p, seed + 8) * 1.5,
2465
+ phase: hash012(p, seed + 9) * TAU
2089
2466
  }));
2090
2467
  for (let i = 0; i < n; i++) {
2091
2468
  const t = i / SAMPLE_RATE, u = t / dur2;
@@ -2146,8 +2523,8 @@ function glitch(seed, pitch) {
2146
2523
  for (let i = 0; i < n; i++) {
2147
2524
  const t = i / SAMPLE_RATE, u = t / dur2;
2148
2525
  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));
2526
+ const on = hash012(c, seed) > 0.4 ? 1 : 0;
2527
+ const freq = 400 * pitch * (1 + Math.floor(hash012(c, seed + 1) * 6));
2151
2528
  phase += TAU * freq / SAMPLE_RATE;
2152
2529
  const crush = Math.round(square(phase) * 4) / 4;
2153
2530
  out[i] = (crush * 0.7 + noise(i, seed + c) * 0.3) * on * (1 - u * 0.3) * 0.55;
@@ -2306,8 +2683,8 @@ function synthSfx(name, params = {}) {
2306
2683
  function pad(freqs, duration, seed, opts) {
2307
2684
  const { out, n } = buffer(duration);
2308
2685
  const voices = freqs.flatMap((f, v) => [
2309
- { 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 },
2310
- { 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 }
2686
+ { 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 },
2687
+ { 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 }
2311
2688
  ]);
2312
2689
  for (let i = 0; i < n; i++) {
2313
2690
  const t = i / SAMPLE_RATE;
@@ -2346,8 +2723,8 @@ function synthTension(duration, seed = 0) {
2346
2723
  const drift = 1 + 0.03 * (t / Math.max(1e-3, duration));
2347
2724
  let s = 0;
2348
2725
  for (let v = 0; v < base.length; v++) {
2349
- const f = base[v] * drift * (1 + (hash01(v, seed) - 0.5) * 6e-3);
2350
- s += Math.sin(TAU * f * t + hash01(v, seed + 1) * TAU);
2726
+ const f = base[v] * drift * (1 + (hash012(v, seed) - 0.5) * 6e-3);
2727
+ s += Math.sin(TAU * f * t + hash012(v, seed + 1) * TAU);
2351
2728
  }
2352
2729
  const swell = 0.6 + 0.4 * Math.sin(TAU * 0.08 * t);
2353
2730
  out[i] = s / base.length * swell * 0.6;
@@ -2365,7 +2742,7 @@ var init_synth = __esm({
2365
2742
  "../render-cli/src/audio/synth.ts"() {
2366
2743
  "use strict";
2367
2744
  init_wav();
2368
- noise = (n, seed) => hash01(n, seed) * 2 - 1;
2745
+ noise = (n, seed) => hash012(n, seed) * 2 - 1;
2369
2746
  TAU = Math.PI * 2;
2370
2747
  expDecay = (t, dur2, k = 5) => Math.exp(-k * t / dur2);
2371
2748
  square = (ph) => (Math.sin(ph) + 0.33 * Math.sin(3 * ph) + 0.2 * Math.sin(5 * ph)) / 1.4;
@@ -3616,15 +3993,15 @@ ${USAGE}`);
3616
3993
  preflightFfmpeg();
3617
3994
  const { tmpdir: tmpdir6 } = await import("node:os");
3618
3995
  const { resolveLogo: resolveLogo2, buildLogoSting: buildLogoSting2 } = await Promise.resolve().then(() => (init_logoSting(), logoSting_exports));
3619
- const num = (k) => flags[k] !== void 0 ? Number(flags[k]) : void 0;
3996
+ const num2 = (k) => flags[k] !== void 0 ? Number(flags[k]) : void 0;
3620
3997
  console.log(`loading logo: ${arg} \u2026`);
3621
3998
  const { data, slug } = await resolveLogo2(arg, positional[1], {
3622
3999
  motion: flags.motion,
3623
- energy: num("energy"),
3624
- speed: num("speed"),
3625
- intensity: num("intensity"),
4000
+ energy: num2("energy"),
4001
+ speed: num2("speed"),
4002
+ intensity: num2("intensity"),
3626
4003
  from: flags.from,
3627
- seed: num("seed")
4004
+ seed: num2("seed")
3628
4005
  });
3629
4006
  const sceneIR = buildLogoSting2(data);
3630
4007
  const tmp = join9(tmpdir6(), `reframe-logo-${slug}-${process.pid}.json`);
@@ -549,14 +549,6 @@
549
549
  return [a, b, c, d, W / 2 - a * x - c * y, H / 2 - b * x - d * y];
550
550
  }
551
551
 
552
- // ../core/src/gradient.ts
553
- function isGradient(p) {
554
- return typeof p === "object" && p !== null && (p.kind === "linear" || p.kind === "radial" || p.kind === "conic");
555
- }
556
-
557
- // ../core/src/presets.ts
558
- var SET = 1 / 120;
559
-
560
552
  // ../core/src/behaviors.ts
561
553
  function sampleBehavior(b, t) {
562
554
  switch (b.name) {
@@ -586,6 +578,11 @@
586
578
  return h / 4294967295;
587
579
  }
588
580
 
581
+ // ../core/src/gradient.ts
582
+ function isGradient(p) {
583
+ return typeof p === "object" && p !== null && (p.kind === "linear" || p.kind === "radial" || p.kind === "conic");
584
+ }
585
+
589
586
  // ../core/src/evaluate.ts
590
587
  var IDENTITY = [1, 0, 0, 1, 0, 0];
591
588
  function multiply(m, n) {
@@ -986,6 +983,9 @@
986
983
  return ops;
987
984
  }
988
985
 
986
+ // ../core/src/presets.ts
987
+ var SET = 1 / 120;
988
+
989
989
  // ../renderer-canvas/src/index.ts
990
990
  function resolvePaint(ctx2, paint, box) {
991
991
  if (typeof paint === "string") return paint;