单频率的FFT

时间:2014-07-08 14:07:44

标签: java fft

我需要获得某个频率的信号幅度。 我使用FFTAnalysis函数。但我得到所有光谱。如何修改它以获得某个频率的信号幅度?

例如我有:

data = 1024点数组;

如果我使用FFTAnalysis,我会得到1024点的FFTdata数组。

但我只需要FFTdata [454]例如();

public static float[] FFTAnalysis(short[] AVal, int Nvl, int Nft) {
  double TwoPi = 6.283185307179586;
  int i, j, n, m, Mmax, Istp;
  double Tmpr, Tmpi, Wtmp, Theta;
  double Wpr, Wpi, Wr, Wi;
  double[] Tmvl;
  float[] FTvl;

  n = Nvl * 2; 
  Tmvl = new double[n];
  FTvl = new float[Nvl];
  for (i = 0; i < Nvl; i++) {
    j = i * 2; Tmvl[j] = 0; Tmvl[j+1] = AVal[i];
  }

  i = 1; j = 1;
  while (i < n) {
    if (j > i) {
      Tmpr = Tmvl[i]; Tmvl[i] = Tmvl[j]; Tmvl[j] = Tmpr;
      Tmpr = Tmvl[i+1]; Tmvl[i+1] = Tmvl[j+1]; Tmvl[j+1] = Tmpr;
    }
    i = i + 2; m = Nvl;
    while ((m >= 2) && (j > m)) {
      j = j - m; m = m >> 1;
    }
    j = j + m;
  }

  Mmax = 2;
  while (n > Mmax) {
    Theta = -TwoPi / Mmax; Wpi = Math.sin(Theta);
    Wtmp = Math.sin(Theta / 2); Wpr = Wtmp * Wtmp * 2;
    Istp = Mmax * 2; Wr = 1; Wi = 0; m = 1;

    while (m < Mmax) {
      i = m; m = m + 2; Tmpr = Wr; Tmpi = Wi;
      Wr = Wr - Tmpr * Wpr - Tmpi * Wpi;
      Wi = Wi + Tmpr * Wpi - Tmpi * Wpr;

      while (i < n) {
        j = i + Mmax;
        Tmpr = Wr * Tmvl[j] - Wi * Tmvl[j-1];
        Tmpi = Wi * Tmvl[j] + Wr * Tmvl[j-1];

        Tmvl[j] = Tmvl[i] - Tmpr; Tmvl[j-1] = Tmvl[i-1] - Tmpi;
        Tmvl[i] = Tmvl[i] + Tmpr; Tmvl[i-1] = Tmvl[i-1] + Tmpi;
        i = i + Istp;
      }
    }

    Mmax = Istp;
  }

  for (i = 0; i < Nft; i++) {
    j = i * 2; FTvl[Nft - i - 1] = (float) Math.sqrt((Tmvl[j]*Tmvl[j]) + (Tmvl[j+1]*Tmvl[j+1]));
  }
return FTvl;

}

3 个答案:

答案 0 :(得分:1)

Goertzel算法(或滤波器)类似于计算FFT的1个bin的幅度。

Goertzel算法与FFT的1 bin相同,但数字伪像除外,如果频率的周期是Goertzel滤波器长度的精确约数。否则,从非周期性孔径大小的矩形窗口以及该窗口如何与输入的相位相关联,会有一些额外的扇形效应。

乘以复数正弦曲线并取复数和的大小在计算上与Goertzel类似,不同之处在于Goertzel不需要每个点单独调用(或查找)trig库函数,因为它通常包含一个trig递归部分算法。

答案 1 :(得分:0)

您在输入数据上乘以(复数)正弦波,并对结果进行积分。

乘以复数正弦等于频移,您希望将目标频率降低到0 Hz。积分是一个低通滤波步骤,带宽是采样长度的倒数。

然后你得到一个复数,这个数字与你在FFT频率上找到的频率相同(因为实质上这就是FFT的作用)。

答案 2 :(得分:0)

快速傅立叶变换(FFT)是一种非常快的方法,可以完成许多离散的傅立叶变换。因此,FFT是为需要从输入中获得许多频率的用户而设计的。如果您只需要一个频率,那么DFT是最好的选择(否则会浪费资源)。

DFT定义为:

DFT

所以,用伪代码:

samples = [#,#,#,#...]
FREQ = 440; // frequency to detect
PI = 3.14159;
E = 2.718;
DFT = 0i; // this is a complex number
for(int sampleNum=0; sampleNum<N; sampleNum++){
    DFT += samples[sampleNum] * E^( (-2*PI*1i*N) / N ); //Note that "i" here means imaginary
}

结果变量DFT将是一个复数,代表所选频率的实数值和虚数值。