/src/aac/libSBRenc/src/ps_encode.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 | | /**************************** SBR encoder library ****************************** |
96 | | |
97 | | Author(s): M. Neuendorf, N. Rettelbach, M. Multrus |
98 | | |
99 | | Description: PS parameter extraction, encoding |
100 | | |
101 | | *******************************************************************************/ |
102 | | |
103 | | /*! |
104 | | \file |
105 | | \brief PS parameter extraction, encoding functions $Revision: 96441 $ |
106 | | */ |
107 | | |
108 | | #include "ps_main.h" |
109 | | #include "ps_encode.h" |
110 | | #include "qmf.h" |
111 | | #include "sbr_misc.h" |
112 | | #include "sbrenc_ram.h" |
113 | | |
114 | | #include "genericStds.h" |
115 | | |
116 | | inline void FDKsbrEnc_addFIXP_DBL(const FIXP_DBL *X, const FIXP_DBL *Y, |
117 | 0 | FIXP_DBL *Z, INT n) { |
118 | 0 | for (INT i = 0; i < n; i++) Z[i] = (X[i] >> 1) + (Y[i] >> 1); |
119 | 0 | } |
120 | | |
121 | | #define LOG10_2_10 3.01029995664f /* 10.0f*log10(2.f) */ |
122 | | |
123 | | static const INT |
124 | | iidGroupBordersLoRes[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES + 1] = { |
125 | | 0, 1, 2, 3, 4, 5, /* 6 subqmf subbands - 0th qmf subband */ |
126 | | 6, 7, /* 2 subqmf subbands - 1st qmf subband */ |
127 | | 8, 9, /* 2 subqmf subbands - 2nd qmf subband */ |
128 | | 10, 11, 12, 13, 14, 15, 16, 18, 21, 25, 30, 42, 71}; |
129 | | |
130 | | static const UCHAR |
131 | | iidGroupWidthLdLoRes[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES] = { |
132 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 3, 4, 5}; |
133 | | |
134 | | static const INT subband2parameter20[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES] = |
135 | | {1, 0, 0, 1, 2, 3, /* 6 subqmf subbands - 0th qmf subband */ |
136 | | 4, 5, /* 2 subqmf subbands - 1st qmf subband */ |
137 | | 6, 7, /* 2 subqmf subbands - 2nd qmf subband */ |
138 | | 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; |
139 | | |
140 | | typedef enum { |
141 | | MAX_TIME_DIFF_FRAMES = 20, |
142 | | MAX_PS_NOHEADER_CNT = 10, |
143 | | MAX_NOENV_CNT = 10, |
144 | | DO_NOT_USE_THIS_MODE = 0x7FFFFF |
145 | | } __PS_CONSTANTS; |
146 | | |
147 | | static const FIXP_DBL iidQuant_fx[15] = { |
148 | | (FIXP_DBL)0xce000000, (FIXP_DBL)0xdc000000, (FIXP_DBL)0xe4000000, |
149 | | (FIXP_DBL)0xec000000, (FIXP_DBL)0xf2000000, (FIXP_DBL)0xf8000000, |
150 | | (FIXP_DBL)0xfc000000, (FIXP_DBL)0x00000000, (FIXP_DBL)0x04000000, |
151 | | (FIXP_DBL)0x08000000, (FIXP_DBL)0x0e000000, (FIXP_DBL)0x14000000, |
152 | | (FIXP_DBL)0x1c000000, (FIXP_DBL)0x24000000, (FIXP_DBL)0x32000000}; |
153 | | |
154 | | static const FIXP_DBL iidQuantFine_fx[31] = { |
155 | | (FIXP_DBL)0x9c000001, (FIXP_DBL)0xa6000001, (FIXP_DBL)0xb0000001, |
156 | | (FIXP_DBL)0xba000001, (FIXP_DBL)0xc4000000, (FIXP_DBL)0xce000000, |
157 | | (FIXP_DBL)0xd4000000, (FIXP_DBL)0xda000000, (FIXP_DBL)0xe0000000, |
158 | | (FIXP_DBL)0xe6000000, (FIXP_DBL)0xec000000, (FIXP_DBL)0xf0000000, |
159 | | (FIXP_DBL)0xf4000000, (FIXP_DBL)0xf8000000, (FIXP_DBL)0xfc000000, |
160 | | (FIXP_DBL)0x00000000, (FIXP_DBL)0x04000000, (FIXP_DBL)0x08000000, |
161 | | (FIXP_DBL)0x0c000000, (FIXP_DBL)0x10000000, (FIXP_DBL)0x14000000, |
162 | | (FIXP_DBL)0x1a000000, (FIXP_DBL)0x20000000, (FIXP_DBL)0x26000000, |
163 | | (FIXP_DBL)0x2c000000, (FIXP_DBL)0x32000000, (FIXP_DBL)0x3c000000, |
164 | | (FIXP_DBL)0x45ffffff, (FIXP_DBL)0x4fffffff, (FIXP_DBL)0x59ffffff, |
165 | | (FIXP_DBL)0x63ffffff}; |
166 | | |
167 | | static const FIXP_DBL iccQuant[8] = { |
168 | | (FIXP_DBL)0x7fffffff, (FIXP_DBL)0x77ef9d7f, (FIXP_DBL)0x6babc97f, |
169 | | (FIXP_DBL)0x4ceaf27f, (FIXP_DBL)0x2f0ed3c0, (FIXP_DBL)0x00000000, |
170 | | (FIXP_DBL)0xb49ba601, (FIXP_DBL)0x80000000}; |
171 | | |
172 | 0 | static FDK_PSENC_ERROR InitPSData(HANDLE_PS_DATA hPsData) { |
173 | 0 | FDK_PSENC_ERROR error = PSENC_OK; |
174 | |
|
175 | 0 | if (hPsData == NULL) { |
176 | 0 | error = PSENC_INVALID_HANDLE; |
177 | 0 | } else { |
178 | 0 | int i, env; |
179 | 0 | FDKmemclear(hPsData, sizeof(PS_DATA)); |
180 | |
|
181 | 0 | for (i = 0; i < PS_MAX_BANDS; i++) { |
182 | 0 | hPsData->iidIdxLast[i] = 0; |
183 | 0 | hPsData->iccIdxLast[i] = 0; |
184 | 0 | } |
185 | |
|
186 | 0 | hPsData->iidEnable = hPsData->iidEnableLast = 0; |
187 | 0 | hPsData->iccEnable = hPsData->iccEnableLast = 0; |
188 | 0 | hPsData->iidQuantMode = hPsData->iidQuantModeLast = PS_IID_RES_COARSE; |
189 | 0 | hPsData->iccQuantMode = hPsData->iccQuantModeLast = PS_ICC_ROT_A; |
190 | |
|
191 | 0 | for (env = 0; env < PS_MAX_ENVELOPES; env++) { |
192 | 0 | hPsData->iccDiffMode[env] = PS_DELTA_FREQ; |
193 | 0 | hPsData->iccDiffMode[env] = PS_DELTA_FREQ; |
194 | |
|
195 | 0 | for (i = 0; i < PS_MAX_BANDS; i++) { |
196 | 0 | hPsData->iidIdx[env][i] = 0; |
197 | 0 | hPsData->iccIdx[env][i] = 0; |
198 | 0 | } |
199 | 0 | } |
200 | |
|
201 | 0 | hPsData->nEnvelopesLast = 0; |
202 | |
|
203 | 0 | hPsData->headerCnt = MAX_PS_NOHEADER_CNT; |
204 | 0 | hPsData->iidTimeCnt = MAX_TIME_DIFF_FRAMES; |
205 | 0 | hPsData->iccTimeCnt = MAX_TIME_DIFF_FRAMES; |
206 | 0 | hPsData->noEnvCnt = MAX_NOENV_CNT; |
207 | 0 | } |
208 | |
|
209 | 0 | return error; |
210 | 0 | } |
211 | | |
212 | | static FIXP_DBL quantizeCoef(const FIXP_DBL *RESTRICT input, const INT nBands, |
213 | | const FIXP_DBL *RESTRICT quantTable, |
214 | | const INT idxOffset, const INT nQuantSteps, |
215 | 0 | INT *RESTRICT quantOut) { |
216 | 0 | INT idx, band; |
217 | 0 | FIXP_DBL quantErr = FL2FXCONST_DBL(0.f); |
218 | |
|
219 | 0 | for (band = 0; band < nBands; band++) { |
220 | 0 | for (idx = 0; idx < nQuantSteps - 1; idx++) { |
221 | 0 | if (fixp_abs((input[band] >> 1) - (quantTable[idx + 1] >> 1)) > |
222 | 0 | fixp_abs((input[band] >> 1) - (quantTable[idx] >> 1))) { |
223 | 0 | break; |
224 | 0 | } |
225 | 0 | } |
226 | 0 | quantErr += (fixp_abs(input[band] - quantTable[idx]) >> |
227 | 0 | PS_QUANT_SCALE); /* don't scale before subtraction; diff |
228 | | smaller (64-25)/64 */ |
229 | 0 | quantOut[band] = idx - idxOffset; |
230 | 0 | } |
231 | |
|
232 | 0 | return quantErr; |
233 | 0 | } |
234 | | |
235 | 0 | static INT getICCMode(const INT nBands, const INT rotType) { |
236 | 0 | INT mode = 0; |
237 | |
|
238 | 0 | switch (nBands) { |
239 | 0 | case PS_BANDS_COARSE: |
240 | 0 | mode = PS_RES_COARSE; |
241 | 0 | break; |
242 | 0 | case PS_BANDS_MID: |
243 | 0 | mode = PS_RES_MID; |
244 | 0 | break; |
245 | 0 | default: |
246 | 0 | mode = 0; |
247 | 0 | } |
248 | 0 | if (rotType == PS_ICC_ROT_B) { |
249 | 0 | mode += 3; |
250 | 0 | } |
251 | |
|
252 | 0 | return mode; |
253 | 0 | } |
254 | | |
255 | 0 | static INT getIIDMode(const INT nBands, const INT iidRes) { |
256 | 0 | INT mode = 0; |
257 | |
|
258 | 0 | switch (nBands) { |
259 | 0 | case PS_BANDS_COARSE: |
260 | 0 | mode = PS_RES_COARSE; |
261 | 0 | break; |
262 | 0 | case PS_BANDS_MID: |
263 | 0 | mode = PS_RES_MID; |
264 | 0 | break; |
265 | 0 | default: |
266 | 0 | mode = 0; |
267 | 0 | break; |
268 | 0 | } |
269 | | |
270 | 0 | if (iidRes == PS_IID_RES_FINE) { |
271 | 0 | mode += 3; |
272 | 0 | } |
273 | |
|
274 | 0 | return mode; |
275 | 0 | } |
276 | | |
277 | | static INT envelopeReducible(FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS], |
278 | | FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS], |
279 | 0 | INT psBands, INT nEnvelopes) { |
280 | 0 | #define THRESH_SCALE 7 |
281 | |
|
282 | 0 | INT reducible = 1; /* true */ |
283 | 0 | INT e = 0, b = 0; |
284 | 0 | FIXP_DBL dIid = FL2FXCONST_DBL(0.f); |
285 | 0 | FIXP_DBL dIcc = FL2FXCONST_DBL(0.f); |
286 | |
|
287 | 0 | FIXP_DBL iidErrThreshold, iccErrThreshold; |
288 | 0 | FIXP_DBL iidMeanError, iccMeanError; |
289 | | |
290 | | /* square values to prevent sqrt, |
291 | | multiply bands to prevent division; bands shifted DFRACT_BITS instead |
292 | | (DFRACT_BITS-1) because fMultDiv2 used*/ |
293 | 0 | iidErrThreshold = |
294 | 0 | fMultDiv2(FL2FXCONST_DBL(6.5f * 6.5f / (IID_SCALE_FT * IID_SCALE_FT)), |
295 | 0 | (FIXP_DBL)(psBands << ((DFRACT_BITS)-THRESH_SCALE))); |
296 | 0 | iccErrThreshold = |
297 | 0 | fMultDiv2(FL2FXCONST_DBL(0.75f * 0.75f), |
298 | 0 | (FIXP_DBL)(psBands << ((DFRACT_BITS)-THRESH_SCALE))); |
299 | |
|
300 | 0 | if (nEnvelopes <= 1) { |
301 | 0 | reducible = 0; |
302 | 0 | } else { |
303 | | /* mean error criterion */ |
304 | 0 | for (e = 0; (e < nEnvelopes / 2) && (reducible != 0); e++) { |
305 | 0 | iidMeanError = iccMeanError = FL2FXCONST_DBL(0.f); |
306 | 0 | for (b = 0; b < psBands; b++) { |
307 | 0 | dIid = (iid[2 * e][b] >> 1) - |
308 | 0 | (iid[2 * e + 1][b] >> 1); /* scale 1 bit; squared -> 2 bit */ |
309 | 0 | dIcc = (icc[2 * e][b] >> 1) - (icc[2 * e + 1][b] >> 1); |
310 | 0 | iidMeanError += fPow2Div2(dIid) >> (5 - 1); /* + (bands=20) scale = 5 */ |
311 | 0 | iccMeanError += fPow2Div2(dIcc) >> (5 - 1); |
312 | 0 | } /* --> scaling = 7 bit = THRESH_SCALE !! */ |
313 | | |
314 | | /* instead sqrt values are squared! |
315 | | instead of division, multiply threshold with psBands |
316 | | scaling necessary!! */ |
317 | | |
318 | | /* quit as soon as threshold is reached */ |
319 | 0 | if ((iidMeanError > (iidErrThreshold)) || |
320 | 0 | (iccMeanError > (iccErrThreshold))) { |
321 | 0 | reducible = 0; |
322 | 0 | } |
323 | 0 | } |
324 | 0 | } /* nEnvelopes != 1 */ |
325 | |
|
326 | 0 | return reducible; |
327 | 0 | } |
328 | | |
329 | | static void processIidData(PS_DATA *psData, |
330 | | FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS], |
331 | | const INT psBands, const INT nEnvelopes, |
332 | 0 | const FIXP_DBL quantErrorThreshold) { |
333 | 0 | INT iidIdxFine[PS_MAX_ENVELOPES][PS_MAX_BANDS]; |
334 | 0 | INT iidIdxCoarse[PS_MAX_ENVELOPES][PS_MAX_BANDS]; |
335 | |
|
336 | 0 | FIXP_DBL errIID = FL2FXCONST_DBL(0.f); |
337 | 0 | FIXP_DBL errIIDFine = FL2FXCONST_DBL(0.f); |
338 | 0 | INT bitsIidFreq = 0; |
339 | 0 | INT bitsIidTime = 0; |
340 | 0 | INT bitsFineTot = 0; |
341 | 0 | INT bitsCoarseTot = 0; |
342 | 0 | INT error = 0; |
343 | 0 | INT env, band; |
344 | 0 | INT diffMode[PS_MAX_ENVELOPES], diffModeFine[PS_MAX_ENVELOPES]; |
345 | 0 | INT loudnDiff = 0; |
346 | 0 | INT iidTransmit = 0; |
347 | | |
348 | | /* Quantize IID coefficients */ |
349 | 0 | for (env = 0; env < nEnvelopes; env++) { |
350 | 0 | errIID += |
351 | 0 | quantizeCoef(iid[env], psBands, iidQuant_fx, 7, 15, iidIdxCoarse[env]); |
352 | 0 | errIIDFine += quantizeCoef(iid[env], psBands, iidQuantFine_fx, 15, 31, |
353 | 0 | iidIdxFine[env]); |
354 | 0 | } |
355 | | |
356 | | /* normalize error to number of envelopes, ps bands |
357 | | errIID /= psBands*nEnvelopes; |
358 | | errIIDFine /= psBands*nEnvelopes; */ |
359 | | |
360 | | /* Check if IID coefficients should be used in this frame */ |
361 | 0 | psData->iidEnable = 0; |
362 | 0 | for (env = 0; env < nEnvelopes; env++) { |
363 | 0 | for (band = 0; band < psBands; band++) { |
364 | 0 | loudnDiff += fixp_abs(iidIdxCoarse[env][band]); |
365 | 0 | iidTransmit++; |
366 | 0 | } |
367 | 0 | } |
368 | |
|
369 | 0 | if (loudnDiff > |
370 | 0 | fMultI(FL2FXCONST_DBL(0.7f), iidTransmit)) { /* 0.7f empiric value */ |
371 | 0 | psData->iidEnable = 1; |
372 | 0 | } |
373 | | |
374 | | /* if iid not active -> RESET data */ |
375 | 0 | if (psData->iidEnable == 0) { |
376 | 0 | psData->iidTimeCnt = MAX_TIME_DIFF_FRAMES; |
377 | 0 | for (env = 0; env < nEnvelopes; env++) { |
378 | 0 | psData->iidDiffMode[env] = PS_DELTA_FREQ; |
379 | 0 | FDKmemclear(psData->iidIdx[env], sizeof(INT) * psBands); |
380 | 0 | } |
381 | 0 | return; |
382 | 0 | } |
383 | | |
384 | | /* count COARSE quantization bits for first envelope*/ |
385 | 0 | bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[0], NULL, psBands, |
386 | 0 | PS_IID_RES_COARSE, PS_DELTA_FREQ, &error); |
387 | |
|
388 | 0 | if ((psData->iidTimeCnt >= MAX_TIME_DIFF_FRAMES) || |
389 | 0 | (psData->iidQuantModeLast == PS_IID_RES_FINE)) { |
390 | 0 | bitsIidTime = DO_NOT_USE_THIS_MODE; |
391 | 0 | } else { |
392 | 0 | bitsIidTime = |
393 | 0 | FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[0], psData->iidIdxLast, psBands, |
394 | 0 | PS_IID_RES_COARSE, PS_DELTA_TIME, &error); |
395 | 0 | } |
396 | | |
397 | | /* decision DELTA_FREQ vs DELTA_TIME */ |
398 | 0 | if (bitsIidTime > bitsIidFreq) { |
399 | 0 | diffMode[0] = PS_DELTA_FREQ; |
400 | 0 | bitsCoarseTot = bitsIidFreq; |
401 | 0 | } else { |
402 | 0 | diffMode[0] = PS_DELTA_TIME; |
403 | 0 | bitsCoarseTot = bitsIidTime; |
404 | 0 | } |
405 | | |
406 | | /* count COARSE quantization bits for following envelopes*/ |
407 | 0 | for (env = 1; env < nEnvelopes; env++) { |
408 | 0 | bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[env], NULL, psBands, |
409 | 0 | PS_IID_RES_COARSE, PS_DELTA_FREQ, &error); |
410 | 0 | bitsIidTime = |
411 | 0 | FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[env], iidIdxCoarse[env - 1], |
412 | 0 | psBands, PS_IID_RES_COARSE, PS_DELTA_TIME, &error); |
413 | | |
414 | | /* decision DELTA_FREQ vs DELTA_TIME */ |
415 | 0 | if (bitsIidTime > bitsIidFreq) { |
416 | 0 | diffMode[env] = PS_DELTA_FREQ; |
417 | 0 | bitsCoarseTot += bitsIidFreq; |
418 | 0 | } else { |
419 | 0 | diffMode[env] = PS_DELTA_TIME; |
420 | 0 | bitsCoarseTot += bitsIidTime; |
421 | 0 | } |
422 | 0 | } |
423 | | |
424 | | /* count FINE quantization bits for first envelope*/ |
425 | 0 | bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxFine[0], NULL, psBands, |
426 | 0 | PS_IID_RES_FINE, PS_DELTA_FREQ, &error); |
427 | |
|
428 | 0 | if ((psData->iidTimeCnt >= MAX_TIME_DIFF_FRAMES) || |
429 | 0 | (psData->iidQuantModeLast == PS_IID_RES_COARSE)) { |
430 | 0 | bitsIidTime = DO_NOT_USE_THIS_MODE; |
431 | 0 | } else { |
432 | 0 | bitsIidTime = |
433 | 0 | FDKsbrEnc_EncodeIid(NULL, iidIdxFine[0], psData->iidIdxLast, psBands, |
434 | 0 | PS_IID_RES_FINE, PS_DELTA_TIME, &error); |
435 | 0 | } |
436 | | |
437 | | /* decision DELTA_FREQ vs DELTA_TIME */ |
438 | 0 | if (bitsIidTime > bitsIidFreq) { |
439 | 0 | diffModeFine[0] = PS_DELTA_FREQ; |
440 | 0 | bitsFineTot = bitsIidFreq; |
441 | 0 | } else { |
442 | 0 | diffModeFine[0] = PS_DELTA_TIME; |
443 | 0 | bitsFineTot = bitsIidTime; |
444 | 0 | } |
445 | | |
446 | | /* count FINE quantization bits for following envelopes*/ |
447 | 0 | for (env = 1; env < nEnvelopes; env++) { |
448 | 0 | bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxFine[env], NULL, psBands, |
449 | 0 | PS_IID_RES_FINE, PS_DELTA_FREQ, &error); |
450 | 0 | bitsIidTime = |
451 | 0 | FDKsbrEnc_EncodeIid(NULL, iidIdxFine[env], iidIdxFine[env - 1], psBands, |
452 | 0 | PS_IID_RES_FINE, PS_DELTA_TIME, &error); |
453 | | |
454 | | /* decision DELTA_FREQ vs DELTA_TIME */ |
455 | 0 | if (bitsIidTime > bitsIidFreq) { |
456 | 0 | diffModeFine[env] = PS_DELTA_FREQ; |
457 | 0 | bitsFineTot += bitsIidFreq; |
458 | 0 | } else { |
459 | 0 | diffModeFine[env] = PS_DELTA_TIME; |
460 | 0 | bitsFineTot += bitsIidTime; |
461 | 0 | } |
462 | 0 | } |
463 | |
|
464 | 0 | if (bitsFineTot == bitsCoarseTot) { |
465 | | /* if same number of bits is needed, use the quantization with lower error |
466 | | */ |
467 | 0 | if (errIIDFine < errIID) { |
468 | 0 | bitsCoarseTot = DO_NOT_USE_THIS_MODE; |
469 | 0 | } else { |
470 | 0 | bitsFineTot = DO_NOT_USE_THIS_MODE; |
471 | 0 | } |
472 | 0 | } else { |
473 | | /* const FIXP_DBL minThreshold = |
474 | | * FL2FXCONST_DBL(0.2f/(IID_SCALE_FT*PS_QUANT_SCALE_FT)*(psBands*nEnvelopes)); |
475 | | */ |
476 | 0 | const FIXP_DBL minThreshold = |
477 | 0 | (FIXP_DBL)((LONG)0x00019999 * (psBands * nEnvelopes)); |
478 | | |
479 | | /* decision RES_FINE vs RES_COARSE */ |
480 | | /* test if errIIDFine*quantErrorThreshold < errIID */ |
481 | | /* shiftVal 2 comes from scaling of quantErrorThreshold */ |
482 | 0 | if (fixMax(((errIIDFine >> 1) + (minThreshold >> 1)) >> 1, |
483 | 0 | fMult(quantErrorThreshold, errIIDFine)) < (errIID >> 2)) { |
484 | 0 | bitsCoarseTot = DO_NOT_USE_THIS_MODE; |
485 | 0 | } else if (fixMax(((errIID >> 1) + (minThreshold >> 1)) >> 1, |
486 | 0 | fMult(quantErrorThreshold, errIID)) < (errIIDFine >> 2)) { |
487 | 0 | bitsFineTot = DO_NOT_USE_THIS_MODE; |
488 | 0 | } |
489 | 0 | } |
490 | | |
491 | | /* decision RES_FINE vs RES_COARSE */ |
492 | 0 | if (bitsFineTot < bitsCoarseTot) { |
493 | 0 | psData->iidQuantMode = PS_IID_RES_FINE; |
494 | 0 | for (env = 0; env < nEnvelopes; env++) { |
495 | 0 | psData->iidDiffMode[env] = diffModeFine[env]; |
496 | 0 | FDKmemcpy(psData->iidIdx[env], iidIdxFine[env], psBands * sizeof(INT)); |
497 | 0 | } |
498 | 0 | } else { |
499 | 0 | psData->iidQuantMode = PS_IID_RES_COARSE; |
500 | 0 | for (env = 0; env < nEnvelopes; env++) { |
501 | 0 | psData->iidDiffMode[env] = diffMode[env]; |
502 | 0 | FDKmemcpy(psData->iidIdx[env], iidIdxCoarse[env], psBands * sizeof(INT)); |
503 | 0 | } |
504 | 0 | } |
505 | | |
506 | | /* Count DELTA_TIME encoding streaks */ |
507 | 0 | for (env = 0; env < nEnvelopes; env++) { |
508 | 0 | if (psData->iidDiffMode[env] == PS_DELTA_TIME) |
509 | 0 | psData->iidTimeCnt++; |
510 | 0 | else |
511 | 0 | psData->iidTimeCnt = 0; |
512 | 0 | } |
513 | 0 | } |
514 | | |
515 | | static INT similarIid(PS_DATA *psData, const INT psBands, |
516 | 0 | const INT nEnvelopes) { |
517 | 0 | const INT diffThr = (psData->iidQuantMode == PS_IID_RES_COARSE) ? 2 : 3; |
518 | 0 | const INT sumDiffThr = diffThr * psBands / 4; |
519 | 0 | INT similar = 0; |
520 | 0 | INT diff = 0; |
521 | 0 | INT sumDiff = 0; |
522 | 0 | INT env = 0; |
523 | 0 | INT b = 0; |
524 | 0 | if ((nEnvelopes == psData->nEnvelopesLast) && (nEnvelopes == 1)) { |
525 | 0 | similar = 1; |
526 | 0 | for (env = 0; env < nEnvelopes; env++) { |
527 | 0 | sumDiff = 0; |
528 | 0 | b = 0; |
529 | 0 | do { |
530 | 0 | diff = fixp_abs(psData->iidIdx[env][b] - psData->iidIdxLast[b]); |
531 | 0 | sumDiff += diff; |
532 | 0 | if ((diff > diffThr) /* more than x quantization steps in any band */ |
533 | 0 | || (sumDiff > sumDiffThr)) { /* more than x quantisations steps |
534 | | overall difference */ |
535 | 0 | similar = 0; |
536 | 0 | } |
537 | 0 | b++; |
538 | 0 | } while ((b < psBands) && (similar > 0)); |
539 | 0 | } |
540 | 0 | } /* nEnvelopes==1 */ |
541 | |
|
542 | 0 | return similar; |
543 | 0 | } |
544 | | |
545 | | static INT similarIcc(PS_DATA *psData, const INT psBands, |
546 | 0 | const INT nEnvelopes) { |
547 | 0 | const INT diffThr = 2; |
548 | 0 | const INT sumDiffThr = diffThr * psBands / 4; |
549 | 0 | INT similar = 0; |
550 | 0 | INT diff = 0; |
551 | 0 | INT sumDiff = 0; |
552 | 0 | INT env = 0; |
553 | 0 | INT b = 0; |
554 | 0 | if ((nEnvelopes == psData->nEnvelopesLast) && (nEnvelopes == 1)) { |
555 | 0 | similar = 1; |
556 | 0 | for (env = 0; env < nEnvelopes; env++) { |
557 | 0 | sumDiff = 0; |
558 | 0 | b = 0; |
559 | 0 | do { |
560 | 0 | diff = fixp_abs(psData->iccIdx[env][b] - psData->iccIdxLast[b]); |
561 | 0 | sumDiff += diff; |
562 | 0 | if ((diff > diffThr) /* more than x quantisation step in any band */ |
563 | 0 | || (sumDiff > sumDiffThr)) { /* more than x quantisations steps |
564 | | overall difference */ |
565 | 0 | similar = 0; |
566 | 0 | } |
567 | 0 | b++; |
568 | 0 | } while ((b < psBands) && (similar > 0)); |
569 | 0 | } |
570 | 0 | } /* nEnvelopes==1 */ |
571 | |
|
572 | 0 | return similar; |
573 | 0 | } |
574 | | |
575 | | static void processIccData( |
576 | | PS_DATA *psData, |
577 | | FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS], /* const input values: |
578 | | unable to declare as |
579 | | const, since it does |
580 | | not poINT to const |
581 | | memory */ |
582 | 0 | const INT psBands, const INT nEnvelopes) { |
583 | 0 | FIXP_DBL errICC = FL2FXCONST_DBL(0.f); |
584 | 0 | INT env, band; |
585 | 0 | INT bitsIccFreq, bitsIccTime; |
586 | 0 | INT error = 0; |
587 | 0 | INT inCoherence = 0, iccTransmit = 0; |
588 | 0 | INT *iccIdxLast; |
589 | |
|
590 | 0 | iccIdxLast = psData->iccIdxLast; |
591 | | |
592 | | /* Quantize ICC coefficients */ |
593 | 0 | for (env = 0; env < nEnvelopes; env++) { |
594 | 0 | errICC += |
595 | 0 | quantizeCoef(icc[env], psBands, iccQuant, 0, 8, psData->iccIdx[env]); |
596 | 0 | } |
597 | | |
598 | | /* Check if ICC coefficients should be used */ |
599 | 0 | psData->iccEnable = 0; |
600 | 0 | for (env = 0; env < nEnvelopes; env++) { |
601 | 0 | for (band = 0; band < psBands; band++) { |
602 | 0 | inCoherence += psData->iccIdx[env][band]; |
603 | 0 | iccTransmit++; |
604 | 0 | } |
605 | 0 | } |
606 | 0 | if (inCoherence > |
607 | 0 | fMultI(FL2FXCONST_DBL(0.5f), iccTransmit)) { /* 0.5f empiric value */ |
608 | 0 | psData->iccEnable = 1; |
609 | 0 | } |
610 | |
|
611 | 0 | if (psData->iccEnable == 0) { |
612 | 0 | psData->iccTimeCnt = MAX_TIME_DIFF_FRAMES; |
613 | 0 | for (env = 0; env < nEnvelopes; env++) { |
614 | 0 | psData->iccDiffMode[env] = PS_DELTA_FREQ; |
615 | 0 | FDKmemclear(psData->iccIdx[env], sizeof(INT) * psBands); |
616 | 0 | } |
617 | 0 | return; |
618 | 0 | } |
619 | | |
620 | 0 | for (env = 0; env < nEnvelopes; env++) { |
621 | 0 | bitsIccFreq = FDKsbrEnc_EncodeIcc(NULL, psData->iccIdx[env], NULL, psBands, |
622 | 0 | PS_DELTA_FREQ, &error); |
623 | |
|
624 | 0 | if (psData->iccTimeCnt < MAX_TIME_DIFF_FRAMES) { |
625 | 0 | bitsIccTime = FDKsbrEnc_EncodeIcc(NULL, psData->iccIdx[env], iccIdxLast, |
626 | 0 | psBands, PS_DELTA_TIME, &error); |
627 | 0 | } else { |
628 | 0 | bitsIccTime = DO_NOT_USE_THIS_MODE; |
629 | 0 | } |
630 | |
|
631 | 0 | if (bitsIccFreq > bitsIccTime) { |
632 | 0 | psData->iccDiffMode[env] = PS_DELTA_TIME; |
633 | 0 | psData->iccTimeCnt++; |
634 | 0 | } else { |
635 | 0 | psData->iccDiffMode[env] = PS_DELTA_FREQ; |
636 | 0 | psData->iccTimeCnt = 0; |
637 | 0 | } |
638 | 0 | iccIdxLast = psData->iccIdx[env]; |
639 | 0 | } |
640 | 0 | } |
641 | | |
642 | | static void calculateIID(FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS], |
643 | | FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS], |
644 | | FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS], |
645 | 0 | INT nEnvelopes, INT psBands) { |
646 | 0 | INT i = 0; |
647 | 0 | INT env = 0; |
648 | 0 | for (env = 0; env < nEnvelopes; env++) { |
649 | 0 | for (i = 0; i < psBands; i++) { |
650 | | /* iid[env][i] = 10.0f*(float)log10(pwrL[env][i]/pwrR[env][i]); |
651 | | */ |
652 | 0 | FIXP_DBL IID = fMultDiv2(FL2FXCONST_DBL(LOG10_2_10 / IID_SCALE_FT), |
653 | 0 | (ldPwrL[env][i] - ldPwrR[env][i])); |
654 | |
|
655 | 0 | IID = fixMin(IID, (FIXP_DBL)(MAXVAL_DBL >> (LD_DATA_SHIFT + 1))); |
656 | 0 | IID = fixMax(IID, (FIXP_DBL)(MINVAL_DBL >> (LD_DATA_SHIFT + 1))); |
657 | 0 | iid[env][i] = IID << (LD_DATA_SHIFT + 1); |
658 | 0 | } |
659 | 0 | } |
660 | 0 | } |
661 | | |
662 | | static void calculateICC(FIXP_DBL pwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS], |
663 | | FIXP_DBL pwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS], |
664 | | FIXP_DBL pwrCr[PS_MAX_ENVELOPES][PS_MAX_BANDS], |
665 | | FIXP_DBL pwrCi[PS_MAX_ENVELOPES][PS_MAX_BANDS], |
666 | | FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS], |
667 | 0 | INT nEnvelopes, INT psBands) { |
668 | 0 | INT i = 0; |
669 | 0 | INT env = 0; |
670 | 0 | INT border = psBands; |
671 | |
|
672 | 0 | switch (psBands) { |
673 | 0 | case PS_BANDS_COARSE: |
674 | 0 | border = 5; |
675 | 0 | break; |
676 | 0 | case PS_BANDS_MID: |
677 | 0 | border = 11; |
678 | 0 | break; |
679 | 0 | default: |
680 | 0 | break; |
681 | 0 | } |
682 | | |
683 | 0 | for (env = 0; env < nEnvelopes; env++) { |
684 | 0 | for (i = 0; i < border; i++) { |
685 | | /* icc[env][i] = min( pwrCr[env][i] / (float) sqrt(pwrL[env][i] * |
686 | | * pwrR[env][i]) , 1.f); |
687 | | */ |
688 | 0 | int scale; |
689 | 0 | FIXP_DBL invNrg = invSqrtNorm2( |
690 | 0 | fMax(fMult(pwrL[env][i], pwrR[env][i]), (FIXP_DBL)1), &scale); |
691 | 0 | icc[env][i] = |
692 | 0 | SATURATE_LEFT_SHIFT(fMult(pwrCr[env][i], invNrg), scale, DFRACT_BITS); |
693 | 0 | } |
694 | |
|
695 | 0 | for (; i < psBands; i++) { |
696 | 0 | int denom_e; |
697 | 0 | FIXP_DBL denom_m = fMultNorm(pwrL[env][i], pwrR[env][i], &denom_e); |
698 | |
|
699 | 0 | if (denom_m == (FIXP_DBL)0) { |
700 | 0 | icc[env][i] = (FIXP_DBL)MAXVAL_DBL; |
701 | 0 | } else { |
702 | 0 | int num_e, result_e; |
703 | 0 | FIXP_DBL num_m, result_m; |
704 | |
|
705 | 0 | num_e = CountLeadingBits( |
706 | 0 | fixMax(fixp_abs(pwrCr[env][i]), fixp_abs(pwrCi[env][i]))); |
707 | 0 | num_m = fPow2Div2((pwrCr[env][i] << num_e)) + |
708 | 0 | fPow2Div2((pwrCi[env][i] << num_e)); |
709 | |
|
710 | 0 | result_m = fDivNorm(num_m, denom_m, &result_e); |
711 | 0 | result_e += (-2 * num_e + 1) - denom_e; |
712 | 0 | icc[env][i] = scaleValueSaturate(sqrtFixp(result_m >> (result_e & 1)), |
713 | 0 | (result_e + (result_e & 1)) >> 1); |
714 | 0 | } |
715 | 0 | } |
716 | 0 | } |
717 | 0 | } |
718 | | |
719 | 0 | void FDKsbrEnc_initPsBandNrgScale(HANDLE_PS_ENCODE hPsEncode) { |
720 | 0 | INT group, bin; |
721 | 0 | INT nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups; |
722 | |
|
723 | 0 | FDKmemclear(hPsEncode->psBandNrgScale, PS_MAX_BANDS * sizeof(SCHAR)); |
724 | |
|
725 | 0 | for (group = 0; group < nIidGroups; group++) { |
726 | | /* Translate group to bin */ |
727 | 0 | bin = hPsEncode->subband2parameterIndex[group]; |
728 | | |
729 | | /* Translate from 20 bins to 10 bins */ |
730 | 0 | if (hPsEncode->psEncMode == PS_BANDS_COARSE) { |
731 | 0 | bin = bin >> 1; |
732 | 0 | } |
733 | |
|
734 | 0 | hPsEncode->psBandNrgScale[bin] = |
735 | 0 | (hPsEncode->psBandNrgScale[bin] == 0) |
736 | 0 | ? (hPsEncode->iidGroupWidthLd[group] + 5) |
737 | 0 | : (fixMax(hPsEncode->iidGroupWidthLd[group], |
738 | 0 | hPsEncode->psBandNrgScale[bin]) + |
739 | 0 | 1); |
740 | 0 | } |
741 | 0 | } |
742 | | |
743 | 0 | FDK_PSENC_ERROR FDKsbrEnc_CreatePSEncode(HANDLE_PS_ENCODE *phPsEncode) { |
744 | 0 | FDK_PSENC_ERROR error = PSENC_OK; |
745 | |
|
746 | 0 | if (phPsEncode == NULL) { |
747 | 0 | error = PSENC_INVALID_HANDLE; |
748 | 0 | } else { |
749 | 0 | HANDLE_PS_ENCODE hPsEncode = NULL; |
750 | 0 | if (NULL == (hPsEncode = GetRam_PsEncode())) { |
751 | 0 | error = PSENC_MEMORY_ERROR; |
752 | 0 | goto bail; |
753 | 0 | } |
754 | 0 | FDKmemclear(hPsEncode, sizeof(PS_ENCODE)); |
755 | 0 | *phPsEncode = hPsEncode; /* return allocated handle */ |
756 | 0 | } |
757 | 0 | bail: |
758 | 0 | return error; |
759 | 0 | } |
760 | | |
761 | | FDK_PSENC_ERROR FDKsbrEnc_InitPSEncode(HANDLE_PS_ENCODE hPsEncode, |
762 | | const PS_BANDS psEncMode, |
763 | 0 | const FIXP_DBL iidQuantErrorThreshold) { |
764 | 0 | FDK_PSENC_ERROR error = PSENC_OK; |
765 | |
|
766 | 0 | if (NULL == hPsEncode) { |
767 | 0 | error = PSENC_INVALID_HANDLE; |
768 | 0 | } else { |
769 | 0 | if (PSENC_OK != (InitPSData(&hPsEncode->psData))) { |
770 | 0 | goto bail; |
771 | 0 | } |
772 | | |
773 | 0 | switch (psEncMode) { |
774 | 0 | case PS_BANDS_COARSE: |
775 | 0 | case PS_BANDS_MID: |
776 | 0 | hPsEncode->nQmfIidGroups = QMF_GROUPS_LO_RES; |
777 | 0 | hPsEncode->nSubQmfIidGroups = SUBQMF_GROUPS_LO_RES; |
778 | 0 | FDKmemcpy(hPsEncode->iidGroupBorders, iidGroupBordersLoRes, |
779 | 0 | (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups + 1) * |
780 | 0 | sizeof(INT)); |
781 | 0 | FDKmemcpy(hPsEncode->subband2parameterIndex, subband2parameter20, |
782 | 0 | (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) * |
783 | 0 | sizeof(INT)); |
784 | 0 | FDKmemcpy(hPsEncode->iidGroupWidthLd, iidGroupWidthLdLoRes, |
785 | 0 | (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) * |
786 | 0 | sizeof(UCHAR)); |
787 | 0 | break; |
788 | 0 | default: |
789 | 0 | error = PSENC_INIT_ERROR; |
790 | 0 | goto bail; |
791 | 0 | } |
792 | | |
793 | 0 | hPsEncode->psEncMode = psEncMode; |
794 | 0 | hPsEncode->iidQuantErrorThreshold = iidQuantErrorThreshold; |
795 | 0 | FDKsbrEnc_initPsBandNrgScale(hPsEncode); |
796 | 0 | } |
797 | 0 | bail: |
798 | 0 | return error; |
799 | 0 | } |
800 | | |
801 | 0 | FDK_PSENC_ERROR FDKsbrEnc_DestroyPSEncode(HANDLE_PS_ENCODE *phPsEncode) { |
802 | 0 | FDK_PSENC_ERROR error = PSENC_OK; |
803 | |
|
804 | 0 | if (NULL != phPsEncode) { |
805 | 0 | FreeRam_PsEncode(phPsEncode); |
806 | 0 | } |
807 | |
|
808 | 0 | return error; |
809 | 0 | } |
810 | | |
811 | | typedef struct { |
812 | | FIXP_DBL pwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS]; |
813 | | FIXP_DBL pwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS]; |
814 | | FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS]; |
815 | | FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS]; |
816 | | FIXP_DBL pwrCr[PS_MAX_ENVELOPES][PS_MAX_BANDS]; |
817 | | FIXP_DBL pwrCi[PS_MAX_ENVELOPES][PS_MAX_BANDS]; |
818 | | |
819 | | } PS_PWR_DATA; |
820 | | |
821 | | FDK_PSENC_ERROR FDKsbrEnc_PSEncode( |
822 | | HANDLE_PS_ENCODE hPsEncode, HANDLE_PS_OUT hPsOut, UCHAR *dynBandScale, |
823 | | UINT maxEnvelopes, |
824 | | FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], |
825 | 0 | const INT frameSize, const INT sendHeader) { |
826 | 0 | FDK_PSENC_ERROR error = PSENC_OK; |
827 | |
|
828 | 0 | HANDLE_PS_DATA hPsData = &hPsEncode->psData; |
829 | 0 | FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS]; |
830 | 0 | FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS]; |
831 | 0 | int envBorder[PS_MAX_ENVELOPES + 1]; |
832 | |
|
833 | 0 | int group, bin, col, subband, band; |
834 | 0 | int i = 0; |
835 | |
|
836 | 0 | int env = 0; |
837 | 0 | int psBands = (int)hPsEncode->psEncMode; |
838 | 0 | int nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups; |
839 | 0 | int nEnvelopes = fixMin(maxEnvelopes, (UINT)PS_MAX_ENVELOPES); |
840 | |
|
841 | 0 | C_ALLOC_SCRATCH_START(pwrData, PS_PWR_DATA, 1) |
842 | |
|
843 | 0 | for (env = 0; env < nEnvelopes + 1; env++) { |
844 | 0 | envBorder[env] = fMultI(GetInvInt(nEnvelopes), frameSize * env); |
845 | 0 | } |
846 | |
|
847 | 0 | for (env = 0; env < nEnvelopes; env++) { |
848 | | /* clear energy array */ |
849 | 0 | for (band = 0; band < psBands; band++) { |
850 | 0 | pwrData->pwrL[env][band] = pwrData->pwrR[env][band] = |
851 | 0 | pwrData->pwrCr[env][band] = pwrData->pwrCi[env][band] = FIXP_DBL(1); |
852 | 0 | } |
853 | | |
854 | | /**** calculate energies and correlation ****/ |
855 | | |
856 | | /* start with hybrid data */ |
857 | 0 | for (group = 0; group < nIidGroups; group++) { |
858 | | /* Translate group to bin */ |
859 | 0 | bin = hPsEncode->subband2parameterIndex[group]; |
860 | | |
861 | | /* Translate from 20 bins to 10 bins */ |
862 | 0 | if (hPsEncode->psEncMode == PS_BANDS_COARSE) { |
863 | 0 | bin >>= 1; |
864 | 0 | } |
865 | | |
866 | | /* determine group border */ |
867 | 0 | int bScale = hPsEncode->psBandNrgScale[bin]; |
868 | |
|
869 | 0 | FIXP_DBL pwrL_env_bin = pwrData->pwrL[env][bin]; |
870 | 0 | FIXP_DBL pwrR_env_bin = pwrData->pwrR[env][bin]; |
871 | 0 | FIXP_DBL pwrCr_env_bin = pwrData->pwrCr[env][bin]; |
872 | 0 | FIXP_DBL pwrCi_env_bin = pwrData->pwrCi[env][bin]; |
873 | |
|
874 | 0 | int scale = (int)dynBandScale[bin]; |
875 | 0 | for (col = envBorder[env]; col < envBorder[env + 1]; col++) { |
876 | 0 | for (subband = hPsEncode->iidGroupBorders[group]; |
877 | 0 | subband < hPsEncode->iidGroupBorders[group + 1]; subband++) { |
878 | 0 | FIXP_DBL l_real = (hybridData[col][0][0][subband]) << scale; |
879 | 0 | FIXP_DBL l_imag = (hybridData[col][0][1][subband]) << scale; |
880 | 0 | FIXP_DBL r_real = (hybridData[col][1][0][subband]) << scale; |
881 | 0 | FIXP_DBL r_imag = (hybridData[col][1][1][subband]) << scale; |
882 | |
|
883 | 0 | pwrL_env_bin += (fPow2Div2(l_real) + fPow2Div2(l_imag)) >> bScale; |
884 | 0 | pwrR_env_bin += (fPow2Div2(r_real) + fPow2Div2(r_imag)) >> bScale; |
885 | 0 | pwrCr_env_bin += |
886 | 0 | (fMultDiv2(l_real, r_real) + fMultDiv2(l_imag, r_imag)) >> bScale; |
887 | 0 | pwrCi_env_bin += |
888 | 0 | (fMultDiv2(r_real, l_imag) - fMultDiv2(l_real, r_imag)) >> bScale; |
889 | 0 | } |
890 | 0 | } |
891 | | /* assure, nrg's of left and right channel are not negative; necessary on |
892 | | * 16 bit multiply units */ |
893 | 0 | pwrData->pwrL[env][bin] = fixMax((FIXP_DBL)0, pwrL_env_bin); |
894 | 0 | pwrData->pwrR[env][bin] = fixMax((FIXP_DBL)0, pwrR_env_bin); |
895 | |
|
896 | 0 | pwrData->pwrCr[env][bin] = pwrCr_env_bin; |
897 | 0 | pwrData->pwrCi[env][bin] = pwrCi_env_bin; |
898 | |
|
899 | 0 | } /* nIidGroups */ |
900 | | |
901 | | /* calc logarithmic energy */ |
902 | 0 | LdDataVector(pwrData->pwrL[env], pwrData->ldPwrL[env], psBands); |
903 | 0 | LdDataVector(pwrData->pwrR[env], pwrData->ldPwrR[env], psBands); |
904 | |
|
905 | 0 | } /* nEnvelopes */ |
906 | | |
907 | | /* calculate iid and icc */ |
908 | 0 | calculateIID(pwrData->ldPwrL, pwrData->ldPwrR, iid, nEnvelopes, psBands); |
909 | 0 | calculateICC(pwrData->pwrL, pwrData->pwrR, pwrData->pwrCr, pwrData->pwrCi, |
910 | 0 | icc, nEnvelopes, psBands); |
911 | | |
912 | | /*** Envelope Reduction ***/ |
913 | 0 | while (envelopeReducible(iid, icc, psBands, nEnvelopes)) { |
914 | 0 | int e = 0; |
915 | | /* sum energies of two neighboring envelopes */ |
916 | 0 | nEnvelopes >>= 1; |
917 | 0 | for (e = 0; e < nEnvelopes; e++) { |
918 | 0 | FDKsbrEnc_addFIXP_DBL(pwrData->pwrL[2 * e], pwrData->pwrL[2 * e + 1], |
919 | 0 | pwrData->pwrL[e], psBands); |
920 | 0 | FDKsbrEnc_addFIXP_DBL(pwrData->pwrR[2 * e], pwrData->pwrR[2 * e + 1], |
921 | 0 | pwrData->pwrR[e], psBands); |
922 | 0 | FDKsbrEnc_addFIXP_DBL(pwrData->pwrCr[2 * e], pwrData->pwrCr[2 * e + 1], |
923 | 0 | pwrData->pwrCr[e], psBands); |
924 | 0 | FDKsbrEnc_addFIXP_DBL(pwrData->pwrCi[2 * e], pwrData->pwrCi[2 * e + 1], |
925 | 0 | pwrData->pwrCi[e], psBands); |
926 | | |
927 | | /* calc logarithmic energy */ |
928 | 0 | LdDataVector(pwrData->pwrL[e], pwrData->ldPwrL[e], psBands); |
929 | 0 | LdDataVector(pwrData->pwrR[e], pwrData->ldPwrR[e], psBands); |
930 | | |
931 | | /* reduce number of envelopes and adjust borders */ |
932 | 0 | envBorder[e] = envBorder[2 * e]; |
933 | 0 | } |
934 | 0 | envBorder[nEnvelopes] = envBorder[2 * nEnvelopes]; |
935 | | |
936 | | /* re-calculate iid and icc */ |
937 | 0 | calculateIID(pwrData->ldPwrL, pwrData->ldPwrR, iid, nEnvelopes, psBands); |
938 | 0 | calculateICC(pwrData->pwrL, pwrData->pwrR, pwrData->pwrCr, pwrData->pwrCi, |
939 | 0 | icc, nEnvelopes, psBands); |
940 | 0 | } |
941 | | |
942 | | /* */ |
943 | 0 | if (sendHeader) { |
944 | 0 | hPsData->headerCnt = MAX_PS_NOHEADER_CNT; |
945 | 0 | hPsData->iidTimeCnt = MAX_TIME_DIFF_FRAMES; |
946 | 0 | hPsData->iccTimeCnt = MAX_TIME_DIFF_FRAMES; |
947 | 0 | hPsData->noEnvCnt = MAX_NOENV_CNT; |
948 | 0 | } |
949 | | |
950 | | /*** Parameter processing, quantisation etc ***/ |
951 | 0 | processIidData(hPsData, iid, psBands, nEnvelopes, |
952 | 0 | hPsEncode->iidQuantErrorThreshold); |
953 | 0 | processIccData(hPsData, icc, psBands, nEnvelopes); |
954 | | |
955 | | /*** Initialize output struct ***/ |
956 | | |
957 | | /* PS Header on/off ? */ |
958 | 0 | if ((hPsData->headerCnt < MAX_PS_NOHEADER_CNT) && |
959 | 0 | ((hPsData->iidQuantMode == hPsData->iidQuantModeLast) && |
960 | 0 | (hPsData->iccQuantMode == hPsData->iccQuantModeLast)) && |
961 | 0 | ((hPsData->iidEnable == hPsData->iidEnableLast) && |
962 | 0 | (hPsData->iccEnable == hPsData->iccEnableLast))) { |
963 | 0 | hPsOut->enablePSHeader = 0; |
964 | 0 | } else { |
965 | 0 | hPsOut->enablePSHeader = 1; |
966 | 0 | hPsData->headerCnt = 0; |
967 | 0 | } |
968 | | |
969 | | /* nEnvelopes = 0 ? */ |
970 | 0 | if ((hPsData->noEnvCnt < MAX_NOENV_CNT) && |
971 | 0 | (similarIid(hPsData, psBands, nEnvelopes)) && |
972 | 0 | (similarIcc(hPsData, psBands, nEnvelopes))) { |
973 | 0 | hPsOut->nEnvelopes = nEnvelopes = 0; |
974 | 0 | hPsData->noEnvCnt++; |
975 | 0 | } else { |
976 | 0 | hPsData->noEnvCnt = 0; |
977 | 0 | } |
978 | |
|
979 | 0 | if (nEnvelopes > 0) { |
980 | 0 | hPsOut->enableIID = hPsData->iidEnable; |
981 | 0 | hPsOut->iidMode = getIIDMode(psBands, hPsData->iidQuantMode); |
982 | |
|
983 | 0 | hPsOut->enableICC = hPsData->iccEnable; |
984 | 0 | hPsOut->iccMode = getICCMode(psBands, hPsData->iccQuantMode); |
985 | |
|
986 | 0 | hPsOut->enableIpdOpd = 0; |
987 | 0 | hPsOut->frameClass = 0; |
988 | 0 | hPsOut->nEnvelopes = nEnvelopes; |
989 | |
|
990 | 0 | for (env = 0; env < nEnvelopes; env++) { |
991 | 0 | hPsOut->frameBorder[env] = envBorder[env + 1]; |
992 | 0 | hPsOut->deltaIID[env] = (PS_DELTA)hPsData->iidDiffMode[env]; |
993 | 0 | hPsOut->deltaICC[env] = (PS_DELTA)hPsData->iccDiffMode[env]; |
994 | 0 | for (band = 0; band < psBands; band++) { |
995 | 0 | hPsOut->iid[env][band] = hPsData->iidIdx[env][band]; |
996 | 0 | hPsOut->icc[env][band] = hPsData->iccIdx[env][band]; |
997 | 0 | } |
998 | 0 | } |
999 | | |
1000 | | /* IPD OPD not supported right now */ |
1001 | 0 | FDKmemclear(hPsOut->ipd, |
1002 | 0 | PS_MAX_ENVELOPES * PS_MAX_BANDS * sizeof(PS_DELTA)); |
1003 | 0 | for (env = 0; env < PS_MAX_ENVELOPES; env++) { |
1004 | 0 | hPsOut->deltaIPD[env] = PS_DELTA_FREQ; |
1005 | 0 | hPsOut->deltaOPD[env] = PS_DELTA_FREQ; |
1006 | 0 | } |
1007 | |
|
1008 | 0 | FDKmemclear(hPsOut->ipdLast, PS_MAX_BANDS * sizeof(INT)); |
1009 | 0 | FDKmemclear(hPsOut->opdLast, PS_MAX_BANDS * sizeof(INT)); |
1010 | |
|
1011 | 0 | for (band = 0; band < PS_MAX_BANDS; band++) { |
1012 | 0 | hPsOut->iidLast[band] = hPsData->iidIdxLast[band]; |
1013 | 0 | hPsOut->iccLast[band] = hPsData->iccIdxLast[band]; |
1014 | 0 | } |
1015 | | |
1016 | | /* save iids and iccs for differential time coding in the next frame */ |
1017 | 0 | hPsData->nEnvelopesLast = nEnvelopes; |
1018 | 0 | hPsData->iidEnableLast = hPsData->iidEnable; |
1019 | 0 | hPsData->iccEnableLast = hPsData->iccEnable; |
1020 | 0 | hPsData->iidQuantModeLast = hPsData->iidQuantMode; |
1021 | 0 | hPsData->iccQuantModeLast = hPsData->iccQuantMode; |
1022 | 0 | for (i = 0; i < psBands; i++) { |
1023 | 0 | hPsData->iidIdxLast[i] = hPsData->iidIdx[nEnvelopes - 1][i]; |
1024 | 0 | hPsData->iccIdxLast[i] = hPsData->iccIdx[nEnvelopes - 1][i]; |
1025 | 0 | } |
1026 | 0 | } /* Envelope > 0 */ |
1027 | |
|
1028 | 0 | C_ALLOC_SCRATCH_END(pwrData, PS_PWR_DATA, 1) |
1029 | |
|
1030 | 0 | return error; |
1031 | 0 | } |