{
  "$schema": "https://www.cooki-ui.design/schema/registry-item.json",
  "name": "audio-spectrum-equalizer",
  "type": "registry:ui",
  "title": "Audio Spectrum Equalizer",
  "description": "Multi-band DSP real-time audio visualizer with peak hold meters, decibel telemetry, and master gain controls.",
  "category": "media",
  "dependencies": [
    "@phosphor-icons/react"
  ],
  "files": [
    {
      "path": "registry/media/audio-spectrum-equalizer/audio-spectrum-equalizer.tsx",
      "type": "registry:ui",
      "target": "components/ui/audio-spectrum-equalizer.tsx",
      "content": "import React, { useState, useEffect, useRef } from 'react';\nimport { Play, Pause, SpeakerHigh, SpeakerSlash, Waveform, Sliders } from '@phosphor-icons/react';\n\nexport interface AudioSpectrumEqualizerProps {\n  barCount?: number;\n  barColor?: 'cyan' | 'violet' | 'emerald' | 'amber';\n  height?: number;\n  interactive?: boolean;\n  showDbMeter?: boolean;\n  className?: string;\n}\n\nconst COLOR_MAP = {\n  cyan: {\n    bar: 'bg-cyan-500',\n    barGradient: 'from-cyan-400 to-blue-600',\n    peak: 'bg-cyan-300',\n    glow: 'shadow-[0_0_12px_rgba(6,182,212,0.5)]',\n    accent: 'text-cyan-400',\n    badge: 'bg-cyan-500/10 text-cyan-400 border-cyan-500/20'\n  },\n  violet: {\n    bar: 'bg-violet-500',\n    barGradient: 'from-violet-400 to-indigo-600',\n    peak: 'bg-violet-300',\n    glow: 'shadow-[0_0_12px_rgba(139,92,246,0.5)]',\n    accent: 'text-violet-400',\n    badge: 'bg-violet-500/10 text-violet-400 border-violet-500/20'\n  },\n  emerald: {\n    bar: 'bg-emerald-500',\n    barGradient: 'from-emerald-400 to-teal-600',\n    peak: 'bg-emerald-300',\n    glow: 'shadow-[0_0_12px_rgba(16,185,129,0.5)]',\n    accent: 'text-emerald-400',\n    badge: 'bg-emerald-500/10 text-emerald-400 border-emerald-500/20'\n  },\n  amber: {\n    bar: 'bg-amber-500',\n    barGradient: 'from-amber-400 to-orange-600',\n    peak: 'bg-amber-300',\n    glow: 'shadow-[0_0_12px_rgba(245,158,11,0.5)]',\n    accent: 'text-amber-400',\n    badge: 'bg-amber-500/10 text-amber-400 border-amber-500/20'\n  }\n};\n\nexport const AudioSpectrumEqualizer: React.FC<AudioSpectrumEqualizerProps> = ({\n  barCount = 24,\n  barColor = 'cyan',\n  height = 140,\n  interactive = true,\n  showDbMeter = true,\n  className = '',\n}) => {\n  const [isPlaying, setIsPlaying] = useState(true);\n  const [isMuted, setIsMuted] = useState(false);\n  const [gain, setGain] = useState(78);\n  const [bands, setBands] = useState<number[]>(() => Array.from({ length: barCount }, () => Math.random() * 80 + 10));\n  const [peaks, setPeaks] = useState<number[]>(() => Array.from({ length: barCount }, () => 90));\n  const animRef = useRef<number | null>(null);\n\n  const colors = COLOR_MAP[barColor] || COLOR_MAP.cyan;\n\n  useEffect(() => {\n    let tick = 0;\n    const updateSpectrum = () => {\n      tick += 0.08;\n      if (isPlaying && !isMuted) {\n        setBands(prev => {\n          const next = prev.map((val, idx) => {\n            const freqBias = Math.sin(tick * 1.5 + idx * 0.4) * 20;\n            const target = Math.max(8, Math.min(100, (Math.sin(tick + idx * 0.3) * 35 + 45) + freqBias + (Math.random() * 20 - 10)));\n            return target * (gain / 100);\n          });\n          \n          setPeaks(prevPeaks => \n            prevPeaks.map((peak, idx) => {\n              const current = next[idx];\n              if (current > peak) return current;\n              return Math.max(current, peak - 1.5);\n            })\n          );\n\n          return next;\n        });\n      } else {\n        setBands(prev => prev.map(val => Math.max(4, val * 0.85)));\n        setPeaks(prev => prev.map(val => Math.max(4, val * 0.9)));\n      }\n      animRef.current = requestAnimationFrame(updateSpectrum);\n    };\n\n    animRef.current = requestAnimationFrame(updateSpectrum);\n    return () => {\n      if (animRef.current) cancelAnimationFrame(animRef.current);\n    };\n  }, [isPlaying, isMuted, gain, barCount]);\n\n  const avgDb = isPlaying && !isMuted ? (-36 + (gain * 0.32)).toFixed(1) : '-96.0';\n  const peakDb = isPlaying && !isMuted ? (-12 + (gain * 0.11)).toFixed(1) : '-96.0';\n\n  return (\n    <div className={`w-full max-w-xl mx-auto rounded-3xl border border-zinc-200 dark:border-white/10 bg-white/90 dark:bg-[#090a0f] p-6 shadow-2xl backdrop-blur-xl font-mono text-xs select-none ${className}`}>\n      {/* Header telemetry */}\n      <div className=\"flex items-center justify-between pb-4 border-b border-zinc-200/80 dark:border-white/5\">\n        <div className=\"flex items-center gap-3\">\n          <div className=\"flex h-8 w-8 items-center justify-center rounded-xl bg-zinc-100 dark:bg-white/5 text-zinc-900 dark:text-white\">\n            <Waveform size={18} weight=\"bold\" className={isPlaying && !isMuted ? colors.accent : 'text-zinc-400'} />\n          </div>\n          <div>\n            <h3 className=\"font-bold text-zinc-900 dark:text-white text-sm\">DSP Spectrum Equalizer</h3>\n            <span className=\"text-[11px] text-zinc-400\">24-Bit / 96kHz Low-Latency Float Stream</span>\n          </div>\n        </div>\n\n        <span className={`px-2.5 py-1 rounded-full text-[10px] font-bold border uppercase ${isPlaying && !isMuted ? colors.badge : 'bg-zinc-100 dark:bg-white/5 text-zinc-400 border-zinc-200 dark:border-white/10'}`}>\n          {isPlaying && !isMuted ? 'LIVE AUDIO' : 'PAUSED'}\n        </span>\n      </div>\n\n      {/* Main Spectrum Visualizer Viewport */}\n      <div \n        style={{ height: `${height}px` }} \n        className=\"relative flex items-end justify-between gap-1 sm:gap-1.5 my-6 px-3 py-2 rounded-2xl bg-zinc-100/60 dark:bg-black/40 border border-zinc-200/60 dark:border-white/5 overflow-hidden\"\n      >\n        {/* Horizontal dB reference lines */}\n        <div className=\"pointer-events-none absolute inset-x-0 top-1/4 border-b border-zinc-200/40 dark:border-white/5\" />\n        <div className=\"pointer-events-none absolute inset-x-0 top-2/4 border-b border-zinc-200/40 dark:border-white/5\" />\n        <div className=\"pointer-events-none absolute inset-x-0 top-3/4 border-b border-zinc-200/40 dark:border-white/5\" />\n\n        {bands.slice(0, barCount).map((level, idx) => {\n          const peak = peaks[idx] || level;\n          return (\n            <div key={idx} className=\"relative flex-1 h-full flex flex-col justify-end items-center group\">\n              {/* Peak indicator dot */}\n              <div \n                style={{ bottom: `${peak}%` }}\n                className={`absolute w-full h-[3px] rounded-full transition-all duration-75 ${colors.peak} ${colors.glow}`}\n              />\n\n              {/* Dynamic Frequency Bar */}\n              <div \n                style={{ height: `${level}%` }}\n                className={`w-full rounded-t-sm bg-gradient-to-t ${colors.barGradient} transition-all duration-75 ${level > 65 ? colors.glow : ''}`}\n              />\n            </div>\n          );\n        })}\n      </div>\n\n      {/* Decibel & Channel Readout */}\n      {showDbMeter && (\n        <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-2 mb-5 p-3 rounded-2xl bg-zinc-100/50 dark:bg-white/[0.02] border border-zinc-200/60 dark:border-white/5 text-[11px]\">\n          <div>\n            <span className=\"text-zinc-400 block text-[10px]\">RMS GAIN</span>\n            <span className=\"font-bold text-zinc-900 dark:text-white\">{avgDb} dB</span>\n          </div>\n          <div>\n            <span className=\"text-zinc-400 block text-[10px]\">PEAK HOLD</span>\n            <span className=\"font-bold text-zinc-900 dark:text-white\">{peakDb} dB</span>\n          </div>\n          <div>\n            <span className=\"text-zinc-400 block text-[10px]\">CHANNELS</span>\n            <span className=\"font-bold text-zinc-900 dark:text-white\">STEREO 2.0</span>\n          </div>\n          <div>\n            <span className=\"text-zinc-400 block text-[10px]\">SAMPLE RATE</span>\n            <span className=\"font-bold text-zinc-900 dark:text-white\">96,000 Hz</span>\n          </div>\n        </div>\n      )}\n\n      {/* Interactive Controls Bar */}\n      {interactive && (\n        <div className=\"flex flex-wrap items-center justify-between gap-4 pt-3 border-t border-zinc-200/80 dark:border-white/5\">\n          <div className=\"flex items-center gap-2\">\n            <button\n              onClick={() => setIsPlaying(!isPlaying)}\n              className=\"flex h-8 w-8 items-center justify-center rounded-xl bg-zinc-900 text-white dark:bg-white dark:text-zinc-900 hover:scale-105 active:scale-95 transition-all cursor-pointer shadow-md\"\n              aria-label={isPlaying ? 'Pause audio' : 'Play audio'}\n            >\n              {isPlaying ? <Pause size={14} weight=\"bold\" /> : <Play size={14} weight=\"fill\" />}\n            </button>\n\n            <button\n              onClick={() => setIsMuted(!isMuted)}\n              className=\"flex h-8 w-8 items-center justify-center rounded-xl border border-zinc-200 dark:border-white/10 bg-zinc-100 dark:bg-white/5 text-zinc-600 dark:text-zinc-300 hover:text-zinc-900 dark:hover:text-white transition-colors cursor-pointer\"\n              aria-label={isMuted ? 'Unmute' : 'Mute'}\n            >\n              {isMuted ? <SpeakerSlash size={14} weight=\"bold\" /> : <SpeakerHigh size={14} weight=\"bold\" />}\n            </button>\n          </div>\n\n          {/* Master Gain Slider */}\n          <div className=\"flex items-center gap-2.5 flex-1 max-w-[200px]\">\n            <Sliders size={14} className=\"text-zinc-400 shrink-0\" />\n            <input\n              type=\"range\"\n              min=\"0\"\n              max=\"100\"\n              value={isMuted ? 0 : gain}\n              onChange={(e) => {\n                setGain(Number(e.target.value));\n                if (isMuted) setIsMuted(false);\n              }}\n              className=\"w-full h-1.5 bg-zinc-200 dark:bg-white/10 rounded-lg appearance-none cursor-pointer accent-cyan-500\"\n              aria-label=\"Master Gain\"\n            />\n            <span className=\"text-[10px] text-zinc-400 font-mono w-7 text-right\">{isMuted ? 0 : gain}%</span>\n          </div>\n        </div>\n      )}\n    </div>\n  );\n};\n"
    }
  ]
}