Skip to content

Commit 212ddf3

Browse files
committed
fix(studio): seed a profiled effect on its curve, not at registry defaults
Found in a running studio, which is the only place it could be found: add a compressor and the module opens reading **Evenness 0.67** with its make-up gain at 0 dB. The registry's defaults are not a point on the profile's curve, and `audioFxProfileStrength` reads the knob back by inverting that curve — so a default-seeded compressor reports a strength it was never set to, and every parameter under the knob disagrees with it. That is the "quieter as you turn it up" failure the measurement pass fixed, arriving on the very first frame instead. Adding a profiled effect now seeds it through the profile at 0.5, so the knob and the mechanism agree from the start. Everything else still arrives exactly as the registry declares it. Falsified: restoring the default seed fails the new test. The old "seeded with its declared defaults" case asserted the behaviour being fixed, and now uses an effect that has no derived knob — which is what it was really about. studio 3696 passing, 18 todo · core 1762.
1 parent 950209e commit 212ddf3

2 files changed

Lines changed: 44 additions & 5 deletions

File tree

packages/studio/src/components/editor/propertyPanelFxSection.test.tsx

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
import { DEFAULT_CARVE } from "@hyperframes/core/audio-carve";
1111
import { BANDS, EFFECT_COPY, PRESET_PROBLEM } from "@hyperframes/core/audio-fx-copy";
1212
import { HF_AUDIO_FX_JOBS, HF_AUDIO_FX_JOB_TYPES } from "@hyperframes/core/audio-fx-jobs";
13+
import { audioFxProfileStrength } from "@hyperframes/core/audio-fx-profiles";
1314
import { getAudioFxPreset } from "@hyperframes/core/audio-fx-presets";
1415

1516
/**
@@ -218,14 +219,17 @@ describe("FxSection chain", () => {
218219
});
219220

220221
it("adds an effect seeded with its declared defaults", () => {
222+
// An effect with no derived knob arrives exactly as the registry declares
223+
// it. The five that DO have one are seeded on their curve instead — see
224+
// "adds a profiled effect on its curve" below.
221225
const { host, onChainChange } = mount();
222226
click(host.querySelector(".hf-fx-add"));
223-
click(byText(host, ".hf-fx-add-item", EFFECT_COPY.compressor?.title ?? ""));
227+
click(byText(host, ".hf-fx-add-item", EFFECT_COPY.delay?.title ?? ""));
224228
expect(onChainChange).toHaveBeenCalledTimes(1);
225229
const next = onChainChange.mock.calls[0]![0] as HfAudioFxChain;
226230
expect(next.nodes).toHaveLength(1);
227-
expect(next.nodes[0]!.type).toBe("compressor");
228-
expect(next.nodes[0]!.params).toEqual(defaultAudioFxParams("compressor"));
231+
expect(next.nodes[0]!.type).toBe("delay");
232+
expect(next.nodes[0]!.params).toEqual(defaultAudioFxParams("delay"));
229233
});
230234

231235
it("renders a control for every parameter the effect declares", () => {
@@ -484,6 +488,23 @@ describe("FxSection chain", () => {
484488
expect(fxCard(host).querySelector(".hf-fx-ruler")).toBeNull();
485489
});
486490

491+
it("adds a profiled effect on its curve, not at registry defaults", () => {
492+
// The registry's defaults are not a point on the profile's curve, so an
493+
// effect seeded with them opened reading a strength it was not set to: a
494+
// compressor arrived showing Evenness 0.67 with its make-up gain at 0 dB —
495+
// the "quieter as you turn it up" bug the profiles exist to prevent, on the
496+
// very first frame. Caught in a running studio, not by these tests.
497+
const { host, onChainChange } = mount({ chain: { version: 1, nodes: [] } });
498+
click(host.querySelector(".hf-fx-add"));
499+
click(byText(host, ".hf-fx-add-item", EFFECT_COPY.compressor?.title ?? ""));
500+
501+
const written = onChainChange.mock.calls[0]?.[0] as HfAudioFxChain | undefined;
502+
const added = written?.nodes[0]?.params ?? {};
503+
expect(audioFxProfileStrength("compressor", added)).toBeCloseTo(0.5, 2);
504+
// And the mechanism agrees with the knob rather than sitting at its default.
505+
expect(added.makeup).not.toBe(defaultAudioFxParams("compressor").makeup);
506+
});
507+
487508
it("gives a module with no single real control a derived one", () => {
488509
// A compressor has seven controls and an author wants one, but no single one
489510
// of them can be its face: threshold means nothing without ratio. So the

packages/studio/src/components/editor/propertyPanelFxSection.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
setAudioEqBandGain,
2727
} from "@hyperframes/core/audio-fx-eq";
2828
import { EFFECT_COPY } from "@hyperframes/core/audio-fx-copy";
29+
import { applyAudioFxProfile, getAudioFxProfile } from "@hyperframes/core/audio-fx-profiles";
2930
import {
3031
audioFxJobNode,
3132
HF_AUDIO_FX_JOBS,
@@ -249,13 +250,30 @@ export function FxSection({
249250
[chain, mutate],
250251
);
251252

252-
/** One effect at its defaults, appended — what both adding and auditioning do. */
253+
/**
254+
* One effect appended, at the values its module opens on.
255+
*
256+
* For most effects that is the registry's defaults. For the five with a
257+
* derived knob it is NOT: the registry defaults are not a point on the
258+
* profile's curve, so the module opened reading a strength it was not set to —
259+
* a compressor arrived showing Evenness 0.67 with its make-up gain at 0 dB,
260+
* which is the "quieter as you turn it up" bug the profiles exist to prevent,
261+
* on the very first frame. Seeding through the profile puts the knob and the
262+
* mechanism in agreement from the start.
263+
*/
253264
const withEffect = useCallback(
254265
(base: HfAudioFxChain, type: string): HfAudioFxChain => ({
255266
...base,
256267
nodes: [
257268
...base.nodes,
258-
{ type, id: mintAudioFxNodeId(base), enabled: true, params: defaultAudioFxParams(type) },
269+
{
270+
type,
271+
id: mintAudioFxNodeId(base),
272+
enabled: true,
273+
params: getAudioFxProfile(type)
274+
? applyAudioFxProfile(type, 0.5, defaultAudioFxParams(type))
275+
: defaultAudioFxParams(type),
276+
},
259277
],
260278
}),
261279
[],

0 commit comments

Comments
 (0)