1 /*
2 * Copyright (c) 2013 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 #include "webrtc/common_audio/signal_processing/complex_fft_tables.h"
13 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
14
15 #define CFFTSFT 14
16 #define CFFTRND 1
17 #define CFFTRND2 16384
18
19 #define CIFFTSFT 14
20 #define CIFFTRND 1
21
WebRtcSpl_ComplexFFT(int16_t frfi[],int stages,int mode)22 int WebRtcSpl_ComplexFFT(int16_t frfi[], int stages, int mode) {
23 int i = 0;
24 int l = 0;
25 int k = 0;
26 int istep = 0;
27 int n = 0;
28 int m = 0;
29 int32_t wr = 0, wi = 0;
30 int32_t tmp1 = 0;
31 int32_t tmp2 = 0;
32 int32_t tmp3 = 0;
33 int32_t tmp4 = 0;
34 int32_t tmp5 = 0;
35 int32_t tmp6 = 0;
36 int32_t tmp = 0;
37 int16_t* ptr_j = NULL;
38 int16_t* ptr_i = NULL;
39
40 n = 1 << stages;
41 if (n > 1024) {
42 return -1;
43 }
44
45 __asm __volatile (
46 ".set push \n\t"
47 ".set noreorder \n\t"
48
49 "addiu %[k], $zero, 10 \n\t"
50 "addiu %[l], $zero, 1 \n\t"
51 "3: \n\t"
52 "sll %[istep], %[l], 1 \n\t"
53 "move %[m], $zero \n\t"
54 "sll %[tmp], %[l], 2 \n\t"
55 "move %[i], $zero \n\t"
56 "2: \n\t"
57 #if defined(MIPS_DSP_R1_LE)
58 "sllv %[tmp3], %[m], %[k] \n\t"
59 "addiu %[tmp2], %[tmp3], 512 \n\t"
60 "addiu %[m], %[m], 1 \n\t"
61 "lhx %[wi], %[tmp3](%[kSinTable1024]) \n\t"
62 "lhx %[wr], %[tmp2](%[kSinTable1024]) \n\t"
63 #else // #if defined(MIPS_DSP_R1_LE)
64 "sllv %[tmp3], %[m], %[k] \n\t"
65 "addu %[ptr_j], %[tmp3], %[kSinTable1024] \n\t"
66 "addiu %[ptr_i], %[ptr_j], 512 \n\t"
67 "addiu %[m], %[m], 1 \n\t"
68 "lh %[wi], 0(%[ptr_j]) \n\t"
69 "lh %[wr], 0(%[ptr_i]) \n\t"
70 #endif // #if defined(MIPS_DSP_R1_LE)
71 "1: \n\t"
72 "sll %[tmp1], %[i], 2 \n\t"
73 "addu %[ptr_i], %[frfi], %[tmp1] \n\t"
74 "addu %[ptr_j], %[ptr_i], %[tmp] \n\t"
75 "lh %[tmp6], 0(%[ptr_i]) \n\t"
76 "lh %[tmp5], 2(%[ptr_i]) \n\t"
77 "lh %[tmp3], 0(%[ptr_j]) \n\t"
78 "lh %[tmp4], 2(%[ptr_j]) \n\t"
79 "addu %[i], %[i], %[istep] \n\t"
80 #if defined(MIPS_DSP_R2_LE)
81 "mult %[wr], %[tmp3] \n\t"
82 "madd %[wi], %[tmp4] \n\t"
83 "mult $ac1, %[wr], %[tmp4] \n\t"
84 "msub $ac1, %[wi], %[tmp3] \n\t"
85 "mflo %[tmp1] \n\t"
86 "mflo %[tmp2], $ac1 \n\t"
87 "sll %[tmp6], %[tmp6], 14 \n\t"
88 "sll %[tmp5], %[tmp5], 14 \n\t"
89 "shra_r.w %[tmp1], %[tmp1], 1 \n\t"
90 "shra_r.w %[tmp2], %[tmp2], 1 \n\t"
91 "subu %[tmp4], %[tmp6], %[tmp1] \n\t"
92 "addu %[tmp1], %[tmp6], %[tmp1] \n\t"
93 "addu %[tmp6], %[tmp5], %[tmp2] \n\t"
94 "subu %[tmp5], %[tmp5], %[tmp2] \n\t"
95 "shra_r.w %[tmp1], %[tmp1], 15 \n\t"
96 "shra_r.w %[tmp6], %[tmp6], 15 \n\t"
97 "shra_r.w %[tmp4], %[tmp4], 15 \n\t"
98 "shra_r.w %[tmp5], %[tmp5], 15 \n\t"
99 #else // #if defined(MIPS_DSP_R2_LE)
100 "mul %[tmp2], %[wr], %[tmp4] \n\t"
101 "mul %[tmp1], %[wr], %[tmp3] \n\t"
102 "mul %[tmp4], %[wi], %[tmp4] \n\t"
103 "mul %[tmp3], %[wi], %[tmp3] \n\t"
104 "sll %[tmp6], %[tmp6], 14 \n\t"
105 "sll %[tmp5], %[tmp5], 14 \n\t"
106 "addiu %[tmp6], %[tmp6], 16384 \n\t"
107 "addiu %[tmp5], %[tmp5], 16384 \n\t"
108 "addu %[tmp1], %[tmp1], %[tmp4] \n\t"
109 "subu %[tmp2], %[tmp2], %[tmp3] \n\t"
110 "addiu %[tmp1], %[tmp1], 1 \n\t"
111 "addiu %[tmp2], %[tmp2], 1 \n\t"
112 "sra %[tmp1], %[tmp1], 1 \n\t"
113 "sra %[tmp2], %[tmp2], 1 \n\t"
114 "subu %[tmp4], %[tmp6], %[tmp1] \n\t"
115 "addu %[tmp1], %[tmp6], %[tmp1] \n\t"
116 "addu %[tmp6], %[tmp5], %[tmp2] \n\t"
117 "subu %[tmp5], %[tmp5], %[tmp2] \n\t"
118 "sra %[tmp4], %[tmp4], 15 \n\t"
119 "sra %[tmp1], %[tmp1], 15 \n\t"
120 "sra %[tmp6], %[tmp6], 15 \n\t"
121 "sra %[tmp5], %[tmp5], 15 \n\t"
122 #endif // #if defined(MIPS_DSP_R2_LE)
123 "sh %[tmp1], 0(%[ptr_i]) \n\t"
124 "sh %[tmp6], 2(%[ptr_i]) \n\t"
125 "sh %[tmp4], 0(%[ptr_j]) \n\t"
126 "blt %[i], %[n], 1b \n\t"
127 " sh %[tmp5], 2(%[ptr_j]) \n\t"
128 "blt %[m], %[l], 2b \n\t"
129 " addu %[i], $zero, %[m] \n\t"
130 "move %[l], %[istep] \n\t"
131 "blt %[l], %[n], 3b \n\t"
132 " addiu %[k], %[k], -1 \n\t"
133
134 ".set pop \n\t"
135
136 : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3),
137 [tmp4] "=&r" (tmp4), [tmp5] "=&r" (tmp5), [tmp6] "=&r" (tmp6),
138 [ptr_i] "=&r" (ptr_i), [i] "=&r" (i), [wi] "=&r" (wi), [wr] "=&r" (wr),
139 [m] "=&r" (m), [istep] "=&r" (istep), [l] "=&r" (l), [k] "=&r" (k),
140 [ptr_j] "=&r" (ptr_j), [tmp] "=&r" (tmp)
141 : [n] "r" (n), [frfi] "r" (frfi), [kSinTable1024] "r" (kSinTable1024)
142 : "hi", "lo", "memory"
143 #if defined(MIPS_DSP_R2_LE)
144 , "$ac1hi", "$ac1lo"
145 #endif // #if defined(MIPS_DSP_R2_LE)
146 );
147
148 return 0;
149 }
150
WebRtcSpl_ComplexIFFT(int16_t frfi[],int stages,int mode)151 int WebRtcSpl_ComplexIFFT(int16_t frfi[], int stages, int mode) {
152 int i = 0, l = 0, k = 0;
153 int istep = 0, n = 0, m = 0;
154 int scale = 0, shift = 0;
155 int32_t wr = 0, wi = 0;
156 int32_t tmp1 = 0, tmp2 = 0, tmp3 = 0, tmp4 = 0;
157 int32_t tmp5 = 0, tmp6 = 0, tmp = 0, tempMax = 0, round2 = 0;
158 int16_t* ptr_j = NULL;
159 int16_t* ptr_i = NULL;
160
161 n = 1 << stages;
162 if (n > 1024) {
163 return -1;
164 }
165
166 __asm __volatile (
167 ".set push \n\t"
168 ".set noreorder \n\t"
169
170 "addiu %[k], $zero, 10 \n\t"
171 "addiu %[l], $zero, 1 \n\t"
172 "move %[scale], $zero \n\t"
173 "3: \n\t"
174 "addiu %[shift], $zero, 14 \n\t"
175 "addiu %[round2], $zero, 8192 \n\t"
176 "move %[ptr_i], %[frfi] \n\t"
177 "move %[tempMax], $zero \n\t"
178 "addu %[i], %[n], %[n] \n\t"
179 "5: \n\t"
180 "lh %[tmp1], 0(%[ptr_i]) \n\t"
181 "lh %[tmp2], 2(%[ptr_i]) \n\t"
182 "lh %[tmp3], 4(%[ptr_i]) \n\t"
183 "lh %[tmp4], 6(%[ptr_i]) \n\t"
184 #if defined(MIPS_DSP_R1_LE)
185 "absq_s.w %[tmp1], %[tmp1] \n\t"
186 "absq_s.w %[tmp2], %[tmp2] \n\t"
187 "absq_s.w %[tmp3], %[tmp3] \n\t"
188 "absq_s.w %[tmp4], %[tmp4] \n\t"
189 #else // #if defined(MIPS_DSP_R1_LE)
190 "slt %[tmp5], %[tmp1], $zero \n\t"
191 "subu %[tmp6], $zero, %[tmp1] \n\t"
192 "movn %[tmp1], %[tmp6], %[tmp5] \n\t"
193 "slt %[tmp5], %[tmp2], $zero \n\t"
194 "subu %[tmp6], $zero, %[tmp2] \n\t"
195 "movn %[tmp2], %[tmp6], %[tmp5] \n\t"
196 "slt %[tmp5], %[tmp3], $zero \n\t"
197 "subu %[tmp6], $zero, %[tmp3] \n\t"
198 "movn %[tmp3], %[tmp6], %[tmp5] \n\t"
199 "slt %[tmp5], %[tmp4], $zero \n\t"
200 "subu %[tmp6], $zero, %[tmp4] \n\t"
201 "movn %[tmp4], %[tmp6], %[tmp5] \n\t"
202 #endif // #if defined(MIPS_DSP_R1_LE)
203 "slt %[tmp5], %[tempMax], %[tmp1] \n\t"
204 "movn %[tempMax], %[tmp1], %[tmp5] \n\t"
205 "addiu %[i], %[i], -4 \n\t"
206 "slt %[tmp5], %[tempMax], %[tmp2] \n\t"
207 "movn %[tempMax], %[tmp2], %[tmp5] \n\t"
208 "slt %[tmp5], %[tempMax], %[tmp3] \n\t"
209 "movn %[tempMax], %[tmp3], %[tmp5] \n\t"
210 "slt %[tmp5], %[tempMax], %[tmp4] \n\t"
211 "movn %[tempMax], %[tmp4], %[tmp5] \n\t"
212 "bgtz %[i], 5b \n\t"
213 " addiu %[ptr_i], %[ptr_i], 8 \n\t"
214 "addiu %[tmp1], $zero, 13573 \n\t"
215 "addiu %[tmp2], $zero, 27146 \n\t"
216 #if !defined(MIPS32_R2_LE)
217 "sll %[tempMax], %[tempMax], 16 \n\t"
218 "sra %[tempMax], %[tempMax], 16 \n\t"
219 #else // #if !defined(MIPS32_R2_LE)
220 "seh %[tempMax] \n\t"
221 #endif // #if !defined(MIPS32_R2_LE)
222 "slt %[tmp1], %[tmp1], %[tempMax] \n\t"
223 "slt %[tmp2], %[tmp2], %[tempMax] \n\t"
224 "addu %[tmp1], %[tmp1], %[tmp2] \n\t"
225 "addu %[shift], %[shift], %[tmp1] \n\t"
226 "addu %[scale], %[scale], %[tmp1] \n\t"
227 "sllv %[round2], %[round2], %[tmp1] \n\t"
228 "sll %[istep], %[l], 1 \n\t"
229 "move %[m], $zero \n\t"
230 "sll %[tmp], %[l], 2 \n\t"
231 "2: \n\t"
232 #if defined(MIPS_DSP_R1_LE)
233 "sllv %[tmp3], %[m], %[k] \n\t"
234 "addiu %[tmp2], %[tmp3], 512 \n\t"
235 "addiu %[m], %[m], 1 \n\t"
236 "lhx %[wi], %[tmp3](%[kSinTable1024]) \n\t"
237 "lhx %[wr], %[tmp2](%[kSinTable1024]) \n\t"
238 #else // #if defined(MIPS_DSP_R1_LE)
239 "sllv %[tmp3], %[m], %[k] \n\t"
240 "addu %[ptr_j], %[tmp3], %[kSinTable1024] \n\t"
241 "addiu %[ptr_i], %[ptr_j], 512 \n\t"
242 "addiu %[m], %[m], 1 \n\t"
243 "lh %[wi], 0(%[ptr_j]) \n\t"
244 "lh %[wr], 0(%[ptr_i]) \n\t"
245 #endif // #if defined(MIPS_DSP_R1_LE)
246 "1: \n\t"
247 "sll %[tmp1], %[i], 2 \n\t"
248 "addu %[ptr_i], %[frfi], %[tmp1] \n\t"
249 "addu %[ptr_j], %[ptr_i], %[tmp] \n\t"
250 "lh %[tmp3], 0(%[ptr_j]) \n\t"
251 "lh %[tmp4], 2(%[ptr_j]) \n\t"
252 "lh %[tmp6], 0(%[ptr_i]) \n\t"
253 "lh %[tmp5], 2(%[ptr_i]) \n\t"
254 "addu %[i], %[i], %[istep] \n\t"
255 #if defined(MIPS_DSP_R2_LE)
256 "mult %[wr], %[tmp3] \n\t"
257 "msub %[wi], %[tmp4] \n\t"
258 "mult $ac1, %[wr], %[tmp4] \n\t"
259 "madd $ac1, %[wi], %[tmp3] \n\t"
260 "mflo %[tmp1] \n\t"
261 "mflo %[tmp2], $ac1 \n\t"
262 "sll %[tmp6], %[tmp6], 14 \n\t"
263 "sll %[tmp5], %[tmp5], 14 \n\t"
264 "shra_r.w %[tmp1], %[tmp1], 1 \n\t"
265 "shra_r.w %[tmp2], %[tmp2], 1 \n\t"
266 "addu %[tmp6], %[tmp6], %[round2] \n\t"
267 "addu %[tmp5], %[tmp5], %[round2] \n\t"
268 "subu %[tmp4], %[tmp6], %[tmp1] \n\t"
269 "addu %[tmp1], %[tmp6], %[tmp1] \n\t"
270 "addu %[tmp6], %[tmp5], %[tmp2] \n\t"
271 "subu %[tmp5], %[tmp5], %[tmp2] \n\t"
272 "srav %[tmp4], %[tmp4], %[shift] \n\t"
273 "srav %[tmp1], %[tmp1], %[shift] \n\t"
274 "srav %[tmp6], %[tmp6], %[shift] \n\t"
275 "srav %[tmp5], %[tmp5], %[shift] \n\t"
276 #else // #if defined(MIPS_DSP_R2_LE)
277 "mul %[tmp1], %[wr], %[tmp3] \n\t"
278 "mul %[tmp2], %[wr], %[tmp4] \n\t"
279 "mul %[tmp4], %[wi], %[tmp4] \n\t"
280 "mul %[tmp3], %[wi], %[tmp3] \n\t"
281 "sll %[tmp6], %[tmp6], 14 \n\t"
282 "sll %[tmp5], %[tmp5], 14 \n\t"
283 "sub %[tmp1], %[tmp1], %[tmp4] \n\t"
284 "addu %[tmp2], %[tmp2], %[tmp3] \n\t"
285 "addiu %[tmp1], %[tmp1], 1 \n\t"
286 "addiu %[tmp2], %[tmp2], 1 \n\t"
287 "sra %[tmp2], %[tmp2], 1 \n\t"
288 "sra %[tmp1], %[tmp1], 1 \n\t"
289 "addu %[tmp6], %[tmp6], %[round2] \n\t"
290 "addu %[tmp5], %[tmp5], %[round2] \n\t"
291 "subu %[tmp4], %[tmp6], %[tmp1] \n\t"
292 "addu %[tmp1], %[tmp6], %[tmp1] \n\t"
293 "addu %[tmp6], %[tmp5], %[tmp2] \n\t"
294 "subu %[tmp5], %[tmp5], %[tmp2] \n\t"
295 "sra %[tmp4], %[tmp4], %[shift] \n\t"
296 "sra %[tmp1], %[tmp1], %[shift] \n\t"
297 "sra %[tmp6], %[tmp6], %[shift] \n\t"
298 "sra %[tmp5], %[tmp5], %[shift] \n\t"
299 #endif // #if defined(MIPS_DSP_R2_LE)
300 "sh %[tmp1], 0(%[ptr_i]) \n\t"
301 "sh %[tmp6], 2(%[ptr_i]) \n\t"
302 "sh %[tmp4], 0(%[ptr_j]) \n\t"
303 "blt %[i], %[n], 1b \n\t"
304 " sh %[tmp5], 2(%[ptr_j]) \n\t"
305 "blt %[m], %[l], 2b \n\t"
306 " addu %[i], $zero, %[m] \n\t"
307 "move %[l], %[istep] \n\t"
308 "blt %[l], %[n], 3b \n\t"
309 " addiu %[k], %[k], -1 \n\t"
310
311 ".set pop \n\t"
312
313 : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3),
314 [tmp4] "=&r" (tmp4), [tmp5] "=&r" (tmp5), [tmp6] "=&r" (tmp6),
315 [ptr_i] "=&r" (ptr_i), [i] "=&r" (i), [m] "=&r" (m), [tmp] "=&r" (tmp),
316 [istep] "=&r" (istep), [wi] "=&r" (wi), [wr] "=&r" (wr), [l] "=&r" (l),
317 [k] "=&r" (k), [round2] "=&r" (round2), [ptr_j] "=&r" (ptr_j),
318 [shift] "=&r" (shift), [scale] "=&r" (scale), [tempMax] "=&r" (tempMax)
319 : [n] "r" (n), [frfi] "r" (frfi), [kSinTable1024] "r" (kSinTable1024)
320 : "hi", "lo", "memory"
321 #if defined(MIPS_DSP_R2_LE)
322 , "$ac1hi", "$ac1lo"
323 #endif // #if defined(MIPS_DSP_R2_LE)
324 );
325
326 return scale;
327
328 }
329