我一直试图找到导致峰值频率的DFT(或FFT)的简单实现。但是,我见过的大多数实现输出了一个复数数组。如何将那些基数-2结果转换为具体的频率?
例如,我输入的数据是16个正弦波函数样本,振荡频率在500 - 2000Hz之间,如下所示:
int n = 16;
double[] input = { 1250, 1537, 1780, 1943, 2000, 1943, 1780, 1537,
1250, 963, 720, 557, 500, 557, 720, 963 };
现在,我假设这个峰值频率恰好是750赫兹,因为(2000 - 500)/ 2 = 750。
我在考虑我的采样率Fs = 2000 Hz
,因为这是我限制正弦的振荡的上限。每个箱k的中心频率定义为k * Fs / n
,因此我的箱为125 Hz,250 Hz,375 Hz,500 Hz,625 Hz和750 Hz。但是因为我的振荡下限是500赫兹,我假设我需要用500赫兹来抵消这些箱子,因此它们变成:750 Hz, 825 Hz, 1000 Hz, 1125 Hz, 1250 Hz, 1375 Hz, 1500 Hz
。
然后使用jtransforms的DoubleFFT_1D类,我得到一些FFT数据:
DoubleFFT_1D fft = new DoubleFFT_1D(n);
fft.realForward(input);
输入变量现在包含:
[20000.0, 0.0, -4.547473508864641E-13, -5999.381020591891, 0.0, 0.0, -1.6292522886374172E-14, 1.1183950775908065, 0.0, -0.0, 1.6292522886374172E-14, -0.7488526914476931, 0.0, 0.0, 4.547473508864641E-13, -1.2482683609296146]
将数组值分组为更易理解的形式(根据我在SO中获得elsewhere的一些信息):
20000.0 [sum of input array values]
0.0, [1625 Hz]
-4.547473508864641E-13, -5999.381020591891, [re1 and im1] [750 Hz]
0.0, 0.0, [re2 and im2] [875 Hz]
-1.6292522886374172E-14, 1.1183950775908065, [re3 and im3] [1000 Hz]
0.0, -0.0, [re4 and im4] [1125 Hz]
1.6292522886374172E-14, -0.7488526914476931, [re5 and im5] [1250 Hz]
0.0, 0.0, [re6 and im6] [1375 Hz]
4.547473508864641E-13, -1.2482683609296146 [re7 and im7] [1500 Hz]
两个问题:
感谢。
答案 0 :(得分:1)
根据定义,FFT的输出值不是频率; 变量(即图中的轴)是频率。您要做的是找到复杂结果的大小以获得绝对值,但这些不是频率 - 相反,产生最大峰值的 x 值是您想要的频率。
如果您不确定,Wikipedia上会描述复数的大小。它只是真实和复杂部分的平方和的平方根,但是为了找到最大值,你显然不需要计算平方根。
答案 1 :(得分:1)
确实,一旦你弄清楚你的垃圾箱的频率,最高幅度的垃圾箱的频率接近峰值。但是你可以通过插值做得更好。你的高峰几乎总是在箱子之间。此网站似乎有几种很好的插值方式:http://www.dspguru.com/dsp/howtos/how-to-interpolate-fft-peak
答案 2 :(得分:0)
对于每个频率仓,您应该有两个值,即实数(x)和虚数(y)。平方和将给出该频率的幅度:
magnitude = sqrt(x*x + y*y);
虽然如果你只想找到峰值,你不需要平方根,只需找到最高的频率
magSquared = x*x + y*y