diff --git a/party-stage/src/scene/fps-counter.js b/party-stage/src/scene/fps-counter.js index e34d524..e6cb6ed 100644 --- a/party-stage/src/scene/fps-counter.js +++ b/party-stage/src/scene/fps-counter.js @@ -125,7 +125,7 @@ export class DebugPanel extends SceneFeature { this.history = new Array(this.canvas.width).fill(0); this.memHistory = new Array(this.memCanvas.width).fill(0); - this.musicHistory = new Array(this.musicCanvas.width).fill({l:0, la:0, low:0, lla:0, high:0, b:0, lt:0, qt:0, m:0.5, bo: false, al: 0}); + this.musicHistory = new Array(this.musicCanvas.width).fill({l:0, la:0, low:0, lla:0, high:0, b:0, lt:0, qt:0, m:0.5, bo: false, al: 0, bt: 0}); // Initialize visibility based on config if (state.config) { @@ -187,19 +187,20 @@ export class DebugPanel extends SceneFeature { const avgLoudness = state.music.averageLoudness || 0; const highs = state.music.loudnessHighs || 0; const beat = state.music.beatIntensity || 0; + const beatThreshold = state.music.beatThreshold || 0; const thresholds = state.music.thresholds || { loud: 0, quiet: 0 }; let modeVal = 0.5; if (state.music.mode === 'Loud') modeVal = 1.0; else if (state.music.mode === 'Quiet') modeVal = 0.0; - this.musicHistory.push({ l: loudness, la: loudnessAvg, low: lows, lla: lowsAvg, high: highs, b: beat, lt: thresholds.loud, qt: thresholds.quiet, m: modeVal, bo: state.blackoutMode, al: avgLoudness }); + this.musicHistory.push({ l: loudness, la: loudnessAvg, low: lows, lla: lowsAvg, high: highs, b: beat, lt: thresholds.loud, qt: thresholds.quiet, m: modeVal, bo: state.blackoutMode, al: avgLoudness, bt: beatThreshold }); if (this.musicHistory.length > this.musicCanvas.width) { this.musicHistory.shift(); } this.drawMusicGraph(); if (this.musicTextElement) { - this.musicTextElement.innerText = `Volume:${loudness.toFixed(2)}\nMode:${state.music.mode}\nBPM:${state.music.bpm}`; + this.musicTextElement.innerText = `Volume: ${loudness.toFixed(2)}\nBPM: ${state.music.bpm}`; } } } @@ -365,6 +366,19 @@ export class DebugPanel extends SceneFeature { } ctx.stroke(); + // Draw Beat Threshold (Cyan) + ctx.beginPath(); + ctx.strokeStyle = '#00ffff'; + ctx.lineWidth = 1; + for (let i = 0; i < this.musicHistory.length; i++) { + const val = this.musicHistory[i].bt !== undefined ? this.musicHistory[i].bt : 0; + const x = i; + const y = h - (val * h); + if (i === 0) ctx.moveTo(x, y); + else ctx.lineTo(x, y); + } + ctx.stroke(); + // Draw Active Threshold (Green for Loud/Blackout, Red for Quiet/Normal) ctx.lineWidth = 1; diff --git a/party-stage/src/scene/music-visualizer.js b/party-stage/src/scene/music-visualizer.js index d2480a1..bd8534e 100644 --- a/party-stage/src/scene/music-visualizer.js +++ b/party-stage/src/scene/music-visualizer.js @@ -26,13 +26,14 @@ export class MusicVisualizer extends SceneFeature { isLoudEnough: false, thresholds: { loud: 0, quiet: 0 }, mode: 'Normal', - bpm: 50, + bpm: 1, loudness: 0, loudnessLows: 0, loudnessHighs: 0, loudnessAverage: 0, loudnessLowsAverage: 0, - frequencyData: null + frequencyData: null, + beatThreshold: 0 }; this.beatPhase = 0; this.measurePhase = 0; @@ -99,20 +100,22 @@ export class MusicVisualizer extends SceneFeature { const beatAvg = state.music.loudnessLowsAverage || 0; // Decay threshold based on time - this.beatThreshold -= deltaTime * 0.8; + this.beatThreshold -= deltaTime * 0.5; const thresholdFloor = Math.max(0.15, beatAvg * 1.1); if (this.beatThreshold < thresholdFloor) this.beatThreshold = thresholdFloor; - if (beatSignal > this.beatThreshold) { - const now = time; - if (now - this.lastBeatTime > 0.25) { // Min interval (~240 BPM) - const interval = now - this.lastBeatTime; - this.lastBeatTime = now; - this.beatThreshold = beatSignal * 1.1; // Bump threshold + state.music.beatThreshold = this.beatThreshold; - // Valid BPM range: 50-200 (interval 1.2s - 0.3s) - if (interval >= 0.3 && interval <= 1.2) { - this.beatIntervals.push(interval); + const now = time; + const lastBeatInterval = now - this.lastBeatTime; + if (beatSignal > this.beatThreshold) { + if (lastBeatInterval > 0.25) { // Min interval (~240 BPM) + this.lastBeatTime = now; + this.beatThreshold = beatSignal * 1.2; // Bump threshold + + // Add only valid BPM range into history of beats + if (lastBeatInterval >= 0.2 && lastBeatInterval <= 1.5) { + this.beatIntervals.push(lastBeatInterval); if (this.beatIntervals.length > 8) this.beatIntervals.shift(); const avgInterval = this.beatIntervals.reduce((a, b) => a + b, 0) / this.beatIntervals.length; @@ -136,7 +139,8 @@ export class MusicVisualizer extends SceneFeature { if (this.measurePhase >= 1) this.measurePhase -= 1; // --- Calculate Beat Intensity --- - state.music.beatIntensity = Math.pow(1.0 - this.beatPhase, 2); + const realBeatFactor = lastBeatInterval < 1.0 ? 1.0 : ((lastBeatInterval > 5) ? 0.0 : (5 - lastBeatInterval)/5); + state.music.beatIntensity = Math.pow(1.0 - this.beatPhase, 2) * realBeatFactor; // --- Calculate Measure Pulse --- state.music.measurePulse = this.measurePhase < 0.2 ? Math.sin(this.measurePhase * Math.PI * 5) : 0;