0

I am rendering a music visualizer in multiple chunks and am having a hard time getting one chunk to transition into the next one gracefully.

I am looking for a way to get frequency data based on a specific time or frame and have it return the same buffer deterministically.

const render = () => {
  return new Promise((resolve, reject) => {
    try {
      if (audioCtxRef.current) {
        const bufferSource: AudioBufferSourceNode = audioCtxRef.current.createBufferSource();
        bufferSource.buffer = sourceRef.current.buffer;
        bufferSource.connect(analyzerRef.current);

        bufferSource.onended = () => {
          analyzerRef.current.getByteFrequencyData(fftRef.current);
          analyzerRef.current.getFloatTimeDomainData(tdRef.current);

          // See screenshots for this log, you will notice they are never the same values
          console.log({
            frameData: fftRef.current
          });

          logger({
            frame,
            frameData: fftRef.current
          });

          // put on UI
          drawCanvas(
            {
              fft: fftRef.current
            },
            canvasRef.current,
            background,
            type
          );

          // finished
          bufferSource.disconnect();
          resolve("");
        };

        bufferSource.start(0, Number((frame / 60).toFixed(2)), 1);
      } else {
        reject("AudioCtx is missing");
        onReady("visualizer");
      }
    } catch (e) {
      reject(e);
      onReady("visualizer");
    }
  });
};

This is the analyzer data from the bufferSource enter image description here

This is a new result of the same analyzer data from the bufferSource with different values even though the time is the same enter image description here

Michael Joseph Aubry
  • 12,282
  • 16
  • 70
  • 135
  • Cool, let me try implementing it – Michael Joseph Aubry Oct 06 '21 at 22:37
  • Opps, [here](https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode) is a better link. – StackSlave Oct 06 '21 at 22:41
  • Currently I have an analyzer being passed into the bufferSource `analyzerRef.current = audioCtxRef.current.createAnalyser();` This code wasnt shared though, it is the same thing it's "the equivalent factory" method. You can see I add it though in the render function `bufferSource.connect(analyzerRef.current);` – Michael Joseph Aubry Oct 06 '21 at 22:45
  • If you're trying to show output of an audio file, perhaps the example [here](https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/getFloatFrequencyData) under `Drawing a spectrum` will help. – StackSlave Oct 06 '21 at 22:52
  • I dont know if you read the question... I have visualizers working but they are choppy https://motionbox.io/template/youtube-music-visualizer this is because the rendering happens in parallel and I cant get them to be seamless – Michael Joseph Aubry Oct 06 '21 at 22:54
  • That's what the `requestAnimationFrame` in the second link I provided is for. – StackSlave Oct 06 '21 at 23:11
  • This works well under one process, but when multiple processes handle rendering then need to combine the results it becomes inconsistent. Render function a will render 0-60 frames, then the buffer from frame 60 needs to transition into function b which starts on frame 61. The problem is the buffer is inconsistent, I think I need to flush it between each frame. – Michael Joseph Aubry Oct 06 '21 at 23:23

0 Answers0