From 1a76054261046ec939edd0d9e2037a8c0d8820b0 Mon Sep 17 00:00:00 2001 From: Pihkaal Date: Sun, 11 Feb 2024 23:15:04 +0100 Subject: [PATCH] feat(music): refactor and basic cava implementation --- src/App.tsx | 11 +-- src/components/Music/Cava.tsx | 82 +++++++++++++++++++ src/components/Music/Music.tsx | 49 ++++++++++++ src/components/Music/SpotifyPlayer.tsx | 79 ++++++++++++++++++ src/components/MusicPlayer.tsx | 106 ------------------------- src/components/MusicVisualizer.tsx | 5 -- 6 files changed, 212 insertions(+), 120 deletions(-) create mode 100644 src/components/Music/Cava.tsx create mode 100644 src/components/Music/Music.tsx create mode 100644 src/components/Music/SpotifyPlayer.tsx delete mode 100644 src/components/MusicPlayer.tsx delete mode 100644 src/components/MusicVisualizer.tsx diff --git a/src/App.tsx b/src/App.tsx index fe0f275..26825d0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,10 +1,9 @@ import { BrowserRouter } from "react-router-dom"; -import { MusicPlayer } from "./components/MusicPlayer"; import { Kitty } from "./components/Kitty"; import { AppContextProvider } from "./context/AppContext"; import { Waybar } from "./components/Waybar/Waybar"; -import { MusicVisualizer } from "./components/MusicVisualizer"; import { useState } from "react"; +import { Music } from "./components/Music/Music"; function App() { const [clicked, setClicked] = useState(false); @@ -23,13 +22,7 @@ function App() {
- - - - - - - + {" "}
) : ( diff --git a/src/components/Music/Cava.tsx b/src/components/Music/Cava.tsx new file mode 100644 index 0000000..3af57c3 --- /dev/null +++ b/src/components/Music/Cava.tsx @@ -0,0 +1,82 @@ +import { Fragment, useRef, useEffect, useState } from "react"; +import { ProgressBar, Group, useFrame, useTerminal } from "react-dom-curse"; +import { theme } from "~/utils/theme"; + +export const Cava = () => { + const { width } = useTerminal(); + + const audioContext = useRef(new AudioContext()); + const analyser = useRef(audioContext.current.createAnalyser()); + const bufferLength = useRef(analyser.current.frequencyBinCount); + const dataArray = useRef(new Uint8Array(bufferLength.current)); + const [barHeights, setBarHeights] = useState( + new Array(Math.round(width / 3)).fill(0), + ); + + useEffect(() => { + const audioElement = document.querySelector("audio"); + if (!audioElement) return; + + const audioSource = + audioContext.current.createMediaElementSource(audioElement); + audioSource.connect(analyser.current); + analyser.current.connect(audioContext.current.destination); + audioElement.play(); + + return () => { + audioSource.disconnect(); + analyser.current.disconnect(); + }; + }, []); + + useFrame(() => { + analyser.current.getByteFrequencyData(dataArray.current); + + const barCount = Math.floor(width / 3); + const barHeights = []; + + for (let i = 0; i < barCount; i++) { + const startIndex = Math.floor((i / barCount) * bufferLength.current); + const endIndex = Math.floor(((i + 1) / barCount) * bufferLength.current); + const slice = dataArray.current.slice(startIndex, endIndex); + const sum = slice.reduce((acc, val) => acc + val, 0); + const average = sum / slice.length; + barHeights.push(average); + } + + setBarHeights(barHeights); + }); + + return ( + + {barHeights.map((height, x) => ( + + + + + ))} + + ); +}; diff --git a/src/components/Music/Music.tsx b/src/components/Music/Music.tsx new file mode 100644 index 0000000..7c135c2 --- /dev/null +++ b/src/components/Music/Music.tsx @@ -0,0 +1,49 @@ +import { useEffect, useRef, useState } from "react"; +import { parseBlob, type IAudioMetadata } from "music-metadata-browser"; + +import song from "/audio/colorful-flowers.mp3"; +import { Kitty } from "../Kitty"; +import { Cava } from "./Cava"; +import { SpotifyPlayer } from "./SpotifyPlayer"; + +export const Music = () => { + const [metadata, setMetadata] = useState(); + const [currentTime, setCurrentTime] = useState(0); + const audio = useRef(null); + + const handleTimeUpdate = () => { + setCurrentTime(audio.current?.currentTime ?? 0); + }; + + useEffect(() => { + if (metadata) return; + + void fetch(song) + .then(r => r.blob()) + .then(b => parseBlob(b)) + .then(setMetadata); + }, [metadata]); + + return ( + <> +