Files
2026-10-19 00:11:20 +07:00

54 lines
2.2 KiB
TypeScript

const sampleRate = 16000
export const soundCheckWav = Buffer.alloc(44 + sampleRate * 2)
soundCheckWav.write('RIFF', 0)
soundCheckWav.writeUInt32LE(soundCheckWav.length - 8, 4)
soundCheckWav.write('WAVEfmt ', 8)
soundCheckWav.writeUInt32LE(16, 16)
soundCheckWav.writeUInt16LE(1, 20)
soundCheckWav.writeUInt16LE(1, 22)
soundCheckWav.writeUInt32LE(sampleRate, 24)
soundCheckWav.writeUInt32LE(sampleRate * 2, 28)
soundCheckWav.writeUInt16LE(2, 32)
soundCheckWav.writeUInt16LE(16, 34)
soundCheckWav.write('data', 36)
soundCheckWav.writeUInt32LE(sampleRate * 2, 40)
for (let sample = 0; sample < sampleRate; sample++) {
const time = sample / sampleRate
const start = time < 0.5 ? 0.05 : 0.55
const elapsed = time - start
if (elapsed < 0 || elapsed >= 0.4) continue
const envelope = Math.min(1, elapsed / 0.02, (0.4 - elapsed) / 0.02)
const frequency = time < 0.5 ? 440 : 660
soundCheckWav.writeInt16LE(Math.round(6553 * envelope * Math.sin(2 * Math.PI * frequency * elapsed)), 44 + sample * 2)
}
// Runs in the audio devices renderer; keep this function independent of module imports.
export function playSoundCheck(): Promise<void> {
const media = document.querySelector('audio')
if (!media) return Promise.reject(new Error('Проверка звука недоступна'))
return new Promise<void>((resolve, reject) => {
let finished = false
const finish = (error?: Error) => {
if (finished) return
finished = true
clearTimeout(timeout)
media.removeEventListener('ended', ended)
media.removeEventListener('error', failed)
media.pause()
media.removeAttribute('src')
media.load()
if (error) reject(error)
else resolve()
}
const ended = () => finish()
const failed = () => finish(new Error('Не удалось воспроизвести проверочный сигнал'))
const timeout = setTimeout(() => finish(new Error('Превышено время проверки звука')), 3000)
media.addEventListener('ended', ended)
media.addEventListener('error', failed)
media.muted = false
media.volume = 1
media.src = 'screen-app://app/sound-check.wav'
void media.play().catch(failed)
})
}