mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-11-14 21:29:34 +00:00
fix(core): stop reading a blank FX parameter as zero
`normalizeAudioFxParams` coerced with a bare `Number(raw)`, and `Number(null)`,
`Number("")`, `Number(false)` and `Number([])` are all 0 — every one of them
finite. So a parameter that arrived missing or blanked clamped to 0 instead of
falling back to the effect's declared default, and because 0 is a legal setting
for most of these knobs nothing downstream could tell the difference: a
compressor whose threshold came through as null sat at 0 dB and never engaged.
Now only a number, or a string that actually spells one, counts — the same rule
`numberOrNull` in audioAutomation.ts already applies. Panel inputs arrive as
strings, so those still work.
Falsified by restoring the bare `Number(raw)`: null reads as 0 dB instead of
-24.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
eb60133e33
commit
eb0080dec8
@@ -69,6 +69,27 @@ describe("normalizeAudioFxParams", () => {
|
||||
expect(v.gain).toBe(0);
|
||||
});
|
||||
|
||||
it("treats a blank or missing value as absent rather than as zero", () => {
|
||||
// `Number(null)`, `Number("")`, `Number(false)` and `Number([])` are all 0
|
||||
// and all finite, so these used to clamp to 0 instead of falling back. Zero
|
||||
// is a legal setting for most of these knobs, so nothing downstream could
|
||||
// tell: a compressor whose threshold arrived as null sat at 0 dB and never
|
||||
// engaged, silently, rather than at its declared -24 dB.
|
||||
const def = defaultAudioFxParams("compressor").threshold;
|
||||
expect(def).not.toBe(0);
|
||||
for (const blank of [null, undefined, "", " ", false, [], {}]) {
|
||||
expect(
|
||||
normalizeAudioFxParams("compressor", { threshold: blank as unknown as number }).threshold,
|
||||
`${JSON.stringify(blank)} was read as a number`,
|
||||
).toBe(def);
|
||||
}
|
||||
// A string that really does spell a number still counts — that is how the
|
||||
// panel's inputs arrive.
|
||||
expect(
|
||||
normalizeAudioFxParams("compressor", { threshold: "-30" as unknown as number }).threshold,
|
||||
).toBe(-30);
|
||||
});
|
||||
|
||||
it("falls back to the default for an unrecognised enum value", () => {
|
||||
expect(normalizeAudioFxParams("saturate", { type: "sawtooth" }).type).toBe("tanh");
|
||||
expect(normalizeAudioFxParams("saturate", { type: "atan" }).type).toBe("atan");
|
||||
|
||||
@@ -761,7 +761,20 @@ export function normalizeAudioFxParams(
|
||||
out[p.key] = ok ? (raw as string) : p.default;
|
||||
continue;
|
||||
}
|
||||
const n = typeof raw === "number" ? raw : Number(raw);
|
||||
// Only a number, or a string that actually spells one. `Number(null)`,
|
||||
// `Number("")`, `Number(false)` and `Number([])` are all 0 and all pass
|
||||
// Number.isFinite, so a missing or blanked value used to clamp to 0 rather
|
||||
// than fall back to the declared default — and 0 is a legal value for most
|
||||
// of these knobs, so nothing downstream could tell. A compressor whose
|
||||
// threshold arrived as null sat at 0 dB and never engaged, silently,
|
||||
// instead of at its -24 dB default. `numberOrNull` in audioAutomation.ts
|
||||
// already guards exactly this.
|
||||
const n =
|
||||
typeof raw === "number"
|
||||
? raw
|
||||
: typeof raw === "string" && raw.trim() !== ""
|
||||
? Number(raw)
|
||||
: Number.NaN;
|
||||
out[p.key] = Number.isFinite(n) ? Math.min(p.max, Math.max(p.min, n)) : p.default;
|
||||
}
|
||||
return out;
|
||||
|
||||
Reference in New Issue
Block a user