2014-05-21 27 views
1

在Android中实现FFT算法时出现问题。我们假设我有一个长度为8.000字节的wav文件。 我知道你必须选择FFT算法的大小(也必须是2的幂)。我的问题是,我现在不确定如何进一步开展工作。假设我已经选择了N = 1024的FFT大小。 我基本上在我的脑海选项: 1)直接应用FFT算法的8.000字节 2)整个阵列划分为1024个字节的块的8000字节数组wav文件(与0's的最后一块补直到有8个确切的块), 然后将fft应用于每个块,最后再次将所有不同的块重新整理成单个字节数组来表示。 8000 * 2 * 1秒= 8192FFT阵列的实现

我觉得it's选项2,但我不能完全肯定。

这里是FFT阵列我使用:

package com.example.acoustics; 

public class FFT { 

    int n, m; 

    // Lookup tables. Only need to recompute when size of FFT changes. 
    double[] cos; 
    double[] sin; 

    public FFT(int n) { 
     this.n = n; 
     this.m = (int) (Math.log(n)/Math.log(2)); 

     // Make sure n is a power of 2 
     if (n != (1 << m)) 
      throw new RuntimeException("FFT length must be power of 2"); 

     // precompute tables 
     cos = new double[n/2]; 
     sin = new double[n/2]; 

     for (int i = 0; i < n/2; i++) { 
      cos[i] = Math.cos(-2 * Math.PI * i/n); 
      sin[i] = Math.sin(-2 * Math.PI * i/n); 
     } 

    } 

    /*************************************************************** 
    * fft.c 
    * Douglas L. Jones 
    * University of Illinois at Urbana-Champaign 
    * January 19, 1992 
    * http://cnx.rice.edu/content/m12016/latest/ 
    * 
    * fft: in-place radix-2 DIT DFT of a complex input 
    * 
    * input: 
    * n: length of FFT: must be a power of two 
    * m: n = 2**m 
    * input/output 
    * x: double array of length n with real part of data 
    * y: double array of length n with imag part of data 
    * 
    * Permission to copy and use this program is granted 
    * as long as this header is included. 
    ****************************************************************/ 

    public void fft(double[] x, double[] y) { 
     int i, j, k, n1, n2, a; 
     double c, s, t1, t2; 

     // Bit-reverse 
     j = 0; 
     n2 = n/2; 
     for (i = 1; i < n - 1; i++) { 
      n1 = n2; 
      while (j >= n1) { 
       j = j - n1; 
       n1 = n1/2; 
      } 
      j = j + n1; 

      if (i < j) { 
       t1 = x[i]; 
       x[i] = x[j]; 
       x[j] = t1; 
       t1 = y[i]; 
       y[i] = y[j]; 
       y[j] = t1; 
      } 
     } 

     // FFT 
     n1 = 0; 
     n2 = 1; 

     for (i = 0; i < m; i++) { 
      n1 = n2; 
      n2 = n2 + n2; 
      a = 0; 

      for (j = 0; j < n1; j++) { 
       c = cos[a]; 
       s = sin[a]; 
       a += 1 << (m - i - 1); 

       for (k = j; k < n; k = k + n2) { 
        t1 = c * x[k + n1] - s * y[k + n1]; 
        t2 = s * x[k + n1] + c * y[k + n1]; 
        x[k + n1] = x[k] - t1; 
        y[k + n1] = y[k] - t2; 
        x[k] = x[k] + t1; 
        y[k] = y[k] + t2; 
       } 
      } 
     } 
    } 
} 
+1

你想要对FFT结果做什么?对于大多数实际应用,您可以将数据阵列分成重叠块,应用窗口,进行FFT,进行滤波/修改,进行逆FFT并使用相同的重叠结构添加结果。窗口可以被安排为统一的分割,以便在没有修改的情况下通过这些操作获得原始阵列。 – LutzL

+0

我试图绘制这样的一个FFT频谱:[剧情](http://www.mathworks.com/help/signal/ug/periodogram_psd.png) – paviflo

回答

1

我认为你可以使用与FFT整个数组。没有问题,你可以使用2^13 = 8192并用零填充数组,这个处理过程也被称为零填充,用于多个FFT的实现。如果你的程序运行良好,运行整个数组并没有问题,但是如果你使用大小为1024的部分来计算FFT,那么你将得到一个分段傅里叶变换,它不能很好地描述整个信号的频谱,因为FFT使用数组中的所有位置来计算新变换数组中的每个值,然后在位置1中得不到正确答案,例如,如果不使用整个信号数组。

这是我对你的问题的分析我不是百分之百肯定的,但是我对傅立叶级数的知识告诉我,如果计算傅立叶变换的分段形式而不是整个系列,这几乎是要做的。

+1

是的,最好是用整个事情的时候是可行的。但是,我认为填充数应该是输入的平均值。或者在用零填充之前标准化数据。我错了吗?正如我所看到的那样,这个想法就是让它看起来像是沉默的声音。如果有直流偏移,则沉默不为零。 –