import { Audio, type AudioErrorContext, type AudioPlayOptions, type AudioSound, type AudioVoice } from "@opentui/core" import { readFile } from "node:fs/promises" let audio: Audio | null | undefined const sounds = new Map>() function getAudio() { if (audio !== undefined) return audio try { const next = Audio.create({ autoStart: false }) next.on("error", (error: Error, context: AudioErrorContext) => { console.debug("tui audio error", { error, context }) }) audio = next return next } catch (error) { console.debug("failed to create tui audio", { error }) audio = null return null } } export function loadSoundFile(file: string) { const current = getAudio() if (!current) return Promise.resolve(null) const cached = sounds.get(file) if (cached) return cached const task = readFile(file) .then((bytes) => current.loadSound(bytes)) .catch((error) => { console.debug("failed to load tui sound", { file, error }) return null }) sounds.set(file, task) return task } export function play(sound: AudioSound, options?: AudioPlayOptions) { const current = getAudio() if (!current) return null if (!current.isStarted() && !current.start()) return null return current.play(sound, options) } export function stopVoice(voice: AudioVoice) { return audio?.stopVoice(voice) ?? false } export function dispose() { audio?.dispose() audio = undefined sounds.clear() }