"use client"; import React, { useState, useEffect, useRef } from "react"; import { Volume2, VolumeX } from "lucide-react"; export default function CosmicAudioToggle() { const [isPlaying, setIsPlaying] = useState(false); const audioCtxRef = useRef(null); const masterGainRef = useRef(null); const osc1Ref = useRef(null); const osc2Ref = useRef(null); const toggleSound = () => { if (isPlaying) { if (masterGainRef.current && audioCtxRef.current) { masterGainRef.current.gain.setTargetAtTime( 0, audioCtxRef.current.currentTime, 0.5 ); setTimeout(() => { setIsPlaying(false); }, 500); } } else { try { const AudioCtx = window.AudioContext || (window as unknown as { webkitAudioContext: typeof AudioContext }) .webkitAudioContext; const ctx = audioCtxRef.current || new AudioCtx(); audioCtxRef.current = ctx; if (ctx.state === "suspended") { ctx.resume(); } const masterGain = ctx.createGain(); masterGain.gain.setValueAtTime(0, ctx.currentTime); masterGain.gain.linearRampToValueAtTime(0.08, ctx.currentTime + 1.5); masterGain.connect(ctx.destination); masterGainRef.current = masterGain; // Lowpass filter for deep cosmic drone const filter = ctx.createBiquadFilter(); filter.type = "lowpass"; filter.frequency.setValueAtTime(140, ctx.currentTime); filter.Q.setValueAtTime(2, ctx.currentTime); filter.connect(masterGain); // Oscillator 1: 55Hz sub drone const osc1 = ctx.createOscillator(); osc1.type = "sine"; osc1.frequency.setValueAtTime(55, ctx.currentTime); osc1.connect(filter); osc1.start(); osc1Ref.current = osc1; // Oscillator 2: 110.2Hz warm harmonic with slight detune const osc2 = ctx.createOscillator(); osc2.type = "triangle"; osc2.frequency.setValueAtTime(110.3, ctx.currentTime); const osc2Gain = ctx.createGain(); osc2Gain.gain.setValueAtTime(0.03, ctx.currentTime); osc2.connect(osc2Gain); osc2Gain.connect(filter); osc2.start(); osc2Ref.current = osc2; setIsPlaying(true); } catch { // Fallback gracefully if Web Audio is blocked } } }; useEffect(() => { return () => { if (audioCtxRef.current && audioCtxRef.current.state !== "closed") { try { audioCtxRef.current.close(); } catch { // Ignore } } }; }, []); return ( ); }