fix(visualizer): improve responsiveness and visibility
- Increase FFT emit rate: ~21fps → ~60fps (interval 2048 → 735 samples) - Boost scale factor: 4x → 50x for more visible response - Gentler log mapping: powf(2.0) → powf(1.4) for better spread across bars - Faster smoothing: attack 0.7→0.85, decay 0.15→0.5 - Faster CSS transitions: 80ms → 35ms - Solid colors instead of gradients for better visibility
This commit is contained in:
1 parent
16b35c33fd
commit
7e17b74f99
2 files changed
+18
-20
No files matched your search
@@ -12,8 +12,8 @@ const OUTPUT_BINS: usize = 32;
|
||||
/// FFT window size (power of 2 for efficiency)
|
||||
const FFT_SIZE: usize = 1024;
|
||||
|
||||
/// How often to compute FFT (in samples) - roughly 20-30fps at 44.1kHz
|
||||
const FFT_INTERVAL: usize = 2048;
|
||||
/// How often to compute FFT (in samples) - ~60fps at 44.1kHz
|
||||
const FFT_INTERVAL: usize = 735;
|
||||
|
||||
/// Visualizer state shared between audio thread and emitter
|
||||
pub struct VisualizerState {
|
||||
@@ -133,34 +133,33 @@ impl VisualizerState {
|
||||
|
||||
let avg = if count > 0 { sum / count as f32 } else { 0.0 };
|
||||
|
||||
// Scale to 0-1 range (with some headroom)
|
||||
// The scaling factor is empirical - adjust for visual effect
|
||||
let scaled = (avg * 4.0 / FFT_SIZE as f32).min(1.0);
|
||||
// Scale to 0-1 range - higher multiplier for more visible response
|
||||
let scaled = (avg * 50.0 / FFT_SIZE as f32).min(1.0);
|
||||
|
||||
self.frequency_bins[i] = scaled;
|
||||
}
|
||||
|
||||
// Apply smoothing (fast attack, slow decay)
|
||||
// Apply smoothing (fast attack, fast decay for responsive feel)
|
||||
for i in 0..OUTPUT_BINS {
|
||||
let current = self.frequency_bins[i];
|
||||
let smoothed = self.smoothed_bins[i];
|
||||
|
||||
if current > smoothed {
|
||||
// Fast attack
|
||||
self.smoothed_bins[i] = smoothed + (current - smoothed) * 0.7;
|
||||
// Very fast attack
|
||||
self.smoothed_bins[i] = smoothed + (current - smoothed) * 0.85;
|
||||
} else {
|
||||
// Slow decay
|
||||
self.smoothed_bins[i] = smoothed + (current - smoothed) * 0.15;
|
||||
// Fast decay for snappy response
|
||||
self.smoothed_bins[i] = smoothed + (current - smoothed) * 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Logarithmic bin mapping for perceptual frequency distribution
|
||||
fn log_bin_start(&self, bin: usize, total_bins: usize) -> usize {
|
||||
// Map 0..OUTPUT_BINS to 0..total_bins logarithmically
|
||||
// This gives more resolution to lower frequencies
|
||||
// Map 0..OUTPUT_BINS to 0..total_bins with mild log curve
|
||||
// Less aggressive = more even distribution across all bars
|
||||
let ratio = bin as f32 / OUTPUT_BINS as f32;
|
||||
let log_ratio = ratio.powf(2.0); // Quadratic gives good distribution
|
||||
let log_ratio = ratio.powf(1.4); // Gentler curve for better spread
|
||||
(log_ratio * total_bins as f32) as usize
|
||||
}
|
||||
|
||||
|
||||
@@ -187,13 +187,12 @@
|
||||
flex: 1;
|
||||
max-width: 20px;
|
||||
height: var(--height);
|
||||
background: linear-gradient(to top, var(--color), transparent);
|
||||
background: var(--color);
|
||||
border-radius: 4px 4px 0 0;
|
||||
/* GPU accelerated - only transform, no layout */
|
||||
transform: scaleY(1);
|
||||
transform-origin: bottom;
|
||||
transition: height 80ms ease-out;
|
||||
transition: height 35ms linear;
|
||||
will-change: height;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* Wave mode */
|
||||
@@ -209,7 +208,7 @@
|
||||
}
|
||||
|
||||
.wave-svg path {
|
||||
transition: d 80ms ease-out;
|
||||
transition: d 35ms linear;
|
||||
}
|
||||
|
||||
/* Mirror mode - bars going up and down from center */
|
||||
@@ -238,9 +237,9 @@
|
||||
width: 100%;
|
||||
height: var(--height);
|
||||
max-height: 48%;
|
||||
background: linear-gradient(to top, var(--color), transparent);
|
||||
background: var(--color);
|
||||
border-radius: 3px;
|
||||
transition: height 80ms ease-out;
|
||||
transition: height 35ms linear;
|
||||
will-change: height;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user