feat: floor speed responds to BPM; skeleton glow reacts to bass
- Beat detection restored with BPM tracking (avg of last 8 beats) - Floor scroll speed = 0.025 * musicSpeed (BPM/120), slower by default - Skeleton drop-shadow intensity driven by bass energy Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
8a73e76e61
commit
7cd9f6bf2b
1 changed files with 21 additions and 4 deletions
|
|
@ -854,7 +854,7 @@ function resizeFloor() {
|
||||||
function drawFloor(ts) {
|
function drawFloor(ts) {
|
||||||
const dt = lastFloorTs ? Math.min((ts - lastFloorTs) / 1000, 0.1) : 0;
|
const dt = lastFloorTs ? Math.min((ts - lastFloorTs) / 1000, 0.1) : 0;
|
||||||
lastFloorTs = ts;
|
lastFloorTs = ts;
|
||||||
floorScroll = (floorScroll + 0.06 * dt) % 1;
|
floorScroll = (floorScroll + 0.025 * dt * (isPlaying ? musicSpeed : 0.4)) % 1;
|
||||||
|
|
||||||
const W = floorCanvas.width;
|
const W = floorCanvas.width;
|
||||||
const H = floorCanvas.height;
|
const H = floorCanvas.height;
|
||||||
|
|
@ -973,14 +973,31 @@ for (let i = 0; i < VU_COUNT; i++) {
|
||||||
|
|
||||||
// Beat detection
|
// Beat detection
|
||||||
const BASS_BARS = 4;
|
const BASS_BARS = 4;
|
||||||
let bassSmooth = 0, bassEma = 0;
|
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 beatWrap = document.querySelector('.beat-wrap');
|
||||||
const horizonEl = document.querySelector('.horizon');
|
const horizonEl = document.querySelector('.horizon');
|
||||||
|
const skeletonImg = document.querySelector('.skeleton-gif');
|
||||||
|
|
||||||
function detectBeat(vals) {
|
function detectBeat(vals) {
|
||||||
const bass = vals.slice(0, BASS_BARS).reduce((s, v) => s + v, 0) / BASS_BARS;
|
const bass = vals.slice(0, BASS_BARS).reduce((s, v) => s + v, 0) / BASS_BARS;
|
||||||
bassSmooth = bassSmooth * 0.6 + bass * 0.4;
|
bassSmooth = bassSmooth * 0.6 + bass * 0.4;
|
||||||
bassEma = bassEma * 0.96 + bass * 0.04;
|
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)
|
// Called with semicolon-separated CAVA values (0–100 per bar)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue