/src/aac/libFDK/src/FDK_trigFcts.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* ----------------------------------------------------------------------------- |
2 | | Software License for The Fraunhofer FDK AAC Codec Library for Android |
3 | | |
4 | | © Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten |
5 | | Forschung e.V. All rights reserved. |
6 | | |
7 | | 1. INTRODUCTION |
8 | | The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software |
9 | | that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding |
10 | | scheme for digital audio. This FDK AAC Codec software is intended to be used on |
11 | | a wide variety of Android devices. |
12 | | |
13 | | AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient |
14 | | general perceptual audio codecs. AAC-ELD is considered the best-performing |
15 | | full-bandwidth communications codec by independent studies and is widely |
16 | | deployed. AAC has been standardized by ISO and IEC as part of the MPEG |
17 | | specifications. |
18 | | |
19 | | Patent licenses for necessary patent claims for the FDK AAC Codec (including |
20 | | those of Fraunhofer) may be obtained through Via Licensing |
21 | | (www.vialicensing.com) or through the respective patent owners individually for |
22 | | the purpose of encoding or decoding bit streams in products that are compliant |
23 | | with the ISO/IEC MPEG audio standards. Please note that most manufacturers of |
24 | | Android devices already license these patent claims through Via Licensing or |
25 | | directly from the patent owners, and therefore FDK AAC Codec software may |
26 | | already be covered under those patent licenses when it is used for those |
27 | | licensed purposes only. |
28 | | |
29 | | Commercially-licensed AAC software libraries, including floating-point versions |
30 | | with enhanced sound quality, are also available from Fraunhofer. Users are |
31 | | encouraged to check the Fraunhofer website for additional applications |
32 | | information and documentation. |
33 | | |
34 | | 2. COPYRIGHT LICENSE |
35 | | |
36 | | Redistribution and use in source and binary forms, with or without modification, |
37 | | are permitted without payment of copyright license fees provided that you |
38 | | satisfy the following conditions: |
39 | | |
40 | | You must retain the complete text of this software license in redistributions of |
41 | | the FDK AAC Codec or your modifications thereto in source code form. |
42 | | |
43 | | You must retain the complete text of this software license in the documentation |
44 | | and/or other materials provided with redistributions of the FDK AAC Codec or |
45 | | your modifications thereto in binary form. You must make available free of |
46 | | charge copies of the complete source code of the FDK AAC Codec and your |
47 | | modifications thereto to recipients of copies in binary form. |
48 | | |
49 | | The name of Fraunhofer may not be used to endorse or promote products derived |
50 | | from this library without prior written permission. |
51 | | |
52 | | You may not charge copyright license fees for anyone to use, copy or distribute |
53 | | the FDK AAC Codec software or your modifications thereto. |
54 | | |
55 | | Your modified versions of the FDK AAC Codec must carry prominent notices stating |
56 | | that you changed the software and the date of any change. For modified versions |
57 | | of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" |
58 | | must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK |
59 | | AAC Codec Library for Android." |
60 | | |
61 | | 3. NO PATENT LICENSE |
62 | | |
63 | | NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without |
64 | | limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. |
65 | | Fraunhofer provides no warranty of patent non-infringement with respect to this |
66 | | software. |
67 | | |
68 | | You may use this FDK AAC Codec software or modifications thereto only for |
69 | | purposes that are authorized by appropriate patent licenses. |
70 | | |
71 | | 4. DISCLAIMER |
72 | | |
73 | | This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright |
74 | | holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, |
75 | | including but not limited to the implied warranties of merchantability and |
76 | | fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
77 | | CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, |
78 | | or consequential damages, including but not limited to procurement of substitute |
79 | | goods or services; loss of use, data, or profits, or business interruption, |
80 | | however caused and on any theory of liability, whether in contract, strict |
81 | | liability, or tort (including negligence), arising in any way out of the use of |
82 | | this software, even if advised of the possibility of such damage. |
83 | | |
84 | | 5. CONTACT INFORMATION |
85 | | |
86 | | Fraunhofer Institute for Integrated Circuits IIS |
87 | | Attention: Audio and Multimedia Departments - FDK AAC LL |
88 | | Am Wolfsmantel 33 |
89 | | 91058 Erlangen, Germany |
90 | | |
91 | | www.iis.fraunhofer.de/amm |
92 | | amm-info@iis.fraunhofer.de |
93 | | ----------------------------------------------------------------------------- */ |
94 | | |
95 | | /******************* Library for basic calculation routines ******************** |
96 | | |
97 | | Author(s): Haricharan Lakshman, Manuel Jander |
98 | | |
99 | | Description: Trigonometric functions fixed point fractional implementation. |
100 | | |
101 | | *******************************************************************************/ |
102 | | |
103 | | #include "FDK_trigFcts.h" |
104 | | |
105 | | #include "fixpoint_math.h" |
106 | | |
107 | | #define IMPROVE_ATAN2_ACCURACY 1 /* 0 --> 59 dB SNR 1 --> 65 dB SNR */ |
108 | | #define MINSFTAB 7 |
109 | 0 | #define MAXSFTAB 25 |
110 | | |
111 | | #if IMPROVE_ATAN2_ACCURACY |
112 | | static const FIXP_DBL f_atan_expand_range[MAXSFTAB - (MINSFTAB - 1)] = { |
113 | | /***************************************************************************** |
114 | | * |
115 | | * Table holds fixp_atan() output values which are outside of input range |
116 | | * of fixp_atan() to improve SNR of fixp_atan2(). |
117 | | * |
118 | | * This Table might also be used in fixp_atan() so there a wider input |
119 | | * range can be covered, too. |
120 | | * |
121 | | *****************************************************************************/ |
122 | | FL2FXCONST_DBL(7.775862990872099e-001), |
123 | | FL2FXCONST_DBL(7.814919928673978e-001), |
124 | | FL2FXCONST_DBL(7.834450483314648e-001), |
125 | | FL2FXCONST_DBL(7.844216021392089e-001), |
126 | | FL2FXCONST_DBL(7.849098823026687e-001), |
127 | | FL2FXCONST_DBL(7.851540227918509e-001), |
128 | | FL2FXCONST_DBL(7.852760930873737e-001), |
129 | | FL2FXCONST_DBL(7.853371282415015e-001), |
130 | | FL2FXCONST_DBL(7.853676458193612e-001), |
131 | | FL2FXCONST_DBL(7.853829046083906e-001), |
132 | | FL2FXCONST_DBL(7.853905340029177e-001), |
133 | | FL2FXCONST_DBL(7.853943487001828e-001), |
134 | | FL2FXCONST_DBL(7.853962560488155e-001), |
135 | | FL2FXCONST_DBL(7.853972097231319e-001), |
136 | | FL2FXCONST_DBL(7.853976865602901e-001), |
137 | | FL2FXCONST_DBL(7.853979249788692e-001), |
138 | | FL2FXCONST_DBL(7.853980441881587e-001), |
139 | | FL2FXCONST_DBL(7.853981037928035e-001), |
140 | | FL2FXCONST_DBL(7.853981335951259e-001) |
141 | | /* pi/4 = 0.785398163397448 = pi/2/ATO_SCALE */ |
142 | | }; |
143 | | #endif |
144 | | |
145 | 0 | FIXP_DBL fixp_atan2(FIXP_DBL y, FIXP_DBL x) { |
146 | 0 | FIXP_DBL q; |
147 | 0 | FIXP_DBL at; /* atan out */ |
148 | 0 | FIXP_DBL at2; /* atan2 out */ |
149 | 0 | FIXP_DBL ret = FL2FXCONST_DBL(-1.0f); |
150 | 0 | INT sf, sfo, stf; |
151 | | |
152 | | /* --- division */ |
153 | |
|
154 | 0 | if (y > FL2FXCONST_DBL(0.0f)) { |
155 | 0 | if (x > FL2FXCONST_DBL(0.0f)) { |
156 | 0 | q = fDivNormHighPrec(y, x, &sf); /* both pos. */ |
157 | 0 | } else if (x < FL2FXCONST_DBL(0.0f)) { |
158 | 0 | q = -fDivNormHighPrec(y, -x, &sf); /* x neg. */ |
159 | 0 | } else { /* (x == FL2FXCONST_DBL(0.0f)) */ |
160 | 0 | q = FL2FXCONST_DBL(+1.0f); /* y/x = pos/zero = +Inf */ |
161 | 0 | sf = 0; |
162 | 0 | } |
163 | 0 | } else if (y < FL2FXCONST_DBL(0.0f)) { |
164 | 0 | if (x > FL2FXCONST_DBL(0.0f)) { |
165 | 0 | q = -fDivNormHighPrec(-y, x, &sf); /* y neg. */ |
166 | 0 | } else if (x < FL2FXCONST_DBL(0.0f)) { |
167 | 0 | q = fDivNormHighPrec(-y, -x, &sf); /* both neg. */ |
168 | 0 | } else { /* (x == FL2FXCONST_DBL(0.0f)) */ |
169 | 0 | q = FL2FXCONST_DBL(-1.0f); /* y/x = neg/zero = -Inf */ |
170 | 0 | sf = 0; |
171 | 0 | } |
172 | 0 | } else { /* (y == FL2FXCONST_DBL(0.0f)) */ |
173 | 0 | q = FL2FXCONST_DBL(0.0f); |
174 | 0 | sf = 0; |
175 | 0 | } |
176 | 0 | sfo = sf; |
177 | | |
178 | | /* --- atan() */ |
179 | |
|
180 | 0 | if (sfo > ATI_SF) { |
181 | | /* --- could not calc fixp_atan() here bec of input data out of range */ |
182 | | /* ==> therefore give back boundary values */ |
183 | |
|
184 | 0 | #if IMPROVE_ATAN2_ACCURACY |
185 | 0 | if (sfo > MAXSFTAB) sfo = MAXSFTAB; |
186 | 0 | #endif |
187 | |
|
188 | 0 | if (q > FL2FXCONST_DBL(0.0f)) { |
189 | 0 | #if IMPROVE_ATAN2_ACCURACY |
190 | 0 | at = +f_atan_expand_range[sfo - ATI_SF - 1]; |
191 | | #else |
192 | | at = FL2FXCONST_DBL(+M_PI / 2 / ATO_SCALE); |
193 | | #endif |
194 | 0 | } else if (q < FL2FXCONST_DBL(0.0f)) { |
195 | 0 | #if IMPROVE_ATAN2_ACCURACY |
196 | 0 | at = -f_atan_expand_range[sfo - ATI_SF - 1]; |
197 | | #else |
198 | | at = FL2FXCONST_DBL(-M_PI / 2 / ATO_SCALE); |
199 | | #endif |
200 | 0 | } else { /* q == FL2FXCONST_DBL(0.0f) */ |
201 | 0 | at = FL2FXCONST_DBL(0.0f); |
202 | 0 | } |
203 | 0 | } else { |
204 | | /* --- calc of fixp_atan() is possible; input data within range */ |
205 | | /* ==> set q on fixed scale level as desired from fixp_atan() */ |
206 | 0 | stf = sfo - ATI_SF; |
207 | 0 | if (stf > 0) |
208 | 0 | q = q << (INT)fMin(stf, DFRACT_BITS - 1); |
209 | 0 | else |
210 | 0 | q = q >> (INT)fMin(-stf, DFRACT_BITS - 1); |
211 | 0 | at = fixp_atan(q); /* ATO_SF */ |
212 | 0 | } |
213 | | |
214 | | // --- atan2() |
215 | |
|
216 | 0 | at2 = at >> (AT2O_SF - ATO_SF); // now AT2O_SF for atan2 |
217 | 0 | if (x > FL2FXCONST_DBL(0.0f)) { |
218 | 0 | ret = at2; |
219 | 0 | } else if (x < FL2FXCONST_DBL(0.0f)) { |
220 | 0 | if (y >= FL2FXCONST_DBL(0.0f)) { |
221 | 0 | ret = at2 + FL2FXCONST_DBL(M_PI / AT2O_SCALE); |
222 | 0 | } else { |
223 | 0 | ret = at2 - FL2FXCONST_DBL(M_PI / AT2O_SCALE); |
224 | 0 | } |
225 | 0 | } else { |
226 | | // x == 0 |
227 | 0 | if (y > FL2FXCONST_DBL(0.0f)) { |
228 | 0 | ret = FL2FXCONST_DBL(+M_PI / 2 / AT2O_SCALE); |
229 | 0 | } else if (y < FL2FXCONST_DBL(0.0f)) { |
230 | 0 | ret = FL2FXCONST_DBL(-M_PI / 2 / AT2O_SCALE); |
231 | 0 | } else if (y == FL2FXCONST_DBL(0.0f)) { |
232 | 0 | ret = FL2FXCONST_DBL(0.0f); |
233 | 0 | } |
234 | 0 | } |
235 | 0 | return ret; |
236 | 0 | } |
237 | | |
238 | 0 | FIXP_DBL fixp_atan(FIXP_DBL x) { |
239 | 0 | INT sign; |
240 | 0 | FIXP_DBL result, temp; |
241 | | |
242 | | /* SNR of fixp_atan() = 56 dB */ |
243 | 0 | FIXP_DBL P281 = (FIXP_DBL)0x00013000; // 0.281 in q18 |
244 | 0 | FIXP_DBL ONEP571 = (FIXP_DBL)0x6487ef00; // 1.571 in q30 |
245 | |
|
246 | 0 | if (x < FIXP_DBL(0)) { |
247 | 0 | sign = 1; |
248 | 0 | x = -x; |
249 | 0 | } else { |
250 | 0 | sign = 0; |
251 | 0 | } |
252 | 0 | FDK_ASSERT(FL2FXCONST_DBL(1.0 / 64.0) == Q(Q_ATANINP)); |
253 | | /* calc of arctan */ |
254 | 0 | if (x < FL2FXCONST_DBL(1.0 / 64.0)) |
255 | | /* |
256 | | Chebyshev polynomial approximation of atan(x) |
257 | | 5th-order approximation: atan(x) = a1*x + a2*x^3 + a3*x^5 = x(a1 + x^2*(a2 + |
258 | | a3*x^2)); a1 = 0.9949493661166540f, a2 = 0.2870606355326520f, a3 = |
259 | | 0.0780371764464410f; 7th-order approximation: atan(x) = a1*x + a2*x^3 + |
260 | | a3*x^5 + a3*x^7 = x(a1 + x^2*(a2 + x^2*(a3 + a4*x^2))); a1 = |
261 | | 0.9991334482227801, a2 = -0.3205332923816640, a3 = 0.1449824901444650, a4 = |
262 | | -0.0382544649702990; 7th-order approximation in use (the most accurate |
263 | | solution) |
264 | | */ |
265 | 0 | { |
266 | 0 | x <<= ATI_SF; |
267 | 0 | FIXP_DBL x2 = fPow2(x); |
268 | 0 | temp = fMultAddDiv2((FL2FXCONST_DBL(0.1449824901444650f) >> 1), x2, |
269 | 0 | FL2FXCONST_DBL(-0.0382544649702990)); |
270 | 0 | temp = fMultAddDiv2((FL2FXCONST_DBL(-0.3205332923816640f) >> 2), x2, temp); |
271 | 0 | temp = fMultAddDiv2((FL2FXCONST_DBL(0.9991334482227801f) >> 3), x2, temp); |
272 | 0 | result = fMult(x, (temp << 2)); |
273 | 0 | } else if (x < FL2FXCONST_DBL(1.28 / 64.0)) { |
274 | 0 | FIXP_DBL delta_fix; |
275 | 0 | FIXP_DBL PI_BY_4 = FL2FXCONST_DBL(3.1415926 / 4.0) >> 1; /* pi/4 in q30 */ |
276 | |
|
277 | 0 | delta_fix = (x - FL2FXCONST_DBL(1.0 / 64.0)) << 5; /* q30 */ |
278 | 0 | result = PI_BY_4 + (delta_fix >> 1) - (fPow2Div2(delta_fix)); |
279 | 0 | } else { |
280 | | /* Other approximation for |x| > 1.28 */ |
281 | 0 | INT res_e; |
282 | |
|
283 | 0 | temp = fPow2Div2(x); /* q25 * q25 - (DFRACT_BITS-1) - 1 = q18 */ |
284 | 0 | temp = temp + P281; /* q18 + q18 = q18 */ |
285 | 0 | result = fDivNorm(x, temp, &res_e); |
286 | 0 | result = scaleValue(result, |
287 | 0 | (Q_ATANOUT - Q_ATANINP + 18 - DFRACT_BITS + 1) + res_e); |
288 | 0 | result = ONEP571 - result; /* q30 + q30 = q30 */ |
289 | 0 | } |
290 | 0 | if (sign) { |
291 | 0 | result = -result; |
292 | 0 | } |
293 | |
|
294 | 0 | return (result); |
295 | 0 | } |
296 | | |
297 | | #include "FDK_tools_rom.h" |
298 | | |
299 | 4.33M | FIXP_DBL fixp_cos(FIXP_DBL x, int scale) { |
300 | 4.33M | FIXP_DBL residual, error, sine, cosine; |
301 | | |
302 | 4.33M | residual = fixp_sin_cos_residual_inline(x, scale, &sine, &cosine); |
303 | 4.33M | error = fMult(sine, residual); |
304 | | |
305 | 4.33M | #ifdef SINETABLE_16BIT |
306 | 4.33M | return cosine - error; |
307 | | #else |
308 | | /* Undo downscaling by 1 which was done at fixp_sin_cos_residual_inline */ |
309 | | return SATURATE_LEFT_SHIFT(cosine - error, 1, DFRACT_BITS); |
310 | | #endif |
311 | 4.33M | } |
312 | | |
313 | 0 | FIXP_DBL fixp_sin(FIXP_DBL x, int scale) { |
314 | 0 | FIXP_DBL residual, error, sine, cosine; |
315 | |
|
316 | 0 | residual = fixp_sin_cos_residual_inline(x, scale, &sine, &cosine); |
317 | 0 | error = fMult(cosine, residual); |
318 | |
|
319 | 0 | #ifdef SINETABLE_16BIT |
320 | 0 | return sine + error; |
321 | | #else |
322 | | return SATURATE_LEFT_SHIFT(sine + error, 1, DFRACT_BITS); |
323 | | #endif |
324 | 0 | } |
325 | | |
326 | 0 | void fixp_cos_sin(FIXP_DBL x, int scale, FIXP_DBL *cos, FIXP_DBL *sin) { |
327 | 0 | FIXP_DBL residual, error0, error1, sine, cosine; |
328 | |
|
329 | 0 | residual = fixp_sin_cos_residual_inline(x, scale, &sine, &cosine); |
330 | 0 | error0 = fMult(sine, residual); |
331 | 0 | error1 = fMult(cosine, residual); |
332 | |
|
333 | 0 | #ifdef SINETABLE_16BIT |
334 | 0 | *cos = cosine - error0; |
335 | 0 | *sin = sine + error1; |
336 | | #else |
337 | | *cos = SATURATE_LEFT_SHIFT(cosine - error0, 1, DFRACT_BITS); |
338 | | *sin = SATURATE_LEFT_SHIFT(sine + error1, 1, DFRACT_BITS); |
339 | | #endif |
340 | 0 | } |