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: ./src/fwd_long_complex_rot.c
21 Funtions: fwd_long_complex_rot
22
23 ------------------------------------------------------------------------------
24 REVISION HISTORY
25
26 Date: 10/18/2002
27 Description:
28 (1) Change the input arguments, no shifts information from
29 long_fft_rx4 is passed, only a single max is passed.
30 (2) Eliminate search for max, a fixed shift has replaced the
31 search for max with minimal loss of precision.
32 (3) Eliminated unused variables
33
34 Date: 10/28/2002
35 Description:
36 (1) Added comments per code review
37 (2) Eliminated hardly used condition on if-else (exp==0)
38
39 Description:
40
41 ------------------------------------------------------------------------------
42 INPUT AND OUTPUT DEFINITIONS
43
44 Inputs:
45
46 Data_in = Input vector (sized for long windows
47 TWICE_FWD_LONG_CX_ROT_LENGTH), with time domain samples
48 type Int32 *
49
50 Data_out = Output vector with a post-rotation by exp(-j(2pi/N)(k+1/8)),
51 (sized for long windows TWICE_FWD_LONG_CX_ROT_LENGTH)
52 type Int32 *
53
54 max = Input, carries the maximum value of the input vector
55 "Data_in"
56 type Int32
57
58
59 Local Stores/Buffers/Pointers Needed:
60 None
61
62 Global Stores/Buffers/Pointers Needed:
63 None
64
65 Outputs:
66 exp = shift factor to reflect signal scaling
67
68 Pointers and Buffers Modified:
69 Results are return in "Data_out"
70
71 Local Stores Modified:
72 None
73
74 Global Stores Modified:
75 None
76 ------------------------------------------------------------------------------
77 FUNCTION DESCRIPTION
78
79 fwd_long_complex_rot() performs the pre complex rotation for the MDCT
80 for the case of long windows. It also performs digit reverse ordering of
81 the first and second halves of the input vector "Data_in", as well as
82 reordering of the two half vectors (following radix-2 decomposition)
83 Word normalization is also done to ensure 16 by 16 bit multiplications.
84
85 ------------------------------------------------------------------------------
86 REQUIREMENTS
87
88 fwd_long_complex_rot() should execute a pre-rotation by
89 exp(-j(2pi/N)(k+1/8)), digit reverse ordering and normalization
90 ------------------------------------------------------------------------------
91 REFERENCES
92
93 ------------------------------------------------------------------------------
94 RESOURCES USED
95 When the code is written for a specific target processor the
96 the resources used should be documented below.
97
98 STACK USAGE: [stack count for this module] + [variable to represent
99 stack usage for each subroutine called]
100
101 where: [stack usage variable] = stack usage for [subroutine
102 name] (see [filename].ext)
103
104 DATA MEMORY USED: x words
105
106 PROGRAM MEMORY USED: x words
107
108 CLOCK CYCLES: [cycle count equation for this module] + [variable
109 used to represent cycle count for each subroutine
110 called]
111
112 where: [cycle count variable] = cycle count for [subroutine
113 name] (see [filename].ext)
114
115 ------------------------------------------------------------------------------
116 */
117
118
119 /*----------------------------------------------------------------------------
120 ; INCLUDES
121 ----------------------------------------------------------------------------*/
122
123 #include "fwd_long_complex_rot.h"
124 #include "digit_reversal_tables.h"
125 #include "imdct_fxp.h"
126 #include "pv_normalize.h"
127
128 #include "fxp_mul32.h"
129
130 /*----------------------------------------------------------------------------
131 ; MACROS
132 ; Define module specific macros here
133 ----------------------------------------------------------------------------*/
134
135 /*----------------------------------------------------------------------------
136 ; DEFINES
137 ; Include all pre-processor statements here. Include conditional
138 ; compile variables also.
139 ----------------------------------------------------------------------------*/
140
141 /*----------------------------------------------------------------------------
142 ; LOCAL FUNCTION DEFINITIONS
143 ; Function Prototype declaration
144 ----------------------------------------------------------------------------*/
145
146 /*----------------------------------------------------------------------------
147 ; LOCAL VARIABLE DEFINITIONS
148 ; Variable declaration - defined here and used outside this module
149 ----------------------------------------------------------------------------*/
150
151 /*----------------------------------------------------------------------------
152 ; EXTERNAL FUNCTION REFERENCES
153 ; Declare functions defined elsewhere and referenced in this module
154 ----------------------------------------------------------------------------*/
155
156 /*----------------------------------------------------------------------------
157 ; EXTERNAL VARIABLES REFERENCES
158 ; Declare variables used in this module but defined elsewhere
159 ----------------------------------------------------------------------------*/
160
fwd_long_complex_rot(Int32 * Data_in,Int32 * Data_out,Int32 max)161 Int fwd_long_complex_rot(
162 Int32 *Data_in,
163 Int32 *Data_out,
164 Int32 max)
165 {
166 Int i;
167 const Int32 *p_rotate;
168 Int32 temp_re;
169 Int32 temp_im;
170 Int32 *pData_in_ref1;
171 Int32 *pData_in_ref2;
172 Int32 exp_jw;
173 Int32 temp_re_32;
174 Int32 temp_im_32;
175
176 Int32 *pData_out_1;
177 Int32 *pData_out_2;
178 Int32 *pData_out_3;
179 Int32 *pData_out_4;
180
181 Int32 *pData_in_1;
182 Int32 *pData_in_2;
183
184 Int exp;
185
186 p_rotate = exp_rotation_N_2048;
187
188 pData_in_ref1 = Data_in;
189 pData_in_ref2 = &Data_in[TWICE_FWD_LONG_CX_ROT_LENGTH];
190
191 pData_out_1 = Data_out;
192 pData_out_2 = &Data_out[LONG_WINDOW_LENGTH_m_1];
193 pData_out_3 = &Data_out[LONG_WINDOW_LENGTH];
194 pData_out_4 = &Data_out[TWICE_LONG_WINDOW_LENGTH_m_1];
195
196 /*
197 * Data_out
198 * >>>> <<<<
199 * pData_out_3 pData_out_4
200 * | | | | |
201 * pData_out_1 pData_out_2
202 * >>>> <<<<
203 */
204
205
206 exp = 16 - pv_normalize(max);
207
208 if (exp < 0)
209 {
210 exp = 0;
211 }
212
213 /*
214 * Apply A/2^(diff) + B
215 */
216
217
218 pData_in_1 = pData_in_ref1;
219 pData_in_2 = pData_in_ref2;
220
221 for (i = FWD_LONG_CX_ROT_LENGTH; i != 0; i--)
222 {
223
224 /*
225 * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8))
226 */
227
228 exp_jw = *p_rotate++;
229
230 /*
231 * Use auxiliary variables to avoid double accesses to memory.
232 * Data in is scaled to use only lower 16 bits.
233 */
234
235 temp_re = *(pData_in_1++) >> exp;
236 temp_im = *(pData_in_1++) >> exp;
237
238 /*
239 * Pre-rotation
240 */
241
242 temp_re_32 = (cmplx_mul32_by_16(temp_re, temp_im, exp_jw));
243 temp_im_32 = (cmplx_mul32_by_16(temp_im, -temp_re, exp_jw));
244
245 *(pData_out_1++) = - temp_re_32;
246 *(pData_out_2--) = temp_im_32;
247 *(pData_out_3++) = - temp_im_32;
248 *(pData_out_4--) = temp_re_32;
249
250 /*
251 * Pointer increment to jump over imag (1 & 4) or real parts
252 * (2 & 3)
253 */
254 pData_out_1++;
255 pData_out_2--;
256 pData_out_3++;
257 pData_out_4--;
258
259 /*
260 * Repeat procedure for odd index at the output
261 */
262
263 exp_jw = *p_rotate++;
264
265 temp_re = *(pData_in_2++) >> exp;
266 temp_im = *(pData_in_2++) >> exp;
267
268 temp_re_32 = (cmplx_mul32_by_16(temp_re, temp_im, exp_jw));
269 temp_im_32 = (cmplx_mul32_by_16(temp_im, -temp_re, exp_jw));
270
271 *(pData_out_1++) = - temp_re_32;
272 *(pData_out_2--) = temp_im_32;
273 *(pData_out_3++) = - temp_im_32;
274 *(pData_out_4--) = temp_re_32;
275
276 pData_out_1++;
277 pData_out_2--;
278 pData_out_3++;
279 pData_out_4--;
280
281 }
282
283 return (exp + 1);
284 }
285