Audio Visualizer Update

This commit is contained in:
2025-03-29 22:18:56 -04:00
parent fd1ac0a0d7
commit da6038f2b2

View File

@@ -308,17 +308,26 @@
// Create audio processor node // Create audio processor node
const source = audioContext.createMediaStreamSource(stream); const source = audioContext.createMediaStreamSource(stream);
// Set up analyser for visualization // Set up analyser for visualization with better settings
analyser = audioContext.createAnalyser(); analyser = audioContext.createAnalyser();
analyser.fftSize = 256; analyser.fftSize = 256;
analyser.smoothingTimeConstant = 0.8; // Add smoothing for nicer visualization
analyser.minDecibels = -90;
analyser.maxDecibels = -10;
visualizerBufferLength = analyser.frequencyBinCount; visualizerBufferLength = analyser.frequencyBinCount;
visualizerDataArray = new Uint8Array(visualizerBufferLength); visualizerDataArray = new Uint8Array(visualizerBufferLength);
// Connect source to analyzer first
source.connect(analyser); source.connect(analyser);
// Hide the label when visualization is active // Hide the label when visualization is active
visualizerLabel.style.opacity = '0'; visualizerLabel.style.opacity = '0';
// Start drawing the visualization // Start drawing the visualization
if (visualizerAnimationFrame) {
cancelAnimationFrame(visualizerAnimationFrame);
}
drawVisualizer(); drawVisualizer();
// Set up processor for audio processing // Set up processor for audio processing
@@ -628,47 +637,81 @@
// Call initially and on window resize // Call initially and on window resize
resizeCanvas(); resizeCanvas();
window.addEventListener('resize', resizeCanvas); window.addEventListener('resize', resizeCanvas);
// Create placeholder data array (will be used before streaming starts)
visualizerBufferLength = 128; // Default size
visualizerDataArray = new Uint8Array(visualizerBufferLength);
} }
// Add the visualization drawing function // Add the visualization drawing function
function drawVisualizer() { function drawVisualizer() {
if (!isStreaming) { // Ensure we have the canvas context
if (visualizerAnimationFrame) { if (!canvasContext) {
cancelAnimationFrame(visualizerAnimationFrame); console.error("Canvas context not available");
visualizerAnimationFrame = null;
}
// Clear the canvas
canvasContext.clearRect(0, 0, visualizerCanvas.width, visualizerCanvas.height);
visualizerLabel.style.opacity = '0.7';
return; return;
} }
visualizerAnimationFrame = requestAnimationFrame(drawVisualizer); visualizerAnimationFrame = requestAnimationFrame(drawVisualizer);
// Get the frequency data // If we're streaming and have an analyzer, get the frequency data
if (isStreaming && analyser) {
try {
analyser.getByteFrequencyData(visualizerDataArray); analyser.getByteFrequencyData(visualizerDataArray);
} catch (e) {
console.error("Error getting frequency data:", e);
}
} else {
// If not streaming, gradually reduce all values to create a fade-out effect
for (let i = 0; i < visualizerDataArray.length; i++) {
visualizerDataArray[i] = Math.max(0, visualizerDataArray[i] - 5);
}
}
// Clear the canvas // Clear the canvas with a very slight background
canvasContext.clearRect(0, 0, visualizerCanvas.width, visualizerCanvas.height); canvasContext.fillStyle = 'rgba(245, 245, 245, 0.2)';
canvasContext.fillRect(0, 0, visualizerCanvas.width, visualizerCanvas.height);
// Calculate bar width based on canvas size and buffer length // Calculate bar width based on canvas size and buffer length
const barWidth = (visualizerCanvas.width / visualizerBufferLength) * 2.5; const width = visualizerCanvas.width;
let barHeight; const height = visualizerCanvas.height;
let x = 0; const barCount = Math.min(visualizerBufferLength, 64); // Limit bars for performance
const barWidth = width / barCount - 1; // Leave 1px gap
// Draw bars // Draw bars
for (let i = 0; i < visualizerBufferLength; i++) { for (let i = 0; i < barCount; i++) {
barHeight = visualizerDataArray[i] / 2; // Scale down to fit in canvas // Use a logarithmic scale for better visualization of lower frequencies
const index = Math.floor(i * visualizerBufferLength / barCount);
const value = visualizerDataArray[index];
// Use a gradient color based on frequency intensity // Scale height (values typically range from 0-255)
const hue = i / visualizerBufferLength * 180 + 180; // Blue to green spectrum const barHeight = (value / 255) * height;
canvasContext.fillStyle = `hsl(${hue}, 100%, ${50 + (barHeight / 2)}%)`;
canvasContext.fillRect(x, visualizerCanvas.height - barHeight, barWidth, barHeight); // Position x coordinate
const x = i * (barWidth + 1);
x += barWidth + 1; // Calculate gradient color based on frequency
const hue = 200 + (i / barCount * 60); // Blue to light-blue/cyan spectrum
const saturation = 90 - (value / 255 * 30); // More saturated for louder sounds
const lightness = 40 + (value / 255 * 30); // Brighter for louder sounds
// Draw the bar
canvasContext.fillStyle = `hsl(${hue}, ${saturation}%, ${lightness}%)`;
canvasContext.fillRect(x, height - barHeight, barWidth, barHeight);
// Add a subtle reflection
const gradientHeight = Math.min(10, barHeight / 3);
const gradient = canvasContext.createLinearGradient(
0, height - barHeight,
0, height - barHeight + gradientHeight
);
gradient.addColorStop(0, 'rgba(255, 255, 255, 0.3)');
gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
canvasContext.fillStyle = gradient;
canvasContext.fillRect(x, height - barHeight, barWidth, gradientHeight);
} }
// Only show the label when not streaming
visualizerLabel.style.opacity = isStreaming ? '0' : '0.7';
} }
</script> </script>
</body> </body>