diff --git a/plugin/contents/ui/dancer.html b/plugin/contents/ui/dancer.html index cd2ef1e..4c2893c 100644 --- a/plugin/contents/ui/dancer.html +++ b/plugin/contents/ui/dancer.html @@ -854,7 +854,7 @@ function resizeFloor() { function drawFloor(ts) { const dt = lastFloorTs ? Math.min((ts - lastFloorTs) / 1000, 0.1) : 0; lastFloorTs = ts; - floorScroll = (floorScroll + 0.06 * dt) % 1; + floorScroll = (floorScroll + 0.025 * dt * (isPlaying ? musicSpeed : 0.4)) % 1; const W = floorCanvas.width; const H = floorCanvas.height; @@ -973,14 +973,31 @@ for (let i = 0; i < VU_COUNT; i++) { // Beat detection const BASS_BARS = 4; -let bassSmooth = 0, bassEma = 0; -const beatWrap = document.querySelector('.beat-wrap'); -const horizonEl = document.querySelector('.horizon'); +const BEAT_THRESH = 1.5; +const BEAT_COOLDOWN = 280; +let bassSmooth = 0, bassEma = 0, lastBeat = 0; +let beatTimes = [], musicSpeed = 0.5; +const beatWrap = document.querySelector('.beat-wrap'); +const horizonEl = document.querySelector('.horizon'); +const skeletonImg = document.querySelector('.skeleton-gif'); function detectBeat(vals) { const bass = vals.slice(0, BASS_BARS).reduce((s, v) => s + v, 0) / BASS_BARS; bassSmooth = bassSmooth * 0.6 + bass * 0.4; bassEma = bassEma * 0.96 + bass * 0.04; + const now = performance.now(); + if (bassSmooth > bassEma * BEAT_THRESH && bassSmooth > 8 && now - lastBeat > BEAT_COOLDOWN) { + lastBeat = now; + beatTimes.push(now); + if (beatTimes.length > 8) beatTimes.shift(); + if (beatTimes.length >= 2) { + const avg = beatTimes.slice(1).reduce((s, t, i) => s + t - beatTimes[i], 0) / (beatTimes.length - 1); + musicSpeed = Math.min(2.0, Math.max(0.4, 60000 / avg / 120)); + } + } + // Skeleton glow responds to bass energy + const glow = 15 + bassSmooth * 0.35; + skeletonImg.style.filter = `drop-shadow(0 0 ${glow.toFixed(1)}px rgba(0,200,255,${(0.25 + bassSmooth / 250).toFixed(2)}))`; } // Called with semicolon-separated CAVA values (0–100 per bar)