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