随着iOS 16 beta 5的更新,细心的小伙伴可能注意到了,系统在播放音乐时,音乐控制台的右上角多了一个小小的频谱显示器。对我这种喜欢音乐的人来说,看着它随着音乐一起动起来,心情似乎也变得好起来。那么问题来了,浏览器上是否可以实现这样的功能?答案是可以,但是似乎有一点小问题。

我们先抛开顾虑,直接查MDN堆代码看看效果。
|
|
|
结果:
这样一通操作下来,一个简单的频谱显示器就完成了(老有成就感了),大概原理也很简单:
- 创建一个音频
上下文
(Audio Context) - 使用上下文映射
<audio>
并赋值为audioSrc
- 创建
分析仪
节点(Analyzer Node) audioSrc
连接分析仪
,分析仪
再连接到ctx.destination
即用户端输出- 图形化
分析仪
的数据
现在,真正的问题来了:不管我尝试什么音乐,我的频谱图永远都是这样的 ⬇️(成就感啪一下没了)
可能会有一些小差异,但是呈现的效果基本差不多:低频看起来很足,高频几乎没有
这时候,作为一名“准专业编曲师”,我有一种直觉,Web Audio API 给出来的频谱数据,可能是线性分布的。为了验证我的猜想,我制作了一段从 30Hz 到 20000Hz 慢慢上升的正弦波音频,调高分析仪的 fftSize ,放进代码里看看输出:
再来看看同样的音频在 Ableton Live 中 Spectrum 线性模式下的输出:
这表现可以说,基本一致,同时也验证了我的猜想 —— Web Audio API 输出的频谱数据是线性分布的。线性分布是什么分布?很好理解:一个坐标系中,X轴上10到20需要走的距离,与2000到2010需要走的距离一样。然而对于人来讲,线性分布这个解决方案,并不是最优的。我们可以先看一些专业EQ插件的截图,看看他们是怎么做频谱分布的。
FabFilter Pro Q3:
Eiosis Air EQ Premium:
SlateDigital Inf EQ:
Ableton Live EQ Eight
可以看到,这些分布基本都是在类似指数分布的频率上进行分段式的对数分布,而且似乎是遵循着等响曲线做出的优化。
我们经常听到“指数级增长”这个词,举个简单的例子:10、100、1000、10000,这个数列就是指数增长。上述频谱图中,频率分布基本是按照指数来的。
关于对数我们不需要了解太多,对数分布也可以根据上面我对线性分布的理解做出延伸:一个坐标系中,X轴上10到20需要走的距离,与2000到2010,同样是10的差距,但是需要走的距离却不一样。如果我们以Ableton Live更加青睐的分布规则,把频谱分析仪的可视化面板看作是一个坐标系,则 X 轴上,10 - 10000 被分成三段,分别为10 - 100、100 - 1000、1000 - 10000,每一段距离都一样且被分成9份进行对数分布。
说到等响曲线,它并不像对数那样客观,而是一个主观概念。此概念阐述的内容如果用大白话来讲就是:同样音量但不同频率的声音,给人听起来的强弱是不一样的。即:60Db 的 4000Hz 正弦波与 60Db 的 10000Hz 正弦波,前者听起来会更响一些。此概念也同样可以用来解释,在删除歌曲 10kHz 以上部分的时候(可以理解为对半切),你不会觉得整首歌的质量下降了50%,主观上听起来可能只有10%。
个人认为,频谱这样的分布模式,其实是为了弥补人耳的缺点,在视觉上模拟出与听觉类似的“缺陷”,真正做到音视一致从而提升用户体验。
关于如何在浏览器里实现,其实很简单,我们只需要模拟指数级分布就好,不用去考虑分段中的对数分布。演示地址: https://jw1.dev/frequency-test/test-2.html
现在再来看一下对比:
哪个体验更好,一眼看过去便知道了。
至此,一个不算完美但是看起来还不错的频谱显示器就算是完成了,我也给 webAudio 开源项目提了issue,希望未来能够添加支持,为开发者带来更佳的体验!
✌️
{{user.login}}
退出登录