// Singleton AudioContext for the whole tab. // See ADR-004. Never closed during normal operation. let _ctx: AudioContext | null = null; type WebkitWindow = typeof window & { webkitAudioContext?: typeof AudioContext; }; export function getAudioContext(): AudioContext { if (_ctx) return _ctx; const w = window as WebkitWindow; const Ctor = w.AudioContext ?? w.webkitAudioContext; if (!Ctor) { throw new Error('Web Audio API is not supported in this environment'); } _ctx = new Ctor({ latencyHint: 'interactive' }); return _ctx; } export async function unlockAudioContext(): Promise { const ctx = getAudioContext(); if (ctx.state === 'suspended') { try { await ctx.resume(); } catch { // Resume requires a user gesture; caller should retry from one. } } } export function isAudioContextRunning(): boolean { return _ctx?.state === 'running'; } // Test-only: drop the singleton between test cases. export function _resetAudioContextForTesting(): void { _ctx = null; }