Files
cruciverb/frontend/src/sounds.ts
T
2025-12-27 20:59:48 +02:00

82 lines
2.1 KiB
TypeScript

import { useStore } from './store'
let ctx: AudioContext | null = null
function getCtx(): AudioContext | null {
if (ctx && ctx.state !== 'closed') return ctx
try { ctx = new AudioContext() } catch { return null }
return ctx
}
function isSoundEnabled(): boolean {
return useStore.getState().narratorSettings.sounds
}
function tone(freq: number, duration: number, type: OscillatorType = 'sine', gain = 0.15) {
if (!isSoundEnabled()) return
const ac = getCtx()
if (!ac) return
if (ac.state === 'suspended') ac.resume()
const osc = ac.createOscillator()
const g = ac.createGain()
osc.type = type
osc.frequency.value = freq
g.gain.value = gain
g.gain.exponentialRampToValueAtTime(0.001, ac.currentTime + duration / 1000)
osc.connect(g).connect(ac.destination)
osc.start()
osc.stop(ac.currentTime + duration / 1000)
}
export function playKeyClick() {
tone(1200, 50, 'sine', 0.08)
}
export function playDelete() {
tone(400, 50, 'sine', 0.08)
}
export function playComplete() {
if (!isSoundEnabled()) return
const ac = getCtx()
if (!ac) return
if (ac.state === 'suspended') ac.resume()
const notes = [523, 659, 784]
notes.forEach((freq, i) => {
const osc = ac.createOscillator()
const g = ac.createGain()
osc.type = 'sine'
osc.frequency.value = freq
g.gain.value = 0.15
const start = ac.currentTime + i * 0.1
g.gain.exponentialRampToValueAtTime(0.001, start + 0.15)
osc.connect(g).connect(ac.destination)
osc.start(start)
osc.stop(start + 0.15)
})
}
export function playHint() {
tone(660, 100, 'sine', 0.1)
}
export function playWordComplete() {
if (!isSoundEnabled()) return
const ac = getCtx()
if (!ac) return
if (ac.state === 'suspended') ac.resume()
const notes = [587, 784]
notes.forEach((freq, i) => {
const osc = ac.createOscillator()
const g = ac.createGain()
osc.type = 'sine'
osc.frequency.value = freq
g.gain.value = 0.12
const start = ac.currentTime + i * 0.1
g.gain.exponentialRampToValueAtTime(0.001, start + 0.12)
osc.connect(g).connect(ac.destination)
osc.start(start)
osc.stop(start + 0.12)
})
}