Files
feuerwerk/src/core/graph/nodes/action/SetSoundFxParameters.ts
T
adminandClaude Opus 5.5 501a1524ed
game-maker / gate (push) Successful in 3m21s
game-maker / suite (push) Successful in 15m26s
Ramp sound FX parameters over a time on the audio clock
A pitch sweep counted down in On update or On fixed update runs in
game time, while the sound runs on the clock of the audio device. A
short sound magnifies any offset between the two, so the sweep came
out different on every play and most of all on the first.

- Set sound FX parameters has a new input time in seconds. The values
  run evenly to their target in that time, scheduled on the audio
  clock with linearRampToValueAtTime or exponentialRampToValueAtTime.
- Evenly in their own unit: a pitch in semitones and a gain in
  decibels, an EQ band and a Mix share linearly in their value.
- A time of 0 or below keeps the quick glide of about 0.1 s.
- Each change starts from where the voice is now. Whatever was still
  planned is dropped, so a change never queues behind an older one.
  Firefox lacks cancelAndHoldAtTime, there the value is held by hand.
- A voice still waiting on its bytes starts a timed change with the
  sound, so the whole sweep is heard.

Tests:
- node-catalog: time is handed on, a time below 0 is a quick glide.
- sound-library: semitones and decibels ramp in their own steps, a
  timed change on a waiting voice starts with the sound.
- sound-library + node-catalog + soundfx: 419 tests, green.
- e2e 34 on melektaus-atx: ALL PASSED, 31 checks. A 2 s ramp from
  depth 7 to -5 read speed 0.979, 0.926 and 0.778 half a second on.
- Counter-check: folding a timed change on a waiting voice into its
  start values fails the new test.
- The gate did not run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 21:47:13 +02:00

38 lines
1.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { NodeDef } from '../../NodeRegistry';
import { asNumber } from '../../values';
import { exec, num } from '../shared';
import { fxParamsOf } from './PlaySound';
/**
* Changes the sound FX parameters of a sound that is already playing (#315). It reaches one voice,
* by the number its `Play sound` handed out: every play is a sound of its own, and two objects with
* the same engine sound – or one object playing it twice – each keep theirs.
*/
export const SetSoundFxParameters: NodeDef = {
type: 'SetSoundFxParameters',
label: 'Set sound FX parameters',
category: 'action',
description:
'Changes the sound FX parameters of a sound while it plays: the voice a Play sound handed out ' +
'glides to the values from a Sound FX parameters node. Keep the voice in a variable to reach it ' +
'from another event. A parameter not given keeps its value, a voice that has ended is not ' +
'reached. A pitch changes by speed here, so the sound gets shorter or longer while it is moved. ' +
'time: seconds the values take to get there, evenly and on the clock of the sound itself, so ' +
'a sweep sounds the same every time; 0 is a quick glide.',
inputs: [
exec(),
{ ...num('voice'), inline: false },
{ key: 'fxParams', label: 'fx params', type: 'fxparams' },
num('time'),
],
outputs: [exec()],
params: [],
run: (ctx, inputs) => {
const voice = asNumber(inputs.voice);
const time = asNumber(inputs.time);
if (voice > 0)
ctx.tuneSound(voice, fxParamsOf(inputs.fxParams), Number.isFinite(time) && time > 0 ? time : 0);
return { next: 'exec' };
},
};