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