diff --git a/public/audio/asinine-vivement-quoi.mp3 b/public/audio/asinine-vivement-quoi.mp3 deleted file mode 100644 index 860c25a..0000000 Binary files a/public/audio/asinine-vivement-quoi.mp3 and /dev/null differ diff --git a/public/audio/mesmerizing_galaxy.mp3 b/public/audio/mesmerizing_galaxy.mp3 new file mode 100644 index 0000000..0e75f72 Binary files /dev/null and b/public/audio/mesmerizing_galaxy.mp3 differ diff --git a/src/components/Music/Cava.tsx b/src/components/Music/Cava.tsx index 98f8eae..3603884 100644 --- a/src/components/Music/Cava.tsx +++ b/src/components/Music/Cava.tsx @@ -1,15 +1,9 @@ -import { - type RefObject, - useCallback, - useEffect, - useRef, - useState, -} from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; import { type InnerKittyProps } from "~/utils/types"; import { CHAR_WIDTH } from "../Kitty"; import { useKitty } from "~/hooks/useKitty"; -export const Cava = (props: { audio: RefObject }) => { +export const Cava = (_props: {}) => { const kitty = useKitty(); return ( @@ -21,7 +15,7 @@ export const Cava = (props: { audio: RefObject }) => { gridTemplateRows: `1fr`, }} > - {kitty && } + {kitty && } ); }; @@ -62,31 +56,32 @@ const FrequencyBar = (props: { }; const InnerCava = (props: InnerKittyProps) => { - const sourceRef = useRef(null); + const sourceRef = useRef(null); const analyserRef = useRef(null); const audioContextRef = useRef(null); + const dataArray = useRef(null); const [barHeights, setBarHeights] = useState( new Array(Math.floor(props.cols / 3)).fill(0), ); const requestRef = useRef(); - const calculateBarHeights = useCallback(() => { - if (!analyserRef.current) return; + const calculateBarHeights = () => { + if (!dataArray.current || !analyserRef.current) return; - const bufferLength = analyserRef.current.frequencyBinCount; - const dataArray = new Uint8Array(bufferLength); - analyserRef.current.getByteFrequencyData(dataArray); + analyserRef.current.getByteFrequencyData(dataArray.current); - const barCount = Math.floor(props.cols / 3); + const barCount = Math.floor(props.cols / 2); const newBarHeights = []; for (let i = 0; i < barCount; i++) { - const startIndex = Math.floor((i / barCount) * bufferLength); - const endIndex = Math.floor(((i + 1) / barCount) * bufferLength); - const slice = dataArray.slice(startIndex, endIndex); + const startIndex = Math.floor((i / barCount) * dataArray.current.length); + const endIndex = Math.floor( + ((i + 1) / barCount) * dataArray.current.length, + ); + const slice = dataArray.current.slice(startIndex, endIndex); const sum = slice.reduce((acc, val) => acc + val, 0); const average = sum / slice.length; - newBarHeights.push(average); + newBarHeights.push(average * 0.9); } const stateBarHeights = @@ -95,45 +90,60 @@ const InnerCava = (props: InnerKittyProps) => { : barHeights; const smoothedBarHeights = newBarHeights.map((height, i) => { - const smoothingFactor = 1; + const smoothingFactor = 0.8; return ( - stateBarHeights[i]! + (height - stateBarHeights[i]!) * smoothingFactor + stateBarHeights[i] + (height - stateBarHeights[i]) * smoothingFactor ); }); setBarHeights(smoothedBarHeights); requestRef.current = requestAnimationFrame(calculateBarHeights); - }, [props.cols, barHeights]); + }; useEffect(() => { - const audioElement = props.audio.current; - if (!audioElement) return; + const fetchAudio = async () => { + try { + const audioContext = new AudioContext(); + audioContextRef.current = audioContext; - const audioContext = new AudioContext(); - audioContextRef.current = audioContext; + const response = await fetch("/audio/mesmerizing_galaxy.mp3"); + const arrayBuffer = await response.arrayBuffer(); + const audioBuffer = await audioContext.decodeAudioData(arrayBuffer); - const analyser = audioContext.createAnalyser(); - analyser.fftSize = 256; + const analyserNode = audioContext.createAnalyser(); + analyserNode.fftSize = 256; - void audioElement.play().then(() => void audioContext.resume()); + const source = audioContext.createBufferSource(); + source.buffer = audioBuffer; + source.loop = true; + source.connect(analyserNode); + analyserNode.connect(audioContext.destination); - if (!sourceRef.current) { - const source = audioContext.createMediaElementSource(audioElement); - source.connect(analyser); - analyser.connect(audioContext.destination); - sourceRef.current = source; - analyserRef.current = analyser; + analyserRef.current = analyserNode; + sourceRef.current = source; + dataArray.current = new Uint8Array(analyserNode.frequencyBinCount); + + requestRef.current = requestAnimationFrame(calculateBarHeights); + + source.start(); + } catch (error) { + console.error("Error fetching or decoding audio:", error); + } + }; + + if (audioContextRef.current) { + requestRef.current = requestAnimationFrame(calculateBarHeights); + } else { + fetchAudio(); } - requestRef.current = requestAnimationFrame(calculateBarHeights); - return () => { if (requestRef.current) cancelAnimationFrame(requestRef.current); }; - }, [props.cols, props.audio]); + }, [calculateBarHeights]); - return barHeights.map((value, i) => ( - + return barHeights.map((height, i) => ( + )); }; diff --git a/src/components/Music/SpotifyPlayer.tsx b/src/components/Music/SpotifyPlayer.tsx index efb5419..cd8bfcb 100644 --- a/src/components/Music/SpotifyPlayer.tsx +++ b/src/components/Music/SpotifyPlayer.tsx @@ -1,4 +1,3 @@ -import { useState } from "react"; import { formatMMSS } from "../../utils/time"; import { CharArray } from "../../utils/string"; import { CHAR_HEIGHT, CHAR_WIDTH } from "../Kitty"; diff --git a/src/components/Music/index.tsx b/src/components/Music/index.tsx index 8e782bb..d7fd42f 100644 --- a/src/components/Music/index.tsx +++ b/src/components/Music/index.tsx @@ -3,6 +3,7 @@ import { Kitty } from "../Kitty"; import { SpotifyPlayer } from "./SpotifyPlayer"; import { useApp } from "~/hooks/useApp"; import { cn, hideIf } from "~/utils/react"; +import { Cava } from "./Cava"; export type CurrentlyPlaying = { item: { @@ -22,7 +23,7 @@ export const Music = () => { useEffect(() => { const fetchCurrentlyPlaying = () => - fetch("http://213.210.20.230:3000/currently-playing?format=json") + fetch("https://api.pihkaal.me/currently-playing?format=json") .then((r) => r.json()) .then((data: CurrentlyPlaying) => { data.progress_ms = Math.max(0, data.progress_ms - 1500); @@ -72,7 +73,7 @@ export const Music = () => { )} rows={5} > - {/**/} + );