Sound
Synthesized UI feedback sounds, off by default.
API Reference
| Name | Description |
|---|---|
configureSound({ enabled, volume }) | Toggle and master volume (0–1, clamped); returns the resulting config |
getSoundConfig() | A copy of the current config |
playSound(type | preset) | Plays; returns whether it actually did |
sound.click() / .key() / .toggle() / .success() / .error() / .open() / .close() | Shorthands |
isSoundSupported() | Whether the browser has Web Audio |
disposeSound() | Closes the graph; the next play rebuilds it |
SOUND_PRESETS | The preset table; read its parameters or start a custom cue from one |
Off by Default
import { configureSound, sound } from '@talex-touch/tuffex/utils'
configureSound({ enabled: true, volume: 0.6 })
sound.click()
- Until enabled, nothing plays and no
AudioContextis created. - The graph is built lazily: browsers suspend an
AudioContextcreated outside a user gesture, so a page that never plays shouldn't hold one.
Why Synthesis
A few oscillators and an envelope ship at zero bundle cost, stay crisp at any sample rate, and cannot 404. The trade-off is timbre: samples are richer.
Presets
Seven, deliberately. Peaks and lengths are measured sample by sample through an OfflineAudioContext.
| Preset | Use | Peak | Length |
|---|---|---|---|
click | Button press | 0.103 | 40ms |
key | Per character in a field | 0.056 | 27ms |
toggle | Switch or checkbox turning on | 0.089 | 65ms |
success | Completed action (rising pair) | 0.090 | 188ms |
error | Rejected action (falling pair) | 0.100 | 216ms |
open | Panel or dialog opening | 0.078 | 91ms |
close | Panel or dialog closing | 0.077 | 91ms |
keyhas the lowest peak: it fires per character, and atclick's level it becomes a typewriter.openandclosemirror each other in peak and length, differing only in glide direction: direction carries the meaning, loudness does not.- Nothing clips; every peak sits between 0.06 and 0.11.
- Tests enforce two length budgets: immediate feedback (
click/key/toggle) ≤ 80ms, status cues (the rest) ≤ 250ms.
Custom Cues
playSound also takes a patch built on the spot:
import { playSound } from '@talex-touch/tuffex/utils'
playSound({
layers: [
{ wave: 'sine', freq: [400, 700], gain: 0.09, decay: 0.12 },
{ wave: 'sine', freq: 900, gain: 0.06, decay: 0.1, delay: 0.08 },
],
})
Two values in freq make a glide; delay offsets the second voice so the pair reads as a figure rather than a chord.
Contract
- Never throws: disabled, unsupported, or before the browser has seen a gesture,
playSoundquietly returnsfalse. - A context parked by the autoplay policy is resumed on the next play; a rejected resume is swallowed.
- Each voice disconnects its own envelope when it ends, so a typing burst leaves no dead nodes on the master gain.
- The noise buffer is shared, not regenerated per keystroke.
- A volume change applies to the existing graph immediately, with no rebuild.
Relationship to Vibration
useVibrate is the other feedback channel at this layer, with the same shape (preset table, main function, shorthand object). Don't fire sound and vibration for the same action: doubled feedback reads as a double trigger.
查看源码
packages/tuffex/packages/components/src/sound/index.ts