1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 /*
19
20 Pathname: .inv_long_complex_rot.c
21 Funtions: inv_long_complex_rot
22
23 ------------------------------------------------------------------------------
24 REVISION HISTORY
25
26 Description: Change the input argument, no shifts information from long fft_rx4
27 , do not have to check for shifts.
28
29 Date: 10/18/2002
30 Description:
31 (1) Change the input argument, only a single max is passed.
32 (2) Eliminate search for max, a fixed shift has replaced the
33 search for max with minimal loss of precision.
34 (3) Eliminated unused variables
35
36 Date: 10/28/2002
37 Description:
38 (1) Added comments per code review
39
40 Description:
41
42 ------------------------------------------------------------------------------
43 INPUT AND OUTPUT DEFINITIONS
44
45 Inputs:
46
47 Data_in = Input vector (sized for long windows
48 TWICE_INV_LONG_CX_ROT_LENGTH), with time domain samples
49 type Int32 *
50
51 Data_out = Output vector with a post-rotation by exp(j(2pi/N)(k+1/8)),
52 (sized for long windows TWICE_INV_LONG_CX_ROT_LENGTH)
53 type Int32 *
54
55 max = Input, carries the maximum value of the input vector
56 "Data_in"
57 type Int32
58
59
60 Local Stores/Buffers/Pointers Needed:
61 None
62
63 Global Stores/Buffers/Pointers Needed:
64 None
65
66 Outputs:
67 exp = shift factor to reflect signal scaling
68
69 Pointers and Buffers Modified:
70 Results are return in "Data_out"
71
72 Local Stores Modified:
73 None
74
75 Global Stores Modified:
76 None
77 ------------------------------------------------------------------------------
78 FUNCTION DESCRIPTION
79
80 inv_long_complex_rot() performs the complex rotation for the inverse MDCT
81 for the case of long windows. It also performs digit reverse ordering of
82 the first and second halves of the input vector "Data_in", as well as
83 reordering of the two half vectors (following radix-2 decomposition)
84 Word normalization is also done to ensure 16 by 16 bit multiplications.
85
86 ------------------------------------------------------------------------------
87 REQUIREMENTS
88
89 inv_long_complex_rot() should execute a post-rotation by
90 exp(-j(2pi/N)(k+1/8)), digit reverse ordering and word normalization
91
92 ------------------------------------------------------------------------------
93 REFERENCES
94
95 ------------------------------------------------------------------------------
96 RESOURCES USED
97 When the code is written for a specific target processor the
98 the resources used should be documented below.
99
100 STACK USAGE: [stack count for this module] + [variable to represent
101 stack usage for each subroutine called]
102
103 where: [stack usage variable] = stack usage for [subroutine
104 name] (see [filename].ext)
105
106 DATA MEMORY USED: x words
107
108 PROGRAM MEMORY USED: x words
109
110 CLOCK CYCLES: [cycle count equation for this module] + [variable
111 used to represent cycle count for each subroutine
112 called]
113
114 where: [cycle count variable] = cycle count for [subroutine
115 name] (see [filename].ext)
116
117 ------------------------------------------------------------------------------
118 */
119 /*----------------------------------------------------------------------------
120 ; INCLUDES
121 ----------------------------------------------------------------------------*/
122
123 #include "digit_reversal_tables.h"
124 #include "inv_long_complex_rot.h"
125 #include "imdct_fxp.h"
126 #include "inv_long_complex_rot.h"
127 #include "pv_normalize.h"
128
129 #include "fxp_mul32.h"
130 #include "aac_mem_funcs.h"
131
132 /*----------------------------------------------------------------------------
133 ; MACROS
134 ; Define module specific macros here
135 ----------------------------------------------------------------------------*/
136
137 /*----------------------------------------------------------------------------
138 ; DEFINES
139 ; Include all pre-processor statements here. Include conditional
140 ; compile variables also.
141 ----------------------------------------------------------------------------*/
142
143 /*----------------------------------------------------------------------------
144 ; LOCAL FUNCTION DEFINITIONS
145 ; Function Prototype declaration
146 ----------------------------------------------------------------------------*/
147
148 /*----------------------------------------------------------------------------
149 ; LOCAL VARIABLE DEFINITIONS
150 ; Variable declaration - defined here and used outside this module
151 ----------------------------------------------------------------------------*/
152
153 /*----------------------------------------------------------------------------
154 ; EXTERNAL FUNCTION REFERENCES
155 ; Declare functions defined elsewhere and referenced in this module
156 ----------------------------------------------------------------------------*/
157
158 /*----------------------------------------------------------------------------
159 ; EXTERNAL VARIABLES REFERENCES
160 ; Declare variables used in this module but defined elsewhere
161 ----------------------------------------------------------------------------*/
162
163
164
inv_long_complex_rot(Int32 * Data,Int32 max)165 Int inv_long_complex_rot(
166 Int32 *Data,
167 Int32 max)
168 {
169 Int i;
170 Int16 I;
171 const Int32 *p_rotate;
172 Int32 temp_re;
173 Int32 temp_im;
174
175 Int32 exp_jw;
176 Int32 *pData_in_1;
177 Int32 *pData_in_2;
178 Int exp;
179 Int32 *pData_in_ref1;
180 Int32 *pData_in_ref2;
181
182
183 Int16 temp_re_0;
184 Int16 temp_im_0;
185 Int16 temp_re_1;
186 Int16 temp_im_1;
187 Int16 *p_Data_Int_precision;
188 Int n = 2048;
189 Int n_2 = n >> 1;
190 Int n_4 = n >> 2;
191 Int n_3_4 = n_2 + n_4;
192
193 Int16 *px_1;
194 Int16 *px_2;
195 Int16 *px_3;
196 Int16 *px_4;
197
198 Int16 J;
199 const Int32 *p_rotate2;
200
201
202
203
204 p_rotate = &exp_rotation_N_2048[255];
205 p_rotate2 = &exp_rotation_N_2048[256];
206
207 pData_in_ref1 = Data;
208 pData_in_ref2 = &Data[TWICE_INV_LONG_CX_ROT_LENGTH];
209
210
211 /*
212 * Apply A/2^(diff) + B
213 */
214
215 p_Data_Int_precision = (Int16 *)Data;
216
217 exp = 16 - pv_normalize(max);
218
219
220 /*
221 * px2--> <--px1 px4--> <--px3
222 *
223 * | | |
224 * |+++++++++++++|+++++++++++++|+++++++++++++|+++++++++++++|
225 * | | | |
226 * n/4 n/2 3n/4
227 */
228
229 I = 255;
230 J = 256;
231
232 pData_in_1 = pData_in_ref2 + I;
233
234 px_1 = (Int16 *)pData_in_1;
235 px_1++;
236
237 pData_in_2 = pData_in_ref2 + J;
238
239 px_4 = (Int16 *)pData_in_2;
240
241
242
243 exp -= 1;
244
245
246 for (i = INV_LONG_CX_ROT_LENGTH >> 1; i != 0; i--)
247 {
248
249 pData_in_2 = pData_in_ref1 + J;
250
251 temp_im = *(pData_in_2++);
252 temp_re = *(pData_in_2);
253
254
255 /*
256 * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8))
257 */
258 exp_jw = *p_rotate2++;
259
260 /*
261 * Post-rotation
262 */
263
264
265
266 temp_re_0 = (Int16)(cmplx_mul32_by_16(temp_re, -temp_im, exp_jw) >> exp);
267 temp_im_0 = (Int16)(cmplx_mul32_by_16(temp_im, temp_re, exp_jw) >> exp);
268
269
270 pData_in_1 = pData_in_ref2 + I;
271
272 /*
273 * Use auxiliary variables to avoid double accesses to memory.
274 * Data in is scaled to use only lower 16 bits.
275 */
276
277 temp_re = *(pData_in_1--);
278 temp_im = *(pData_in_1);
279
280 /*
281 * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8))
282 */
283 exp_jw = *p_rotate--;
284
285
286 /*
287 * Post-rotation
288 */
289
290 temp_re_1 = (Int16)(cmplx_mul32_by_16(temp_re, -temp_im, exp_jw) >> exp);
291 temp_im_1 = (Int16)(cmplx_mul32_by_16(temp_im, temp_re, exp_jw) >> exp);
292
293
294 /*
295 * Repeat procedure for odd index at the output
296 */
297
298 pData_in_2 = pData_in_ref2 + J;
299 J += 2;
300
301 temp_im = *(pData_in_2++);
302 temp_re = *(pData_in_2);
303
304
305 *(px_1--) = temp_re_0;
306 *(px_1--) = temp_im_1;
307 *(px_4++) = temp_im_0;
308 *(px_4++) = temp_re_1;
309
310
311 exp_jw = *p_rotate2++;
312
313
314 *(px_1--) = (Int16)(cmplx_mul32_by_16(temp_re, -temp_im, exp_jw) >> exp);
315 *(px_4++) = (Int16)(cmplx_mul32_by_16(temp_im, temp_re, exp_jw) >> exp);
316
317
318
319 /*
320 * Repeat procedure for odd index at the output
321 */
322
323 pData_in_1 = pData_in_ref1 + I;
324 I -= 2;
325
326 temp_re = *(pData_in_1--);
327 temp_im = *(pData_in_1);
328
329
330 exp_jw = *p_rotate--;
331
332
333 *(px_4++) = (Int16)(cmplx_mul32_by_16(temp_re, -temp_im, exp_jw) >> exp);
334 *(px_1--) = (Int16)(cmplx_mul32_by_16(temp_im, temp_re, exp_jw) >> exp);
335
336 }
337
338 /*
339 * <--px1 px4-->
340 *
341 * | | |
342 * |-------------|-------------|/////////////|\\\\\\\\\\\\\|
343 * | | | |
344 * n/4 n/2 3n/4
345 */
346
347
348 px_1 = p_Data_Int_precision + n_2 - 1;
349 px_2 = p_Data_Int_precision;
350
351 px_4 = p_Data_Int_precision + n_3_4 - 1;
352
353 for (i = 0; i<INV_LONG_CX_ROT_LENGTH >> 1; i++)
354 {
355
356 Int16 temp_re_0 = *(px_4--);
357 Int16 temp_im_1 = *(px_4--);
358 Int16 temp_re_2 = *(px_4--);
359 Int16 temp_im_3 = *(px_4--);
360 *(px_1--) = temp_re_0;
361 *(px_1--) = temp_im_1;
362 *(px_1--) = temp_re_2;
363 *(px_1--) = temp_im_3;
364
365 *(px_2++) = (-temp_re_0);
366 *(px_2++) = (-temp_im_1);
367 *(px_2++) = (-temp_re_2);
368 *(px_2++) = (-temp_im_3);
369
370 }
371
372
373 px_4 = p_Data_Int_precision + n_2;
374
375
376 pv_memcpy(px_4, pData_in_ref2 + 256, TWICE_INV_LONG_CX_ROT_LENGTH*sizeof(*px_4));
377
378
379
380 /*
381 * px2--> <--px1 px4--> <--px3
382 *
383 * | | |
384 * |+++++++++++++|+++++++++++++|+++++++++++++|+++++++++++++|
385 * | | | |
386 * n/4 n/2 3n/4
387 */
388 px_3 = p_Data_Int_precision + n - 1;
389
390
391 for (i = 0; i<INV_LONG_CX_ROT_LENGTH >> 1; i++)
392 {
393
394 Int16 temp_im_0 = *(px_4++);
395 Int16 temp_re_1 = *(px_4++);
396 Int16 temp_im_2 = *(px_4++);
397 Int16 temp_re_3 = *(px_4++);
398 *(px_3--) = temp_im_0;
399 *(px_3--) = temp_re_1;
400 *(px_3--) = temp_im_2;
401 *(px_3--) = temp_re_3;
402
403 }
404
405
406 return (exp + 1);
407 }
408
409