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 { const media = document.querySelector('audio') if (!media) return Promise.reject(new Error('Проверка звука недоступна')) return new Promise((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) }) }