{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "card-place-4",
  "type": "registry:block",
  "title": "Card Place 4",
  "author": "Kenney <https://kenney.nl>",
  "description": "An extended, subtle sound of a virtual card being placed, useful for a smooth, unhurried placement animation.",
  "files": [
    {
      "path": "registry/soundcn/sounds/card-place-4/card-place-4.ts",
      "content": "import type { SoundAsset } from \"@/lib/sound-types\";\n\nexport const cardPlace4Sound: SoundAsset = {\n  name: \"card-place-4\",\n  dataUri: \"data:audio/mpeg;base64,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\",\n  duration: 0.601,\n  format: \"mp3\",\n  license: \"CC0\",\n  author: \"Kenney\",\n};\n",
      "type": "registry:lib"
    },
    {
      "path": "registry/soundcn/lib/sound-types.ts",
      "content": "export interface SoundAsset {\r\n  /** Unique identifier for the sound */\r\n  name: string;\r\n  /** Base64-encoded data URI (data:audio/mpeg;base64,...) */\r\n  dataUri: string;\r\n  /** Duration in seconds */\r\n  duration: number;\r\n  /** Audio format */\r\n  format: \"mp3\" | \"wav\" | \"ogg\";\r\n  /** License identifier */\r\n  license: \"CC0\" | \"OGA-BY\" | \"MIT\";\r\n  /** Original author/creator */\r\n  author: string;\r\n}\r\n\r\nexport interface UseSoundOptions {\r\n  /** Volume level from 0 to 1. Default: 1 */\r\n  volume?: number;\r\n  /** Playback speed multiplier. Default: 1 */\r\n  playbackRate?: number;\r\n  /** If true, calling play() stops current playback first. Default: false */\r\n  interrupt?: boolean;\r\n  /** If false, play() does nothing. Useful for user preferences. Default: true */\r\n  soundEnabled?: boolean;\r\n  /** Called when playback starts */\r\n  onPlay?: () => void;\r\n  /** Called when playback ends naturally */\r\n  onEnd?: () => void;\r\n  /** Called when pause() is called */\r\n  onPause?: () => void;\r\n  /** Called when stop() is called */\r\n  onStop?: () => void;\r\n}\r\n\r\nexport type PlayFunction = (overrides?: {\r\n  volume?: number;\r\n  playbackRate?: number;\r\n}) => void;\r\n\r\nexport interface SoundControls {\r\n  stop: () => void;\r\n  pause: () => void;\r\n  isPlaying: boolean;\r\n  duration: number | null;\r\n  sound: SoundAsset;\r\n}\r\n\r\nexport type UseSoundReturn = readonly [PlayFunction, SoundControls];\r\n",
      "type": "registry:lib"
    },
    {
      "path": "registry/soundcn/lib/sound-engine.ts",
      "content": "let audioContext: AudioContext | null = null;\nconst bufferCache = new Map<string, AudioBuffer>();\n\nexport function getAudioContext(): AudioContext {\n  if (!audioContext) {\n    audioContext = new AudioContext();\n  }\n  return audioContext;\n}\n\nexport async function decodeAudioData(dataUri: string): Promise<AudioBuffer> {\n  const cached = bufferCache.get(dataUri);\n  if (cached) return cached;\n\n  const ctx = getAudioContext();\n  const base64 = dataUri.split(\",\")[1];\n  const binaryString = atob(base64);\n  const bytes = new Uint8Array(binaryString.length);\n  for (let i = 0; i < binaryString.length; i++) {\n    bytes[i] = binaryString.charCodeAt(i);\n  }\n\n  const audioBuffer = await ctx.decodeAudioData(bytes.buffer.slice(0));\n  bufferCache.set(dataUri, audioBuffer);\n  return audioBuffer;\n}\n\nexport interface PlaySoundOptions {\n  volume?: number;\n  playbackRate?: number;\n  onEnd?: () => void;\n}\n\nexport interface SoundPlayback {\n  stop: () => void;\n}\n\nexport async function playSound(\n  dataUri: string,\n  options: PlaySoundOptions = {}\n): Promise<SoundPlayback> {\n  const { volume = 1, playbackRate = 1, onEnd } = options;\n  const ctx = getAudioContext();\n  if (ctx.state === \"suspended\") {\n    await ctx.resume();\n  }\n\n  const buffer = await decodeAudioData(dataUri);\n  const source = ctx.createBufferSource();\n  const gain = ctx.createGain();\n\n  source.buffer = buffer;\n  source.playbackRate.value = playbackRate;\n  gain.gain.value = volume;\n\n  source.connect(gain);\n  gain.connect(ctx.destination);\n\n  source.onended = () => {\n    onEnd?.();\n  };\n\n  source.start(0);\n\n  return {\n    stop: () => {\n      try {\n        source.stop();\n      } catch {\n        // No-op if already stopped.\n      }\n    },\n  };\n}\n",
      "type": "registry:lib"
    }
  ],
  "meta": {
    "duration": 0.601,
    "format": "mp3",
    "sizeKb": 5,
    "license": "CC0",
    "tags": [
      "card",
      "place",
      "4"
    ],
    "keywords": [
      "card",
      "place",
      "drop",
      "set",
      "put",
      "game",
      "ui",
      "extended",
      "subtle",
      "smooth",
      "interaction",
      "feedback",
      "lay",
      "play",
      "deal",
      "board",
      "surface",
      "gentle",
      "quiet",
      "deliberate",
      "flow",
      "calm"
    ]
  },
  "categories": [
    "card"
  ]
}