Sound Hook
lyminhnghia/use-soundFreeHook
Custom React hook to load and play a sound from a given URL using the Web Audio API.
Install it
npx shadcn@latest add https://lyminhnghia.github.io/r/use-sound.jsonSource
1"use client"23import { useCallback, useEffect, useRef, useState } from "react"45/**6 * Cache storage for loaded audio buffers to prevent duplicate network requests and memory usage.7 * Maps audio URL to its decoded AudioBuffer.8 */9const audioCache = new Map<10 string,11 {12 buffer: AudioBuffer13 loading: Promise<AudioBuffer>14 } | null15>()1617/**18 * Shared AudioContext instance to avoid creating multiple contexts.19 * Multiple AudioContexts can cause performance issues and resource exhaustion.20 */21let sharedAudioContext: AudioContext | null = null2223/**24 * Gets or creates a shared AudioContext instance.25 */26function getAudioContext(): AudioContext | null {27 if (sharedAudioContext) return sharedAudioContext2829 const AudioContextClass =30 window.AudioContext ||31 (window as unknown as { webkitAudioContext: typeof AudioContext })32 .webkitAudioContext3334 if (!AudioContextClass) {35 console.warn("Web Audio API is not supported in this browser.")36 return null37 }3839 sharedAudioContext = new AudioContextClass()40 return sharedAudioContext41}4243/**44 * Custom React hook to load and play a sound from a given URL using the Web Audio API.45 *46 * This hook implements caching to prevent duplicate network requests and memory usage47 * when the same audio file is used across multiple components.48 *49 * @param url - The URL of the audio file to load and play.50 * @returns A function that, when called, plays the loaded sound.51 *52 * @remarks53 * - Audio buffers are cached globally, so the same file is only loaded once54 * - Uses a shared AudioContext to avoid resource exhaustion55 * - If the Web Audio API is not supported in the browser, a warning is logged and playback is disabled56 * - Errors during fetching or decoding the audio are logged to the console57 *58 * @example59 * ```tsx60 * const playClick = useSound('/sounds/click.mp3');61 * // Later in an event handler:62 * playClick();63 * ```64 */65export function useSound(url: string) {66 const audioCtxRef = useRef<AudioContext | null>(null)67 const bufferRef = useRef<AudioBuffer | null>(null)6869 useEffect(() => {70 const audioCtx = getAudioContext()71 if (!audioCtx) return7273 audioCtxRef.current = audioCtx7475 // Check if already cached76 const cached = audioCache.get(url)77 if (cached?.buffer) {78 bufferRef.current = cached.buffer79 return80 }8182 // Check if already loading83 if (cached?.loading) {84 cached.loading85 .then((decoded) => {86 bufferRef.current = decoded87 })88// … truncated
Files it writes
More from lyminhnghia
All 26 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Controllable State Hookuse-controllable-state | lyminhnghia | Hooks | Free | no deps · 2 files |
