如何获得FFT中每个值的频率?

Ran*_*ngo 144 c# signal-processing fft

我有一个FFT结果.它们存储在两个double数组中:实部数组和虚部数组.如何确定与这些阵列中每个元素对应的频率?

换句话说,我想创建一个存储FFT的每个实部和虚部的频率的数组.

Pau*_*l R 331

FFT中的第一个bin是DC(0 Hz),第二个bin是Fs / N,其中Fs是采样率,N是FFT的大小.下一个箱子是2 * Fs / N.为了概括地表达这一点,第n个 bin是n * Fs / N.

因此,如果您的采样率Fs(例如44.1 kHz)和FFT大小N为1024,那么FFT输出箱位于:

  0:   0 * 44100 / 1024 =     0.0 Hz
  1:   1 * 44100 / 1024 =    43.1 Hz
  2:   2 * 44100 / 1024 =    86.1 Hz
  3:   3 * 44100 / 1024 =   129.2 Hz
  4: ...
  5: ...
     ...
511: 511 * 44100 / 1024 = 22006.9 Hz
Run Code Online (Sandbox Code Playgroud)

注意,对于一个真实的输入信号(虚部全零)的FFT的第二半(从箱N / 2 + 1N - 1)不包含任何有用的附加信息(它们具有与第一复共轭对称N / 2 - 1仓).最后一个有用的箱(用于实际应用)是at N / 2 - 1,其对应于上例中的22006.9Hz.bin处N / 2表示奈奎斯特频率的能量,即Fs / 2(在该示例中= 22050Hz),但这通常不具有任何实际用途,因为抗混叠滤波器通常将衰减任何信号等等Fs / 2.

  • @PaulR - 我想感谢你多年来为我提供的这个精彩答案.在我有一个StackOverflow帐户之前,我会访问这个答案,我忘记了在我注册后感谢你.我最近看了一下FFT的东西,我记得你的答案,现在就去看了.一旦我到了这里,我记得要感谢你......谢谢!每当我和某人讨论解释FFT横轴上的每个点是什么时,我只是将它们指向这个链接. (12认同)
  • 注意 - 答案有点错误 - 第512个桶包含22050的级别,即奈奎斯特限制.包含0到N/2的区间包含有用的值. (6认同)
  • 我希望我能得到答案.这个答案甚至比原来的问题更好! (5认同)
  • @rayryeng:非常感谢你 - 我认为这是我在这里回答问题约5年来最好的回应! (5认同)
  • 感谢编辑和澄清...我想这是我揭示缺乏实用性的地方.我:但是主人,FFT的工作达到了nyquist!你:Padawan,你真的应该过滤掉它. (3认同)
  • 好的,这有助于我理解我的FFT代码出错了.我把所有的垃圾箱作为有效的数据认为它是有用的.我还在读取内存缓冲区的末尾,因为KISS FFT只返回下半部分?这也有助于我更好地理解频谱. (3认同)
  • @user532017:否 - `sqrt(re*re+im*im)` 将是给定 **bin** 的 **频率** 处信号的**幅度**。根据我上面的回答,垃圾箱的 **频率** 由其索引决定。如果您找到具有最大 **magnitude** 的 bin,那么您可以根据上述索引确定此峰值的 **频率**。 (2认同)
  • @david:是的,但在实际应用中,Nyquist的bin很少有用.我会编辑答案,但请注意这一点. (2认同)

Jas*_*n B 54

看看我的答案在这里.

回答评论:

FFT实际上在一系列等间隔频率上计算输入信号与正弦和余弦函数(基函数)的互相关.对于给定的FFT输出,我发布的答案给出了相应的频率(F).输出样本的实部是输入信号cos(2*pi*F*t)的互相关,虚部是输入信号的互相关sin(2*pi*F*t).输入信号与其相关sin并且cos起作用的原因是考虑输入信号和基函数之间的相位差.

通过获取复数FFT输出的幅度,您可以测量输入信号与一组频率的正弦曲线相关的程度,而不管输入信号的相位如何.如果您只是分析信号的频率内容,您几乎总是会得到FFT复数输出的幅度或幅度平方.

  • 这个答案值得更多的爱. (4认同)

rob*_*rto 17

我使用了以下内容:

public static double Index2Freq(int i, double samples, int nFFT) {
  return (double) i * (samples / nFFT / 2.);
}

public static int Freq2Index(double freq, double samples, int nFFT) {
  return (int) (freq / (samples / nFFT / 2.0));
}
Run Code Online (Sandbox Code Playgroud)

输入是:

  • i:Bin访问
  • samples:以赫兹为单位的采样率(即8000 Hz,44100Hz等)
  • nFFT:FFT矢量的大小

  • 接受的答案说这应该是`i*samples/nFFT`.为什么那里有额外的"2"?我错过了什么吗? (14认同)
  • 人们不能完全知道你用`samples`或`nFFT`代表什么.所以请说明一下. (7认同)
  • 另外,我认为在这种情况下,“nFFT”仅与实际 FFT 的一半相关(许多函数都这样做,因为后半部分只是前半部分的镜像) (2认同)

小智 11

FFT输出系数(对于大小为N的复数输入)从0到N-1分组为[LOW,MID,HI,HI,MID,LOW]频率.

我认为k处的元素具有与Nk处的元素相同的频率,因为对于实数据,FFT [Nk] = FFT [k]的复共轭.

从低频到高频的扫描顺序是

0,

 1,
 N-1,

 2,
 N-2

 ...

 [N/2] - 1,
 N - ([N/2] - 1) = [N/2]+1,

 [N/2]
Run Code Online (Sandbox Code Playgroud)

从索引i = 0到[N/2]有[N/2] +1个频率组,每个都有 frequency = i * SamplingFrequency / N

所以bin FFT [k]的频率是:

if k <= [N/2] then k * SamplingFrequency / N
if k >= [N/2] then (N-k) * SamplingFrequency / N
Run Code Online (Sandbox Code Playgroud)


Neo*_*Neo 5

您的 k FFT结果的频率为2 * pi * k / N。

  • 我想这会以弧度为单位 (6认同)