diff --git a/src/components/Player/Waveform3D.jsx b/src/components/Player/Waveform3D.jsx
new file mode 100644
index 0000000..213b97a
--- /dev/null
+++ b/src/components/Player/Waveform3D.jsx
@@ -0,0 +1,49 @@
+import { useRef, useMemo } from 'react'
+import { Canvas, useFrame } from '@react-three/fiber'
+import * as THREE from 'three'
+
+const BAR_COUNT = 28
+
+function Waveform({ isPlaying }) {
+ const barsRef = useRef([])
+ const phases = useMemo(() => Array.from({ length: BAR_COUNT }, () => Math.random() * Math.PI * 2), [])
+
+ useFrame(({ clock }) => {
+ const t = clock.getElapsedTime()
+ barsRef.current.forEach((mesh, i) => {
+ if (!mesh) return
+ const target = isPlaying
+ ? Math.abs(Math.sin(t * 3.5 + phases[i])) * 0.7 + 0.04
+ : 0.04 + Math.abs(Math.sin(t * 0.4 + phases[i])) * 0.08
+ mesh.scale.y = THREE.MathUtils.lerp(mesh.scale.y, target, 0.18)
+ mesh.position.y = mesh.scale.y * 0.5
+ })
+ })
+
+ return (
+
+ {Array.from({ length: BAR_COUNT }, (_, i) => (
+ (barsRef.current[i] = el)}
+ position={[(i - BAR_COUNT / 2) * 0.075, 0.04, 0]}
+ >
+
+
+
+ ))}
+
+ )
+}
+
+export default function Waveform3D({ isPlaying }) {
+ return (
+
+ )
+}