diff --git a/frontend/src/components/AudioVisualizer.tsx b/frontend/src/components/AudioVisualizer.tsx index 0d9345a..f0e4d1c 100644 --- a/frontend/src/components/AudioVisualizer.tsx +++ b/frontend/src/components/AudioVisualizer.tsx @@ -10,17 +10,14 @@ const MAX_AMPLITUDE = 0.22; const PADDING = 6; export default function AudioVisualizer({ height = 80 }: AudioVisualizerProps) { - const { isPlaying, currentTime, duration, getFrequencyData } = useAudio(); + const { isPlaying, currentTime, duration } = useAudio(); const canvasRef = useRef(null); const rafRef = useRef(0); const heightsRef = useRef(Array(NUM_POINTS).fill(0)); const playingRef = useRef(isPlaying); - const getDataRef = useRef(getFrequencyData); const timeRef = useRef({ currentTime, duration }); - const hasRealDataRef = useRef(false); useEffect(() => { playingRef.current = isPlaying; }, [isPlaying]); - useEffect(() => { getDataRef.current = getFrequencyData; }, [getFrequencyData]); useEffect(() => { timeRef.current = { currentTime, duration }; }, [currentTime, duration]); useEffect(() => { @@ -48,47 +45,21 @@ export default function AudioVisualizer({ height = 80 }: AudioVisualizerProps) { const animate = () => { if (!ctx || !canvas) return; frame++; - const raw = getDataRef.current?.(); const hts = heightsRef.current; const step = drawW / (NUM_POINTS - 1); const { currentTime: ct, duration: dur } = timeRef.current; const progress = dur > 0 ? ct / dur : 0; const playing = playingRef.current; - // Detect if real frequency data is available (CORS allows it) - if (raw && playing) { - const sum = raw.reduce((a, b) => a + b, 0); - hasRealDataRef.current = sum > 0; - } - - // Update heights + // Simulated waveform animation (Web Audio API not used to avoid CORS muting) if (playing) { - if (raw && hasRealDataRef.current) { - // Real frequency data from Web Audio API - for (let i = 0; i < NUM_POINTS; i++) { - const bucketSize = raw.length / NUM_POINTS; - const startIdx = Math.floor(i * bucketSize); - const endIdx = Math.floor((i + 1) * bucketSize); - let sum = 0; - let count = 0; - for (let j = startIdx; j < endIdx && j < raw.length; j++) { - sum += raw[j]; - count++; - } - const avg = count > 0 ? sum / count : 0; - const target = (avg / 255) * MAX_AMPLITUDE; - hts[i] += (target - hts[i]) * 0.25; - } - } else { - // Simulated visualization for cross-origin audio (no CORS) - for (let i = 0; i < NUM_POINTS; i++) { - const wave = Math.sin(frame * 0.04 + i * 0.35) * 0.5 + 0.5; - const noise = Math.sin(frame * 0.07 + i * 1.7) * 0.3 + 0.7; - const target = MAX_AMPLITUDE * 0.6 * (0.5 + wave * noise); - hts[i] += (target - hts[i]) * 0.18; - } + for (let i = 0; i < NUM_POINTS; i++) { + const wave = Math.sin(frame * 0.04 + i * 0.35) * 0.5 + 0.5; + const noise = Math.sin(frame * 0.07 + i * 1.7) * 0.3 + 0.7; + const target = MAX_AMPLITUDE * 0.6 * (0.5 + wave * noise); + hts[i] += (target - hts[i]) * 0.18; } - } else if (!playing) { + } else { for (let i = 0; i < NUM_POINTS; i++) { hts[i] += (0 - hts[i]) * 0.08; } diff --git a/frontend/src/context/AudioContext.tsx b/frontend/src/context/AudioContext.tsx index dc2d84f..310194c 100644 --- a/frontend/src/context/AudioContext.tsx +++ b/frontend/src/context/AudioContext.tsx @@ -33,9 +33,6 @@ const AudioContext = createContext(undefined); export function AudioProvider({ children }: { children: ReactNode }) { const audioRef = useRef(null); - const webAudioRef = useRef(null); - const analyserRef = useRef(null); - const dataArrayRef = useRef(null); const [currentEpisode, setCurrentEpisode] = useState(null); const [isPlaying, setIsPlaying] = useState(false); const [currentTime, setCurrentTime] = useState(0); @@ -107,44 +104,8 @@ export function AudioProvider({ children }: { children: ReactNode }) { }).catch(() => setIsResuming(false)); }, [currentEpisode?._id, userId]); - // Initialize Web Audio Analyser when audio element is available - useEffect(() => { - if (!audioRef.current || !currentEpisode) return; - - try { - const AudioCtx = (window as any).AudioContext || (window as any).webkitAudioContext; - if (!AudioCtx) return; - - const ctx = new AudioCtx(); - const source = ctx.createMediaElementSource(audioRef.current); - const analyser = ctx.createAnalyser(); - analyser.fftSize = 128; - analyser.smoothingTimeConstant = 0.8; - source.connect(analyser); - analyser.connect(ctx.destination); - - webAudioRef.current = ctx; - analyserRef.current = analyser; - dataArrayRef.current = new Uint8Array(analyser.frequencyBinCount); - } catch { - // Fallback: audio plays without visualizer - } - - return () => { - if (webAudioRef.current && webAudioRef.current.state !== 'closed') { - webAudioRef.current.close().catch(() => {}); - } - analyserRef.current = null; - dataArrayRef.current = null; - webAudioRef.current = null; - }; - }, [currentEpisode?._id]); - - const getFrequencyData = () => { - if (!analyserRef.current || !dataArrayRef.current) return null; - analyserRef.current.getByteFrequencyData(dataArrayRef.current as Uint8Array); - return dataArrayRef.current; - }; + // getFrequencyData returns null — visualizer uses simulated data + const getFrequencyData = () => null; // Actions const playEpisode = (episode: Episode) => { @@ -154,12 +115,6 @@ export function AudioProvider({ children }: { children: ReactNode }) { const closePlayer = () => { if (audioRef.current) audioRef.current.pause(); - if (webAudioRef.current && webAudioRef.current.state !== 'closed') { - webAudioRef.current.close().catch(() => {}); - } - analyserRef.current = null; - dataArrayRef.current = null; - webAudioRef.current = null; setCurrentEpisode(null); setIsPlaying(false); setCurrentTime(0);