Files
SIGE-WEB-snapshot/wp-content/plugins/jetpack/extensions/blocks/voice-to-content/components/oscilloscope.tsx

120 lines
2.5 KiB
TypeScript

/**
* External dependencies
*/
import { useEffect, useRef } from '@wordpress/element';
function animate(
analyser: AnalyserNode,
canvas: HTMLCanvasElement,
pausedRef: React.MutableRefObject< boolean >
) {
const canvasCtx = canvas.getContext( '2d' );
const points = 10;
let isCanceled = false;
if ( ! canvasCtx ) {
return;
}
analyser.fftSize = Math.pow( 2, 13 ); // 8192
const bufferLength = analyser.fftSize;
const dataArray = new Float32Array( bufferLength );
const slice = bufferLength / points;
const { width, height } = canvas;
const center = height / 2;
canvasCtx.lineWidth = 4;
canvasCtx.lineCap = 'round';
canvasCtx.strokeStyle =
getComputedStyle( canvas ).getPropertyValue( '--jp-green-50' ) || '#008710';
const draw = () => {
canvasCtx.clearRect( 0, 0, width, height );
analyser.getFloatTimeDomainData( dataArray );
for ( let i = 1; i <= points; i++ ) {
let amplitude = 0;
if ( ! pausedRef.current ) {
// get the average amplitude for this slice
amplitude =
dataArray.slice( i * slice, ( i + 1 ) * slice ).reduce( ( a, b ) => a + b, 0 ) / slice;
// scale it
amplitude *= 2048;
// make it positive
amplitude = Math.abs( amplitude );
// ensure it is between 0 and 16
amplitude = Math.min( 16, Math.max( 0, amplitude ) );
}
canvasCtx.beginPath();
canvasCtx.moveTo( 2 + i * 6, center - amplitude );
canvasCtx.lineTo( 2 + i * 6, center + amplitude );
canvasCtx.stroke();
}
setTimeout( () => {
if ( isCanceled ) {
return;
}
requestAnimationFrame( draw );
}, 50 ); // 20 fps
};
draw();
return () => {
isCanceled = true;
};
}
export default function Oscilloscope( {
analyser,
paused = false,
}: {
analyser: AnalyserNode;
paused?: boolean;
} ) {
const canvasRef = useRef( null );
const pausedRef = useRef( paused );
const cancelAnimation = useRef( null );
useEffect( () => {
pausedRef.current = paused;
}, [ paused ] );
useEffect( () => {
if ( ! analyser ) {
return;
}
if ( ! canvasRef.current ) {
return;
}
if ( cancelAnimation.current ) {
cancelAnimation.current();
}
cancelAnimation.current = animate( analyser, canvasRef.current, pausedRef );
}, [ analyser, canvasRef, pausedRef ] );
useEffect( () => {
return () => {
if ( cancelAnimation.current ) {
cancelAnimation.current();
}
};
}, [] );
return (
<canvas
className="jetpack-ai-voice-to-content__oscilloscope"
width={ 70 }
height={ 38 }
ref={ canvasRef }
/>
);
}