Thursday, January 8, 2026

Paradime App.https://claude.ai/public/artifacts/2366f48b-b3de-4d5a-a05a-b432397df0a9


 https://claude.ai/public/artifacts/2366f48b-b3de-4d5a-a05a-b432397df0a9,import React, { useState, useEffect, useRef } from 'react';

import { Play, Pause, Volume2, Palette, Sparkles, Waves } from 'lucide-react';


const MusicVisualizer = () => {

  const [mode, setMode] = useState('particles');

  const [isPlaying, setIsPlaying] = useState(false);

  const [color, setColor] = useState('#00ffff');

  const [intensity, setIntensity] = useState(50);

  const canvasRef = useRef(null);

  const animationRef = useRef(null);

  const particlesRef = useRef([]);

  const timeRef = useRef(0);

  const audioContextRef = useRef(null);

  const analyserRef = useRef(null);

  const dataArrayRef = useRef(null);


  const modes = [

    { id: 'particles', name: 'Particle Storm', icon: Sparkles },

    { id: 'waveform', name: 'Waveform', icon: Waves },

    { id: 'spectrum', name: 'Spectrum Bars', icon: Volume2 },

    { id: 'kaleidoscope', name: 'Kaleidoscope', icon: Palette }

  ];


  useEffect(() => {

    const canvas = canvasRef.current;

    if (!canvas) return;

    

    canvas.width = canvas.offsetWidth;

    canvas.height = canvas.offsetHeight;


    // Initialize particles

    for (let i = 0; i < 100; i++) {

      particlesRef.current.push({

        x: Math.random() * canvas.width,

        y: Math.random() * canvas.height,

        vx: (Math.random() - 0.5) * 2,

        vy: (Math.random() - 0.5) * 2,

        size: Math.random() * 3 + 1,

        hue: Math.random() * 360

      });

    }


    const handleResize = () => {

      canvas.width = canvas.offsetWidth;

      canvas.height = canvas.offsetHeight;

    };


    window.addEventListener('resize', handleResize);

    return () => window.removeEventListener('resize', handleResize);

  }, []);


  const initAudio = async () => {

    try {

      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });

      audioContextRef.current = new (window.AudioContext || window.webkitAudioContext)();

      analyserRef.current = audioContextRef.current.createAnalyser();

      analyserRef.current.fftSize = 256;

      

      const source = audioContextRef.current.createMediaStreamSource(stream);

      source.connect(analyserRef.current);

      

      const bufferLength = analyserRef.current.frequencyBinCount;

      dataArrayRef.current = new Uint8Array(bufferLength);

    } catch (err) {

      console.log('Audio input not available, using simulated data');

    }

  };


  const getAudioData = () => {

    if (analyserRef.current && dataArrayRef.current) {

      analyserRef.current.getByteFrequencyData(dataArrayRef.current);

      return dataArrayRef.current;

    }

    // Simulated audio data

    const simulated = new Uint8Array(128);

    for (let i = 0; i < simulated.length; i++) {

      simulated[i] = Math.sin(timeRef.current * 0.01 + i * 0.1) * 128 + 128;

    }

    return simulated;

  };


  const drawParticles = (ctx, audioData) => {

    const canvas = ctx.canvas;

    ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';

    ctx.fillRect(0, 0, canvas.width, canvas.height);


    const avgFreq = audioData.reduce((a, b) => a + b) / audioData.length;

    const scale = (avgFreq / 128) * (intensity / 50);


    particlesRef.current.forEach((p, i) => {

      const freq = audioData[i % audioData.length] / 255;

      

      p.x += p.vx * (1 + freq * scale);

      p.y += p.vy * (1 + freq * scale);


      if (p.x < 0 || p.x > canvas.width) p.vx *= -1;

      if (p.y < 0 || p.y > canvas.height) p.vy *= -1;


      p.x = Math.max(0, Math.min(canvas.width, p.x));

      p.y = Math.max(0, Math.min(canvas.height, p.y));


      const hue = (p.hue + freq * 50) % 360;

      ctx.fillStyle = `hsla(${hue}, 100%, 50%, ${0.8 * freq})`;

      ctx.beginPath();

      ctx.arc(p.x, p.y, p.size * (1 + freq * 2), 0, Math.PI * 2);

      ctx.fill();


      // Draw connections

      particlesRef.current.slice(i + 1, i + 4).forEach(p2 => {

        const dist = Math.hypot(p.x - p2.x, p.y - p2.y);

        if (dist < 100) {

          ctx.strokeStyle = `hsla(${hue}, 100%, 50%, ${0.2 * (1 - dist / 100)})`;

          ctx.lineWidth = 1;

          ctx.beginPath();

          ctx.moveTo(p.x, p.y);

          ctx.lineTo(p2.x, p2.y);

          ctx.stroke();

        }

      });

    });

  };


  const drawWaveform = (ctx, audioData) => {

    const canvas = ctx.canvas;

    ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';

    ctx.fillRect(0, 0, canvas.width, canvas.height);


    const sliceWidth = canvas.width / audioData.length;

    

    for (let pass = 0; pass < 3; pass++) {

      ctx.beginPath();

      ctx.lineWidth = 3;

      

      for (let i = 0; i < audioData.length; i++) {

        const x = i * sliceWidth;

        const v = audioData[i] / 255;

        const y = canvas.height / 2 + (v - 0.5) * canvas.height * (intensity / 50) * Math.sin(timeRef.current * 0.001 + pass);

        

        if (i === 0) {

          ctx.moveTo(x, y);

        } else {

          ctx.lineTo(x, y);

        }

      }

      

      const hue = (timeRef.current * 0.5 + pass * 120) % 360;

      ctx.strokeStyle = `hsla(${hue}, 100%, 50%, 0.6)`;

      ctx.stroke();

    }

  };


  const drawSpectrum = (ctx, audioData) => {

    const canvas = ctx.canvas;

    ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';

    ctx.fillRect(0, 0, canvas.width, canvas.height);


    const barWidth = canvas.width / audioData.length;

    

    audioData.forEach((value, i) => {

      const height = (value / 255) * canvas.height * (intensity / 50);

      const x = i * barWidth;

      const hue = (i / audioData.length) * 360;

      

      const gradient = ctx.createLinearGradient(x, canvas.height - height, x, canvas.height);

      gradient.addColorStop(0, `hsla(${hue}, 100%, 50%, 0.8)`);

      gradient.addColorStop(1, `hsla(${(hue + 60) % 360}, 100%, 30%, 0.8)`);

      

      ctx.fillStyle = gradient;

      ctx.fillRect(x, canvas.height - height, barWidth - 2, height);

      

      // Reflection

      ctx.fillStyle = `hsla(${hue}, 100%, 50%, 0.2)`;

      ctx.fillRect(x, canvas.height, barWidth - 2, height * 0.3);

    });

  };


  const drawKaleidoscope = (ctx, audioData) => {

    const canvas = ctx.canvas;

    ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';

    ctx.fillRect(0, 0, canvas.width, canvas.height);


    const centerX = canvas.width / 2;

    const centerY = canvas.height / 2;

    const segments = 8;


    ctx.save();

    ctx.translate(centerX, centerY);


    for (let seg = 0; seg < segments; seg++) {

      ctx.save();

      ctx.rotate((Math.PI * 2 * seg) / segments);


      audioData.forEach((value, i) => {

        const radius = (i / audioData.length) * Math.min(centerX, centerY) * (intensity / 50);

        const size = (value / 255) * 20;

        const angle = (i / audioData.length) * Math.PI * 2 + timeRef.current * 0.001;

        

        const x = Math.cos(angle) * radius;

        const y = Math.sin(angle) * radius;

        

        const hue = (timeRef.current * 0.5 + i) % 360;

        ctx.fillStyle = `hsla(${hue}, 100%, 50%, 0.6)`;

        ctx.fillRect(x - size / 2, y - size / 2, size, size);

      });


      ctx.restore();

    }


    ctx.restore();

  };


  const animate = () => {

    const canvas = canvasRef.current;

    if (!canvas) return;


    const ctx = canvas.getContext('2d');

    const audioData = getAudioData();


    timeRef.current++;


    switch (mode) {

      case 'particles':

        drawParticles(ctx, audioData);

        break;

      case 'waveform':

        drawWaveform(ctx, audioData);

        break;

      case 'spectrum':

        drawSpectrum(ctx, audioData);

        break;

      case 'kaleidoscope':

        drawKaleidoscope(ctx, audioData);

        break;

    }


    if (isPlaying) {

      animationRef.current = requestAnimationFrame(animate);

    }

  };


  useEffect(() => {

    if (isPlaying) {

      animate();

    } else if (animationRef.current) {

      cancelAnimationFrame(animationRef.current);

    }


    return () => {

      if (animationRef.current) {

        cancelAnimationFrame(animationRef.current);

      }

    };

  }, [isPlaying, mode, intensity]);


  const togglePlay = async () => {

    if (!isPlaying && !audioContextRef.current) {

      await initAudio();

    }

    setIsPlaying(!isPlaying);

  };


  return (

    <div className="w-full h-screen bg-black flex flex-col">

      <div className="flex-1 relative">

        <canvas

          ref={canvasRef}

          className="w-full h-full"

        />

      </div>


      <div className="bg-gray-900 p-4 space-y-4">

        <div className="flex items-center justify-center gap-4">

          <button

            onClick={togglePlay}

            className="bg-cyan-500 hover:bg-cyan-600 text-white p-4 rounded-full transition-colors"

          >

            {isPlaying ? <Pause size={24} /> : <Play size={24} />}

          </button>

        </div>


        <div className="grid grid-cols-2 md:grid-cols-4 gap-2">

          {modes.map((m) => {

            const Icon = m.icon;

            return (

              <button

                key={m.id}

                onClick={() => setMode(m.id)}

                className={`p-3 rounded-lg flex flex-col items-center gap-2 transition-colors ${

                  mode === m.id

                    ? 'bg-cyan-500 text-white'

                    : 'bg-gray-800 text-gray-300 hover:bg-gray-700'

                }`}

              >

                <Icon size={20} />

                <span className="text-sm">{m.name}</span>

              </button>

            );

          })}

        </div>


        <div className="space-y-2">

          <label className="text-white text-sm flex items-center gap-2">

            <Sparkles size={16} />

            Intensity: {intensity}%

          </label>

          <input

            type="range"

            min="10"

            max="100"

            value={intensity}

            onChange={(e) => setIntensity(Number(e.target.value))}

            className="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer"

            style={{

              accentColor: '#06b6d4'

            }}

          />

        </div>


        <div className="text-center text-gray-400 text-sm space-y-1">

          <p>🎵 Play your music from YouTube/Spotify/etc alongside this visualizer</p>

          <p>💡 Perfect for MagicLight A.I. - screen colors sync with the beat!</p>

          <p>🎤 Grant microphone permission for audio-reactive mode</p>https://claude.ai/public/artifacts/2366f48b-b3de-4d5a-a05a-b432397df0a9

        </div>

      </div>https://claude.ai/public/artifacts/2366f48b-b3de-4d5a-a05a-b432397df0a9

    </div>


  );

};



export default MusicVisualizer;https://claude.ai/public/artifacts/2366f48b-b3de-4d5a-a05a-b432397df0a9

No comments:

Post a Comment

Batman alpha7 protocolhttps://claude.ai/public/artifacts/904390fd-57fd-41d4-b084-8f188e3eb738

 https://claude.ai/public/artifacts/904390fd-57fd-41d4-b084-8f188e3eb738 https://claude.ai/public/artifacts/904390fd-57fd-41d4-b084-8f188e3e...