Home | History | Annotate | Download | only in loopback
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package org.drrickorang.loopback;
     18 
     19 
     20 /**
     21  * This class computes FFT of inputting data.
     22  * Note: this part of code is originally from another project, so there's actually multiple copies
     23  * of this code. Should somehow merge these copies in the future. Also, no modification on
     24  * naming has been made, but naming should be changed once we merge all copies.
     25  */
     26 
     27 public class FFT {
     28     private int       m;
     29     private double[]  cos;   // precomputed cosine tables for FFT
     30     private double[]  sin;   // precomputed sine tables for FFT
     31     private final int mFFTSamplingSize;
     32 
     33 
     34     FFT(int FFTSamplingSize) {
     35         mFFTSamplingSize = FFTSamplingSize;
     36 
     37         // set up variables needed for computing FFT
     38         m = (int) (Math.log(mFFTSamplingSize) / Math.log(2));
     39 
     40         // Make sure n is a power of 2
     41         if (mFFTSamplingSize != (1 << m))
     42             throw new RuntimeException("FFT sampling size must be power of 2");
     43 
     44         // precomputed tables
     45         cos = new double[mFFTSamplingSize / 2];
     46         sin = new double[mFFTSamplingSize / 2];
     47 
     48         for (int i = 0; i < mFFTSamplingSize / 2; i++) {
     49             cos[i] = Math.cos(-2 * Math.PI * i / mFFTSamplingSize);
     50             sin[i] = Math.sin(-2 * Math.PI * i / mFFTSamplingSize);
     51         }
     52     }
     53 
     54 
     55     /**
     56      * Do FFT, and store the result's real part to "x", imaginary part to "y".
     57      */
     58     public void fft(double[] x, double[] y, int sign) {
     59         int i, j, k, n1, n2, a;
     60         double c, s, t1, t2;
     61 
     62         // Bit-reverse
     63         j = 0;
     64         n2 = mFFTSamplingSize / 2;
     65         for (i = 1; i < mFFTSamplingSize - 1; i++) {
     66             n1 = n2;
     67             while (j >= n1) {
     68                 j = j - n1;
     69                 n1 = n1 / 2;
     70             }
     71             j = j + n1;
     72 
     73             if (i < j) {
     74                 t1 = x[i];
     75                 x[i] = x[j];
     76                 x[j] = t1;
     77                 t1 = y[i];
     78                 y[i] = y[j];
     79                 y[j] = t1;
     80             }
     81         }
     82 
     83         // FFT
     84         n1 = 0;
     85         n2 = 1;
     86 
     87         for (i = 0; i < m; i++) {
     88             n1 = n2;
     89             n2 = n2 + n2;
     90             a = 0;
     91 
     92             for (j = 0; j < n1; j++) {
     93                 c = cos[a];
     94                 s = sign * sin[a];
     95                 a += 1 << (m - i - 1);
     96 
     97                 for (k = j; k < mFFTSamplingSize; k = k + n2) {
     98                     t1 = c * x[k + n1] - s * y[k + n1];
     99                     t2 = s * x[k + n1] + c * y[k + n1];
    100                     x[k + n1] = x[k] - t1;
    101                     y[k + n1] = y[k] - t2;
    102                     x[k] = x[k] + t1;
    103                     y[k] = y[k] + t2;
    104                 }
    105             }
    106         }
    107     }
    108 
    109 }
    110