useSound
ncdai/use-soundUnverifiedHook
Hook for playing sound effects with volume, playback rate, and interrupt controls.
Install it
npx shadcn@latest add https://raw.githubusercontent.com/Untel/untel.github.io/master/public/r/use-sound.jsonSource
1"use client"23import { useCallback, useEffect, useRef, useState } from "react"45import {6 fetchAndDecodeAudio,7 getAudioContext,8} from "@/registry/lib/sound/sound-engine"9import type {10 PlayFunction,11 SoundControls,12 UseSoundOptions,13 UseSoundReturn,14} from "@/registry/lib/sound/sound-types"1516export function useSound(17 url: string,18 options: UseSoundOptions = {}19): UseSoundReturn {20 const {21 volume = 1,22 playbackRate = 1,23 interrupt = false,24 soundEnabled = true,25 lazy = false,26 onPlay,27 onEnd,28 onPause,29 onStop,30 } = options3132 const [isPlaying, setIsPlaying] = useState(false)3334 const sourceRef = useRef<AudioBufferSourceNode | null>(null)35 const gainRef = useRef<GainNode | null>(null)36 const bufferRef = useRef<AudioBuffer | null>(null)3738 useEffect(() => {39 bufferRef.current = null4041 if (lazy) return4243 let cancelled = false4445 fetchAndDecodeAudio(url).then((buffer) => {46 if (cancelled) return47 bufferRef.current = buffer48 })4950 return () => {51 cancelled = true52 }53 }, [url, lazy])5455 const stop = useCallback(() => {56 if (sourceRef.current) {57 try {58 sourceRef.current.stop()59 } catch {60 // Already stopped.61 }62 sourceRef.current = null63 }64 setIsPlaying(false)65 onStop?.()66 }, [onStop])6768 const play: PlayFunction = useCallback(69 (overrides?) => {70 if (!soundEnabled) return7172 const startPlayback = (buffer: AudioBuffer) => {73 const ctx = getAudioContext()7475 if (ctx.state === "suspended") {76 ctx.resume()77 }7879 if (interrupt && sourceRef.current) {80 stop()81 }8283 const source = ctx.createBufferSource()84 const gain = ctx.createGain()8586 source.buffer = buffer87 source.playbackRate.value = overrides?.playbackRate ?? playbackRate88 gain.gain.value = overrides?.volume ?? volume8990 source.connect(gain)91 gain.connect(ctx.destination)9293 source.onended = () => {94 setIsPlaying(false)95 onEnd?.()96 }9798 source.start(0)99 sourceRef.current = source100 gainRef.current = gain101 setIsPlaying(true)102 onPlay?.()103 }104105 if (bufferRef.current) {106 startPlayback(bufferRef.current)107 return108 }109110 // Lazy: load on first play, then play immediately.111 fetchAndDecodeAudio(url).then((buffer) => {112 bufferRef.current = buffer113 startPlayback(buffer)114 })115// … truncated
Files it writes
More from ncdai
All 17 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| useControllableStateuse-controllable-state | ncdai | Hooks | Unverified | no deps |
