Git init
[external/opencore-amr.git] / opencore / codecs_v2 / audio / gsm_amr / amr_nb / common / src / sqrt_l.cpp
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 Portions of this file are derived from the following 3GPP standard:
20
21     3GPP TS 26.073
22     ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23     Available from http://www.3gpp.org
24
25 (C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
26 Permission to distribute, modify and use this file under the standard license
27 terms listed above has been obtained from the copyright holder.
28 ****************************************************************************************/
29 /*
30
31  Filename: sqrt_l.cpp
32
33 ------------------------------------------------------------------------------
34 */
35
36 /*----------------------------------------------------------------------------
37 ; INCLUDES
38 ----------------------------------------------------------------------------*/
39 #include    "sqrt_l.h"
40 #include    "typedef.h"
41 #include    "basic_op.h"
42
43 /*----------------------------------------------------------------------------
44 ; MACROS
45 ; Define module specific macros here
46 ----------------------------------------------------------------------------*/
47
48
49 /*----------------------------------------------------------------------------
50 ; DEFINES
51 ; Include all pre-processor statements here. Include conditional
52 ; compile variables also.
53 ----------------------------------------------------------------------------*/
54
55
56 /*----------------------------------------------------------------------------
57 ; LOCAL FUNCTION DEFINITIONS
58 ; Function Prototype declaration
59 ----------------------------------------------------------------------------*/
60
61
62 /*----------------------------------------------------------------------------
63 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
64 ; Variable declaration - defined here and used outside this module
65 ----------------------------------------------------------------------------*/
66
67
68 /*
69 ------------------------------------------------------------------------------
70  FUNCTION NAME: sqrt_l_exp
71 ------------------------------------------------------------------------------
72  INPUT AND OUTPUT DEFINITIONS
73
74  Inputs:
75     L_x = input value (Word32)
76     pExp = pointer to right shift to be applied to result
77     pOverflow = pointer to overflow flag
78
79  Outputs:
80     pOverflow -> if the Inv_sqrt operation resulted in an overflow.
81
82  Returns:
83     L_y = squareroot of L_x (Word32)
84
85  Global Variables Used:
86     None.
87
88  Local Variables Needed:
89     None.
90
91 ------------------------------------------------------------------------------
92  FUNCTION DESCRIPTION
93
94  This function computes sqrt(L_x),  where  L_x is positive.
95  If L_var is negative or zero, the result is 0
96
97  The function sqrt(L_x) is approximated by a table and linear
98  interpolation. The square root is computed using the
99  following steps:
100     1- Normalization of L_x.
101     2- If exponent is even then shift right once.
102     3- exponent = exponent/2
103     4- i = bit25-b31 of L_x;  16<=i<=63  because of normalization.
104     5- a = bit10-b24
105     6- i -=16
106     7- L_y = table[i]<<16 - (table[i] - table[i+1]) * a * 2
107     8- return L_y and exponent so caller can do denormalization
108
109 ------------------------------------------------------------------------------
110  REQUIREMENTS
111
112  None.
113
114 ------------------------------------------------------------------------------
115  REFERENCES
116
117  sqrt_l.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
118
119 ------------------------------------------------------------------------------
120  PSEUDO-CODE
121
122 Word32 sqrt_l_exp (     // o : output value
123     Word32 L_x,         // i : input value
124     Word16 *exp         // o : right shift to be applied to result
125 )
126 {
127
128 //          y = sqrt(x)
129 //          x = f * 2^-e,   0.5 <= f < 1   (normalization)
130 //          y = sqrt(f) * 2^(-e/2)
131 //
132 //          a) e = 2k   --> y = sqrt(f)   * 2^-k  (k = e div 2,
133 //                                                 0.707 <= sqrt(f) < 1)
134 //          b) e = 2k+1 --> y = sqrt(f/2) * 2^-k  (k = e div 2,
135                                                  0.5 <= sqrt(f/2) < 0.707)
136
137
138     Word16 e, i, a, tmp;
139     Word32 L_y;
140
141     if (L_x <= (Word32) 0)
142     {
143         *exp = 0;
144         return (Word32) 0;
145     }
146
147 * The reference ETSI code uses a global Overflow flag. In the actual
148 * implementation a pointer to the overflow flag is passed into the function.
149 * This pointer is in turn passed into the basic math functions such as add(),
150 * L_shl(), L_shr(), sub() called by this module.
151
152     e = norm_l (L_x) & 0xFFFE;              // get next lower EVEN norm. exp
153     L_x = L_shl (L_x, e);                   // L_x is normalized to [0.25..1)
154     *exp = e;                               // return 2*exponent (or Q1)
155
156     L_x = L_shr (L_x, 9);
157     i = extract_h (L_x);                    // Extract b25-b31, 16 <= i <= 63
158                                                 because of normalization
159     L_x = L_shr (L_x, 1);
160     a = extract_l (L_x);                    // Extract b10-b24
161     a = a & (Word16) 0x7fff;
162
163     i = sub (i, 16);                        // 0 <= i <= 47
164
165     L_y = L_deposit_h (table[i]);           // table[i] << 16
166     tmp = sub (table[i], table[i + 1]);     // table[i] - table[i+1])
167     L_y = L_msu (L_y, tmp, a);              // L_y -= tmp*a*2
168
169     return (L_y);
170 }
171
172 ------------------------------------------------------------------------------
173  CAUTION [optional]
174  [State any special notes, constraints or cautions for users of this function]
175
176 ------------------------------------------------------------------------------
177 */
178
179 OSCL_EXPORT_REF Word32 sqrt_l_exp(      /* o : output value,          Q31 */
180     Word32 L_x,         /* i : input value,                           Q31 */
181     Word16 *pExp,       /* o : right shift to be applied to result,   Q1  */
182     Flag   *pOverflow   /* i : pointer to overflow flag */
183 )
184
185 {
186     Word16 e;
187     Word16 i;
188     Word16 a;
189     Word16 tmp;
190     Word32 L_y;
191
192     /*
193           y = sqrt(x)
194           x = f * 2^-e,   0.5 <= f < 1   (normalization)
195           y = sqrt(f) * 2^(-e/2)
196           a) e = 2k   --> y = sqrt(f)   * 2^-k  (k = e div 2,
197                                                  0.707 <= sqrt(f) < 1)
198           b) e = 2k+1 --> y = sqrt(f/2) * 2^-k  (k = e div 2,
199                                                  0.5 <= sqrt(f/2) < 0.707)
200      */
201
202     if (L_x <= (Word32) 0)
203     {
204         *pExp = 0;
205         return (Word32) 0;
206     }
207
208     e = norm_l(L_x) & 0xFFFE;               /* get next lower EVEN norm. exp  */
209     L_x = L_shl(L_x, e, pOverflow);         /* L_x is normalized to [0.25..1) */
210     *pExp = e;                              /* return 2*exponent (or Q1)      */
211
212     L_x >>= 10;
213     i = (Word16)(L_x >> 15) & 63;            /* Extract b25-b31, 16<= i <=63  */
214     /* because of normalization       */
215
216     a = (Word16)(L_x);                      /* Extract b10-b24 */
217     a &= (Word16) 0x7fff;
218
219     if (i > 15)
220     {
221         i -= 16;                              /* 0 <= i <= 47                   */
222     }
223
224     L_y = ((Word32) sqrt_l_tbl[i] << 16);      /* sqrt_l_tbl[i] << 16            */
225
226     /* sqrt_l_tbl[i] - sqrt_l_tbl[i+1]) */
227     tmp = sqrt_l_tbl[i] - sqrt_l_tbl[i + 1];
228
229     L_y = L_msu(L_y, tmp, a, pOverflow);    /* L_y -= tmp*a*2                 */
230
231     /* L_y = L_shr (L_y, *exp); */          /* denormalization done by caller */
232
233     return (L_y);
234 }
235