sound.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. let files: Record<string, () => Promise<string>> | undefined
  2. let loads: Record<SoundID, () => Promise<string>> | undefined
  3. function getFiles() {
  4. if (files) return files
  5. files = import.meta.glob("../../../ui/src/assets/audio/*.aac", { import: "default" }) as Record<
  6. string,
  7. () => Promise<string>
  8. >
  9. return files
  10. }
  11. export const SOUND_OPTIONS = [
  12. { id: "alert-01", label: "sound.option.alert01" },
  13. { id: "alert-02", label: "sound.option.alert02" },
  14. { id: "alert-03", label: "sound.option.alert03" },
  15. { id: "alert-04", label: "sound.option.alert04" },
  16. { id: "alert-05", label: "sound.option.alert05" },
  17. { id: "alert-06", label: "sound.option.alert06" },
  18. { id: "alert-07", label: "sound.option.alert07" },
  19. { id: "alert-08", label: "sound.option.alert08" },
  20. { id: "alert-09", label: "sound.option.alert09" },
  21. { id: "alert-10", label: "sound.option.alert10" },
  22. { id: "bip-bop-01", label: "sound.option.bipbop01" },
  23. { id: "bip-bop-02", label: "sound.option.bipbop02" },
  24. { id: "bip-bop-03", label: "sound.option.bipbop03" },
  25. { id: "bip-bop-04", label: "sound.option.bipbop04" },
  26. { id: "bip-bop-05", label: "sound.option.bipbop05" },
  27. { id: "bip-bop-06", label: "sound.option.bipbop06" },
  28. { id: "bip-bop-07", label: "sound.option.bipbop07" },
  29. { id: "bip-bop-08", label: "sound.option.bipbop08" },
  30. { id: "bip-bop-09", label: "sound.option.bipbop09" },
  31. { id: "bip-bop-10", label: "sound.option.bipbop10" },
  32. { id: "staplebops-01", label: "sound.option.staplebops01" },
  33. { id: "staplebops-02", label: "sound.option.staplebops02" },
  34. { id: "staplebops-03", label: "sound.option.staplebops03" },
  35. { id: "staplebops-04", label: "sound.option.staplebops04" },
  36. { id: "staplebops-05", label: "sound.option.staplebops05" },
  37. { id: "staplebops-06", label: "sound.option.staplebops06" },
  38. { id: "staplebops-07", label: "sound.option.staplebops07" },
  39. { id: "nope-01", label: "sound.option.nope01" },
  40. { id: "nope-02", label: "sound.option.nope02" },
  41. { id: "nope-03", label: "sound.option.nope03" },
  42. { id: "nope-04", label: "sound.option.nope04" },
  43. { id: "nope-05", label: "sound.option.nope05" },
  44. { id: "nope-06", label: "sound.option.nope06" },
  45. { id: "nope-07", label: "sound.option.nope07" },
  46. { id: "nope-08", label: "sound.option.nope08" },
  47. { id: "nope-09", label: "sound.option.nope09" },
  48. { id: "nope-10", label: "sound.option.nope10" },
  49. { id: "nope-11", label: "sound.option.nope11" },
  50. { id: "nope-12", label: "sound.option.nope12" },
  51. { id: "yup-01", label: "sound.option.yup01" },
  52. { id: "yup-02", label: "sound.option.yup02" },
  53. { id: "yup-03", label: "sound.option.yup03" },
  54. { id: "yup-04", label: "sound.option.yup04" },
  55. { id: "yup-05", label: "sound.option.yup05" },
  56. { id: "yup-06", label: "sound.option.yup06" },
  57. ] as const
  58. export type SoundOption = (typeof SOUND_OPTIONS)[number]
  59. export type SoundID = SoundOption["id"]
  60. function getLoads() {
  61. if (loads) return loads
  62. loads = Object.fromEntries(
  63. Object.entries(getFiles()).flatMap(([path, load]) => {
  64. const file = path.split("/").at(-1)
  65. if (!file) return []
  66. return [[file.replace(/\.aac$/, ""), load] as const]
  67. }),
  68. ) as Record<SoundID, () => Promise<string>>
  69. return loads
  70. }
  71. const cache = new Map<SoundID, Promise<string | undefined>>()
  72. export function soundSrc(id: string | undefined) {
  73. const loads = getLoads()
  74. if (!id || !(id in loads)) return Promise.resolve(undefined)
  75. const key = id as SoundID
  76. const hit = cache.get(key)
  77. if (hit) return hit
  78. const next = loads[key]().catch(() => undefined)
  79. cache.set(key, next)
  80. return next
  81. }
  82. export function playSound(src: string | undefined) {
  83. if (typeof Audio === "undefined") return
  84. if (!src) return
  85. const audio = new Audio(src)
  86. audio.play().catch(() => undefined)
  87. return () => {
  88. audio.pause()
  89. audio.currentTime = 0
  90. }
  91. }
  92. export function playSoundById(id: string | undefined) {
  93. return soundSrc(id).then((src) => playSound(src))
  94. }