Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 
     12 /*
     13  * This file contains the function WebRtcSpl_ComplexFFT().
     14  * The description header can be found in signal_processing_library.h
     15  *
     16  */
     17 
     18 #include "signal_processing_library.h"
     19 
     20 #define CFFTSFT 14
     21 #define CFFTRND 1
     22 #define CFFTRND2 16384
     23 
     24 #if (defined ARM9E_GCC) || (defined ARM_WINM) || (defined ANDROID_AECOPT)
     25 extern "C" int FFT_4OFQ14(void *src, void *dest, int NC, int shift);
     26 
     27 // For detailed description of the fft functions, check the readme files in fft_ARM9E folder.
     28 int WebRtcSpl_ComplexFFT2(WebRtc_Word16 frfi[], WebRtc_Word16 frfiOut[], int stages, int mode)
     29 {
     30     return FFT_4OFQ14(frfi, frfiOut, 1 << stages, 0);
     31 }
     32 #endif
     33 
     34 int WebRtcSpl_ComplexFFT(WebRtc_Word16 frfi[], int stages, int mode)
     35 {
     36     int i, j, l, k, istep, n, m;
     37     WebRtc_Word16 wr, wi;
     38     WebRtc_Word32 tr32, ti32, qr32, qi32;
     39 
     40     /* The 1024-value is a constant given from the size of WebRtcSpl_kSinTable1024[],
     41      * and should not be changed depending on the input parameter 'stages'
     42      */
     43     n = 1 << stages;
     44     if (n > 1024)
     45         return -1;
     46 
     47     l = 1;
     48     k = 10 - 1; /* Constant for given WebRtcSpl_kSinTable1024[]. Do not change
     49          depending on the input parameter 'stages' */
     50 
     51     if (mode == 0)
     52     {
     53         // mode==0: Low-complexity and Low-accuracy mode
     54         while (l < n)
     55         {
     56             istep = l << 1;
     57 
     58             for (m = 0; m < l; ++m)
     59             {
     60                 j = m << k;
     61 
     62                 /* The 256-value is a constant given as 1/4 of the size of
     63                  * WebRtcSpl_kSinTable1024[], and should not be changed depending on the input
     64                  * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
     65                  */
     66                 wr = WebRtcSpl_kSinTable1024[j + 256];
     67                 wi = -WebRtcSpl_kSinTable1024[j];
     68 
     69                 for (i = m; i < n; i += istep)
     70                 {
     71                     j = i + l;
     72 
     73                     tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j])
     74                             - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1])), 15);
     75 
     76                     ti32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1])
     77                             + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j])), 15);
     78 
     79                     qr32 = (WebRtc_Word32)frfi[2 * i];
     80                     qi32 = (WebRtc_Word32)frfi[2 * i + 1];
     81                     frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qr32 - tr32, 1);
     82                     frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qi32 - ti32, 1);
     83                     frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qr32 + tr32, 1);
     84                     frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qi32 + ti32, 1);
     85                 }
     86             }
     87 
     88             --k;
     89             l = istep;
     90 
     91         }
     92 
     93     } else
     94     {
     95         // mode==1: High-complexity and High-accuracy mode
     96         while (l < n)
     97         {
     98             istep = l << 1;
     99 
    100             for (m = 0; m < l; ++m)
    101             {
    102                 j = m << k;
    103 
    104                 /* The 256-value is a constant given as 1/4 of the size of
    105                  * WebRtcSpl_kSinTable1024[], and should not be changed depending on the input
    106                  * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
    107                  */
    108                 wr = WebRtcSpl_kSinTable1024[j + 256];
    109                 wi = -WebRtcSpl_kSinTable1024[j];
    110 
    111                 for (i = m; i < n; i += istep)
    112                 {
    113                     j = i + l;
    114 
    115                     tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j])
    116                             - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1]) + CFFTRND),
    117                             15 - CFFTSFT);
    118 
    119                     ti32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1])
    120                             + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CFFTRND), 15 - CFFTSFT);
    121 
    122                     qr32 = ((WebRtc_Word32)frfi[2 * i]) << CFFTSFT;
    123                     qi32 = ((WebRtc_Word32)frfi[2 * i + 1]) << CFFTSFT;
    124                     frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
    125                             (qr32 - tr32 + CFFTRND2), 1 + CFFTSFT);
    126                     frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
    127                             (qi32 - ti32 + CFFTRND2), 1 + CFFTSFT);
    128                     frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
    129                             (qr32 + tr32 + CFFTRND2), 1 + CFFTSFT);
    130                     frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
    131                             (qi32 + ti32 + CFFTRND2), 1 + CFFTSFT);
    132                 }
    133             }
    134 
    135             --k;
    136             l = istep;
    137         }
    138     }
    139     return 0;
    140 }
    141