waveform AI changes

Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2025-06-04 20:31:02 +02:00
padre 3533003456
commit 8df02d7832

Ver fichero

@@ -12,30 +12,32 @@ const BLUE_SHADES = [
const animateFallbackBars = (canvas, ctx, fallbackData) => {
const HEIGHT = canvas.height;
const barCount = 64; // Increased for more detail
const barWidth = Math.max(6, Math.floor(canvas.width / barCount)); // Minimum 6px width
const barWidth = Math.max(8, Math.floor(canvas.width / barCount)); // Minimum 8px width for visibility
const centerY = HEIGHT / 2; // Center point for bars
let x = 0;
for (let i = 0; i < barCount; i++) {
// Make bars taller and more visible
const barHeight = Math.max(20, fallbackData[i] * HEIGHT * 0.4); // Minimum 20px height, use 40% of screen
const blueShade = Math.min(3, Math.floor(fallbackData[i] * 4));
console.log('Drawing', barCount, 'bars with data:', fallbackData.slice(0, 5));
for (let i = 0; i < barCount && i < fallbackData.length; i++) {
// Make bars much taller and more visible
const normalizedHeight = Math.max(0.1, Math.min(1, fallbackData[i]));
const barHeight = Math.max(30, normalizedHeight * HEIGHT * 0.6); // Minimum 30px height, use 60% of screen
const blueShade = Math.min(3, Math.floor(normalizedHeight * 4));
// Create gradient for better visibility
const gradient = ctx.createLinearGradient(0, centerY - barHeight/2, 0, centerY + barHeight/2);
gradient.addColorStop(0, BLUE_SHADES[0]);
gradient.addColorStop(0.5, BLUE_SHADES[blueShade] || BLUE_SHADES[0]);
gradient.addColorStop(1, BLUE_SHADES[3]);
// Use solid bright colors instead of gradients for better Tizen visibility
ctx.fillStyle = BLUE_SHADES[blueShade] || BLUE_SHADES[0];
ctx.fillStyle = gradient;
// Draw bars from center, extending up and down
ctx.fillRect(x + 2, centerY - barHeight/2, barWidth - 4, barHeight);
const barY = centerY - barHeight/2;
const barX = x + 2;
const barW = barWidth - 4;
// Add glow effect
ctx.shadowColor = "rgba(255,255,255,0.8)";
ctx.shadowBlur = 5;
ctx.fillRect(x + 2, centerY - barHeight/2, barWidth - 4, barHeight);
ctx.shadowBlur = 0;
ctx.fillRect(barX, barY, barW, barHeight);
// Add strong white outline for maximum visibility
ctx.strokeStyle = "rgba(255,255,255,1)";
ctx.lineWidth = 2;
ctx.strokeRect(barX, barY, barW, barHeight);
x += barWidth;
}
@@ -86,14 +88,16 @@ const animateBars = (analyser, canvas, ctx, dataArray, bufferLength) => {
const WaveForm = ({ analyzerData }) => {
const canvasRef = useRef(null);
const [width, height] = useSize();
const [useFallback, setUseFallback] = useState(false);
const [useFallback, setUseFallback] = useState(true); // Start with fallback immediately
const [fallbackData, setFallbackData] = useState([]);
const fallbackIntervalRef = useRef(null);
const animationRef = useRef(null);
// Initialize fallback data
useEffect(() => {
const initialData = Array(64).fill(0).map(() => Math.random() * 0.7 + 0.3); // Higher initial values, more bars
const initialData = Array(64).fill(0).map(() => Math.random() * 0.8 + 0.2); // Higher initial values, more bars
setFallbackData(initialData);
console.log('WaveForm initialized with fallback data');
}, []);
useEffect(() => {
@@ -103,7 +107,8 @@ const WaveForm = ({ analyzerData }) => {
const ctx = canvas.getContext("2d");
if (!ctx) return;
let animationId;
console.log('Canvas initialized:', canvas.width, 'x', canvas.height);
let webAudioWorking = true;
// Check if we have valid analyzer data
@@ -112,6 +117,8 @@ const WaveForm = ({ analyzerData }) => {
analyzerData.dataArray &&
analyzerData.bufferLength;
console.log('Has valid analyzer:', hasValidAnalyzer);
const render = () => {
try {
// Clear canvas completely (transparent background)
@@ -122,6 +129,7 @@ const WaveForm = ({ analyzerData }) => {
if (hasValidAnalyzer && webAudioWorking && !useFallback) {
// Try Web Audio API first
console.log('Using Web Audio API');
const success = animateBars(
analyzerData.analyzer,
canvas,
@@ -133,6 +141,7 @@ const WaveForm = ({ analyzerData }) => {
if (!success) {
webAudioWorking = false;
setUseFallback(true);
console.log('Web Audio failed, switching to fallback');
}
} else {
// Use fallback animation
@@ -140,65 +149,85 @@ const WaveForm = ({ analyzerData }) => {
}
ctx.restore();
animationId = requestAnimationFrame(render);
animationRef.current = requestAnimationFrame(render);
} catch (error) {
console.warn('Canvas rendering error:', error);
setUseFallback(true);
animationId = requestAnimationFrame(render);
animationRef.current = requestAnimationFrame(render);
}
};
// Always start fallback animation for immediate visibility
// Start animation data updates
console.log('Starting animation updates');
fallbackIntervalRef.current = setInterval(() => {
setFallbackData(prevData =>
prevData.map((val, index) => {
// Create wave-like pattern with more dramatic changes
const wave = Math.sin((Date.now() * 0.005) + (index * 0.2)) * 0.3;
const target = Math.random() * 0.6 + 0.4 + wave; // Higher amplitude with wave effect
const smoothing = 0.3; // Faster transitions
return Math.max(0.2, Math.min(1, val + (target - val) * smoothing));
})
);
}, 50); // Much faster updates for smoother animation
setFallbackData(prevData => {
const newData = prevData.map((val, index) => {
// Create more dramatic wave pattern
const time = Date.now() * 0.008; // Slower for more visible movement
const wave = Math.sin(time + (index * 0.3)) * 0.4; // Bigger wave amplitude
const randomness = (Math.random() - 0.5) * 0.3;
const target = 0.5 + wave + randomness; // Base of 0.5 + wave + randomness
const smoothing = 0.15; // Smoother transitions
return Math.max(0.1, Math.min(1, val + (target - val) * smoothing));
});
return newData;
});
}, 60); // 60ms updates for smooth motion
render();
return () => {
if (animationId) {
cancelAnimationFrame(animationId);
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
}
if (fallbackIntervalRef.current) {
clearInterval(fallbackIntervalRef.current);
}
};
}, [analyzerData, width, height, useFallback, fallbackData]);
}, [analyzerData, width, height, fallbackData]);
return (
<canvas
style={{
position: "absolute", // Changed back to absolute
top: 0,
left: 0,
width: "100%", // Use percentage instead of viewport units
height: "100%",
zIndex: -1, // Put behind other content
// Tizen TV optimizations
willChange: "auto",
imageRendering: "auto",
// Ensure complete transparency
backgroundColor: "transparent",
// Prevent touch/click interference
pointerEvents: "none",
// Ensure it doesn't interfere with layout
display: "block"
}}
ref={canvasRef}
width={width || window.innerWidth} // Fallback dimensions
height={height || window.innerHeight}
// Add accessibility for Smart TV navigation
role="img"
aria-label={useFallback ? "Audio visualization (compatibility mode)" : "Real-time audio visualization"}
/>
<div style={{ position: 'relative' }}>
<canvas
style={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
zIndex: -1,
willChange: "auto",
imageRendering: "auto",
backgroundColor: "transparent",
pointerEvents: "none",
display: "block"
}}
ref={canvasRef}
width={width || window.innerWidth}
height={height || window.innerHeight}
role="img"
aria-label={useFallback ? "Audio visualization (compatibility mode)" : "Real-time audio visualization"}
/>
{/* Debug info - remove this in production */}
<div style={{
position: 'fixed',
top: '10px',
right: '10px',
background: 'rgba(0,0,0,0.7)',
color: 'white',
padding: '10px',
borderRadius: '5px',
fontSize: '12px',
zIndex: 1000,
fontFamily: 'monospace'
}}>
<div>Canvas: {width}x{height}</div>
<div>Fallback: {useFallback ? 'YES' : 'NO'}</div>
<div>Data: {fallbackData.length} bars</div>
<div>Sample: {fallbackData.slice(0,3).map(v => v.toFixed(2)).join(', ')}</div>
</div>
</div>
);
};