【问题标题】:Improving visualizer look改善可视化器外观
【发布时间】:2021-11-10 18:46:29
【问题描述】:

我不满意这段代码如何使用画布和getByteFrequencyData 绘制这个音乐可视化工具。 https://share.getcloudapp.com/Kou7AJb1

似乎条形太大,我认为这是因为 FFT(快速傅立叶变换)数组包含广泛的数据,但在我的代码中,我根据画布的宽度生成 n 个条形。

然后,在拥有 n 个柱之后,我将 FFT 映射到柱的相同索引,而忽略了许多有用的信息。

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;

我认为需要做的是根据循环中的条数对 FFT 进行平均。如果这是有道理的,那么实现这一目标的实用方法是什么?

我希望这是有道理的,如果需要,很高兴澄清。

【问题讨论】:

  • 也许您可以添加条形图的草图以及条形图的外观以更好地说明您的问题。
  • 很公平,云应用视频包含它们当前的外观,这些模板看起来更好elements.envato.com/podcast-audio-visualization-pack-ETCVTNT 这足以说明还是我需要更多细节?干杯:)
  • 我们越来越接近迈克尔 ;) - 我只是不确定您所说的“条形太大”是什么意思。单杠的行程是不是太粗了?还是条形的总高度太高了?
  • 我认为因为 FFT 数组可以包含 500 多个项目,并且循环固定在 100 条,问题是它只读取 FFT 数组中的前 100 项数据。我的假设是,如果分布更均匀,它看起来会更自然。这有意义吗?
  • 还记得您之前的一个问题中的滚动平均值吗?你可以使用同样的策略……你需要简化你的问题,拿出画布,从纯数学的角度思考这个问题

标签: javascript audio canvas fft


【解决方案1】:

我假设frameData.fft 是包含AnalyserNode.getByteFrequencyData() 方法返回的实际频率数据的Uint8Array。

您的假设是正确的 - 条形图的数量当然与存储在数组中的项目数不匹配,并且带有类似循环

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

您只是使用从零到柱数的前几个值,并最终跳过整个数组的其余部分。

虽然修复很简单:

不是以 1 为间隔从数组中获取值,间隔必须是数组中元素的数量除以柱的数量。然后这个数字乘以 for 循环内的变量 i 并四舍五入,因为除法可能会产生十进制数字,并且数组的元素位于整数位置。

这是一个例子:

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)]);
}

【讨论】:

  • 你仍然遗漏了很多有用的信息......在它跳过数组的末尾之前,现在已经结束了......正确的输出应该是平均间隔
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-20
  • 1970-01-01
  • 1970-01-01
  • 2011-02-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多