AnalyserNode.getByteFrequencyData() 返回的“bin”的频率(以赫兹为单位)是多少?

问题描述 投票:0回答:3

我目前正在开发一个项目,该项目使用 JavaScript 的 WebAudio API 来显示音频频率图。 AnalyserNode.getByteFrequencyData() 填充一个数组,该数组分为“容器”,每个容器都有一个频率范围。我想知道这些“频率”对应的频率(以赫兹为单位)。

我尝试将每个 bin 解释为 1Hz 步长,但这显然是不正确的。

javascript web-audio-api
3个回答
2
投票

来自 MDN 文档

AnalyserNode.getByteFrequencyData()

数组中的每一项代表特定频率的分贝值。频率从采样率的 0 到 1/2 线性扩展。例如,对于

48000
采样率,数组的最后一项将表示
24000
Hz 的分贝值。

采样率可以从

sampleRate
上的
AudioContext
属性获取(继承自
BaseAudioContext
):

sampleRate
接口的
BaseAudioContext
属性返回一个浮点数,表示采样率(以每秒样本数为单位),供此音频上下文中的所有节点使用。 (文档

您可以在创建

AudioContext
时通过构造函数的
options
参数设置其采样率。

您可以在创建时通过构造函数的

AudioAnalyzer
参数以及之后的任何时间通过
options
属性设置
fftSize
的 FFT 窗口大小。 来自 AnalyserNode.fftSize 的文档:

fftSize

接口的
AnalyserNode
属性是一个无符号长整型值,表示在执行快速傅里叶变换(FFT)以获取频域数据时使用的样本窗口大小。


2
投票
这取决于样品。

数组中的每一项代表特定的分贝值 频率。

频率从 0 到 1/2 线性扩展 采样率。例如,对于 48000 采样率,最后一项 数组将代表 24000 Hz 的分贝值。

https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/getByteFrequencyData


0
投票

k

 个 bin 的频率为 
k/N*sr
,其中 
sr
 是采样率,
N
 是 FFT 中的点数。

我认为 MDN 文档是不正确的,除非他们用 FFT 做了一些非常不标准的事情。如果采样率为 48000 并进行 128 点 FFT,则

getByteFrequencyData()

 中的最后一个值的索引为 63,频率为 
63/128*48000 = 23625Hz

一般而言,

N

点 FFT
1 会获取 N
 时域样本,并为您提供 
N
 频域样本。如果您的采样频率为 
sr
,则每个 bin 的 bin 间距为 
sr/N
2。因此,如果您的采样率为 8kHz 并进行了 8 点 FFT,则 bin 频率将为

[0, 1k, 2k, 3k, 4k, 5k, 6k, 7k]
您还可以将“奈奎斯特”(

sr/2

) 以上的频率视为负频率
3,因此您可以将该列表重新编号为:

[0, 1k, 2k, 3k, 4k, -3k, -2k, -1k]
如果时域信号是实值(音频就是这种情况),则频谱是对称的

4,因此负频率中没有新信息。处理音频信号的 DSP 工程师经常只使用非负频率,并且大多数 FFT 库都具有用于此目的的 rfft

 函数。对于 N 点 FFT,
rfft
 函数通常会给出长度为 
N/2+1
 的结果,从而避免需要计算负频率。

由于某种原因,WebAudio 设计者放弃了最后一个频率仓,其频率为

sr/2

。在实践中,在奈奎斯特频率上通常不会发生太多有趣的事情,并且分析器节点只为您提供频谱的幅度,因此它更适合可视化而不是花哨的频域处理。


1 在数学中通常称为DFT(离散傅里叶变换)。 FFT(快速傅立叶变换)是一种计算 DFT 的特殊算法。

2 如果您查看 DFT 定义,对于第 k

 个谱仓,您使用正弦曲线 
w(n) = exp(-i*2*pi*k/N*n)
,其频率为 
k/N
。采样率为 1,因为我们正在测量样本中的时间。

3 从概念上讲,DFT 结果是周期性的,周期为 N

,因此 
X[k] = X[k+N]
 始终为真。请记住 
k
 是这里的索引,而不是 bin 频率,并且我们允许负索引从末尾开始环绕,numpy 风格。

4 特别共轭对称所以 X[-k] = conj(X[k])


    

© www.soinside.com 2019 - 2024. All rights reserved.