blob: ddc9a97b599d856980c46b6a95688a95cfe577b7 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "common_audio/signal_processing/complex_fft_tables.h"
19#include "common_audio/signal_processing/include/signal_processing_library.h"
Niels Möllera12c42a2018-07-25 16:05:48 +020020#include "rtc_base/system/arch.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000021
22#define CFFTSFT 14
23#define CFFTRND 1
24#define CFFTRND2 16384
25
bjornv@webrtc.org132feb12011-12-01 15:40:50 +000026#define CIFFTSFT 14
27#define CIFFTRND 1
28
bjornv@webrtc.org132feb12011-12-01 15:40:50 +000029
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000030int WebRtcSpl_ComplexFFT(int16_t frfi[], int stages, int mode)
niklase@google.com470e71d2011-07-07 08:21:25 +000031{
32 int i, j, l, k, istep, n, m;
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000033 int16_t wr, wi;
34 int32_t tr32, ti32, qr32, qi32;
niklase@google.com470e71d2011-07-07 08:21:25 +000035
bjornv@webrtc.org132feb12011-12-01 15:40:50 +000036 /* The 1024-value is a constant given from the size of kSinTable1024[],
niklase@google.com470e71d2011-07-07 08:21:25 +000037 * and should not be changed depending on the input parameter 'stages'
38 */
39 n = 1 << stages;
40 if (n > 1024)
41 return -1;
42
43 l = 1;
bjornv@webrtc.org132feb12011-12-01 15:40:50 +000044 k = 10 - 1; /* Constant for given kSinTable1024[]. Do not change
niklase@google.com470e71d2011-07-07 08:21:25 +000045 depending on the input parameter 'stages' */
46
47 if (mode == 0)
48 {
49 // mode==0: Low-complexity and Low-accuracy mode
50 while (l < n)
51 {
52 istep = l << 1;
53
54 for (m = 0; m < l; ++m)
55 {
56 j = m << k;
57
58 /* The 256-value is a constant given as 1/4 of the size of
bjornv@webrtc.org132feb12011-12-01 15:40:50 +000059 * kSinTable1024[], and should not be changed depending on the input
niklase@google.com470e71d2011-07-07 08:21:25 +000060 * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
61 */
bjornv@webrtc.org132feb12011-12-01 15:40:50 +000062 wr = kSinTable1024[j + 256];
63 wi = -kSinTable1024[j];
niklase@google.com470e71d2011-07-07 08:21:25 +000064
65 for (i = m; i < n; i += istep)
66 {
67 j = i + l;
68
bjornv@webrtc.orgf5670952014-10-29 10:29:16 +000069 tr32 = (wr * frfi[2 * j] - wi * frfi[2 * j + 1]) >> 15;
niklase@google.com470e71d2011-07-07 08:21:25 +000070
bjornv@webrtc.orgf5670952014-10-29 10:29:16 +000071 ti32 = (wr * frfi[2 * j + 1] + wi * frfi[2 * j]) >> 15;
niklase@google.com470e71d2011-07-07 08:21:25 +000072
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000073 qr32 = (int32_t)frfi[2 * i];
74 qi32 = (int32_t)frfi[2 * i + 1];
bjornv@webrtc.orgf5670952014-10-29 10:29:16 +000075 frfi[2 * j] = (int16_t)((qr32 - tr32) >> 1);
76 frfi[2 * j + 1] = (int16_t)((qi32 - ti32) >> 1);
77 frfi[2 * i] = (int16_t)((qr32 + tr32) >> 1);
78 frfi[2 * i + 1] = (int16_t)((qi32 + ti32) >> 1);
niklase@google.com470e71d2011-07-07 08:21:25 +000079 }
80 }
81
82 --k;
83 l = istep;
84
85 }
86
87 } else
88 {
89 // mode==1: High-complexity and High-accuracy mode
90 while (l < n)
91 {
92 istep = l << 1;
93
94 for (m = 0; m < l; ++m)
95 {
96 j = m << k;
97
98 /* The 256-value is a constant given as 1/4 of the size of
bjornv@webrtc.org132feb12011-12-01 15:40:50 +000099 * kSinTable1024[], and should not be changed depending on the input
niklase@google.com470e71d2011-07-07 08:21:25 +0000100 * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
101 */
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000102 wr = kSinTable1024[j + 256];
103 wi = -kSinTable1024[j];
niklase@google.com470e71d2011-07-07 08:21:25 +0000104
kma@webrtc.org94771cb2012-08-28 04:09:50 +0000105#ifdef WEBRTC_ARCH_ARM_V7
pbos@webrtc.orgb0913072013-04-09 16:40:28 +0000106 int32_t wri = 0;
kma@webrtc.org7d6f1132013-03-01 23:01:14 +0000107 __asm __volatile("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) :
pbos@webrtc.orgb0913072013-04-09 16:40:28 +0000108 "r"((int32_t)wr), "r"((int32_t)wi));
kma@google.com78dc99e2011-08-16 20:00:18 +0000109#endif
110
niklase@google.com470e71d2011-07-07 08:21:25 +0000111 for (i = m; i < n; i += istep)
112 {
113 j = i + l;
114
kma@webrtc.org94771cb2012-08-28 04:09:50 +0000115#ifdef WEBRTC_ARCH_ARM_V7
bjornv@webrtc.orgaafd7a82014-06-05 08:53:51 +0000116 register int32_t frfi_r;
117 __asm __volatile(
118 "pkhbt %[frfi_r], %[frfi_even], %[frfi_odd],"
119 " lsl #16\n\t"
120 "smlsd %[tr32], %[wri], %[frfi_r], %[cfftrnd]\n\t"
121 "smladx %[ti32], %[wri], %[frfi_r], %[cfftrnd]\n\t"
122 :[frfi_r]"=&r"(frfi_r),
123 [tr32]"=&r"(tr32),
124 [ti32]"=r"(ti32)
125 :[frfi_even]"r"((int32_t)frfi[2*j]),
126 [frfi_odd]"r"((int32_t)frfi[2*j +1]),
127 [wri]"r"(wri),
128 [cfftrnd]"r"(CFFTRND));
kma@google.com78dc99e2011-08-16 20:00:18 +0000129#else
Bjorn Volckeraffcfb22015-04-24 08:12:07 +0200130 tr32 = wr * frfi[2 * j] - wi * frfi[2 * j + 1] + CFFTRND;
niklase@google.com470e71d2011-07-07 08:21:25 +0000131
Bjorn Volckeraffcfb22015-04-24 08:12:07 +0200132 ti32 = wr * frfi[2 * j + 1] + wi * frfi[2 * j] + CFFTRND;
kma@google.com78dc99e2011-08-16 20:00:18 +0000133#endif
134
bjornv@webrtc.orgf5670952014-10-29 10:29:16 +0000135 tr32 >>= 15 - CFFTSFT;
136 ti32 >>= 15 - CFFTSFT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000137
Alex Loikoee67ca32018-01-12 13:48:06 +0100138 qr32 = ((int32_t)frfi[2 * i]) * (1 << CFFTSFT);
139 qi32 = ((int32_t)frfi[2 * i + 1]) * (1 << CFFTSFT);
kma@google.com78dc99e2011-08-16 20:00:18 +0000140
bjornv@webrtc.orgf5670952014-10-29 10:29:16 +0000141 frfi[2 * j] = (int16_t)(
142 (qr32 - tr32 + CFFTRND2) >> (1 + CFFTSFT));
143 frfi[2 * j + 1] = (int16_t)(
144 (qi32 - ti32 + CFFTRND2) >> (1 + CFFTSFT));
145 frfi[2 * i] = (int16_t)(
146 (qr32 + tr32 + CFFTRND2) >> (1 + CFFTSFT));
147 frfi[2 * i + 1] = (int16_t)(
148 (qi32 + ti32 + CFFTRND2) >> (1 + CFFTSFT));
niklase@google.com470e71d2011-07-07 08:21:25 +0000149 }
150 }
151
152 --k;
153 l = istep;
154 }
155 }
156 return 0;
157}
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000158
pbos@webrtc.orgb0913072013-04-09 16:40:28 +0000159int WebRtcSpl_ComplexIFFT(int16_t frfi[], int stages, int mode)
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000160{
Peter Kastingdce40cf2015-08-24 14:52:23 -0700161 size_t i, j, l, istep, n, m;
162 int k, scale, shift;
pbos@webrtc.orgb0913072013-04-09 16:40:28 +0000163 int16_t wr, wi;
164 int32_t tr32, ti32, qr32, qi32;
165 int32_t tmp32, round2;
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000166
167 /* The 1024-value is a constant given from the size of kSinTable1024[],
168 * and should not be changed depending on the input parameter 'stages'
169 */
Mirko Bonadeif9c29522018-07-04 11:47:33 +0200170 n = ((size_t)1) << stages;
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000171 if (n > 1024)
172 return -1;
173
174 scale = 0;
175
176 l = 1;
177 k = 10 - 1; /* Constant for given kSinTable1024[]. Do not change
178 depending on the input parameter 'stages' */
179
180 while (l < n)
181 {
182 // variable scaling, depending upon data
183 shift = 0;
184 round2 = 8192;
185
Peter Kastingb7e50542015-06-11 12:55:50 -0700186 tmp32 = WebRtcSpl_MaxAbsValueW16(frfi, 2 * n);
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000187 if (tmp32 > 13573)
188 {
189 shift++;
190 scale++;
191 round2 <<= 1;
192 }
193 if (tmp32 > 27146)
194 {
195 shift++;
196 scale++;
197 round2 <<= 1;
198 }
199
200 istep = l << 1;
201
202 if (mode == 0)
203 {
204 // mode==0: Low-complexity and Low-accuracy mode
205 for (m = 0; m < l; ++m)
206 {
207 j = m << k;
208
209 /* The 256-value is a constant given as 1/4 of the size of
210 * kSinTable1024[], and should not be changed depending on the input
211 * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
212 */
213 wr = kSinTable1024[j + 256];
214 wi = kSinTable1024[j];
215
216 for (i = m; i < n; i += istep)
217 {
218 j = i + l;
219
bjornv@webrtc.orgf5670952014-10-29 10:29:16 +0000220 tr32 = (wr * frfi[2 * j] - wi * frfi[2 * j + 1]) >> 15;
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000221
bjornv@webrtc.orgf5670952014-10-29 10:29:16 +0000222 ti32 = (wr * frfi[2 * j + 1] + wi * frfi[2 * j]) >> 15;
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000223
pbos@webrtc.orgb0913072013-04-09 16:40:28 +0000224 qr32 = (int32_t)frfi[2 * i];
225 qi32 = (int32_t)frfi[2 * i + 1];
bjornv@webrtc.orgf5670952014-10-29 10:29:16 +0000226 frfi[2 * j] = (int16_t)((qr32 - tr32) >> shift);
227 frfi[2 * j + 1] = (int16_t)((qi32 - ti32) >> shift);
228 frfi[2 * i] = (int16_t)((qr32 + tr32) >> shift);
229 frfi[2 * i + 1] = (int16_t)((qi32 + ti32) >> shift);
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000230 }
231 }
232 } else
233 {
234 // mode==1: High-complexity and High-accuracy mode
235
236 for (m = 0; m < l; ++m)
237 {
238 j = m << k;
239
240 /* The 256-value is a constant given as 1/4 of the size of
241 * kSinTable1024[], and should not be changed depending on the input
242 * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
243 */
244 wr = kSinTable1024[j + 256];
245 wi = kSinTable1024[j];
246
kma@webrtc.org94771cb2012-08-28 04:09:50 +0000247#ifdef WEBRTC_ARCH_ARM_V7
pbos@webrtc.orgb0913072013-04-09 16:40:28 +0000248 int32_t wri = 0;
kma@webrtc.org7d6f1132013-03-01 23:01:14 +0000249 __asm __volatile("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) :
pbos@webrtc.orgb0913072013-04-09 16:40:28 +0000250 "r"((int32_t)wr), "r"((int32_t)wi));
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000251#endif
252
253 for (i = m; i < n; i += istep)
254 {
255 j = i + l;
256
kma@webrtc.org94771cb2012-08-28 04:09:50 +0000257#ifdef WEBRTC_ARCH_ARM_V7
bjornv@webrtc.orgaafd7a82014-06-05 08:53:51 +0000258 register int32_t frfi_r;
kma@webrtc.org7d6f1132013-03-01 23:01:14 +0000259 __asm __volatile(
260 "pkhbt %[frfi_r], %[frfi_even], %[frfi_odd], lsl #16\n\t"
261 "smlsd %[tr32], %[wri], %[frfi_r], %[cifftrnd]\n\t"
262 "smladx %[ti32], %[wri], %[frfi_r], %[cifftrnd]\n\t"
bjornv@webrtc.orgaafd7a82014-06-05 08:53:51 +0000263 :[frfi_r]"=&r"(frfi_r),
264 [tr32]"=&r"(tr32),
kma@webrtc.org7d6f1132013-03-01 23:01:14 +0000265 [ti32]"=r"(ti32)
pbos@webrtc.orgb0913072013-04-09 16:40:28 +0000266 :[frfi_even]"r"((int32_t)frfi[2*j]),
267 [frfi_odd]"r"((int32_t)frfi[2*j +1]),
kma@webrtc.org7d6f1132013-03-01 23:01:14 +0000268 [wri]"r"(wri),
269 [cifftrnd]"r"(CIFFTRND)
270 );
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000271#else
272
Bjorn Volckeraffcfb22015-04-24 08:12:07 +0200273 tr32 = wr * frfi[2 * j] - wi * frfi[2 * j + 1] + CIFFTRND;
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000274
Bjorn Volckeraffcfb22015-04-24 08:12:07 +0200275 ti32 = wr * frfi[2 * j + 1] + wi * frfi[2 * j] + CIFFTRND;
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000276#endif
bjornv@webrtc.orgf5670952014-10-29 10:29:16 +0000277 tr32 >>= 15 - CIFFTSFT;
278 ti32 >>= 15 - CIFFTSFT;
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000279
Alex Loikoee67ca32018-01-12 13:48:06 +0100280 qr32 = ((int32_t)frfi[2 * i]) * (1 << CIFFTSFT);
281 qi32 = ((int32_t)frfi[2 * i + 1]) * (1 << CIFFTSFT);
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000282
bjornv@webrtc.orgf5670952014-10-29 10:29:16 +0000283 frfi[2 * j] = (int16_t)(
284 (qr32 - tr32 + round2) >> (shift + CIFFTSFT));
285 frfi[2 * j + 1] = (int16_t)(
286 (qi32 - ti32 + round2) >> (shift + CIFFTSFT));
287 frfi[2 * i] = (int16_t)(
288 (qr32 + tr32 + round2) >> (shift + CIFFTSFT));
289 frfi[2 * i + 1] = (int16_t)(
290 (qi32 + ti32 + round2) >> (shift + CIFFTSFT));
bjornv@webrtc.org132feb12011-12-01 15:40:50 +0000291 }
292 }
293
294 }
295 --k;
296 l = istep;
297 }
298 return scale;
299}