Home>

I am writing a sound visualizer in React using Web Audio API methods

In general, everything works fine except for requestAnimationFrame, this function goes into an endless loop that cannot be stopped by calling cancelAnimationFrame

I have already tried about 10 different options and still did not get the desired result

import React, {useEffect, useState} from 'react';
import "./equalizer.css"
//Work around the bug in chrome and safari
const AudioContext= window.AudioContext || window.webkitAudioContext
function Equalizer ({audio, playPauseSwitch}) {
   useEffect (()= >
 {
      //Variables for the sound analyzer
      let context, analyzer, audioNode, arrayVolums
      function getAnalaizerAudio () {
         //Check for an error while creating the audio object
         if (audio!== undefined) {
            //remove CORS policy
            audio.crossOrigin= "anonymous"
            //Create audio context
            context= new AudioContext ();
            //Create a function to get the frequency
            analyser= context.createAnalyser ()
            //Set the wave averaging
            analyser.smoothingTimeConstant= 0.3;
            //Set the number of blocks with a frequency -64
            analyser.fftSize= 128;
            //Create an audio node
            audioNode= context.createMediaElementSource (audio);
            //Connect it to the frequency analyzer
            audioNode.connect (analyzer)
            //sound output to speakers
            analyser.connect (context.destination);
            getVolumeEqualizer ()
         }
      }
      //Control requestAnimationFrame for getVolumeEqualize
      let animationFrameSwitch
      //Function for frequency visualization
      function getVolumeEqualizer () {
         animationFrameSwitch= undefined
         //Form a binary array and fill it with frequency data
         arrayVolums= new Uint8Array (analyser.frequencyBinCount)
         analyser.getByteFrequencyData (arrayVolums)
         start ()
      }
      function start () {
         if (playPauseSwitch=== true) {
            animationFrameSwitch= window.requestAnimationFrame (getVolumeEqualizer)
         }
      }
      function stop () {
         if (playPauseSwitch=== false) {
            window.cancelAnimationFrame (animationFrameSwitch)
            return animationFrameSwitch= undefined
         }
      }
      stop ()
      getAnalaizerAudio ()
   }, [audio])
   return (
      <
div >
         <
div className= "equalizer__wraper" >
            <
/div >
         <
/div >
      <
/div >
   );
}
export default Equalizer;

In getAnalaizerAudio you call getVolumeEqualizer, and in it you call start, which schedules getVolumeEqualizer to be called again (window.requestAnimationFrame (getVolumeEqualizer)), which will call start again.

Вася Воронцов2021-12-27 18:49:56

You let animationFrameSwitch is initialized anew every time the component is redrawn. In other words, you are losing the link and therefore cannot be stopped. Use useRef ()

Sanya H2021-12-27 19:56:10