/src/aac/libSACenc/src/sacenc_vectorfunctions.cpp
Line | Count | Source |
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 | | /*********************** MPEG surround encoder library ************************* |
96 | | |
97 | | Author(s): Josef Hoepfl |
98 | | |
99 | | Description: Encoder Library Interface |
100 | | vector functions |
101 | | |
102 | | *******************************************************************************/ |
103 | | |
104 | | /***************************************************************************** |
105 | | \file |
106 | | This file contains vector functions |
107 | | ******************************************************************************/ |
108 | | |
109 | | /* Includes ******************************************************************/ |
110 | | #include "sacenc_vectorfunctions.h" |
111 | | |
112 | | /* Defines *******************************************************************/ |
113 | | |
114 | | /* Data Types ****************************************************************/ |
115 | | |
116 | | /* Constants *****************************************************************/ |
117 | | |
118 | | /* Function / Class Declarations *********************************************/ |
119 | | |
120 | | /* Function / Class Definition ***********************************************/ |
121 | | |
122 | | FIXP_DBL sumUpCplxPow2(const FIXP_DPK *const x, const INT scaleMode, |
123 | | const INT inScaleFactor, INT *const outScaleFactor, |
124 | 0 | const INT n) { |
125 | 0 | int i, cs; |
126 | |
|
127 | 0 | if (scaleMode == SUM_UP_DYNAMIC_SCALE) { |
128 | | /* calculate headroom */ |
129 | 0 | FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); |
130 | 0 | for (i = 0; i < n; i++) { |
131 | 0 | maxVal |= fAbs(x[i].v.re); |
132 | 0 | maxVal |= fAbs(x[i].v.im); |
133 | 0 | } |
134 | 0 | cs = inScaleFactor - fixMax(0, CntLeadingZeros(maxVal) - 1); |
135 | 0 | } else { |
136 | 0 | cs = inScaleFactor; |
137 | 0 | } |
138 | | |
139 | | /* consider scaling of energy and scaling in fPow2Div2 and addition */ |
140 | 0 | *outScaleFactor = 2 * cs + 2; |
141 | | |
142 | | /* make sure that the scalefactor is in the range of -(DFRACT_BITS-1), ... , |
143 | | * (DFRACT_BITS-1) */ |
144 | 0 | cs = fixMax(fixMin(cs, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); |
145 | | |
146 | | /* sum up complex energy samples */ |
147 | 0 | FIXP_DBL re, im, sum; |
148 | |
|
149 | 0 | re = im = sum = FL2FXCONST_DBL(0.0); |
150 | 0 | if (cs < 0) { |
151 | 0 | cs = -cs; |
152 | 0 | for (i = 0; i < n; i++) { |
153 | 0 | re += fPow2Div2(x[i].v.re << cs); |
154 | 0 | im += fPow2Div2(x[i].v.im << cs); |
155 | 0 | } |
156 | 0 | } else { |
157 | 0 | cs = 2 * cs; |
158 | 0 | for (i = 0; i < n; i++) { |
159 | 0 | re += fPow2Div2(x[i].v.re) >> cs; |
160 | 0 | im += fPow2Div2(x[i].v.im) >> cs; |
161 | 0 | } |
162 | 0 | } |
163 | |
|
164 | 0 | sum = (re >> 1) + (im >> 1); |
165 | |
|
166 | 0 | return (sum); |
167 | 0 | } |
168 | | |
169 | | FIXP_DBL sumUpCplxPow2Dim2(const FIXP_DPK *const *const x, const INT scaleMode, |
170 | | const INT inScaleFactor, INT *const outScaleFactor, |
171 | | const INT sDim1, const INT nDim1, const INT sDim2, |
172 | 0 | const INT nDim2) { |
173 | 0 | int i, j, cs; |
174 | |
|
175 | 0 | if (scaleMode == SUM_UP_DYNAMIC_SCALE) { |
176 | | /* calculate headroom */ |
177 | 0 | FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); |
178 | 0 | for (i = sDim1; i < nDim1; i++) { |
179 | 0 | for (j = sDim2; j < nDim2; j++) { |
180 | 0 | maxVal |= fAbs(x[i][j].v.re); |
181 | 0 | maxVal |= fAbs(x[i][j].v.im); |
182 | 0 | } |
183 | 0 | } |
184 | 0 | cs = inScaleFactor - fixMax(0, CntLeadingZeros(maxVal) - 1); |
185 | 0 | } else { |
186 | 0 | cs = inScaleFactor; |
187 | 0 | } |
188 | | |
189 | | /* consider scaling of energy and scaling in fPow2Div2 and addition */ |
190 | 0 | *outScaleFactor = 2 * cs + 2; |
191 | | |
192 | | /* make sure that the scalefactor is in the range of -(DFRACT_BITS-1), ... , |
193 | | * (DFRACT_BITS-1) */ |
194 | 0 | cs = fixMax(fixMin(cs, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); |
195 | | |
196 | | /* sum up complex energy samples */ |
197 | 0 | FIXP_DBL re, im, sum; |
198 | |
|
199 | 0 | re = im = sum = FL2FXCONST_DBL(0.0); |
200 | 0 | if (cs < 0) { |
201 | 0 | cs = -cs; |
202 | 0 | for (i = sDim1; i < nDim1; i++) { |
203 | 0 | for (j = sDim2; j < nDim2; j++) { |
204 | 0 | re += fPow2Div2(x[i][j].v.re << cs); |
205 | 0 | im += fPow2Div2(x[i][j].v.im << cs); |
206 | 0 | } |
207 | 0 | } |
208 | 0 | } else { |
209 | 0 | cs = 2 * cs; |
210 | 0 | for (i = sDim1; i < nDim1; i++) { |
211 | 0 | for (j = sDim2; j < nDim2; j++) { |
212 | 0 | re += fPow2Div2(x[i][j].v.re) >> cs; |
213 | 0 | im += fPow2Div2(x[i][j].v.im) >> cs; |
214 | 0 | } |
215 | 0 | } |
216 | 0 | } |
217 | |
|
218 | 0 | sum = (re >> 1) + (im >> 1); |
219 | |
|
220 | 0 | return (sum); |
221 | 0 | } |
222 | | |
223 | 0 | void copyCplxVec(FIXP_DPK *const Z, const FIXP_DPK *const X, const INT n) { |
224 | 0 | FDKmemmove(Z, X, sizeof(FIXP_DPK) * n); |
225 | 0 | } |
226 | | |
227 | 0 | void setCplxVec(FIXP_DPK *const Z, const FIXP_DBL a, const INT n) { |
228 | 0 | int i; |
229 | |
|
230 | 0 | for (i = 0; i < n; i++) { |
231 | 0 | Z[i].v.re = a; |
232 | 0 | Z[i].v.im = a; |
233 | 0 | } |
234 | 0 | } |
235 | | |
236 | | void cplx_cplxScalarProduct(FIXP_DPK *const Z, const FIXP_DPK *const *const X, |
237 | | const FIXP_DPK *const *const Y, const INT scaleX, |
238 | | const INT scaleY, INT *const scaleZ, |
239 | | const INT sDim1, const INT nDim1, const INT sDim2, |
240 | 0 | const INT nDim2) { |
241 | 0 | int i, j, sx, sy; |
242 | 0 | FIXP_DBL xre, yre, xim, yim, re, im; |
243 | | |
244 | | /* make sure that the scalefactor is in the range of -(DFRACT_BITS-1), ... , |
245 | | * (DFRACT_BITS-1) */ |
246 | 0 | sx = fixMax(fixMin(scaleX, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); |
247 | 0 | sy = fixMax(fixMin(scaleY, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); |
248 | | |
249 | | /* consider scaling of energy and scaling in fMultDiv2 and shift of result |
250 | | * values */ |
251 | 0 | *scaleZ = sx + sy + 2; |
252 | |
|
253 | 0 | re = (FIXP_DBL)0; |
254 | 0 | im = (FIXP_DBL)0; |
255 | 0 | if ((sx < 0) && (sy < 0)) { |
256 | 0 | sx = -sx; |
257 | 0 | sy = -sy; |
258 | 0 | for (i = sDim1; i < nDim1; i++) { |
259 | 0 | for (j = sDim2; j < nDim2; j++) { |
260 | 0 | xre = X[i][j].v.re << sx; |
261 | 0 | xim = X[i][j].v.im << sx; |
262 | 0 | yre = Y[i][j].v.re << sy; |
263 | 0 | yim = Y[i][j].v.im << sy; |
264 | 0 | re += fMultDiv2(xre, yre) + fMultDiv2(xim, yim); |
265 | 0 | im += fMultDiv2(xim, yre) - fMultDiv2(xre, yim); |
266 | 0 | } |
267 | 0 | } |
268 | 0 | } else if ((sx >= 0) && (sy >= 0)) { |
269 | 0 | for (i = sDim1; i < nDim1; i++) { |
270 | 0 | for (j = sDim2; j < nDim2; j++) { |
271 | 0 | xre = X[i][j].v.re; |
272 | 0 | xim = X[i][j].v.im; |
273 | 0 | yre = Y[i][j].v.re; |
274 | 0 | yim = Y[i][j].v.im; |
275 | 0 | re += (fMultDiv2(xre, yre) + fMultDiv2(xim, yim)) >> (sx + sy); |
276 | 0 | im += (fMultDiv2(xim, yre) - fMultDiv2(xre, yim)) >> (sx + sy); |
277 | 0 | } |
278 | 0 | } |
279 | 0 | } else if ((sx < 0) && (sy >= 0)) { |
280 | 0 | sx = -sx; |
281 | 0 | for (i = sDim1; i < nDim1; i++) { |
282 | 0 | for (j = sDim2; j < nDim2; j++) { |
283 | 0 | xre = X[i][j].v.re << sx; |
284 | 0 | xim = X[i][j].v.im << sx; |
285 | 0 | yre = Y[i][j].v.re; |
286 | 0 | yim = Y[i][j].v.im; |
287 | 0 | re += (fMultDiv2(xre, yre) + fMultDiv2(xim, yim)) >> sy; |
288 | 0 | im += (fMultDiv2(xim, yre) - fMultDiv2(xre, yim)) >> sy; |
289 | 0 | } |
290 | 0 | } |
291 | 0 | } else { |
292 | 0 | sy = -sy; |
293 | 0 | for (i = sDim1; i < nDim1; i++) { |
294 | 0 | for (j = sDim2; j < nDim2; j++) { |
295 | 0 | xre = X[i][j].v.re; |
296 | 0 | xim = X[i][j].v.im; |
297 | 0 | yre = Y[i][j].v.re << sy; |
298 | 0 | yim = Y[i][j].v.im << sy; |
299 | 0 | re += (fMultDiv2(xre, yre) + fMultDiv2(xim, yim)) >> sx; |
300 | 0 | im += (fMultDiv2(xim, yre) - fMultDiv2(xre, yim)) >> sx; |
301 | 0 | } |
302 | 0 | } |
303 | 0 | } |
304 | |
|
305 | 0 | Z->v.re = re >> 1; |
306 | 0 | Z->v.im = im >> 1; |
307 | 0 | } |
308 | | |
309 | | void FDKcalcCorrelationVec(FIXP_DBL *const z, const FIXP_DBL *const pr12, |
310 | | const FIXP_DBL *const p1, const FIXP_DBL *const p2, |
311 | 0 | const INT n) { |
312 | 0 | int i, s; |
313 | 0 | FIXP_DBL p12, cor; |
314 | | |
315 | | /* correlation */ |
316 | 0 | for (i = 0; i < n; i++) { |
317 | 0 | p12 = fMult(p1[i], p2[i]); |
318 | 0 | if (p12 > FL2FXCONST_DBL(0.0f)) { |
319 | 0 | p12 = invSqrtNorm2(p12, &s); |
320 | 0 | cor = fMult(pr12[i], p12); |
321 | 0 | z[i] = SATURATE_LEFT_SHIFT(cor, s, DFRACT_BITS); |
322 | 0 | } else { |
323 | 0 | z[i] = (FIXP_DBL)MAXVAL_DBL; |
324 | 0 | } |
325 | 0 | } |
326 | 0 | } |
327 | | |
328 | | void calcCoherenceVec(FIXP_DBL *const z, const FIXP_DBL *const p12r, |
329 | | const FIXP_DBL *const p12i, const FIXP_DBL *const p1, |
330 | | const FIXP_DBL *const p2, const INT scaleP12, |
331 | 0 | const INT scaleP, const INT n) { |
332 | 0 | int i, s, s1, s2; |
333 | 0 | FIXP_DBL coh, p12, p12ri; |
334 | |
|
335 | 0 | for (i = 0; i < n; i++) { |
336 | 0 | s2 = fixMin(fixMax(0, CountLeadingBits(p12r[i]) - 1), |
337 | 0 | fixMax(0, CountLeadingBits(p12i[i]) - 1)); |
338 | 0 | p12ri = sqrtFixp(fPow2Div2(p12r[i] << s2) + fPow2Div2(p12i[i] << s2)); |
339 | 0 | s1 = fixMin(fixMax(0, CountLeadingBits(p1[i]) - 1), |
340 | 0 | fixMax(0, CountLeadingBits(p2[i]) - 1)); |
341 | 0 | p12 = fMultDiv2(p1[i] << s1, p2[i] << s1); |
342 | |
|
343 | 0 | if (p12 > FL2FXCONST_DBL(0.0f)) { |
344 | 0 | p12 = invSqrtNorm2(p12, &s); |
345 | 0 | coh = fMult(p12ri, p12); |
346 | 0 | s = fixMax(fixMin((scaleP12 - scaleP + s + s1 - s2), DFRACT_BITS - 1), |
347 | 0 | -(DFRACT_BITS - 1)); |
348 | 0 | if (s < 0) { |
349 | 0 | z[i] = coh >> (-s); |
350 | 0 | } else { |
351 | 0 | z[i] = SATURATE_LEFT_SHIFT(coh, s, DFRACT_BITS); |
352 | 0 | } |
353 | 0 | } else { |
354 | 0 | z[i] = (FIXP_DBL)MAXVAL_DBL; |
355 | 0 | } |
356 | 0 | } |
357 | 0 | } |
358 | | |
359 | | void addWeightedCplxVec(FIXP_DPK *const *const Z, const FIXP_DBL *const a, |
360 | | const FIXP_DPK *const *const X, const FIXP_DBL *const b, |
361 | | const FIXP_DPK *const *const Y, const INT scale, |
362 | | INT *const scaleCh1, const INT scaleCh2, |
363 | | const UCHAR *const pParameterBand2HybridBandOffset, |
364 | | const INT nParameterBands, const INT nTimeSlots, |
365 | 0 | const INT startTimeSlot) { |
366 | 0 | int pb, j, i; |
367 | 0 | int cs, s1, s2; |
368 | | |
369 | | /* determine maximum scale of both channels */ |
370 | 0 | cs = fixMax(*scaleCh1, scaleCh2); |
371 | 0 | s1 = cs - (*scaleCh1); |
372 | 0 | s2 = cs - scaleCh2; |
373 | | |
374 | | /* scalefactor 1 is updated with common scale of channel 1 and channel2 */ |
375 | 0 | *scaleCh1 = cs; |
376 | | |
377 | | /* scale of a and b; additional scale for fMultDiv2() */ |
378 | 0 | for (j = 0, pb = 0; pb < nParameterBands; pb++) { |
379 | 0 | FIXP_DBL aPb, bPb; |
380 | 0 | aPb = a[pb], bPb = b[pb]; |
381 | 0 | for (; j < pParameterBand2HybridBandOffset[pb]; j++) { |
382 | 0 | for (i = startTimeSlot; i < nTimeSlots; i++) { |
383 | 0 | Z[j][i].v.re = ((fMultDiv2(aPb, X[j][i].v.re) >> s1) + |
384 | 0 | (fMultDiv2(bPb, Y[j][i].v.re) >> s2)) |
385 | 0 | << (scale + 1); |
386 | 0 | Z[j][i].v.im = ((fMultDiv2(aPb, X[j][i].v.im) >> s1) + |
387 | 0 | (fMultDiv2(bPb, Y[j][i].v.im) >> s2)) |
388 | 0 | << (scale + 1); |
389 | 0 | } |
390 | 0 | } |
391 | 0 | } |
392 | 0 | } |
393 | | |
394 | | void FDKcalcPbScaleFactor(const FIXP_DPK *const *const x, |
395 | | const UCHAR *const pParameterBand2HybridBandOffset, |
396 | | INT *const outScaleFactor, const INT startTimeSlot, |
397 | 0 | const INT nTimeSlots, const INT nParamBands) { |
398 | 0 | int i, j, pb; |
399 | | |
400 | | /* calculate headroom */ |
401 | 0 | for (j = 0, pb = 0; pb < nParamBands; pb++) { |
402 | 0 | FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); |
403 | 0 | for (; j < pParameterBand2HybridBandOffset[pb]; j++) { |
404 | 0 | for (i = startTimeSlot; i < nTimeSlots; i++) { |
405 | 0 | maxVal |= fAbs(x[i][j].v.re); |
406 | 0 | maxVal |= fAbs(x[i][j].v.im); |
407 | 0 | } |
408 | 0 | } |
409 | 0 | outScaleFactor[pb] = -fixMax(0, CntLeadingZeros(maxVal) - 1); |
410 | 0 | } |
411 | 0 | } |
412 | | |
413 | | INT FDKcalcScaleFactor(const FIXP_DBL *const x, const FIXP_DBL *const y, |
414 | 0 | const INT n) { |
415 | 0 | int i; |
416 | | |
417 | | /* calculate headroom */ |
418 | 0 | FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); |
419 | 0 | if (x != NULL) { |
420 | 0 | for (i = 0; i < n; i++) { |
421 | 0 | maxVal |= fAbs(x[i]); |
422 | 0 | } |
423 | 0 | } |
424 | |
|
425 | 0 | if (y != NULL) { |
426 | 0 | for (i = 0; i < n; i++) { |
427 | 0 | maxVal |= fAbs(y[i]); |
428 | 0 | } |
429 | 0 | } |
430 | |
|
431 | 0 | if (maxVal == (FIXP_DBL)0) |
432 | 0 | return (-(DFRACT_BITS - 1)); |
433 | 0 | else |
434 | 0 | return (-CountLeadingBits(maxVal)); |
435 | 0 | } |
436 | | |
437 | | INT FDKcalcScaleFactorDPK(const FIXP_DPK *RESTRICT x, const INT startBand, |
438 | 0 | const INT bands) { |
439 | 0 | INT qs, clz; |
440 | 0 | FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); |
441 | |
|
442 | 0 | for (qs = startBand; qs < bands; qs++) { |
443 | 0 | maxVal |= fAbs(x[qs].v.re); |
444 | 0 | maxVal |= fAbs(x[qs].v.im); |
445 | 0 | } |
446 | |
|
447 | 0 | clz = -fixMax(0, CntLeadingZeros(maxVal) - 1); |
448 | |
|
449 | 0 | return (clz); |
450 | 0 | } |