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_ComplexIFFT().
     14  * The description header can be found in signal_processing_library.h
     15  *
     16  */
     17 
     18 #include "signal_processing_library.h"
     19 
     20 #define CIFFTSFT 14
     21 #define CIFFTRND 1
     22 
     23 #if (defined ARM9E_GCC) || (defined ARM_WINM) || (defined ANDROID_AECOPT)
     24 extern "C" int FFT_4OIQ14(void *src, void *dest, int NC, int shift);
     25 
     26 // For detailed description of the fft functions, check the readme files in fft_ARM9E folder.
     27 int WebRtcSpl_ComplexIFFT2(WebRtc_Word16 frfi[], WebRtc_Word16 frfiOut[], int stages, int mode)
     28 {
     29     FFT_4OIQ14(frfi, frfiOut, 1 << stages, 0);
     30     return 0;
     31 }
     32 #endif
     33 
     34 int WebRtcSpl_ComplexIFFT(WebRtc_Word16 frfi[], int stages, int mode)
     35 {
     36     int i, j, l, k, istep, n, m, scale, shift;
     37     WebRtc_Word16 wr, wi;
     38     WebRtc_Word32 tr32, ti32, qr32, qi32;
     39     WebRtc_Word32 tmp32, round2;
     40 
     41     /* The 1024-value is a constant given from the size of WebRtcSpl_kSinTable1024[],
     42      * and should not be changed depending on the input parameter 'stages'
     43      */
     44     n = 1 << stages;
     45     if (n > 1024)
     46         return -1;
     47 
     48     scale = 0;
     49 
     50     l = 1;
     51     k = 10 - 1; /* Constant for given WebRtcSpl_kSinTable1024[]. Do not change
     52          depending on the input parameter 'stages' */
     53 
     54     while (l < n)
     55     {
     56         // variable scaling, depending upon data
     57         shift = 0;
     58         round2 = 8192;
     59 
     60         tmp32 = (WebRtc_Word32)WebRtcSpl_MaxAbsValueW16(frfi, 2 * n);
     61         if (tmp32 > 13573)
     62         {
     63             shift++;
     64             scale++;
     65             round2 <<= 1;
     66         }
     67         if (tmp32 > 27146)
     68         {
     69             shift++;
     70             scale++;
     71             round2 <<= 1;
     72         }
     73 
     74         istep = l << 1;
     75 
     76         if (mode == 0)
     77         {
     78             // mode==0: Low-complexity and Low-accuracy mode
     79             for (m = 0; m < l; ++m)
     80             {
     81                 j = m << k;
     82 
     83                 /* The 256-value is a constant given as 1/4 of the size of
     84                  * WebRtcSpl_kSinTable1024[], and should not be changed depending on the input
     85                  * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
     86                  */
     87                 wr = WebRtcSpl_kSinTable1024[j + 256];
     88                 wi = WebRtcSpl_kSinTable1024[j];
     89 
     90                 for (i = m; i < n; i += istep)
     91                 {
     92                     j = i + l;
     93 
     94                     tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16_RSFT(wr, frfi[2 * j], 0)
     95                             - WEBRTC_SPL_MUL_16_16_RSFT(wi, frfi[2 * j + 1], 0)), 15);
     96 
     97                     ti32 = WEBRTC_SPL_RSHIFT_W32(
     98                             (WEBRTC_SPL_MUL_16_16_RSFT(wr, frfi[2 * j + 1], 0)
     99                                     + WEBRTC_SPL_MUL_16_16_RSFT(wi,frfi[2*j],0)), 15);
    100 
    101                     qr32 = (WebRtc_Word32)frfi[2 * i];
    102                     qi32 = (WebRtc_Word32)frfi[2 * i + 1];
    103                     frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qr32 - tr32, shift);
    104                     frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qi32 - ti32, shift);
    105                     frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qr32 + tr32, shift);
    106                     frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qi32 + ti32, shift);
    107                 }
    108             }
    109         } else
    110         {
    111             // mode==1: High-complexity and High-accuracy mode
    112 
    113             for (m = 0; m < l; ++m)
    114             {
    115                 j = m << k;
    116 
    117                 /* The 256-value is a constant given as 1/4 of the size of
    118                  * WebRtcSpl_kSinTable1024[], and should not be changed depending on the input
    119                  * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
    120                  */
    121                 wr = WebRtcSpl_kSinTable1024[j + 256];
    122                 wi = WebRtcSpl_kSinTable1024[j];
    123 
    124                 for (i = m; i < n; i += istep)
    125                 {
    126                     j = i + l;
    127 
    128                     tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16_RSFT(wr, frfi[2 * j], 0)
    129                             - WEBRTC_SPL_MUL_16_16_RSFT(wi, frfi[2 * j + 1], 0) + CIFFTRND),
    130                             15 - CIFFTSFT);
    131 
    132                     ti32 = WEBRTC_SPL_RSHIFT_W32(
    133                                     (WEBRTC_SPL_MUL_16_16_RSFT(wr, frfi[2 * j + 1], 0)
    134                                             + WEBRTC_SPL_MUL_16_16_RSFT(wi, frfi[2 * j], 0)
    135                                             + CIFFTRND), 15 - CIFFTSFT);
    136 
    137                     qr32 = ((WebRtc_Word32)frfi[2 * i]) << CIFFTSFT;
    138                     qi32 = ((WebRtc_Word32)frfi[2 * i + 1]) << CIFFTSFT;
    139                     frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((qr32 - tr32+round2),
    140                                                                        shift+CIFFTSFT);
    141                     frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
    142                             (qi32 - ti32 + round2), shift + CIFFTSFT);
    143                     frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((qr32 + tr32 + round2),
    144                                                                        shift + CIFFTSFT);
    145                     frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
    146                             (qi32 + ti32 + round2), shift + CIFFTSFT);
    147                 }
    148             }
    149 
    150         }
    151         --k;
    152         l = istep;
    153     }
    154     return scale;
    155 }
    156