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 "webrtc/common_audio/signal_processing/complex_fft_tables.h" 19 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 20 21 #define CFFTSFT 14 22 #define CFFTRND 1 23 #define CFFTRND2 16384 24 25 #define CIFFTSFT 14 26 #define CIFFTRND 1 27 28 29 int WebRtcSpl_ComplexFFT(int16_t frfi[], int stages, int mode) 30 { 31 int i, j, l, k, istep, n, m; 32 int16_t wr, wi; 33 int32_t tr32, ti32, qr32, qi32; 34 35 /* The 1024-value is a constant given from the size of kSinTable1024[], 36 * and should not be changed depending on the input parameter 'stages' 37 */ 38 n = 1 << stages; 39 if (n > 1024) 40 return -1; 41 42 l = 1; 43 k = 10 - 1; /* Constant for given kSinTable1024[]. Do not change 44 depending on the input parameter 'stages' */ 45 46 if (mode == 0) 47 { 48 // mode==0: Low-complexity and Low-accuracy mode 49 while (l < n) 50 { 51 istep = l << 1; 52 53 for (m = 0; m < l; ++m) 54 { 55 j = m << k; 56 57 /* The 256-value is a constant given as 1/4 of the size of 58 * kSinTable1024[], and should not be changed depending on the input 59 * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 60 */ 61 wr = kSinTable1024[j + 256]; 62 wi = -kSinTable1024[j]; 63 64 for (i = m; i < n; i += istep) 65 { 66 j = i + l; 67 68 tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j]) 69 - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1])), 15); 70 71 ti32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1]) 72 + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j])), 15); 73 74 qr32 = (int32_t)frfi[2 * i]; 75 qi32 = (int32_t)frfi[2 * i + 1]; 76 frfi[2 * j] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qr32 - tr32, 1); 77 frfi[2 * j + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qi32 - ti32, 1); 78 frfi[2 * i] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qr32 + tr32, 1); 79 frfi[2 * i + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qi32 + ti32, 1); 80 } 81 } 82 83 --k; 84 l = istep; 85 86 } 87 88 } else 89 { 90 // mode==1: High-complexity and High-accuracy mode 91 while (l < n) 92 { 93 istep = l << 1; 94 95 for (m = 0; m < l; ++m) 96 { 97 j = m << k; 98 99 /* The 256-value is a constant given as 1/4 of the size of 100 * kSinTable1024[], and should not be changed depending on the input 101 * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 102 */ 103 wr = kSinTable1024[j + 256]; 104 wi = -kSinTable1024[j]; 105 106 #ifdef WEBRTC_ARCH_ARM_V7 107 int32_t wri = 0; 108 __asm __volatile("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) : 109 "r"((int32_t)wr), "r"((int32_t)wi)); 110 #endif 111 112 for (i = m; i < n; i += istep) 113 { 114 j = i + l; 115 116 #ifdef WEBRTC_ARCH_ARM_V7 117 register int32_t frfi_r; 118 __asm __volatile( 119 "pkhbt %[frfi_r], %[frfi_even], %[frfi_odd]," 120 " lsl #16\n\t" 121 "smlsd %[tr32], %[wri], %[frfi_r], %[cfftrnd]\n\t" 122 "smladx %[ti32], %[wri], %[frfi_r], %[cfftrnd]\n\t" 123 :[frfi_r]"=&r"(frfi_r), 124 [tr32]"=&r"(tr32), 125 [ti32]"=r"(ti32) 126 :[frfi_even]"r"((int32_t)frfi[2*j]), 127 [frfi_odd]"r"((int32_t)frfi[2*j +1]), 128 [wri]"r"(wri), 129 [cfftrnd]"r"(CFFTRND)); 130 #else 131 tr32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j]) 132 - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1]) + CFFTRND; 133 134 ti32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1]) 135 + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CFFTRND; 136 #endif 137 138 tr32 = WEBRTC_SPL_RSHIFT_W32(tr32, 15 - CFFTSFT); 139 ti32 = WEBRTC_SPL_RSHIFT_W32(ti32, 15 - CFFTSFT); 140 141 qr32 = ((int32_t)frfi[2 * i]) << CFFTSFT; 142 qi32 = ((int32_t)frfi[2 * i + 1]) << CFFTSFT; 143 144 frfi[2 * j] = (int16_t)WEBRTC_SPL_RSHIFT_W32( 145 (qr32 - tr32 + CFFTRND2), 1 + CFFTSFT); 146 frfi[2 * j + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32( 147 (qi32 - ti32 + CFFTRND2), 1 + CFFTSFT); 148 frfi[2 * i] = (int16_t)WEBRTC_SPL_RSHIFT_W32( 149 (qr32 + tr32 + CFFTRND2), 1 + CFFTSFT); 150 frfi[2 * i + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32( 151 (qi32 + ti32 + CFFTRND2), 1 + CFFTSFT); 152 } 153 } 154 155 --k; 156 l = istep; 157 } 158 } 159 return 0; 160 } 161 162 int WebRtcSpl_ComplexIFFT(int16_t frfi[], int stages, int mode) 163 { 164 int i, j, l, k, istep, n, m, scale, shift; 165 int16_t wr, wi; 166 int32_t tr32, ti32, qr32, qi32; 167 int32_t tmp32, round2; 168 169 /* The 1024-value is a constant given from the size of kSinTable1024[], 170 * and should not be changed depending on the input parameter 'stages' 171 */ 172 n = 1 << stages; 173 if (n > 1024) 174 return -1; 175 176 scale = 0; 177 178 l = 1; 179 k = 10 - 1; /* Constant for given kSinTable1024[]. Do not change 180 depending on the input parameter 'stages' */ 181 182 while (l < n) 183 { 184 // variable scaling, depending upon data 185 shift = 0; 186 round2 = 8192; 187 188 tmp32 = (int32_t)WebRtcSpl_MaxAbsValueW16(frfi, 2 * n); 189 if (tmp32 > 13573) 190 { 191 shift++; 192 scale++; 193 round2 <<= 1; 194 } 195 if (tmp32 > 27146) 196 { 197 shift++; 198 scale++; 199 round2 <<= 1; 200 } 201 202 istep = l << 1; 203 204 if (mode == 0) 205 { 206 // mode==0: Low-complexity and Low-accuracy mode 207 for (m = 0; m < l; ++m) 208 { 209 j = m << k; 210 211 /* The 256-value is a constant given as 1/4 of the size of 212 * kSinTable1024[], and should not be changed depending on the input 213 * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 214 */ 215 wr = kSinTable1024[j + 256]; 216 wi = kSinTable1024[j]; 217 218 for (i = m; i < n; i += istep) 219 { 220 j = i + l; 221 222 tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16_RSFT(wr, frfi[2 * j], 0) 223 - WEBRTC_SPL_MUL_16_16_RSFT(wi, frfi[2 * j + 1], 0)), 15); 224 225 ti32 = WEBRTC_SPL_RSHIFT_W32( 226 (WEBRTC_SPL_MUL_16_16_RSFT(wr, frfi[2 * j + 1], 0) 227 + WEBRTC_SPL_MUL_16_16_RSFT(wi,frfi[2*j],0)), 15); 228 229 qr32 = (int32_t)frfi[2 * i]; 230 qi32 = (int32_t)frfi[2 * i + 1]; 231 frfi[2 * j] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qr32 - tr32, shift); 232 frfi[2 * j + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qi32 - ti32, shift); 233 frfi[2 * i] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qr32 + tr32, shift); 234 frfi[2 * i + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qi32 + ti32, shift); 235 } 236 } 237 } else 238 { 239 // mode==1: High-complexity and High-accuracy mode 240 241 for (m = 0; m < l; ++m) 242 { 243 j = m << k; 244 245 /* The 256-value is a constant given as 1/4 of the size of 246 * kSinTable1024[], and should not be changed depending on the input 247 * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 248 */ 249 wr = kSinTable1024[j + 256]; 250 wi = kSinTable1024[j]; 251 252 #ifdef WEBRTC_ARCH_ARM_V7 253 int32_t wri = 0; 254 __asm __volatile("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) : 255 "r"((int32_t)wr), "r"((int32_t)wi)); 256 #endif 257 258 for (i = m; i < n; i += istep) 259 { 260 j = i + l; 261 262 #ifdef WEBRTC_ARCH_ARM_V7 263 register int32_t frfi_r; 264 __asm __volatile( 265 "pkhbt %[frfi_r], %[frfi_even], %[frfi_odd], lsl #16\n\t" 266 "smlsd %[tr32], %[wri], %[frfi_r], %[cifftrnd]\n\t" 267 "smladx %[ti32], %[wri], %[frfi_r], %[cifftrnd]\n\t" 268 :[frfi_r]"=&r"(frfi_r), 269 [tr32]"=&r"(tr32), 270 [ti32]"=r"(ti32) 271 :[frfi_even]"r"((int32_t)frfi[2*j]), 272 [frfi_odd]"r"((int32_t)frfi[2*j +1]), 273 [wri]"r"(wri), 274 [cifftrnd]"r"(CIFFTRND) 275 ); 276 #else 277 278 tr32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j]) 279 - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1]) + CIFFTRND; 280 281 ti32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1]) 282 + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CIFFTRND; 283 #endif 284 tr32 = WEBRTC_SPL_RSHIFT_W32(tr32, 15 - CIFFTSFT); 285 ti32 = WEBRTC_SPL_RSHIFT_W32(ti32, 15 - CIFFTSFT); 286 287 qr32 = ((int32_t)frfi[2 * i]) << CIFFTSFT; 288 qi32 = ((int32_t)frfi[2 * i + 1]) << CIFFTSFT; 289 290 frfi[2 * j] = (int16_t)WEBRTC_SPL_RSHIFT_W32((qr32 - tr32+round2), 291 shift+CIFFTSFT); 292 frfi[2 * j + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32( 293 (qi32 - ti32 + round2), shift + CIFFTSFT); 294 frfi[2 * i] = (int16_t)WEBRTC_SPL_RSHIFT_W32((qr32 + tr32 + round2), 295 shift + CIFFTSFT); 296 frfi[2 * i + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32( 297 (qi32 + ti32 + round2), shift + CIFFTSFT); 298 } 299 } 300 301 } 302 --k; 303 l = istep; 304 } 305 return scale; 306 } 307