waveform AI changes

Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2025-06-04 21:50:07 +02:00
padre d4a5527706
commit df2b634b9f

Ver fichero

@@ -1,5 +1,4 @@
import { useRef, useEffect, useState } from "react";
import useSize from "./useSize";
import { useRef, useEffect } from "react";
const BLUE_SHADES = [
"rgba(255,255,255,0.9)",
@@ -8,63 +7,20 @@ const BLUE_SHADES = [
"rgba(255,255,255,0.3)",
];
// Fallback animation for Tizen browsers without Web Audio API
const animateFallbackBars = (canvas, ctx, time) => {
const HEIGHT = canvas.height;
const WIDTH = canvas.width;
const barCount = 64;
const barWidth = WIDTH / barCount;
// Set rendering properties for better Tizen compatibility
ctx.imageSmoothingEnabled = false;
ctx.globalCompositeOperation = 'source-over';
for (let i = 0; i < barCount; i++) {
// Create animated wave pattern with smaller, more realistic bar heights
const wave1 = Math.sin(time * 0.003 + i * 0.3) * 0.4;
const wave2 = Math.sin(time * 0.002 + i * 0.2) * 0.3;
const normalizedHeight = Math.max(0.1, Math.min(0.4, 0.2 + wave1 + wave2));
const barHeight = Math.max(10, normalizedHeight * HEIGHT * 0.3); // Smaller bars like original
// Use original blue/white gradient colors
const intensity = normalizedHeight;
const blueShade = Math.min(3, Math.floor(intensity * 4));
// Create gradient for better visibility (bottom to top)
const barX = i * barWidth + 2;
const barW = barWidth - 4;
const barY = HEIGHT - barHeight; // Start from bottom
const gradient = ctx.createLinearGradient(0, HEIGHT, 0, barY);
gradient.addColorStop(0, BLUE_SHADES[3]);
gradient.addColorStop(0.5, BLUE_SHADES[blueShade] || BLUE_SHADES[0]);
gradient.addColorStop(1, BLUE_SHADES[0]);
ctx.fillStyle = gradient;
ctx.fillRect(barX, barY, barW, barHeight);
// Add glow effect like the Web Audio version
ctx.shadowColor = "rgba(255,255,255,0.8)";
ctx.shadowBlur = 5;
ctx.fillRect(barX, barY, barW, barHeight);
ctx.shadowBlur = 0;
}
};
// Real Web Audio API animation
const animateBars = (analyser, canvas, ctx, dataArray, bufferLength) => {
try {
analyser.getByteFrequencyData(dataArray);
const HEIGHT = canvas.height;
const barCount = Math.min(64, bufferLength); // Reduced for better visibility
const barWidth = Math.max(6, Math.floor(canvas.width / barCount));
const barCount = Math.min(128, bufferLength); // More bars for thinner appearance
const barWidth = Math.max(3, Math.floor(canvas.width / barCount)); // Thinner bars
const step = Math.floor(bufferLength / barCount);
let x = 0;
for (let i = 0; i < barCount; i++) {
const dataIndex = i * step;
const barHeight = Math.max(5, (dataArray[dataIndex] / 255) * HEIGHT * 0.25); // Smaller bars like original
const barHeight = Math.max(20, (dataArray[dataIndex] / 255) * HEIGHT * 0.4); // Original height like original code
const blueShade = Math.min(3, Math.floor((dataArray[dataIndex] / 255) * 4));
// Create gradient for better visibility (bottom to top)
@@ -87,7 +43,6 @@ const animateBars = (analyser, canvas, ctx, dataArray, bufferLength) => {
x += barWidth;
}
} catch (error) {
console.warn('Error in Web Audio API animation:', error);
return false;
}
return true;
@@ -95,8 +50,6 @@ const animateBars = (analyser, canvas, ctx, dataArray, bufferLength) => {
const WaveForm = ({ analyzerData }) => {
const canvasRef = useRef(null);
const [width, height] = useSize();
const [useFallback, setUseFallback] = useState(false);
const animationRef = useRef(null);
useEffect(() => {
@@ -106,69 +59,41 @@ const WaveForm = ({ analyzerData }) => {
const ctx = canvas.getContext("2d");
if (!ctx) return;
let webAudioWorking = true;
// Check if we have valid analyzer data
const hasValidAnalyzer = analyzerData &&
analyzerData.analyzer &&
analyzerData.dataArray &&
analyzerData.bufferLength;
console.log('Audio analyzer status:', {
hasAnalyzerData: !!analyzerData,
hasAnalyzer: !!(analyzerData && analyzerData.analyzer),
useFallback,
webAudioWorking
});
const render = () => {
try {
const currentTime = Date.now();
// Set canvas dimensions like SimpleWaveForm
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Set canvas dimensions
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Add subtle background
ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.save();
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Add subtle background
ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.save();
if (hasValidAnalyzer && webAudioWorking && !useFallback) {
const success = animateBars(
analyzerData.analyzer,
canvas,
ctx,
analyzerData.dataArray,
analyzerData.bufferLength
);
if (!success) {
webAudioWorking = false;
setUseFallback(true);
console.log('Web Audio failed, switching to fallback');
}
} else {
// Use fallback animation with current time
animateFallbackBars(canvas, ctx, currentTime);
}
ctx.restore();
animationRef.current = requestAnimationFrame(render);
} catch (error) {
console.warn('Canvas rendering error:', error);
setUseFallback(true);
animationRef.current = requestAnimationFrame(render);
if (hasValidAnalyzer) {
animateBars(
analyzerData.analyzer,
canvas,
ctx,
analyzerData.dataArray,
analyzerData.bufferLength
);
}
ctx.restore();
animationRef.current = requestAnimationFrame(render);
};
// Start animation
console.log('Starting animation');
render();
return () => {
@@ -176,7 +101,7 @@ const WaveForm = ({ analyzerData }) => {
cancelAnimationFrame(animationRef.current);
}
};
}, [analyzerData]); // Simplified dependencies
}, [analyzerData]);
return (
<div style={{
@@ -185,7 +110,7 @@ const WaveForm = ({ analyzerData }) => {
left: 0,
width: '100vw',
height: '100vh',
zIndex: -1, // Behind content, not 1000
zIndex: -1,
pointerEvents: 'none'
}}>
<canvas
@@ -195,14 +120,11 @@ const WaveForm = ({ analyzerData }) => {
left: 0,
width: "100%",
height: "100%",
willChange: "contents",
backgroundColor: "transparent",
pointerEvents: "none",
display: "block"
}}
ref={canvasRef}
role="img"
aria-label={useFallback ? "Audio visualization (compatibility mode)" : "Real-time audio visualization"}
/>
</div>
);