Home | History | Annotate | Download | only in audioquality
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * 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, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 
     17 #include "Fft.h"
     18 
     19 #include <stdlib.h>
     20 #include <math.h>
     21 
     22 Fft::Fft(void) : mCosine(0), mSine(0), mFftSize(0), mFftTableSize(0) { }
     23 
     24 Fft::~Fft(void) {
     25     fftCleanup();
     26 }
     27 
     28 /* Construct a FFT table suitable to perform a DFT of size 2^power. */
     29 void Fft::fftInit(int power) {
     30     fftCleanup();
     31     fftMakeTable(power);
     32 }
     33 
     34 void Fft::fftCleanup() {
     35         delete [] mSine;
     36         delete [] mCosine;
     37         mSine = NULL;
     38         mCosine = NULL;
     39         mFftTableSize = 0;
     40         mFftSize = 0;
     41 }
     42 
     43 /* z <- (10 * log10(x^2 + y^2))    for n elements */
     44 int Fft::fftLogMag(float *x, float *y, float *z, int n) {
     45     float *xp, *yp, *zp, t1, t2, ssq;
     46 
     47     if(x && y && z && n) {
     48         for(xp=x+n, yp=y+n, zp=z+n; zp > z;) {
     49             t1 = *--xp;
     50             t2 = *--yp;
     51             ssq = (t1*t1)+(t2*t2);
     52             *--zp = (ssq > 0.0)? 10.0 * log10((double)ssq) : -200.0;
     53         }
     54         return 1;    //true
     55     } else {
     56         return 0;    // false/fail
     57     }
     58 }
     59 
     60 int Fft::fftMakeTable(int pow2) {
     61     int lmx, lm;
     62     float *c, *s;
     63     double scl, arg;
     64 
     65     mFftSize = 1 << pow2;
     66     mFftTableSize = lmx = mFftSize/2;
     67     mSine = new float[lmx];
     68     mCosine = new float[lmx];
     69     scl = (M_PI*2.0)/mFftSize;
     70     for (s=mSine, c=mCosine, lm=0; lm<lmx; lm++ ) {
     71         arg = scl * lm;
     72         *s++ = sin(arg);
     73         *c++ = cos(arg);
     74     }
     75     mBase = (mFftTableSize * 2)/mFftSize;
     76     mPower2 = pow2;
     77     return(mFftTableSize);
     78 }
     79 
     80 
     81 /* Compute the discrete Fourier transform of the 2**l complex sequence
     82  * in x (real) and y (imaginary).  The DFT is computed in place and the
     83  * Fourier coefficients are returned in x and y.
     84  */
     85 void Fft::fft( float *x, float *y ) {
     86     float c, s, t1, t2;
     87     int j1, j2, li, lix, i;
     88     int lmx, lo, lixnp, lm, j, nv2, k=mBase, im, jm, l = mPower2;
     89 
     90     for (lmx=mFftSize, lo=0; lo < l; lo++, k *= 2) {
     91         lix = lmx;
     92         lmx /= 2;
     93         lixnp = mFftSize - lix;
     94         for (i=0, lm=0; lm<lmx; lm++, i += k ) {
     95             c = mCosine[i];
     96             s = mSine[i];
     97             for ( li = lixnp+lm, j1 = lm, j2 = lm+lmx; j1<=li;
     98                   j1+=lix, j2+=lix ) {
     99                 t1 = x[j1] - x[j2];
    100                 t2 = y[j1] - y[j2];
    101                 x[j1] += x[j2];
    102                 y[j1] += y[j2];
    103                 x[j2] = (c * t1) + (s * t2);
    104                 y[j2] = (c * t2) - (s * t1);
    105             }
    106         }
    107     }
    108 
    109     /* Now perform the bit reversal. */
    110     j = 1;
    111     nv2 = mFftSize/2;
    112     for ( i=1; i < mFftSize; i++ ) {
    113         if ( j < i ) {
    114             jm = j-1;
    115             im = i-1;
    116             t1 = x[jm];
    117             t2 = y[jm];
    118             x[jm] = x[im];
    119             y[jm] = y[im];
    120             x[im] = t1;
    121             y[im] = t2;
    122         }
    123         k = nv2;
    124         while ( j > k ) {
    125             j -= k;
    126             k /= 2;
    127         }
    128         j += k;
    129     }
    130 }
    131 
    132 /* Compute the discrete inverse Fourier transform of the 2**l complex
    133  * sequence in x (real) and y (imaginary).  The DFT is computed in
    134  * place and the Fourier coefficients are returned in x and y.  Note
    135  * that this DOES NOT scale the result by the inverse FFT size.
    136  */
    137 void Fft::ifft(float *x, float *y ) {
    138     float c, s, t1, t2;
    139     int j1, j2, li, lix, i;
    140     int lmx, lo, lixnp, lm, j, nv2, k=mBase, im, jm, l = mPower2;
    141 
    142     for (lmx=mFftSize, lo=0; lo < l; lo++, k *= 2) {
    143         lix = lmx;
    144         lmx /= 2;
    145         lixnp = mFftSize - lix;
    146         for (i=0, lm=0; lm<lmx; lm++, i += k ) {
    147             c = mCosine[i];
    148             s = - mSine[i];
    149             for ( li = lixnp+lm, j1 = lm, j2 = lm+lmx; j1<=li;
    150                         j1+=lix, j2+=lix ) {
    151                 t1 = x[j1] - x[j2];
    152                 t2 = y[j1] - y[j2];
    153                 x[j1] += x[j2];
    154                 y[j1] += y[j2];
    155                 x[j2] = (c * t1) + (s * t2);
    156                 y[j2] = (c * t2) - (s * t1);
    157             }
    158         }
    159     }
    160 
    161     /* Now perform the bit reversal. */
    162     j = 1;
    163     nv2 = mFftSize/2;
    164     for ( i=1; i < mFftSize; i++ ) {
    165         if ( j < i ) {
    166             jm = j-1;
    167             im = i-1;
    168             t1 = x[jm];
    169             t2 = y[jm];
    170             x[jm] = x[im];
    171             y[jm] = y[im];
    172             x[im] = t1;
    173             y[im] = t2;
    174         }
    175         k = nv2;
    176         while ( j > k ) {
    177             j -= k;
    178             k /= 2;
    179         }
    180         j += k;
    181     }
    182 }
    183 
    184 int Fft::fftGetSize(void) { return mFftSize; }
    185 
    186 int Fft::fftGetPower2(void) { return mPower2; }
    187