理解Web音频中的getByteTimeDomainData和getByteFrequencyData方法

25
这两种方法的文档都非常通用,无论我在哪里查看。我想知道每个方法返回的数组具体代表什么。
对于getByteTimeDomainData,每次传递涵盖了多长时间周期?我相信大多数示波器每次传递覆盖32毫秒的跨度。这是在此处也被包括在内吗?对于实际元素值本身,范围似乎是0-255。这是否等同于-1到+1伏特?
对于getByteFrequencyData,涵盖的频率基于采样率,因此每个索引都是实际频率,但是实际元素值本身呢?是否有一个分贝范围,等价于返回数组中的值?

相关问题:https://stackoverflow.com/questions/60983069/web-audio-analysers-getfloattimedomaindata-buffer-offset-wrt-buffers-at-other-t - mathheadinclouds
3个回答

32
getByteTimeDomainData(和更新的getFloatTimeDomainData)返回一个你请求大小的数组 - 它的frequencyBinCount,计算公式为所请求的fftSize的一半。当然,该数组在当前AudioContext上公开的sampleRate下,因此如果使用默认的2048个fftSizefrequencyBinCount将为1024,如果您的设备以44.1kHz运行,则对应约23ms的数据。

字节值的范围在0-255之间,是映射到了-1到+1,因此128是零。(不是电压,而是全幅无单位值)

如果使用getFloatFrequencyData,则返回的值以分贝为单位;如果使用Byte版本,则根据minDecibels/maxDecibels进行映射(参见minDecibels/maxDecibels描述)。


1
你是如何从频率分辨率为1024和采样率为44.1kHz中得出2.3ms的时间? - Brad.Smith
1
哎呀,差了一个数量级!我应该说23毫秒。1024个样本除以每秒44100个样本(又称赫兹)等于0.023219...秒。 - cwilso
4
为什么要使用frequencyBinCount作为时域数据的宽度?时间域窗口和FFT的频率bin数量之间是否存在某种关系,我是否遗漏了什么? - user993683
1
这就是FFT的工作原理 - 时域音频数据长度和频率之间存在对称性。 - cwilso
3
@cwilso: 你搞反了,看看我的回答。https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/getFloatTimeDomainData https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/getFloatFrequencyData - mathheadinclouds
显示剩余3条评论

16

Mozilla的文档描述了getFloatTimeDomainDatagetFloatFrequencyData之间的区别,以下是我的总结。Mozilla文档引用了Web音频实验; voice-change-o-matic。voice-change-o-matic向我说明了这个概念上的区别(它只在我的Firefox浏览器中工作;它在我的Chrome浏览器中不起作用)。

TimeDomain/getFloatTimeDomainData

  • TimeDomain函数涉及一段时间
  • 我们通常使用示波器来可视化TimeDomain数据。
  • 换句话说:
    • 我们使用折线图来可视化TimeDomain数据,
    • 其中x轴(也称为"原始域")是时间
    • 而y轴是信号的度量(也称为“振幅”)。
  • 将voice-change-o-matic的“可视化设置”更改为Sinewave以查看getFloatTimeDomainData(...)

visualizer-setting to Sinewave illustrates TimeDomain data like an oscilloscope

频率/getFloatFrequencyData

  • 频率函数(GetByteFrequencyData)是在某个时间点获取的; 即现在; "当前的频率数据"
  • 我们有时会在mp3播放器/ "winamp bargraph style" 音乐播放器 (也称为"均衡器"可视化)中看到这些。
  • 换句话说:
    • 我们用条形图来可视化频率数据
    • x轴(也称为"域")是频率频率带
    • y轴是每个频率带的强度
  • 将声音变换器"可视化设置"更改为频率条,以查看getFloatFrequencyData(...)

visualizer-setting to sinewave illustrates Frequency data like an mp3 player

傅里叶变换(又称快速傅里叶变换/FFT)

  • 另一种思考“时间域与频率”的方法如下图所示,来自Fast Fourier Transform wikipedia
    • getFloatTimeDomainData 提供了上图(x轴为时间)
    • getFloatFrequencyData 提供了下图(x轴为频率)
    • 快速傅里叶变换(FFT)将时间域数据转换为频率数据,换句话说,FFT将第一个图表转换为第二个图表。

Fast Fourier Transform (FFT) converts Time Domain data to Frequency data original source https://en.wikipedia.org/wiki/Fast_Fourier_transform#/media/File:FFT_of_Cosine_Summation_Function.svg


1
换句话说,我们使用条形图来可视化频率数据,其中x轴是频率带,y轴是每个频率带的强度。可以说数组的每个元素代表每个bin的分贝音量吗? - sebas.varela
1
是的@SebastiánVarellaGmz,您正在引用getFloatFrequencyData,并且正如文档所述:“数组中的每个项目表示特定频率的分贝值。这些频率从0线性地扩展到采样率的1/2。例如,对于48000 Hz的采样率,数组的最后一个项目将表示24000 Hz的分贝值。” - Nate Anderson

10

cwilso 误解了。

时间数据数组是较长的一个(fftSize),频率数据数组是较短的一个(半数,即frequencyBinCount)。

在通常的采样率44.1kHz下,fftSize为2048意味着每个样本持续时间为1/44100秒,你手头上有2048个样本,因此覆盖了一个持续时间为2048/44100秒,即46毫秒,而不是23毫秒, frequencyBinCount确实是1024,但这指的是频域(就像名字所暗示的那样),而不是时域,在这个上下文中,计算1024/44100与把你的生日加到fftSize上一样有意义。

下面是一点数学证明:傅里叶变换是一种“向量空间同构”,也就是说,它在两个相同维度的向量空间之间具有可逆性,这两个向量空间是“时间域”和“频率域”,这里我们考虑的向量空间维度(在这两种情况下)都是fftSize。

那么这个“半数”从哪里来?频率域系数“计数两次”。或者因为它们“实际上是”复数,或者因为你有“正弦”和“余弦”味道。或者,因为你有一个“幅度”和一个“相位”,如果你知道复数是如何工作的,你就会理解这一点。(这些都是用不同的行话说同一件事情的方式.)

我不知道为什么当涉及频率时,API只提供了一半相关数字 - 我只能猜测。我的猜测是那些是“幅度”数字,而“相位”数字被扔掉了。原因是在应用中,幅度比相位更重要。但我很惊讶API会丢失信息,如果真正懂行的专家可以确认是确实是幅度,我会很高兴。或者 - 更好的是(我喜欢学习) - 纠正我。

我在 WebAudio API 的问题中发现了这个线程,解释了为什么我们只能得到幅度值。https://github.com/WebAudio/web-audio-api-v2/issues/107#issuecomment-742704691 - meta-meta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接