如何使用 Web Audio API 重新创建 John Locke 的 3D 音频可视化?

How can I recreate John Locke's 3D audio visualization using the Web Audio API?

提问人:Jan Schultke 提问时间:11/15/2023 最后编辑:Jan Schultke 更新时间:11/15/2023 访问量:59

问:

我想重新创建约翰·洛克(John Locke)制作的可视化。 作者不再在他们的博客上做出回应,但我发现结果在视觉上很有趣,并想重现它们。

John 的项目和代码

enter image description here enter image description here

从本质上讲,它是声音的图,其中一个轴是时间,另一个轴是声音频率,高度是该频率的 FFT(快速傅里叶变换)值。

John 的可视化代码看起来像是使用了 Minim 库中的 FFT,其中输出频率采用对数刻度,并且是平均的:

fftLog = new FFT(groove.bufferSize(),groove.sampleRate());
fftLog.logAverages(22,4);     //adjust numbers to adjust spacing
// ...
z = height/4-fftLog.getAvg(i)*10;
// ...
text(round(fftLog.getAvg(i)*100),0,0,0);

请注意,代码中的 与这篇博客文章中第二个屏幕截图中的注释匹配,并指示生成介于 和 之间的值。textgetAvg030

我失败的尝试

我尝试使用 Web Audio API 重新创建它但失败了。 我正在使用 Web Audio,因为我需要完全在前端进行此可视化。

我在高层次上所做的是:

  1. 加载一个音频文件,并通过OfflineAudioContext
  2. 使用ChannelMergerNode
  3. 使用 形式的 FFT,并使用平均法获得对数刻度的频率。AnalyserNode
  4. 将分贝值转换为线性,并以巨大的因素进行缩放。

代码的最后一步如下所示:

dest[i] = rangeAverage(buffer, previous, logPos) * 10000;

这给了我这样的风景:
enter image description here

我的方法几乎可以肯定是错误的,但我真的不知道我还能做些什么。 我最初试图将所有东西都保持在分贝内,但这给了我一个非常无聊的景观,比如:

dest[i] = dbToPositive(linearToDb(rangeAverage(buffer, previous, logPos)));

enter image description here

完整的代码可以在这里找到我做错了什么,我怎样才能重现约翰的可视化?

注意:此代码仅在 Chrome/Chromium 中运行,因为它使用了 Firefox 等不支持的 API 功能。要使用测试页面,只需选择一个文件,然后使用 THREE.js 生成景观

更新

修复我的 dB 计算后,我得到了更准确的结果:

function dbToLinear(f) {
    //                               previously / 10
    return f === -Infinity ? 0 : Math.pow(10, f / 20);
}

image

不过,在较低频率上也有一些巨大的峰值。

javascript 音频 three.js web-audio-api

评论

0赞 fdcpp 11/15/2023
这里有几点值得注意。1. 高度是该频率的FFT(快速傅里叶变换)值。不完全是,它是“每个频率箱在幅度尺度上的绝对值。logAverages 将设置每个倍频程的平均值,并真正关注频谱的计算方式。
0赞 fdcpp 11/15/2023
getAvg 实际上并没有规定它是幅度、对数、功率还是 dB 刻度结果。正如您所指出的,然后有一些缩放来整理数据。从原版的外观来看,我可以放心地说它是星等尺度。
1赞 fdcpp 11/15/2023
如果你有 dB ,因为回到幅度,它将是 。您的 dB 计算为 。从表面上看,我认为最终结果可能还有一些幕后的“美化”。你已经有正确的想法了 github.com/Eisenwave/audio-terrain/blob/......xpow(10.0, x / 20.0)20*log10(magnitude)
1赞 fdcpp 11/15/2023
再通读一遍后,一切似乎都很好。代替除数会让事情稍微偏离一点。一个好的方法是先将所有频域数据解压缩到某个地方,然后将其作为点数据添加到网格中。这将允许您创建一个前端工具来通过界面进行一些调整,并且用户可能也会喜欢。不过,这已经开始进入 softwareengineering.stackexchange.com 的领域1020
1赞 Jan Schultke 11/15/2023
@fdcpp使用而不是肯定地使结果更接近它应该有的样子。你知道什么可以解释这个巨大的高峰或如何摆脱它吗?我知道你对数刻度的意思;目前,我正在使用线性 FFT 将信号分成 512 个频段,并通过对位于倍频程中的所有箱进行平均来获得对数版本。井。。。它不完全是八度音阶,但它是一个对数音阶。这种方法是否有意义,还是会有太多的垃圾箱?Minim 版本看起来每个八度音程仅使用 4 个箱。2010

答: 暂无答案