niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 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 | |
pbos@webrtc.org | aa30bb7 | 2013-05-27 09:49:58 +0000 | [diff] [blame] | 18 | #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 19 | |
| 20 | #define CFFTSFT 14 |
| 21 | #define CFFTRND 1 |
| 22 | #define CFFTRND2 16384 |
| 23 | |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 24 | #define CIFFTSFT 14 |
| 25 | #define CIFFTRND 1 |
| 26 | |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 27 | static const int16_t kSinTable1024[] = { |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 28 | 0, 201, 402, 603, 804, 1005, 1206, 1406, |
| 29 | 1607, 1808, 2009, 2209, 2410, 2610, 2811, 3011, |
| 30 | 3211, 3411, 3611, 3811, 4011, 4210, 4409, 4608, |
| 31 | 4807, 5006, 5205, 5403, 5601, 5799, 5997, 6195, |
| 32 | 6392, 6589, 6786, 6982, 7179, 7375, 7571, 7766, |
| 33 | 7961, 8156, 8351, 8545, 8739, 8932, 9126, 9319, |
| 34 | 9511, 9703, 9895, 10087, 10278, 10469, 10659, 10849, |
| 35 | 11038, 11227, 11416, 11604, 11792, 11980, 12166, 12353, |
| 36 | 12539, 12724, 12909, 13094, 13278, 13462, 13645, 13827, |
| 37 | 14009, 14191, 14372, 14552, 14732, 14911, 15090, 15268, |
| 38 | 15446, 15623, 15799, 15975, 16150, 16325, 16499, 16672, |
| 39 | 16845, 17017, 17189, 17360, 17530, 17699, 17868, 18036, |
| 40 | 18204, 18371, 18537, 18702, 18867, 19031, 19194, 19357, |
| 41 | 19519, 19680, 19840, 20000, 20159, 20317, 20474, 20631, |
| 42 | 20787, 20942, 21096, 21249, 21402, 21554, 21705, 21855, |
| 43 | 22004, 22153, 22301, 22448, 22594, 22739, 22883, 23027, |
| 44 | 23169, 23311, 23452, 23592, 23731, 23869, 24006, 24143, |
| 45 | 24278, 24413, 24546, 24679, 24811, 24942, 25072, 25201, |
| 46 | 25329, 25456, 25582, 25707, 25831, 25954, 26077, 26198, |
| 47 | 26318, 26437, 26556, 26673, 26789, 26905, 27019, 27132, |
| 48 | 27244, 27355, 27466, 27575, 27683, 27790, 27896, 28001, |
| 49 | 28105, 28208, 28309, 28410, 28510, 28608, 28706, 28802, |
| 50 | 28897, 28992, 29085, 29177, 29268, 29358, 29446, 29534, |
| 51 | 29621, 29706, 29790, 29873, 29955, 30036, 30116, 30195, |
| 52 | 30272, 30349, 30424, 30498, 30571, 30643, 30713, 30783, |
| 53 | 30851, 30918, 30984, 31049, |
| 54 | 31113, 31175, 31236, 31297, |
| 55 | 31356, 31413, 31470, 31525, 31580, 31633, 31684, 31735, |
| 56 | 31785, 31833, 31880, 31926, 31970, 32014, 32056, 32097, |
| 57 | 32137, 32176, 32213, 32249, 32284, 32318, 32350, 32382, |
| 58 | 32412, 32441, 32468, 32495, 32520, 32544, 32567, 32588, |
| 59 | 32609, 32628, 32646, 32662, 32678, 32692, 32705, 32717, |
| 60 | 32727, 32736, 32744, 32751, 32757, 32761, 32764, 32766, |
| 61 | 32767, 32766, 32764, 32761, 32757, 32751, 32744, 32736, |
| 62 | 32727, 32717, 32705, 32692, 32678, 32662, 32646, 32628, |
| 63 | 32609, 32588, 32567, 32544, 32520, 32495, 32468, 32441, |
| 64 | 32412, 32382, 32350, 32318, 32284, 32249, 32213, 32176, |
| 65 | 32137, 32097, 32056, 32014, 31970, 31926, 31880, 31833, |
| 66 | 31785, 31735, 31684, 31633, 31580, 31525, 31470, 31413, |
| 67 | 31356, 31297, 31236, 31175, 31113, 31049, 30984, 30918, |
| 68 | 30851, 30783, 30713, 30643, 30571, 30498, 30424, 30349, |
| 69 | 30272, 30195, 30116, 30036, 29955, 29873, 29790, 29706, |
| 70 | 29621, 29534, 29446, 29358, 29268, 29177, 29085, 28992, |
| 71 | 28897, 28802, 28706, 28608, 28510, 28410, 28309, 28208, |
| 72 | 28105, 28001, 27896, 27790, 27683, 27575, 27466, 27355, |
| 73 | 27244, 27132, 27019, 26905, 26789, 26673, 26556, 26437, |
| 74 | 26318, 26198, 26077, 25954, 25831, 25707, 25582, 25456, |
| 75 | 25329, 25201, 25072, 24942, 24811, 24679, 24546, 24413, |
| 76 | 24278, 24143, 24006, 23869, 23731, 23592, 23452, 23311, |
| 77 | 23169, 23027, 22883, 22739, 22594, 22448, 22301, 22153, |
| 78 | 22004, 21855, 21705, 21554, 21402, 21249, 21096, 20942, |
| 79 | 20787, 20631, 20474, 20317, 20159, 20000, 19840, 19680, |
| 80 | 19519, 19357, 19194, 19031, 18867, 18702, 18537, 18371, |
| 81 | 18204, 18036, 17868, 17699, 17530, 17360, 17189, 17017, |
| 82 | 16845, 16672, 16499, 16325, 16150, 15975, 15799, 15623, |
| 83 | 15446, 15268, 15090, 14911, 14732, 14552, 14372, 14191, |
| 84 | 14009, 13827, 13645, 13462, 13278, 13094, 12909, 12724, |
| 85 | 12539, 12353, 12166, 11980, 11792, 11604, 11416, 11227, |
| 86 | 11038, 10849, 10659, 10469, 10278, 10087, 9895, 9703, |
| 87 | 9511, 9319, 9126, 8932, 8739, 8545, 8351, 8156, |
| 88 | 7961, 7766, 7571, 7375, 7179, 6982, 6786, 6589, |
| 89 | 6392, 6195, 5997, 5799, 5601, 5403, 5205, 5006, |
| 90 | 4807, 4608, 4409, 4210, 4011, 3811, 3611, 3411, |
| 91 | 3211, 3011, 2811, 2610, 2410, 2209, 2009, 1808, |
| 92 | 1607, 1406, 1206, 1005, 804, 603, 402, 201, |
| 93 | 0, -201, -402, -603, -804, -1005, -1206, -1406, |
| 94 | -1607, -1808, -2009, -2209, -2410, -2610, -2811, -3011, |
| 95 | -3211, -3411, -3611, -3811, -4011, -4210, -4409, -4608, |
| 96 | -4807, -5006, -5205, -5403, -5601, -5799, -5997, -6195, |
| 97 | -6392, -6589, -6786, -6982, -7179, -7375, -7571, -7766, |
| 98 | -7961, -8156, -8351, -8545, -8739, -8932, -9126, -9319, |
| 99 | -9511, -9703, -9895, -10087, -10278, -10469, -10659, -10849, |
| 100 | -11038, -11227, -11416, -11604, -11792, -11980, -12166, -12353, |
| 101 | -12539, -12724, -12909, -13094, -13278, -13462, -13645, -13827, |
| 102 | -14009, -14191, -14372, -14552, -14732, -14911, -15090, -15268, |
| 103 | -15446, -15623, -15799, -15975, -16150, -16325, -16499, -16672, |
| 104 | -16845, -17017, -17189, -17360, -17530, -17699, -17868, -18036, |
| 105 | -18204, -18371, -18537, -18702, -18867, -19031, -19194, -19357, |
| 106 | -19519, -19680, -19840, -20000, -20159, -20317, -20474, -20631, |
| 107 | -20787, -20942, -21096, -21249, -21402, -21554, -21705, -21855, |
| 108 | -22004, -22153, -22301, -22448, -22594, -22739, -22883, -23027, |
| 109 | -23169, -23311, -23452, -23592, -23731, -23869, -24006, -24143, |
| 110 | -24278, -24413, -24546, -24679, -24811, -24942, -25072, -25201, |
| 111 | -25329, -25456, -25582, -25707, -25831, -25954, -26077, -26198, |
| 112 | -26318, -26437, -26556, -26673, -26789, -26905, -27019, -27132, |
| 113 | -27244, -27355, -27466, -27575, -27683, -27790, -27896, -28001, |
| 114 | -28105, -28208, -28309, -28410, -28510, -28608, -28706, -28802, |
| 115 | -28897, -28992, -29085, -29177, -29268, -29358, -29446, -29534, |
| 116 | -29621, -29706, -29790, -29873, -29955, -30036, -30116, -30195, |
| 117 | -30272, -30349, -30424, -30498, -30571, -30643, -30713, -30783, |
| 118 | -30851, -30918, -30984, -31049, -31113, -31175, -31236, -31297, |
| 119 | -31356, -31413, -31470, -31525, -31580, -31633, -31684, -31735, |
| 120 | -31785, -31833, -31880, -31926, -31970, -32014, -32056, -32097, |
| 121 | -32137, -32176, -32213, -32249, -32284, -32318, -32350, -32382, |
| 122 | -32412, -32441, -32468, -32495, -32520, -32544, -32567, -32588, |
| 123 | -32609, -32628, -32646, -32662, -32678, -32692, -32705, -32717, |
| 124 | -32727, -32736, -32744, -32751, -32757, -32761, -32764, -32766, |
| 125 | -32767, -32766, -32764, -32761, -32757, -32751, -32744, -32736, |
| 126 | -32727, -32717, -32705, -32692, -32678, -32662, -32646, -32628, |
| 127 | -32609, -32588, -32567, -32544, -32520, -32495, -32468, -32441, |
| 128 | -32412, -32382, -32350, -32318, -32284, -32249, -32213, -32176, |
| 129 | -32137, -32097, -32056, -32014, -31970, -31926, -31880, -31833, |
| 130 | -31785, -31735, -31684, -31633, -31580, -31525, -31470, -31413, |
| 131 | -31356, -31297, -31236, -31175, -31113, -31049, -30984, -30918, |
| 132 | -30851, -30783, -30713, -30643, -30571, -30498, -30424, -30349, |
| 133 | -30272, -30195, -30116, -30036, -29955, -29873, -29790, -29706, |
| 134 | -29621, -29534, -29446, -29358, -29268, -29177, -29085, -28992, |
| 135 | -28897, -28802, -28706, -28608, -28510, -28410, -28309, -28208, |
| 136 | -28105, -28001, -27896, -27790, -27683, -27575, -27466, -27355, |
| 137 | -27244, -27132, -27019, -26905, -26789, -26673, -26556, -26437, |
| 138 | -26318, -26198, -26077, -25954, -25831, -25707, -25582, -25456, |
| 139 | -25329, -25201, -25072, -24942, -24811, -24679, -24546, -24413, |
| 140 | -24278, -24143, -24006, -23869, -23731, -23592, -23452, -23311, |
| 141 | -23169, -23027, -22883, -22739, -22594, -22448, -22301, -22153, |
| 142 | -22004, -21855, -21705, -21554, -21402, -21249, -21096, -20942, |
| 143 | -20787, -20631, -20474, -20317, -20159, -20000, -19840, -19680, |
| 144 | -19519, -19357, -19194, -19031, -18867, -18702, -18537, -18371, |
| 145 | -18204, -18036, -17868, -17699, -17530, -17360, -17189, -17017, |
| 146 | -16845, -16672, -16499, -16325, -16150, -15975, -15799, -15623, |
| 147 | -15446, -15268, -15090, -14911, -14732, -14552, -14372, -14191, |
| 148 | -14009, -13827, -13645, -13462, -13278, -13094, -12909, -12724, |
| 149 | -12539, -12353, -12166, -11980, -11792, -11604, -11416, -11227, |
| 150 | -11038, -10849, -10659, -10469, -10278, -10087, -9895, -9703, |
| 151 | -9511, -9319, -9126, -8932, -8739, -8545, -8351, -8156, |
| 152 | -7961, -7766, -7571, -7375, -7179, -6982, -6786, -6589, |
| 153 | -6392, -6195, -5997, -5799, -5601, -5403, -5205, -5006, |
| 154 | -4807, -4608, -4409, -4210, -4011, -3811, -3611, -3411, |
| 155 | -3211, -3011, -2811, -2610, -2410, -2209, -2009, -1808, |
| 156 | -1607, -1406, -1206, -1005, -804, -603, -402, -201 |
| 157 | }; |
| 158 | |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 159 | int WebRtcSpl_ComplexFFT(int16_t frfi[], int stages, int mode) |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 160 | { |
| 161 | int i, j, l, k, istep, n, m; |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 162 | int16_t wr, wi; |
| 163 | int32_t tr32, ti32, qr32, qi32; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 164 | |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 165 | /* The 1024-value is a constant given from the size of kSinTable1024[], |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 166 | * and should not be changed depending on the input parameter 'stages' |
| 167 | */ |
| 168 | n = 1 << stages; |
| 169 | if (n > 1024) |
| 170 | return -1; |
| 171 | |
| 172 | l = 1; |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 173 | k = 10 - 1; /* Constant for given kSinTable1024[]. Do not change |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 174 | depending on the input parameter 'stages' */ |
| 175 | |
| 176 | if (mode == 0) |
| 177 | { |
| 178 | // mode==0: Low-complexity and Low-accuracy mode |
| 179 | while (l < n) |
| 180 | { |
| 181 | istep = l << 1; |
| 182 | |
| 183 | for (m = 0; m < l; ++m) |
| 184 | { |
| 185 | j = m << k; |
| 186 | |
| 187 | /* The 256-value is a constant given as 1/4 of the size of |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 188 | * kSinTable1024[], and should not be changed depending on the input |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 189 | * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 |
| 190 | */ |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 191 | wr = kSinTable1024[j + 256]; |
| 192 | wi = -kSinTable1024[j]; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 193 | |
| 194 | for (i = m; i < n; i += istep) |
| 195 | { |
| 196 | j = i + l; |
| 197 | |
| 198 | tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j]) |
| 199 | - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1])), 15); |
| 200 | |
| 201 | ti32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1]) |
| 202 | + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j])), 15); |
| 203 | |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 204 | qr32 = (int32_t)frfi[2 * i]; |
| 205 | qi32 = (int32_t)frfi[2 * i + 1]; |
| 206 | frfi[2 * j] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qr32 - tr32, 1); |
| 207 | frfi[2 * j + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qi32 - ti32, 1); |
| 208 | frfi[2 * i] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qr32 + tr32, 1); |
| 209 | frfi[2 * i + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qi32 + ti32, 1); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 210 | } |
| 211 | } |
| 212 | |
| 213 | --k; |
| 214 | l = istep; |
| 215 | |
| 216 | } |
| 217 | |
| 218 | } else |
| 219 | { |
| 220 | // mode==1: High-complexity and High-accuracy mode |
| 221 | while (l < n) |
| 222 | { |
| 223 | istep = l << 1; |
| 224 | |
| 225 | for (m = 0; m < l; ++m) |
| 226 | { |
| 227 | j = m << k; |
| 228 | |
| 229 | /* The 256-value is a constant given as 1/4 of the size of |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 230 | * kSinTable1024[], and should not be changed depending on the input |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 231 | * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 |
| 232 | */ |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 233 | wr = kSinTable1024[j + 256]; |
| 234 | wi = -kSinTable1024[j]; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 235 | |
kma@webrtc.org | 94771cb | 2012-08-28 04:09:50 +0000 | [diff] [blame] | 236 | #ifdef WEBRTC_ARCH_ARM_V7 |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 237 | int32_t wri = 0; |
| 238 | int32_t frfi_r = 0; |
kma@webrtc.org | 7d6f113 | 2013-03-01 23:01:14 +0000 | [diff] [blame] | 239 | __asm __volatile("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) : |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 240 | "r"((int32_t)wr), "r"((int32_t)wi)); |
kma@google.com | 78dc99e | 2011-08-16 20:00:18 +0000 | [diff] [blame] | 241 | #endif |
| 242 | |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 243 | for (i = m; i < n; i += istep) |
| 244 | { |
| 245 | j = i + l; |
| 246 | |
kma@webrtc.org | 94771cb | 2012-08-28 04:09:50 +0000 | [diff] [blame] | 247 | #ifdef WEBRTC_ARCH_ARM_V7 |
kma@webrtc.org | 7d6f113 | 2013-03-01 23:01:14 +0000 | [diff] [blame] | 248 | __asm __volatile( |
| 249 | "pkhbt %[frfi_r], %[frfi_even], %[frfi_odd], lsl #16\n\t" |
| 250 | "smlsd %[tr32], %[wri], %[frfi_r], %[cfftrnd]\n\t" |
| 251 | "smladx %[ti32], %[wri], %[frfi_r], %[cfftrnd]\n\t" |
| 252 | :[frfi_r]"+r"(frfi_r), |
| 253 | [tr32]"=r"(tr32), |
| 254 | [ti32]"=r"(ti32) |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 255 | :[frfi_even]"r"((int32_t)frfi[2*j]), |
| 256 | [frfi_odd]"r"((int32_t)frfi[2*j +1]), |
kma@webrtc.org | 7d6f113 | 2013-03-01 23:01:14 +0000 | [diff] [blame] | 257 | [wri]"r"(wri), |
| 258 | [cfftrnd]"r"(CFFTRND) |
| 259 | ); |
kma@google.com | 78dc99e | 2011-08-16 20:00:18 +0000 | [diff] [blame] | 260 | |
| 261 | #else |
| 262 | tr32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j]) |
| 263 | - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1]) + CFFTRND; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 264 | |
kma@google.com | 78dc99e | 2011-08-16 20:00:18 +0000 | [diff] [blame] | 265 | ti32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1]) |
| 266 | + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CFFTRND; |
| 267 | #endif |
| 268 | |
| 269 | tr32 = WEBRTC_SPL_RSHIFT_W32(tr32, 15 - CFFTSFT); |
| 270 | ti32 = WEBRTC_SPL_RSHIFT_W32(ti32, 15 - CFFTSFT); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 271 | |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 272 | qr32 = ((int32_t)frfi[2 * i]) << CFFTSFT; |
| 273 | qi32 = ((int32_t)frfi[2 * i + 1]) << CFFTSFT; |
kma@google.com | 78dc99e | 2011-08-16 20:00:18 +0000 | [diff] [blame] | 274 | |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 275 | frfi[2 * j] = (int16_t)WEBRTC_SPL_RSHIFT_W32( |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 276 | (qr32 - tr32 + CFFTRND2), 1 + CFFTSFT); |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 277 | frfi[2 * j + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32( |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 278 | (qi32 - ti32 + CFFTRND2), 1 + CFFTSFT); |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 279 | frfi[2 * i] = (int16_t)WEBRTC_SPL_RSHIFT_W32( |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 280 | (qr32 + tr32 + CFFTRND2), 1 + CFFTSFT); |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 281 | frfi[2 * i + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32( |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 282 | (qi32 + ti32 + CFFTRND2), 1 + CFFTSFT); |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | --k; |
| 287 | l = istep; |
| 288 | } |
| 289 | } |
| 290 | return 0; |
| 291 | } |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 292 | |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 293 | int WebRtcSpl_ComplexIFFT(int16_t frfi[], int stages, int mode) |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 294 | { |
| 295 | int i, j, l, k, istep, n, m, scale, shift; |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 296 | int16_t wr, wi; |
| 297 | int32_t tr32, ti32, qr32, qi32; |
| 298 | int32_t tmp32, round2; |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 299 | |
| 300 | /* The 1024-value is a constant given from the size of kSinTable1024[], |
| 301 | * and should not be changed depending on the input parameter 'stages' |
| 302 | */ |
| 303 | n = 1 << stages; |
| 304 | if (n > 1024) |
| 305 | return -1; |
| 306 | |
| 307 | scale = 0; |
| 308 | |
| 309 | l = 1; |
| 310 | k = 10 - 1; /* Constant for given kSinTable1024[]. Do not change |
| 311 | depending on the input parameter 'stages' */ |
| 312 | |
| 313 | while (l < n) |
| 314 | { |
| 315 | // variable scaling, depending upon data |
| 316 | shift = 0; |
| 317 | round2 = 8192; |
| 318 | |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 319 | tmp32 = (int32_t)WebRtcSpl_MaxAbsValueW16(frfi, 2 * n); |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 320 | if (tmp32 > 13573) |
| 321 | { |
| 322 | shift++; |
| 323 | scale++; |
| 324 | round2 <<= 1; |
| 325 | } |
| 326 | if (tmp32 > 27146) |
| 327 | { |
| 328 | shift++; |
| 329 | scale++; |
| 330 | round2 <<= 1; |
| 331 | } |
| 332 | |
| 333 | istep = l << 1; |
| 334 | |
| 335 | if (mode == 0) |
| 336 | { |
| 337 | // mode==0: Low-complexity and Low-accuracy mode |
| 338 | for (m = 0; m < l; ++m) |
| 339 | { |
| 340 | j = m << k; |
| 341 | |
| 342 | /* The 256-value is a constant given as 1/4 of the size of |
| 343 | * kSinTable1024[], and should not be changed depending on the input |
| 344 | * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 |
| 345 | */ |
| 346 | wr = kSinTable1024[j + 256]; |
| 347 | wi = kSinTable1024[j]; |
| 348 | |
| 349 | for (i = m; i < n; i += istep) |
| 350 | { |
| 351 | j = i + l; |
| 352 | |
| 353 | tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16_RSFT(wr, frfi[2 * j], 0) |
| 354 | - WEBRTC_SPL_MUL_16_16_RSFT(wi, frfi[2 * j + 1], 0)), 15); |
| 355 | |
| 356 | ti32 = WEBRTC_SPL_RSHIFT_W32( |
| 357 | (WEBRTC_SPL_MUL_16_16_RSFT(wr, frfi[2 * j + 1], 0) |
| 358 | + WEBRTC_SPL_MUL_16_16_RSFT(wi,frfi[2*j],0)), 15); |
| 359 | |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 360 | qr32 = (int32_t)frfi[2 * i]; |
| 361 | qi32 = (int32_t)frfi[2 * i + 1]; |
| 362 | frfi[2 * j] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qr32 - tr32, shift); |
| 363 | frfi[2 * j + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qi32 - ti32, shift); |
| 364 | frfi[2 * i] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qr32 + tr32, shift); |
| 365 | frfi[2 * i + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qi32 + ti32, shift); |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 366 | } |
| 367 | } |
| 368 | } else |
| 369 | { |
| 370 | // mode==1: High-complexity and High-accuracy mode |
| 371 | |
| 372 | for (m = 0; m < l; ++m) |
| 373 | { |
| 374 | j = m << k; |
| 375 | |
| 376 | /* The 256-value is a constant given as 1/4 of the size of |
| 377 | * kSinTable1024[], and should not be changed depending on the input |
| 378 | * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 |
| 379 | */ |
| 380 | wr = kSinTable1024[j + 256]; |
| 381 | wi = kSinTable1024[j]; |
| 382 | |
kma@webrtc.org | 94771cb | 2012-08-28 04:09:50 +0000 | [diff] [blame] | 383 | #ifdef WEBRTC_ARCH_ARM_V7 |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 384 | int32_t wri = 0; |
| 385 | int32_t frfi_r = 0; |
kma@webrtc.org | 7d6f113 | 2013-03-01 23:01:14 +0000 | [diff] [blame] | 386 | __asm __volatile("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) : |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 387 | "r"((int32_t)wr), "r"((int32_t)wi)); |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 388 | #endif |
| 389 | |
| 390 | for (i = m; i < n; i += istep) |
| 391 | { |
| 392 | j = i + l; |
| 393 | |
kma@webrtc.org | 94771cb | 2012-08-28 04:09:50 +0000 | [diff] [blame] | 394 | #ifdef WEBRTC_ARCH_ARM_V7 |
kma@webrtc.org | 7d6f113 | 2013-03-01 23:01:14 +0000 | [diff] [blame] | 395 | __asm __volatile( |
| 396 | "pkhbt %[frfi_r], %[frfi_even], %[frfi_odd], lsl #16\n\t" |
| 397 | "smlsd %[tr32], %[wri], %[frfi_r], %[cifftrnd]\n\t" |
| 398 | "smladx %[ti32], %[wri], %[frfi_r], %[cifftrnd]\n\t" |
| 399 | :[frfi_r]"+r"(frfi_r), |
| 400 | [tr32]"=r"(tr32), |
| 401 | [ti32]"=r"(ti32) |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 402 | :[frfi_even]"r"((int32_t)frfi[2*j]), |
| 403 | [frfi_odd]"r"((int32_t)frfi[2*j +1]), |
kma@webrtc.org | 7d6f113 | 2013-03-01 23:01:14 +0000 | [diff] [blame] | 404 | [wri]"r"(wri), |
| 405 | [cifftrnd]"r"(CIFFTRND) |
| 406 | ); |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 407 | #else |
| 408 | |
| 409 | tr32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j]) |
| 410 | - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1]) + CIFFTRND; |
| 411 | |
| 412 | ti32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1]) |
| 413 | + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CIFFTRND; |
| 414 | #endif |
| 415 | tr32 = WEBRTC_SPL_RSHIFT_W32(tr32, 15 - CIFFTSFT); |
| 416 | ti32 = WEBRTC_SPL_RSHIFT_W32(ti32, 15 - CIFFTSFT); |
| 417 | |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 418 | qr32 = ((int32_t)frfi[2 * i]) << CIFFTSFT; |
| 419 | qi32 = ((int32_t)frfi[2 * i + 1]) << CIFFTSFT; |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 420 | |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 421 | frfi[2 * j] = (int16_t)WEBRTC_SPL_RSHIFT_W32((qr32 - tr32+round2), |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 422 | shift+CIFFTSFT); |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 423 | frfi[2 * j + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32( |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 424 | (qi32 - ti32 + round2), shift + CIFFTSFT); |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 425 | frfi[2 * i] = (int16_t)WEBRTC_SPL_RSHIFT_W32((qr32 + tr32 + round2), |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 426 | shift + CIFFTSFT); |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 427 | frfi[2 * i + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32( |
bjornv@webrtc.org | 132feb1 | 2011-12-01 15:40:50 +0000 | [diff] [blame] | 428 | (qi32 + ti32 + round2), shift + CIFFTSFT); |
| 429 | } |
| 430 | } |
| 431 | |
| 432 | } |
| 433 | --k; |
| 434 | l = istep; |
| 435 | } |
| 436 | return scale; |
| 437 | } |