Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

116
Vistas
Improving visualizer look

I am not happy with how this code draws this music visualizer using canvas and getByteFrequencyData. https://share.getcloudapp.com/Kou7AJb1

It seems the bars are too large and I think its because the FFT (Fast Fourier Transform) array contains a wide spectrum of data but in my code I am generating n amount of bars based on the width of the canvas.

Then after having n bars I am mapping the FFT to the same index of the bar leaving out lots of useful information.

function convertRange(value: any, r1: any, r2: any) {
  return ((value - r1[0]) * (r2[1] - r2[0])) / (r1[1] - r1[0]) + r2[0];
}

// line up and down
const drawVisualizer2 = ({ canvas, frameData, background }: any) => {
  const ctx = canvas.getContext("2d");
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // TODO: Improve?
  const bars = Math.round(canvas.width) / 15 - 1;
  const max_of_array = Math.max.apply(Math, frameData.fft);

  for (let i = 0; i < bars; i++) {
    const height = convertRange(frameData.fft[i], [0, max_of_array], [0, canvas.height / 2 - 20]);
    const centerY = canvas.height / 2;

    // draw the bar
    ctx.strokeStyle = background ? background.colors[0] : "#ffffff";
    ctx.lineWidth = 10;
    ctx.lineCap = "round";

    ctx.beginPath();
    ctx.moveTo((i + 1) * 15, centerY);
    ctx.lineTo((i + 1) * 15, centerY + height);
    ctx.stroke();

    ctx.beginPath();
    ctx.moveTo((i + 1) * 15, centerY);
    ctx.lineTo((i + 1) * 15, centerY - height);
    ctx.stroke();
  }
};

export default drawVisualizer2;

What I think needs to be done is average out the FFT based on the amount of bars in the loop. If that makes sense what is a practical approach code wise to achieve that?

I hope this makes sense, happy to clarify if needed.

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

I assume that frameData.fft is the Uint8Array containing the actual frequency data returned by the AnalyserNode.getByteFrequencyData() method.

Your assumption is right - the number of bars of course doesn't match the number of items stored in array and with a loop like

for (let i = 0; i < bars; i++) {
...
frameData.fft[i]
...
}

you're just using the first few values from zero up to the number of bars and ultimately skipping the entire rest of the array.

The fix is quite simple though:

Instead of grabbing values from the array in intervals of 1, the interval must be the number of elements in the array divided by the number of bars. This number is then multiplied by the variable i inside the for-loop and rounded as the division might result in a decimal number and the array's elements are at integer positions.

Here's an example:

let frameData = {
  fft: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
};
let bars = 5;
let steps = frameData.fft.length / bars;
for (let i = 0; i < bars; i++) {
  console.log(frameData.fft[Math.round(i * steps)]);
}

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda