FFT返回其成为NaN的较大值 [英] FFT returns large values which become NaN

查看:363
本文介绍了FFT返回其成为NaN的较大值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用FFT类来获得​​基频。我传递一些double值的数组。数组类似于队列。当添加一个新的值的数组将被更新。但我的问题是输出数组将成为大批不时。它成为电子的功率值,最后返回NaN。使用下面FFT级即时通讯和我在哪里出了问题感到困惑。它是一个很大的帮助,如果任何人都可以给搞清楚原因的帮助。

这是我的FFT类

 公共类FFT {  INT N,M;  //查找表。只需要重新计算时的大小变化FFT。
  双[] COS;
  双[]罪。  双[]窗口;  公共FFT(INT N){
    this.n = N;
    this.m =(int)的(将Math.log(N)/将Math.log(2));    //确保n是2的幂
    如果(N =(1 <<;!&所述; m)段)
      抛出新的RuntimeException(FFT长度必须是2的幂);    // precompute表
    COS =新的双[N / 2];
    罪=新的双[N / 2];//的for(int i = 0; I&LT; N / 4;我++){
// COS [I] = Math.cos(-2 * Math.PI * I / N);
//罪[N / 4-I] = COS [I]
// COS [N / 2-ⅰ] = -cos [I];
//罪[N / 4 + 1] = COS [I]
// COS [N / 2 + I] = -cos [I];
//罪[N * 3/4​​-I] = -cos [I]
// COS [N-1] = COS [I];
//罪[N * 3/4​​ + I] = -cos [I]
//}    的for(int i = 0; I&LT; N / 2;我++){
      COS [I] = Math.cos(-2 * Math.PI * I / N);
      罪[I] = Math.sin(-2 * Math.PI * I / N);
    }    makeWindow();
  }  保护无效makeWindow(){
    //做一个布莱克曼窗口:
    // W(N)= 0.42-0.5cos {(2 * PI * N)/(N-1)} + 0.08cos {(4 * PI * N)/(N-1)};
    窗口=新的双[N];
    的for(int i = 0; I&LT; window.length;我++)
      窗口[I] = 0.42 - 0.5 * Math.cos(2 * Math.PI *的i /(N-1))
    + 0.08 * Math.cos(4 * Math.PI *的i /(N-1));
  }  市民双[] getWindow(){
    返回窗口;
  }
  / ******************* **************
  * fft.c
  道格拉斯·琼斯L.
  *伊利诺伊大学厄巴纳 - 香槟分校
  * 1992年1月19日
  * http://cnx.rice.edu/content/m12016/latest/
  *
  * FFT:一个复杂的输入的就地基数2 DIT DFT
  *
  *输入:
  * N:FFT的长度:必须是二的幂
  * M:N = 2 ** M
  * 输入输出
  * X:双长度为n的阵列数据的实部
  * Y:长度为n的双阵列数据IMAG部分
  *
  *许可复制并使用这个程序被授予
  *只要这个头是包括在内。
  ************************************************** ************** /
  公共无效FFT(双[] X,双[] Y)
  {
    INT I,J,K,N1,N2,一个;
    双C,S,E,T1,T2;
    //位反转
    J = 0;
    N2 = N / 2;
    对于(i = 1; I&LT; N - 1;我++){
      N1 = N2;
      而(J&GT; = N1){
    当J = J - N1;
    N1 = N1 / 2;
      }
      当J = J + N1;      如果(ⅰ&所述; 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;    对于(i = 0; I&LT;米;我++){
      N1 = N2;
      N2 = N + N2;
      一个= 0;      为(J = 0; J&LT; N1; J ++){
    C = COS [A];
    S =罪[A];
    A + = 1&LT;&LT; (M-1);    对于(K =焦耳; K&LT; N,K = K + N2){
      T1 = C * X [K + N1] - S * Y [K + N1];
      T2 = S * X [K + N1] + C * Y [K + N1];
      ×〔K + N1] = X [k]的 - T1;
      Y [K + N1] = Y [K] - T2;
      X [k]的= X [K] + T1;
      Y [K] = Y [K] + T2;
    }
      }
    }
  }
  //测试FFT,以确保它的工作
  公共静态无效的主要(字串[] args){
    INT N = 8;    FFT FFT =新的FFT(N);    双[] =窗口fft.getWindow();
    双[] =重新新型双[N];
    双[] =即时通讯新的双[N];    // 冲动
    重新[0] = 1;即时[0] = 0;
    的for(int i = 1; I&LT; N;我++)
      再由[i] =即时[I] ​​= 0;
    beforeAfter(FFT,重,即时通讯);    //奈奎斯特
    的for(int i = 0; I&LT; N;我++){
      再由[i] = Math.pow(-1,I);
      即时[I] ​​= 0;
    }
    beforeAfter(FFT,重,即时通讯);    //单罪
    的for(int i = 0; I&LT; N;我++){
      再由[i] = Math.cos(2 * Math.PI * I / N);
      即时[I] ​​= 0;
    }
    beforeAfter(FFT,重,即时通讯);    //斜坡
    的for(int i = 0; I&LT; N;我++){
      再由[i] =我;
      即时[I] ​​= 0;
    }
    beforeAfter(FFT,重,即时通讯);    很长一段时间= System.currentTimeMillis的();
    双ITER = 30000;
    的for(int i = 0; I&LT; ITER;我++)
      fft.fft(RE,即时通讯);
    时间= System.currentTimeMillis的() - 时间;
    的System.out.println(平均+(时间/ ITER)+每次迭代毫秒);
  }  保护静态无效beforeAfter(FFT快速傅里叶变换,双[]再次,双[] IM){
    的System.out.println(前:);
    printReIm(RE,即时通讯);
    fft.fft(RE,即时通讯);
    的System.out.println(后);
    printReIm(RE,即时通讯);
  }  保护静态无效printReIm(双[]再次,双[] IM){
    System.out.print(回复:[);
    的for(int i = 0; I&LT; re.length;我++)
      System.out.print(((INT)(重新[I] * 1000)/1000.0)+);    System.out.print(] \\稔:);
    的for(int i = 0; I&LT; im.length;我++)
      System.out.print(((int)的(IM [I] * 1000)/1000.0)+);    的System.out.println(]);
  }
}

下面是我的android的主要活动类,它使用了FFT实例

 公共类MainActivity扩展活动实现SensorEventListener {    静态最终浮动ALPHA = 0.15f;    私人诠释计数= 0;
    私有静态GraphicalView图。
    专用线图线=新线图();
    私有静态线程线程;
    私人的SensorManager mSensorManager;
    私人传感器mAccelerometer;
    TextView的称号,电视,TV1,TV2,TV3,TV4,TV5,TV6;
    RelativeLayout的布局;
    私人双A;
    私人双M = 0;
    私人浮动P,Q,R;
    众长[] myList中;
    市民双[] myList2;
    市民双[] gettedList;
    静态字符串K1,K2,K3,K4;
    INT iniX = 0;
    公共FFT FFT;
    公共myArray的myArrayQueue;    @覆盖
    保护无效的onCreate(捆绑savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.activity_main);
         FFT =新的FFT(128);
         myList中=新长[128];
         myList2 =新的双[128];
         gettedList =新的双[128];
        myArrayQueue =新myArray的(128);        //获取传感器服务
        mSensorManager =(的SensorManager)getSystemService(Context.SENSOR_SERVICE);
        //获取加速度传感器
        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        //获取布局
        布局=(RelativeLayout的)findViewById(R.id.relative);
        的LinearLayout布局=(的LinearLayout)findViewById(R.id.layoutC);
        鉴于= line.getView(本);
        layout.addView(视图);
        //获取textviews
        标题=(的TextView)findViewById(R.id.name);
        //tv=(TextView)findViewById(R.id.xval);
        //tv1=(TextView)findViewById(R.id.yval);
        //tv2=(TextView)findViewById(R.id.zval);
        TV3 =(的TextView)findViewById(R.id.TextView04);
        TV4 =(的TextView)findViewById(R.id.TextView01);
        TV5 =(的TextView)findViewById(R.id.TextView02);
        TV6 =(的TextView)findViewById(R.id.TextView03);        的for(int i = 0; I&LT; myList2.length;我++){
            myList2 [I] = 0;        }    }    公众最终无效onAccuracyChanged(传感器传感器,精度INT)
    {
        //这里做的东西,如果传感器的精度变化。
    }
    @覆盖
    公众最终无效onSensorChanged(SensorEvent事件)
    {
        数= + 1;
        //许多传感器返回3个值,一个用于每个轴。
        浮X = event.values​​ [0];
        浮Y = event.values​​ [1];
        浮Z = event.values​​ [2];        //浮动[] =第{X,Y,Z};
        //浮[] larst = {P,Q,R};        // larst =低通(第一,larst);
        //双FY = b.Filter(Y);
        //双FZ = b.Filter(Z);        //获取合并值
        // M =(浮点)的Math.sqrt(larst [0] * larst [0] + larst [1] * larst [1] + larst [2] * larst [2]);
        M =(双)的Math.sqrt(X * X + Y * Y + Z * Z);
        使用的TextView //显示值
        //title.setText(R.string.app_name);
        //tv.setText(\"X轴+\\ t \\ t+ X);
        //tv1.setText(\"Y轴+\\ t \\ t+ Y);
        //tv2.setText(\"Z轴+\\ t \\ t+ Z);        // myList上[iniX] = m * m的;
        // myList中[iniX + 1] = myList中[iniX];            iniX = + 1;            // myList中[3] = myList中[2];
            // myList中[2] = myList中[1];
            // myList中[1] = myList中[0];        myArrayQueue.insert(m * m的);
    gettedList = myArrayQueue.getMyList();
        为/ *(int类型的= myList.length-1;一个大于0; A--)
            {
            myList中[α] = myList中[A-1];
            }
            myList中[0] = m * m的;
        * /
    fft.fft(gettedList,myList2);
            K1 = Double.toString(myList2 [0]);
            K2 = Double.toString(myList2 [1]);
            K3 = Double.toString(myList2 [2]);
            K4 = Double.toString(myList2 [3]);            tv3.setText([0] =+ K1);
            tv4.setText([1] =1 + K 2);
            tv5.setText([2] =+ K3);
            tv6.setText([3] =+ K4);
            line.addNewPoint(iniX,(浮点)M);
            view.repaint();
    }    @覆盖
    保护无效onResume()
    {
        super.onResume();
        mSensorManager.registerListener(这一点,mAccelerometer,SensorManager.SENSOR_DELAY_NORMAL);
    }
    @覆盖
    保护无效的onPause()
    {
        super.onPause();
        mSensorManager.unregisterListener(本);
    }    公共无效LineGraphHandler(查看视图){    }    //低通滤波器
    保护浮法[]低通(浮法[]输入,浮动[]输出){
        如果(输出== NULL)返回输入;        的for(int i = 0; I&LT; input.length;我++){
            输出[I] =输出[I] + ALPHA *(输入[I] - 输出[I]);
        }
        返回输出;
    }
    / * @覆盖
    公共无效调用onStart(){
        super.onStart();
        鉴于= line.getView(本);
        的setContentView(视图);
    } * /}


解决方案

这是FFT输出只会产生非数字如果输入包含其中。所以调用它来调试code之前明确检查输入数组的FFT任何超出范围的值。然后从那里向后工作,以找出他们是从哪里来的。

I'm using a FFT class to get the fundamental frequency. I'm passing an array of some double values. Array is like queue. when add a new values array will be updated. But my problem is output array will become large numbers time to time. Its become E to the power value and finally returns NaN. Im using below FFT class and I'm confused in where is the problem. Its a big help if anyone can give a help by figuring out the cause.

here is my FFT class

  public class FFT {

  int n, m;

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

  double[] window;

  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/4; i++) {
//       cos[i] = Math.cos(-2*Math.PI*i/n);
//       sin[n/4-i] = cos[i];
//       cos[n/2-i] = -cos[i];
//       sin[n/4+i] = cos[i];
//       cos[n/2+i] = -cos[i];
//       sin[n*3/4-i] = -cos[i];
//       cos[n-i]   = cos[i];
//       sin[n*3/4+i] = -cos[i];    
//     }

    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);
    }

    makeWindow();
  }

  protected void makeWindow() {
    // Make a blackman window:
    // w(n)=0.42-0.5cos{(2*PI*n)/(N-1)}+0.08cos{(4*PI*n)/(N-1)};
    window = new double[n];
    for(int i = 0; i < window.length; i++)
      window[i] = 0.42 - 0.5 * Math.cos(2*Math.PI*i/(n-1)) 
    + 0.08 * Math.cos(4*Math.PI*i/(n-1));
  }

  public double[] getWindow() {
    return window;
  }


  /***************************************************************
  * 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,e,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;
    }
      }
    }
  }                          




  // Test the FFT to make sure it's working
  public static void main(String[] args) {
    int N = 8;

    FFT fft = new FFT(N);

    double[] window = fft.getWindow();
    double[] re = new double[N];
    double[] im = new double[N];

    // Impulse
    re[0] = 1; im[0] = 0;
    for(int i=1; i<N; i++)
      re[i] = im[i] = 0;
    beforeAfter(fft, re, im);

    // Nyquist
    for(int i=0; i<N; i++) {
      re[i] = Math.pow(-1, i);
      im[i] = 0;
    }
    beforeAfter(fft, re, im);

    // Single sin
    for(int i=0; i<N; i++) {
      re[i] = Math.cos(2*Math.PI*i / N);
      im[i] = 0;
    }
    beforeAfter(fft, re, im);

    // Ramp
    for(int i=0; i<N; i++) {
      re[i] = i;
      im[i] = 0;
    }
    beforeAfter(fft, re, im);

    long time = System.currentTimeMillis();
    double iter = 30000;
    for(int i=0; i<iter; i++)
      fft.fft(re,im);
    time = System.currentTimeMillis() - time;
    System.out.println("Averaged " + (time/iter) + "ms per iteration");
  }

  protected static void beforeAfter(FFT fft, double[] re, double[] im) {
    System.out.println("Before: ");
    printReIm(re, im);
    fft.fft(re, im);
    System.out.println("After: ");
    printReIm(re, im);
  }

  protected static void printReIm(double[] re, double[] im) {
    System.out.print("Re: [");
    for(int i=0; i<re.length; i++)
      System.out.print(((int)(re[i]*1000)/1000.0) + " ");

    System.out.print("]\nIm: [");
    for(int i=0; i<im.length; i++)
      System.out.print(((int)(im[i]*1000)/1000.0) + " ");

    System.out.println("]");
  }
}

Below is my main activity class in android which uses the FFT instance

    public class MainActivity extends Activity implements SensorEventListener{

    static final float ALPHA = 0.15f;

    private int count=0;
    private static GraphicalView view;
    private LineGraph line = new LineGraph();
    private static Thread thread;
    private SensorManager mSensorManager;
    private Sensor mAccelerometer;
    TextView title,tv,tv1,tv2,tv3,tv4,tv5,tv6;
    RelativeLayout layout;
    private double a;
    private double m = 0;
    private float p,q,r;
    public long[] myList;
    public double[] myList2;
    public double[] gettedList;
    static String k1,k2,k3,k4;
    int iniX=0;  
    public  FFT fft;
    public  myArray myArrayQueue;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
         fft=new FFT(128);
         myList=new long[128];
         myList2=new double[128];
         gettedList=new double[128];
        myArrayQueue=new myArray(128);

        //get the sensor service
        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        //get the accelerometer sensor
        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        //get layout
        layout = (RelativeLayout)findViewById(R.id.relative);
        LinearLayout layout = (LinearLayout) findViewById(R.id.layoutC);
        view= line.getView(this);
        layout.addView(view);
        //get textviews
        title=(TextView)findViewById(R.id.name);
        //tv=(TextView)findViewById(R.id.xval);
        //tv1=(TextView)findViewById(R.id.yval);
        //tv2=(TextView)findViewById(R.id.zval);


        tv3=(TextView)findViewById(R.id.TextView04);
        tv4=(TextView)findViewById(R.id.TextView01);
        tv5=(TextView)findViewById(R.id.TextView02);
        tv6=(TextView)findViewById(R.id.TextView03);



        for (int i = 0; i < myList2.length; i++){
            myList2[i] =0;

        }



    }

    public final void onAccuracyChanged(Sensor sensor, int accuracy)
    {
        // Do something here if sensor accuracy changes.
    }
    @Override
    public final void onSensorChanged(SensorEvent event)
    {
        count=+1;
        // Many sensors return 3 values, one for each axis.


        float x = event.values[0];
        float y = event.values[1];
        float z = event.values[2];



        //float[] first={x,y,z};
        //  float[] larst={p,q,r};

        //larst= lowPass(first,larst);
        //double FY= b.Filter(y);
        //double FZ= b.Filter(z);

        //get merged value
        //  m = (float) Math.sqrt(larst[0]*larst[0]+larst[1]*larst[1]+larst[2]*larst[2]);
        m=(double)Math.sqrt(x*x+y*y+z*z);


        //display values using TextView
        //title.setText(R.string.app_name);
        //tv.setText("X axis" +"\t\t"+x);
        //tv1.setText("Y axis" + "\t\t" +y);
        //tv2.setText("Z axis" +"\t\t" +z);



        //myList[iniX]=m*m;
        //myList[iniX+1]=myList[iniX];

            iniX=+1;

            //myList[3]=myList[2];
            //myList[2]=myList[1];
            //myList[1]=myList[0];

        myArrayQueue.insert(m*m);
    gettedList=myArrayQueue.getMyList();
        /*  for(int a = myList.length-1;a>0;a--)
            {
            myList[a]=myList[a-1];


            }
            myList[0]=m*m;
        */  


    fft.fft(gettedList, myList2);
            k1=Double.toString(myList2[0]);
            k2=Double.toString(myList2[1]);
            k3=Double.toString(myList2[2]);
            k4=Double.toString(myList2[3]);

            tv3.setText("[0]= "+k1);
            tv4.setText("[1]= "+k2);
            tv5.setText("[2]= "+k3);
            tv6.setText("[3]= "+k4);
            line.addNewPoint(iniX,(float) m);
            view.repaint();


    }

    @Override
    protected void onResume()
    {
        super.onResume();
        mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
    }
    @Override
    protected void onPause()
    {
        super.onPause();
        mSensorManager.unregisterListener(this);
    }

    public void LineGraphHandler(View view){



    }

    //Low pass filter
    protected float[] lowPass( float[] input, float[] output ) {
        if ( output == null ) return input;

        for ( int i=0; i<input.length; i++ ) {
            output[i] = output[i] + ALPHA * (input[i] - output[i]);
        }
        return output;
    }
    /*@Override
    public void onStart(){
        super.onStart();    
        view= line.getView(this);
        setContentView(view);
    }*/

}

解决方案

An FFT output will only produce NaNs if the input contains them. So explicitly check the input array to the FFT for any out-of-range values before calling it to debug your code. Then work backwards from there to find out where they are coming from.

这篇关于FFT返回其成为NaN的较大值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆