@maruaudio/dsp/physical/struck holds the instrument-independent laws of a struck-idiophone voice, shared by the gamelan and gong voices: velocity to gain, a velocity-coupled effective hardness, the contact-time laws that turn hardness into an exciter burst length, cutoff and impulse level, a noise mix, a deterministic xorshift32 exciter noise with per-strike seeding, and three body-size laws for decay, inharmonicity stretch and ombak beat rate. Each body is the literal expression the gamelan voice once inlined, in the same operation order, so the voice's golden render pins it.
| Function | Law |
|---|---|
struckVelocityGain(v) | v², f32 |
struckEffectiveHardness(h, velTone, v) | h + velTone · (v − 0.7) · 0.6, clamped 0 to 1 |
struckBurstSeconds(hEff, base, slope) | base − hEff · slope (gamelan 0.012, 0.01; gong 0.014, 0.0115) |
struckExciterCutoff(hEff) | 800 + hEff · 11200 Hz |
struckContactImpulse(hEff), struckNoiseMix(n) | 0.35 + x · 0.65 |
struckStrikeSeed(voice, note, counter) | Three odd multipliers, never 0 |
struckSizeDecayFactor(size), struckSizeStretch(size) | 1 / size; 1 + (1 − size) · 0.06 |
struckSizeOmbakRate(rate, amount, size) | rate · amount / size |
Lifecycle
None: free functions over numbers, with no classes, state or allocation. The caller keeps each voice's raw 32-bit noise state and advances it with struckRngNext; struckRngSample maps it to bipolar f32 noise in [−1, 1).
When to use it
Building a struck bar, gong or bell voice that should respond to velocity and mallet hardness, and to the size of the body, the way the gamelan and gong voices do.
Limits
velTone = 0returns the hardness unchanged, so velocity coupling is defeatable to the bit;size = 1makes the stretch exactly 1.- The stretch is an exponent on each mode's ratio, so the fundamental, whose ratio is 1, keeps its pitch at any size.
- The size laws return factors; the caller applies them in its own order.
struckBurstSecondsdoes not clamp; callers pass their own bounds.