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 /**************************** AAC encoder library ******************************
96
97 Author(s): M. Werner
98
99 Description: Threshold compensation
100
101 *******************************************************************************/
102
103 #include "adj_thr.h"
104 #include "sf_estim.h"
105 #include "aacEnc_ram.h"
106
107 #define NUM_NRG_LEVS (8)
108 #define INV_INT_TAB_SIZE (8)
109 static const FIXP_DBL invInt[INV_INT_TAB_SIZE] = {
110 0x7fffffff, 0x7fffffff, 0x40000000, 0x2aaaaaaa,
111 0x20000000, 0x19999999, 0x15555555, 0x12492492};
112
113 #define INV_SQRT4_TAB_SIZE (8)
114 static const FIXP_DBL invSqrt4[INV_SQRT4_TAB_SIZE] = {
115 0x7fffffff, 0x7fffffff, 0x6ba27e65, 0x61424bb5,
116 0x5a827999, 0x55994845, 0x51c8e33c, 0x4eb160d1};
117
118 /*static const INT invRedExp = 4;*/
119 static const FIXP_DBL SnrLdMin1 =
120 (FIXP_DBL)0xfcad0ddf; /*FL2FXCONST_DBL(FDKlog(0.316)/FDKlog(2.0)/LD_DATA_SCALING);*/
121 static const FIXP_DBL SnrLdMin2 =
122 (FIXP_DBL)0x0351e1a2; /*FL2FXCONST_DBL(FDKlog(3.16)
123 /FDKlog(2.0)/LD_DATA_SCALING);*/
124 static const FIXP_DBL SnrLdFac =
125 (FIXP_DBL)0xff5b2c3e; /*FL2FXCONST_DBL(FDKlog(0.8)
126 /FDKlog(2.0)/LD_DATA_SCALING);*/
127
128 static const FIXP_DBL SnrLdMin3 =
129 (FIXP_DBL)0xfe000000; /*FL2FXCONST_DBL(FDKlog(0.5)
130 /FDKlog(2.0)/LD_DATA_SCALING);*/
131 static const FIXP_DBL SnrLdMin4 =
132 (FIXP_DBL)0x02000000; /*FL2FXCONST_DBL(FDKlog(2.0)
133 /FDKlog(2.0)/LD_DATA_SCALING);*/
134 static const FIXP_DBL SnrLdMin5 =
135 (FIXP_DBL)0xfc000000; /*FL2FXCONST_DBL(FDKlog(0.25)
136 /FDKlog(2.0)/LD_DATA_SCALING);*/
137
138 /*
139 The bits2Pe factors are choosen for the case that some times
140 the crash recovery strategy will be activated once.
141 */
142 #define AFTERBURNER_STATI 2
143 #define MAX_ALLOWED_EL_CHANNELS 2
144
145 typedef struct {
146 INT bitrate;
147 FIXP_DBL bits2PeFactor[AFTERBURNER_STATI][MAX_ALLOWED_EL_CHANNELS];
148 } BIT_PE_SFAC;
149
150 typedef struct {
151 INT sampleRate;
152 const BIT_PE_SFAC *pPeTab;
153 INT nEntries;
154
155 } BITS2PE_CFG_TAB;
156
157 #define FL2B2PE(value) FL2FXCONST_DBL((value) / (1 << 2))
158
159 static const BIT_PE_SFAC S_Bits2PeTab16000[] = {
160 /* bitrate| afterburner off | afterburner on | | nCh=1
161 | nCh=2 | nCh=1 | nCh=2 */
162 {10000,
163 {{FL2B2PE(1.60f), FL2B2PE(0.00f)}, {FL2B2PE(1.40f), FL2B2PE(0.00f)}}},
164 {24000,
165 {{FL2B2PE(1.80f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}},
166 {32000,
167 {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
168 {48000,
169 {{FL2B2PE(1.60f), FL2B2PE(1.80f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
170 {64000,
171 {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.20f), FL2B2PE(1.60f)}}},
172 {96000,
173 {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}},
174 {128000,
175 {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.80f)}}},
176 {148000,
177 {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.40f)}}}};
178
179 static const BIT_PE_SFAC S_Bits2PeTab22050[] = {
180 /* bitrate| afterburner off | afterburner on | | nCh=1
181 | nCh=2 | nCh=1 | nCh=2 */
182 {16000,
183 {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}},
184 {24000,
185 {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.40f), FL2B2PE(1.00f)}}},
186 {32000,
187 {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.40f), FL2B2PE(1.20f)}}},
188 {48000,
189 {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.20f), FL2B2PE(1.40f)}}},
190 {64000,
191 {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
192 {96000,
193 {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
194 {128000,
195 {{FL2B2PE(1.80f), FL2B2PE(1.80f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
196 {148000,
197 {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}}};
198
199 static const BIT_PE_SFAC S_Bits2PeTab24000[] = {
200 /* bitrate| afterburner off | afterburner on | | nCh=1
201 | nCh=2 | nCh=1 | nCh=2 */
202 {16000,
203 {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}},
204 {24000,
205 {{FL2B2PE(1.60f), FL2B2PE(1.20f)}, {FL2B2PE(1.40f), FL2B2PE(1.00f)}}},
206 {32000,
207 {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.40f), FL2B2PE(0.80f)}}},
208 {48000,
209 {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.40f)}}},
210 {64000,
211 {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
212 {96000,
213 {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
214 {128000,
215 {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.80f)}}},
216 {148000,
217 {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.80f)}}}};
218
219 static const BIT_PE_SFAC S_Bits2PeTab32000[] = {
220 /* bitrate| afterburner off | afterburner on | | nCh=1
221 | nCh=2 | nCh=1 | nCh=2 */
222 {16000,
223 {{FL2B2PE(1.20f), FL2B2PE(1.40f)}, {FL2B2PE(0.80f), FL2B2PE(0.80f)}}},
224 {24000,
225 {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.60f)}}},
226 {32000,
227 {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}},
228 {48000,
229 {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(1.20f)}}},
230 {64000,
231 {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}},
232 {96000,
233 {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
234 {128000,
235 {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
236 {148000,
237 {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
238 {160000,
239 {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
240 {200000,
241 {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}},
242 {320000,
243 {{FL2B2PE(3.20f), FL2B2PE(1.80f)}, {FL2B2PE(3.20f), FL2B2PE(1.80f)}}}};
244
245 static const BIT_PE_SFAC S_Bits2PeTab44100[] = {
246 /* bitrate| afterburner off | afterburner on | | nCh=1
247 | nCh=2 | nCh=1 | nCh=2 */
248 {16000,
249 {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(0.80f), FL2B2PE(1.00f)}}},
250 {24000,
251 {{FL2B2PE(1.00f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}},
252 {32000,
253 {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(0.80f), FL2B2PE(0.60f)}}},
254 {48000,
255 {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}},
256 {64000,
257 {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(1.00f)}}},
258 {96000,
259 {{FL2B2PE(1.60f), FL2B2PE(1.20f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}},
260 {128000,
261 {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
262 {148000,
263 {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
264 {160000,
265 {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
266 {200000,
267 {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
268 {320000,
269 {{FL2B2PE(3.20f), FL2B2PE(1.60f)}, {FL2B2PE(3.20f), FL2B2PE(1.60f)}}}};
270
271 static const BIT_PE_SFAC S_Bits2PeTab48000[] = {
272 /* bitrate| afterburner off | afterburner on | | nCh=1
273 | nCh=2 | nCh=1 | nCh=2 */
274 {16000,
275 {{FL2B2PE(1.40f), FL2B2PE(0.00f)}, {FL2B2PE(0.80f), FL2B2PE(0.00f)}}},
276 {24000,
277 {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}},
278 {32000,
279 {{FL2B2PE(1.00f), FL2B2PE(1.20f)}, {FL2B2PE(0.60f), FL2B2PE(0.80f)}}},
280 {48000,
281 {{FL2B2PE(1.20f), FL2B2PE(1.00f)}, {FL2B2PE(0.80f), FL2B2PE(0.80f)}}},
282 {64000,
283 {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(1.00f)}}},
284 {96000,
285 {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}},
286 {128000,
287 {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
288 {148000,
289 {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
290 {160000,
291 {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
292 {200000,
293 {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
294 {320000,
295 {{FL2B2PE(3.20f), FL2B2PE(1.60f)}, {FL2B2PE(3.20f), FL2B2PE(1.60f)}}}};
296
297 static const BITS2PE_CFG_TAB bits2PeConfigTab[] = {
298 {16000, S_Bits2PeTab16000, sizeof(S_Bits2PeTab16000) / sizeof(BIT_PE_SFAC)},
299 {22050, S_Bits2PeTab22050, sizeof(S_Bits2PeTab22050) / sizeof(BIT_PE_SFAC)},
300 {24000, S_Bits2PeTab24000, sizeof(S_Bits2PeTab24000) / sizeof(BIT_PE_SFAC)},
301 {32000, S_Bits2PeTab32000, sizeof(S_Bits2PeTab32000) / sizeof(BIT_PE_SFAC)},
302 {44100, S_Bits2PeTab44100, sizeof(S_Bits2PeTab44100) / sizeof(BIT_PE_SFAC)},
303 {48000, S_Bits2PeTab48000,
304 sizeof(S_Bits2PeTab48000) / sizeof(BIT_PE_SFAC)}};
305
306 /* values for avoid hole flag */
307 enum _avoid_hole_state { NO_AH = 0, AH_INACTIVE = 1, AH_ACTIVE = 2 };
308
309 /* Q format definitions */
310 #define Q_BITFAC \
311 (24) /* Q scaling used in FDKaacEnc_bitresCalcBitFac() calculation */
312 #define Q_AVGBITS (17) /* scale bit values */
313
314 /*****************************************************************************
315 functionname: FDKaacEnc_InitBits2PeFactor
316 description: retrieve bits2PeFactor from table
317 *****************************************************************************/
FDKaacEnc_InitBits2PeFactor(FIXP_DBL * bits2PeFactor_m,INT * bits2PeFactor_e,const INT bitRate,const INT nChannels,const INT sampleRate,const INT advancedBitsToPe,const INT dZoneQuantEnable,const INT invQuant)318 static void FDKaacEnc_InitBits2PeFactor(
319 FIXP_DBL *bits2PeFactor_m, INT *bits2PeFactor_e, const INT bitRate,
320 const INT nChannels, const INT sampleRate, const INT advancedBitsToPe,
321 const INT dZoneQuantEnable, const INT invQuant) {
322 /**** 1) Set default bits2pe factor ****/
323 FIXP_DBL bit2PE_m = FL2FXCONST_DBL(1.18f / (1 << (1)));
324 INT bit2PE_e = 1;
325
326 /**** 2) For AAC-(E)LD, make use of advanced bits to pe factor table ****/
327 if (advancedBitsToPe && nChannels <= (2)) {
328 int i;
329 const BIT_PE_SFAC *peTab = NULL;
330 INT size = 0;
331
332 /*** 2.1) Get correct table entry ***/
333 for (i = 0; i < (INT)(sizeof(bits2PeConfigTab) / sizeof(BITS2PE_CFG_TAB));
334 i++) {
335 if (sampleRate >= bits2PeConfigTab[i].sampleRate) {
336 peTab = bits2PeConfigTab[i].pPeTab;
337 size = bits2PeConfigTab[i].nEntries;
338 }
339 }
340
341 if ((peTab != NULL) && (size != 0)) {
342 INT startB = -1; /* bitrate entry in table that is the next-lower to
343 actual bitrate */
344 INT stopB = -1; /* bitrate entry in table that is the next-higher to
345 actual bitrate */
346 FIXP_DBL startPF =
347 FL2FXCONST_DBL(0.0f); /* bits2PE factor entry in table that is the
348 next-lower to actual bits2PE factor */
349 FIXP_DBL stopPF = FL2FXCONST_DBL(0.0f); /* bits2PE factor entry in table
350 that is the next-higher to
351 actual bits2PE factor */
352 FIXP_DBL slope = FL2FXCONST_DBL(
353 0.0f); /* the slope from the start bits2Pe entry to the next one */
354 const int qualityIdx = (invQuant == 0) ? 0 : 1;
355
356 if (bitRate >= peTab[size - 1].bitrate) {
357 /* Chosen bitrate is higher than the highest bitrate in table.
358 The slope for extrapolating the bits2PE factor must be zero.
359 Values are set accordingly. */
360 startB = peTab[size - 1].bitrate;
361 stopB =
362 bitRate +
363 1; /* Can be an arbitrary value greater than startB and bitrate. */
364 startPF = peTab[size - 1].bits2PeFactor[qualityIdx][nChannels - 1];
365 stopPF = peTab[size - 1].bits2PeFactor[qualityIdx][nChannels - 1];
366 } else {
367 for (i = 0; i < size - 1; i++) {
368 if ((peTab[i].bitrate <= bitRate) &&
369 (peTab[i + 1].bitrate > bitRate)) {
370 startB = peTab[i].bitrate;
371 stopB = peTab[i + 1].bitrate;
372 startPF = peTab[i].bits2PeFactor[qualityIdx][nChannels - 1];
373 stopPF = peTab[i + 1].bits2PeFactor[qualityIdx][nChannels - 1];
374 break;
375 }
376 }
377 }
378
379 /*** 2.2) Configuration available? ***/
380 if (startB != -1) {
381 /** 2.2.1) linear interpolate to actual PEfactor **/
382 FIXP_DBL bit2PE = 0;
383
384 const FIXP_DBL maxBit2PE = FL2FXCONST_DBL(3.f / 4.f);
385
386 /* bit2PE = ((stopPF-startPF)/(stopB-startB))*(bitRate-startB)+startPF;
387 */
388 slope = fDivNorm(bitRate - startB, stopB - startB);
389 bit2PE = fMult(slope, stopPF - startPF) + startPF;
390
391 bit2PE = fMin(maxBit2PE, bit2PE);
392
393 /** 2.2.2) sanity check if bits2pe value is high enough **/
394 if (bit2PE >= (FL2FXCONST_DBL(0.35f) >> 2)) {
395 bit2PE_m = bit2PE;
396 bit2PE_e = 2; /* table is fixed scaled */
397 }
398 } /* br */
399 } /* sr */
400 } /* advancedBitsToPe */
401
402 if (dZoneQuantEnable) {
403 if (bit2PE_m >= (FL2FXCONST_DBL(0.6f)) >> bit2PE_e) {
404 /* Additional headroom for addition */
405 bit2PE_m >>= 1;
406 bit2PE_e += 1;
407 }
408
409 /* the quantTendencyCompensator compensates a lower bit consumption due to
410 * increasing the tendency to quantize low spectral values to the lower
411 * quantizer border for bitrates below a certain bitrate threshold --> see
412 * also function calcSfbDistLD in quantize.c */
413 if ((bitRate / nChannels > 32000) && (bitRate / nChannels <= 40000)) {
414 bit2PE_m += (FL2FXCONST_DBL(0.4f)) >> bit2PE_e;
415 } else if (bitRate / nChannels > 20000) {
416 bit2PE_m += (FL2FXCONST_DBL(0.3f)) >> bit2PE_e;
417 } else if (bitRate / nChannels >= 16000) {
418 bit2PE_m += (FL2FXCONST_DBL(0.3f)) >> bit2PE_e;
419 } else {
420 bit2PE_m += (FL2FXCONST_DBL(0.0f)) >> bit2PE_e;
421 }
422 }
423
424 /***** 3.) Return bits2pe factor *****/
425 *bits2PeFactor_m = bit2PE_m;
426 *bits2PeFactor_e = bit2PE_e;
427 }
428
429 /*****************************************************************************
430 functionname: FDKaacEnc_bits2pe2
431 description: convert from bits to pe
432 *****************************************************************************/
FDKaacEnc_bits2pe2(const INT bits,const FIXP_DBL factor_m,const INT factor_e)433 FDK_INLINE INT FDKaacEnc_bits2pe2(const INT bits, const FIXP_DBL factor_m,
434 const INT factor_e) {
435 return (INT)(fMult(factor_m, (FIXP_DBL)(bits << Q_AVGBITS)) >>
436 (Q_AVGBITS - factor_e));
437 }
438
439 /*****************************************************************************
440 functionname: FDKaacEnc_calcThreshExp
441 description: loudness calculation (threshold to the power of redExp)
442 *****************************************************************************/
FDKaacEnc_calcThreshExp(FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB],const QC_OUT_CHANNEL * const qcOutChannel[(2)],const PSY_OUT_CHANNEL * const psyOutChannel[(2)],const INT nChannels)443 static void FDKaacEnc_calcThreshExp(
444 FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB],
445 const QC_OUT_CHANNEL *const qcOutChannel[(2)],
446 const PSY_OUT_CHANNEL *const psyOutChannel[(2)], const INT nChannels) {
447 INT ch, sfb, sfbGrp;
448 FIXP_DBL thrExpLdData;
449
450 for (ch = 0; ch < nChannels; ch++) {
451 for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
452 sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
453 for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
454 thrExpLdData = psyOutChannel[ch]->sfbThresholdLdData[sfbGrp + sfb] >> 2;
455 thrExp[ch][sfbGrp + sfb] = CalcInvLdData(thrExpLdData);
456 }
457 }
458 }
459 }
460
461 /*****************************************************************************
462 functionname: FDKaacEnc_adaptMinSnr
463 description: reduce minSnr requirements for bands with relative low
464 energies
465 *****************************************************************************/
FDKaacEnc_adaptMinSnr(QC_OUT_CHANNEL * const qcOutChannel[(2)],const PSY_OUT_CHANNEL * const psyOutChannel[(2)],const MINSNR_ADAPT_PARAM * const msaParam,const INT nChannels)466 static void FDKaacEnc_adaptMinSnr(
467 QC_OUT_CHANNEL *const qcOutChannel[(2)],
468 const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
469 const MINSNR_ADAPT_PARAM *const msaParam, const INT nChannels) {
470 INT ch, sfb, sfbGrp, nSfb;
471 FIXP_DBL avgEnLD64, dbRatio, minSnrRed;
472 FIXP_DBL minSnrLimitLD64 =
473 FL2FXCONST_DBL(-0.00503012648262f); /* ld64(0.8f) */
474 FIXP_DBL nSfbLD64;
475 FIXP_DBL accu;
476
477 FIXP_DBL msaParam_maxRed = msaParam->maxRed;
478 FIXP_DBL msaParam_startRatio = msaParam->startRatio;
479 FIXP_DBL msaParam_redRatioFac =
480 fMult(msaParam->redRatioFac, FL2FXCONST_DBL(0.3010299956f));
481 FIXP_DBL msaParam_redOffs = msaParam->redOffs;
482
483 for (ch = 0; ch < nChannels; ch++) {
484 /* calc average energy per scalefactor band */
485 nSfb = 0;
486 accu = FL2FXCONST_DBL(0.0f);
487
488 DWORD_ALIGNED(psyOutChannel[ch]->sfbEnergy);
489
490 for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
491 sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
492 int maxSfbPerGroup = psyOutChannel[ch]->maxSfbPerGroup;
493 nSfb += maxSfbPerGroup;
494 for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
495 accu += psyOutChannel[ch]->sfbEnergy[sfbGrp + sfb] >> 6;
496 }
497 }
498
499 if ((accu == FL2FXCONST_DBL(0.0f)) || (nSfb == 0)) {
500 avgEnLD64 = FL2FXCONST_DBL(-1.0f);
501 } else {
502 nSfbLD64 = CalcLdInt(nSfb);
503 avgEnLD64 = CalcLdData(accu);
504 avgEnLD64 = avgEnLD64 + FL2FXCONST_DBL(0.09375f) -
505 nSfbLD64; /* 0.09375f: compensate shift with 6 */
506 }
507
508 /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */
509 int maxSfbPerGroup = psyOutChannel[ch]->maxSfbPerGroup;
510 int sfbCnt = psyOutChannel[ch]->sfbCnt;
511 int sfbPerGroup = psyOutChannel[ch]->sfbPerGroup;
512
513 for (sfbGrp = 0; sfbGrp < sfbCnt; sfbGrp += sfbPerGroup) {
514 FIXP_DBL *RESTRICT psfbEnergyLdData =
515 &qcOutChannel[ch]->sfbEnergyLdData[sfbGrp];
516 FIXP_DBL *RESTRICT psfbMinSnrLdData =
517 &qcOutChannel[ch]->sfbMinSnrLdData[sfbGrp];
518 for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
519 FIXP_DBL sfbEnergyLdData = *psfbEnergyLdData++;
520 FIXP_DBL sfbMinSnrLdData = *psfbMinSnrLdData;
521 dbRatio = avgEnLD64 - sfbEnergyLdData;
522 int update = (msaParam_startRatio < dbRatio) ? 1 : 0;
523 minSnrRed = msaParam_redOffs + fMult(msaParam_redRatioFac,
524 dbRatio); /* scaled by 1.0f/64.0f*/
525 minSnrRed =
526 fixMax(minSnrRed, msaParam_maxRed); /* scaled by 1.0f/64.0f*/
527 minSnrRed = (fMult(sfbMinSnrLdData, minSnrRed)) << 6;
528 minSnrRed = fixMin(minSnrLimitLD64, minSnrRed);
529 *psfbMinSnrLdData++ = update ? minSnrRed : sfbMinSnrLdData;
530 }
531 }
532 }
533 }
534
535 /*****************************************************************************
536 functionname: FDKaacEnc_initAvoidHoleFlag
537 description: determine bands where avoid hole is not necessary resp. possible
538 *****************************************************************************/
FDKaacEnc_initAvoidHoleFlag(QC_OUT_CHANNEL * const qcOutChannel[(2)],const PSY_OUT_CHANNEL * const psyOutChannel[(2)],UCHAR ahFlag[(2)][MAX_GROUPED_SFB],const struct TOOLSINFO * const toolsInfo,const INT nChannels,const AH_PARAM * const ahParam)539 static void FDKaacEnc_initAvoidHoleFlag(
540 QC_OUT_CHANNEL *const qcOutChannel[(2)],
541 const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
542 UCHAR ahFlag[(2)][MAX_GROUPED_SFB], const struct TOOLSINFO *const toolsInfo,
543 const INT nChannels, const AH_PARAM *const ahParam) {
544 INT ch, sfb, sfbGrp;
545 FIXP_DBL sfbEn, sfbEnm1;
546 FIXP_DBL sfbEnLdData;
547 FIXP_DBL avgEnLdData;
548
549 /* decrease spread energy by 3dB for long blocks, resp. 2dB for shorts
550 (avoid more holes in long blocks) */
551 for (ch = 0; ch < nChannels; ch++) {
552 QC_OUT_CHANNEL *const qcOutChan = qcOutChannel[ch];
553
554 if (psyOutChannel[ch]->lastWindowSequence != SHORT_WINDOW) {
555 for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
556 sfbGrp += psyOutChannel[ch]->sfbPerGroup)
557 for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++)
558 qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] >>= 1;
559 } else {
560 for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
561 sfbGrp += psyOutChannel[ch]->sfbPerGroup)
562 for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++)
563 qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] = fMult(
564 FL2FXCONST_DBL(0.63f), qcOutChan->sfbSpreadEnergy[sfbGrp + sfb]);
565 }
566 }
567
568 /* increase minSnr for local peaks, decrease it for valleys */
569 if (ahParam->modifyMinSnr) {
570 for (ch = 0; ch < nChannels; ch++) {
571 QC_OUT_CHANNEL *const qcOutChan = qcOutChannel[ch];
572 for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
573 sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
574 for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
575 FIXP_DBL sfbEnp1, avgEn;
576 if (sfb > 0)
577 sfbEnm1 = qcOutChan->sfbEnergy[sfbGrp + sfb - 1];
578 else
579 sfbEnm1 = qcOutChan->sfbEnergy[sfbGrp + sfb];
580
581 if (sfb < psyOutChannel[ch]->maxSfbPerGroup - 1)
582 sfbEnp1 = qcOutChan->sfbEnergy[sfbGrp + sfb + 1];
583 else
584 sfbEnp1 = qcOutChan->sfbEnergy[sfbGrp + sfb];
585
586 avgEn = (sfbEnm1 >> 1) + (sfbEnp1 >> 1);
587 avgEnLdData = CalcLdData(avgEn);
588 sfbEn = qcOutChan->sfbEnergy[sfbGrp + sfb];
589 sfbEnLdData = qcOutChan->sfbEnergyLdData[sfbGrp + sfb];
590 /* peak ? */
591 if (sfbEn > avgEn) {
592 FIXP_DBL tmpMinSnrLdData;
593 if (psyOutChannel[ch]->lastWindowSequence == LONG_WINDOW)
594 tmpMinSnrLdData =
595 fixMax(SnrLdFac + (FIXP_DBL)(avgEnLdData - sfbEnLdData),
596 (FIXP_DBL)SnrLdMin1);
597 else
598 tmpMinSnrLdData =
599 fixMax(SnrLdFac + (FIXP_DBL)(avgEnLdData - sfbEnLdData),
600 (FIXP_DBL)SnrLdMin3);
601
602 qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] = fixMin(
603 qcOutChan->sfbMinSnrLdData[sfbGrp + sfb], tmpMinSnrLdData);
604 }
605 /* valley ? */
606 if (((sfbEnLdData + (FIXP_DBL)SnrLdMin4) < (FIXP_DBL)avgEnLdData) &&
607 (sfbEn > FL2FXCONST_DBL(0.0))) {
608 FIXP_DBL tmpMinSnrLdData = avgEnLdData - sfbEnLdData -
609 (FIXP_DBL)SnrLdMin4 +
610 qcOutChan->sfbMinSnrLdData[sfbGrp + sfb];
611 tmpMinSnrLdData = fixMin((FIXP_DBL)SnrLdFac, tmpMinSnrLdData);
612 qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] =
613 fixMin(tmpMinSnrLdData,
614 (FIXP_DBL)(qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] +
615 SnrLdMin2));
616 }
617 }
618 }
619 }
620 }
621
622 /* stereo: adapt the minimum requirements sfbMinSnr of mid and
623 side channels to avoid spending unnoticable bits */
624 if (nChannels == 2) {
625 QC_OUT_CHANNEL *qcOutChanM = qcOutChannel[0];
626 QC_OUT_CHANNEL *qcOutChanS = qcOutChannel[1];
627 const PSY_OUT_CHANNEL *const psyOutChanM = psyOutChannel[0];
628 for (sfbGrp = 0; sfbGrp < psyOutChanM->sfbCnt;
629 sfbGrp += psyOutChanM->sfbPerGroup) {
630 for (sfb = 0; sfb < psyOutChanM->maxSfbPerGroup; sfb++) {
631 if (toolsInfo->msMask[sfbGrp + sfb]) {
632 FIXP_DBL maxSfbEnLd =
633 fixMax(qcOutChanM->sfbEnergyLdData[sfbGrp + sfb],
634 qcOutChanS->sfbEnergyLdData[sfbGrp + sfb]);
635 FIXP_DBL maxThrLd, sfbMinSnrTmpLd;
636
637 if (((SnrLdMin5 >> 1) + (maxSfbEnLd >> 1) +
638 (qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] >> 1)) <=
639 FL2FXCONST_DBL(-0.5f))
640 maxThrLd = FL2FXCONST_DBL(-1.0f);
641 else
642 maxThrLd = SnrLdMin5 + maxSfbEnLd +
643 qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb];
644
645 if (qcOutChanM->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f))
646 sfbMinSnrTmpLd =
647 maxThrLd - qcOutChanM->sfbEnergyLdData[sfbGrp + sfb];
648 else
649 sfbMinSnrTmpLd = FL2FXCONST_DBL(0.0f);
650
651 qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] =
652 fixMax(qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb], sfbMinSnrTmpLd);
653
654 if (qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] <= FL2FXCONST_DBL(0.0f))
655 qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] = fixMin(
656 qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb], (FIXP_DBL)SnrLdFac);
657
658 if (qcOutChanS->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f))
659 sfbMinSnrTmpLd =
660 maxThrLd - qcOutChanS->sfbEnergyLdData[sfbGrp + sfb];
661 else
662 sfbMinSnrTmpLd = FL2FXCONST_DBL(0.0f);
663
664 qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] =
665 fixMax(qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb], sfbMinSnrTmpLd);
666
667 if (qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] <= FL2FXCONST_DBL(0.0f))
668 qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] = fixMin(
669 qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb], (FIXP_DBL)SnrLdFac);
670
671 if (qcOutChanM->sfbEnergy[sfbGrp + sfb] >
672 qcOutChanM->sfbSpreadEnergy[sfbGrp + sfb])
673 qcOutChanS->sfbSpreadEnergy[sfbGrp + sfb] = fMult(
674 qcOutChanS->sfbEnergy[sfbGrp + sfb], FL2FXCONST_DBL(0.9f));
675
676 if (qcOutChanS->sfbEnergy[sfbGrp + sfb] >
677 qcOutChanS->sfbSpreadEnergy[sfbGrp + sfb])
678 qcOutChanM->sfbSpreadEnergy[sfbGrp + sfb] = fMult(
679 qcOutChanM->sfbEnergy[sfbGrp + sfb], FL2FXCONST_DBL(0.9f));
680
681 } /* if (toolsInfo->msMask[sfbGrp+sfb]) */
682 } /* sfb */
683 } /* sfbGrp */
684 } /* nChannels==2 */
685
686 /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
687 for (ch = 0; ch < nChannels; ch++) {
688 QC_OUT_CHANNEL *qcOutChan = qcOutChannel[ch];
689 const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch];
690 for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
691 sfbGrp += psyOutChan->sfbPerGroup) {
692 for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
693 if ((qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] >
694 qcOutChan->sfbEnergy[sfbGrp + sfb]) ||
695 (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f))) {
696 ahFlag[ch][sfbGrp + sfb] = NO_AH;
697 } else {
698 ahFlag[ch][sfbGrp + sfb] = AH_INACTIVE;
699 }
700 }
701 }
702 }
703 }
704
705 /**
706 * \brief Calculate constants that do not change during successive pe
707 * calculations.
708 *
709 * \param peData Pointer to structure containing PE data of
710 * current element.
711 * \param psyOutChannel Pointer to PSY_OUT_CHANNEL struct holding
712 * nChannels elements.
713 * \param qcOutChannel Pointer to QC_OUT_CHANNEL struct holding
714 * nChannels elements.
715 * \param nChannels Number of channels in element.
716 * \param peOffset Fixed PE offset defined while
717 * FDKaacEnc_AdjThrInit() depending on bitrate.
718 *
719 * \return void
720 */
FDKaacEnc_preparePe(PE_DATA * const peData,const PSY_OUT_CHANNEL * const psyOutChannel[(2)],const QC_OUT_CHANNEL * const qcOutChannel[(2)],const INT nChannels,const INT peOffset)721 static void FDKaacEnc_preparePe(PE_DATA *const peData,
722 const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
723 const QC_OUT_CHANNEL *const qcOutChannel[(2)],
724 const INT nChannels, const INT peOffset) {
725 INT ch;
726
727 for (ch = 0; ch < nChannels; ch++) {
728 const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch];
729 FDKaacEnc_prepareSfbPe(
730 &peData->peChannelData[ch], psyOutChan->sfbEnergyLdData,
731 psyOutChan->sfbThresholdLdData, qcOutChannel[ch]->sfbFormFactorLdData,
732 psyOutChan->sfbOffsets, psyOutChan->sfbCnt, psyOutChan->sfbPerGroup,
733 psyOutChan->maxSfbPerGroup);
734 }
735 peData->offset = peOffset;
736 }
737
738 /**
739 * \brief Calculate weighting factor for threshold adjustment.
740 *
741 * Calculate weighting factor to be applied at energies and thresholds in ld64
742 * format.
743 *
744 * \param peData, Pointer to PE data in current element.
745 * \param psyOutChannel Pointer to PSY_OUT_CHANNEL struct holding
746 * nChannels elements.
747 * \param qcOutChannel Pointer to QC_OUT_CHANNEL struct holding
748 * nChannels elements.
749 * \param toolsInfo Pointer to tools info struct of current element.
750 * \param adjThrStateElement Pointer to ATS_ELEMENT holding enFacPatch
751 * states.
752 * \param nChannels Number of channels in element.
753 * \param usePatchTool Apply the weighting tool 0 (no) else (yes).
754 *
755 * \return void
756 */
FDKaacEnc_calcWeighting(const PE_DATA * const peData,const PSY_OUT_CHANNEL * const psyOutChannel[(2)],QC_OUT_CHANNEL * const qcOutChannel[(2)],const struct TOOLSINFO * const toolsInfo,ATS_ELEMENT * const adjThrStateElement,const INT nChannels,const INT usePatchTool)757 static void FDKaacEnc_calcWeighting(
758 const PE_DATA *const peData,
759 const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
760 QC_OUT_CHANNEL *const qcOutChannel[(2)],
761 const struct TOOLSINFO *const toolsInfo,
762 ATS_ELEMENT *const adjThrStateElement, const INT nChannels,
763 const INT usePatchTool) {
764 int ch, noShortWindowInFrame = TRUE;
765 INT exePatchM = 0;
766
767 for (ch = 0; ch < nChannels; ch++) {
768 if (psyOutChannel[ch]->lastWindowSequence == SHORT_WINDOW) {
769 noShortWindowInFrame = FALSE;
770 }
771 FDKmemclear(qcOutChannel[ch]->sfbEnFacLd,
772 MAX_GROUPED_SFB * sizeof(FIXP_DBL));
773 }
774
775 if (usePatchTool == 0) {
776 return; /* tool is disabled */
777 }
778
779 for (ch = 0; ch < nChannels; ch++) {
780 const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch];
781
782 if (noShortWindowInFrame) { /* retain energy ratio between blocks of
783 different length */
784
785 FIXP_DBL nrgSum14, nrgSum12, nrgSum34, nrgTotal;
786 FIXP_DBL nrgFacLd_14, nrgFacLd_12, nrgFacLd_34;
787 INT usePatch, exePatch;
788 int sfb, sfbGrp, nLinesSum = 0;
789
790 nrgSum14 = nrgSum12 = nrgSum34 = nrgTotal = FL2FXCONST_DBL(0.f);
791
792 /* calculate flatness of audible spectrum, i.e. spectrum above masking
793 * threshold. */
794 for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
795 sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
796 for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
797 FIXP_DBL nrgFac12 = CalcInvLdData(
798 psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1); /* nrg^(1/2) */
799 FIXP_DBL nrgFac14 = CalcInvLdData(
800 psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 2); /* nrg^(1/4) */
801
802 /* maximal number of bands is 64, results scaling factor 6 */
803 nLinesSum += peData->peChannelData[ch]
804 .sfbNLines[sfbGrp + sfb]; /* relevant lines */
805 nrgTotal +=
806 (psyOutChan->sfbEnergy[sfbGrp + sfb] >> 6); /* sum up nrg */
807 nrgSum12 += (nrgFac12 >> 6); /* sum up nrg^(2/4) */
808 nrgSum14 += (nrgFac14 >> 6); /* sum up nrg^(1/4) */
809 nrgSum34 += (fMult(nrgFac14, nrgFac12) >> 6); /* sum up nrg^(3/4) */
810 }
811 }
812
813 nrgTotal = CalcLdData(nrgTotal); /* get ld64 of total nrg */
814
815 nrgFacLd_14 =
816 CalcLdData(nrgSum14) - nrgTotal; /* ld64(nrgSum14/nrgTotal) */
817 nrgFacLd_12 =
818 CalcLdData(nrgSum12) - nrgTotal; /* ld64(nrgSum12/nrgTotal) */
819 nrgFacLd_34 =
820 CalcLdData(nrgSum34) - nrgTotal; /* ld64(nrgSum34/nrgTotal) */
821
822 /* Note: nLinesSum cannot be larger than the number of total lines, thats
823 * taken care of in line_pe.cpp FDKaacEnc_prepareSfbPe() */
824 adjThrStateElement->chaosMeasureEnFac[ch] =
825 fMax(FL2FXCONST_DBL(0.1875f),
826 fDivNorm(nLinesSum, psyOutChan->sfbOffsets[psyOutChan->sfbCnt]));
827
828 usePatch = (adjThrStateElement->chaosMeasureEnFac[ch] >
829 FL2FXCONST_DBL(0.78125f));
830 exePatch = ((usePatch) && (adjThrStateElement->lastEnFacPatch[ch]));
831
832 for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
833 sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
834 for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
835 INT sfbExePatch;
836 /* for MS coupled SFBs, also execute patch in side channel if done in
837 * mid channel */
838 if ((ch == 1) && (toolsInfo->msMask[sfbGrp + sfb])) {
839 sfbExePatch = exePatchM;
840 } else {
841 sfbExePatch = exePatch;
842 }
843
844 if ((sfbExePatch) &&
845 (psyOutChan->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.f))) {
846 /* execute patch based on spectral flatness calculated above */
847 if (adjThrStateElement->chaosMeasureEnFac[ch] >
848 FL2FXCONST_DBL(0.8125f)) {
849 qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] =
850 ((nrgFacLd_14 +
851 (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] +
852 (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1))) >>
853 1); /* sfbEnergy^(3/4) */
854 } else if (adjThrStateElement->chaosMeasureEnFac[ch] >
855 FL2FXCONST_DBL(0.796875f)) {
856 qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] =
857 ((nrgFacLd_12 + psyOutChan->sfbEnergyLdData[sfbGrp + sfb]) >>
858 1); /* sfbEnergy^(2/4) */
859 } else {
860 qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] =
861 ((nrgFacLd_34 +
862 (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1)) >>
863 1); /* sfbEnergy^(1/4) */
864 }
865 qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] =
866 fixMin(qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb], (FIXP_DBL)0);
867 }
868 }
869 } /* sfb loop */
870
871 adjThrStateElement->lastEnFacPatch[ch] = usePatch;
872 exePatchM = exePatch;
873 } else {
874 /* !noShortWindowInFrame */
875 adjThrStateElement->chaosMeasureEnFac[ch] = FL2FXCONST_DBL(0.75f);
876 adjThrStateElement->lastEnFacPatch[ch] =
877 TRUE; /* allow use of sfbEnFac patch in upcoming frame */
878 }
879
880 } /* ch loop */
881 }
882
883 /*****************************************************************************
884 functionname: FDKaacEnc_calcPe
885 description: calculate pe for both channels
886 *****************************************************************************/
FDKaacEnc_calcPe(const PSY_OUT_CHANNEL * const psyOutChannel[(2)],const QC_OUT_CHANNEL * const qcOutChannel[(2)],PE_DATA * const peData,const INT nChannels)887 static void FDKaacEnc_calcPe(const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
888 const QC_OUT_CHANNEL *const qcOutChannel[(2)],
889 PE_DATA *const peData, const INT nChannels) {
890 INT ch;
891
892 peData->pe = peData->offset;
893 peData->constPart = 0;
894 peData->nActiveLines = 0;
895 for (ch = 0; ch < nChannels; ch++) {
896 PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch];
897
898 FDKaacEnc_calcSfbPe(
899 peChanData, qcOutChannel[ch]->sfbWeightedEnergyLdData,
900 qcOutChannel[ch]->sfbThresholdLdData, psyOutChannel[ch]->sfbCnt,
901 psyOutChannel[ch]->sfbPerGroup, psyOutChannel[ch]->maxSfbPerGroup,
902 psyOutChannel[ch]->isBook, psyOutChannel[ch]->isScale);
903
904 peData->pe += peChanData->pe;
905 peData->constPart += peChanData->constPart;
906 peData->nActiveLines += peChanData->nActiveLines;
907 }
908 }
909
FDKaacEnc_peCalculation(PE_DATA * const peData,const PSY_OUT_CHANNEL * const psyOutChannel[(2)],QC_OUT_CHANNEL * const qcOutChannel[(2)],const struct TOOLSINFO * const toolsInfo,ATS_ELEMENT * const adjThrStateElement,const INT nChannels)910 void FDKaacEnc_peCalculation(PE_DATA *const peData,
911 const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
912 QC_OUT_CHANNEL *const qcOutChannel[(2)],
913 const struct TOOLSINFO *const toolsInfo,
914 ATS_ELEMENT *const adjThrStateElement,
915 const INT nChannels) {
916 /* constants that will not change during successive pe calculations */
917 FDKaacEnc_preparePe(peData, psyOutChannel, qcOutChannel, nChannels,
918 adjThrStateElement->peOffset);
919
920 /* calculate weighting factor for threshold adjustment */
921 FDKaacEnc_calcWeighting(peData, psyOutChannel, qcOutChannel, toolsInfo,
922 adjThrStateElement, nChannels, 1);
923 {
924 /* no weighting of threholds and energies for mlout */
925 /* weight energies and thresholds */
926 int ch;
927 for (ch = 0; ch < nChannels; ch++) {
928 int sfb, sfbGrp;
929 QC_OUT_CHANNEL *pQcOutCh = qcOutChannel[ch];
930
931 for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
932 sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
933 for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
934 pQcOutCh->sfbWeightedEnergyLdData[sfb + sfbGrp] =
935 pQcOutCh->sfbEnergyLdData[sfb + sfbGrp] -
936 pQcOutCh->sfbEnFacLd[sfb + sfbGrp];
937 pQcOutCh->sfbThresholdLdData[sfb + sfbGrp] -=
938 pQcOutCh->sfbEnFacLd[sfb + sfbGrp];
939 }
940 }
941 }
942 }
943
944 /* pe without reduction */
945 FDKaacEnc_calcPe(psyOutChannel, qcOutChannel, peData, nChannels);
946 }
947
948 /*****************************************************************************
949 functionname: FDKaacEnc_FDKaacEnc_calcPeNoAH
950 description: sum the pe data only for bands where avoid hole is inactive
951 *****************************************************************************/
952 #define CONSTPART_HEADROOM 4
FDKaacEnc_FDKaacEnc_calcPeNoAH(INT * const pe,INT * const constPart,INT * const nActiveLines,const PE_DATA * const peData,const UCHAR ahFlag[(2)][MAX_GROUPED_SFB],const PSY_OUT_CHANNEL * const psyOutChannel[(2)],const INT nChannels)953 static void FDKaacEnc_FDKaacEnc_calcPeNoAH(
954 INT *const pe, INT *const constPart, INT *const nActiveLines,
955 const PE_DATA *const peData, const UCHAR ahFlag[(2)][MAX_GROUPED_SFB],
956 const PSY_OUT_CHANNEL *const psyOutChannel[(2)], const INT nChannels) {
957 INT ch, sfb, sfbGrp;
958
959 INT pe_tmp = peData->offset;
960 INT constPart_tmp = 0;
961 INT nActiveLines_tmp = 0;
962 for (ch = 0; ch < nChannels; ch++) {
963 const PE_CHANNEL_DATA *const peChanData = &peData->peChannelData[ch];
964 for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
965 sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
966 for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
967 if (ahFlag[ch][sfbGrp + sfb] < AH_ACTIVE) {
968 pe_tmp += peChanData->sfbPe[sfbGrp + sfb];
969 constPart_tmp +=
970 peChanData->sfbConstPart[sfbGrp + sfb] >> CONSTPART_HEADROOM;
971 nActiveLines_tmp += peChanData->sfbNActiveLines[sfbGrp + sfb];
972 }
973 }
974 }
975 }
976 /* correct scaled pe and constPart values */
977 *pe = pe_tmp >> PE_CONSTPART_SHIFT;
978 *constPart = constPart_tmp >> (PE_CONSTPART_SHIFT - CONSTPART_HEADROOM);
979
980 *nActiveLines = nActiveLines_tmp;
981 }
982
983 /*****************************************************************************
984 functionname: FDKaacEnc_reduceThresholdsCBR
985 description: apply reduction formula
986 *****************************************************************************/
987 static const FIXP_DBL limitThrReducedLdData =
988 (FIXP_DBL)0x00008000; /*FL2FXCONST_DBL(FDKpow(2.0,-LD_DATA_SCALING/4.0));*/
989
FDKaacEnc_reduceThresholdsCBR(QC_OUT_CHANNEL * const qcOutChannel[(2)],const PSY_OUT_CHANNEL * const psyOutChannel[(2)],UCHAR ahFlag[(2)][MAX_GROUPED_SFB],const FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB],const INT nChannels,const FIXP_DBL redVal_m,const SCHAR redVal_e)990 static void FDKaacEnc_reduceThresholdsCBR(
991 QC_OUT_CHANNEL *const qcOutChannel[(2)],
992 const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
993 UCHAR ahFlag[(2)][MAX_GROUPED_SFB],
994 const FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], const INT nChannels,
995 const FIXP_DBL redVal_m, const SCHAR redVal_e) {
996 INT ch, sfb, sfbGrp;
997 FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData;
998 FIXP_DBL sfbThrExp;
999
1000 for (ch = 0; ch < nChannels; ch++) {
1001 QC_OUT_CHANNEL *qcOutChan = qcOutChannel[ch];
1002 for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
1003 sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
1004 for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
1005 sfbEnLdData = qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb];
1006 sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp + sfb];
1007 sfbThrExp = thrExp[ch][sfbGrp + sfb];
1008 if ((sfbEnLdData > sfbThrLdData) &&
1009 (ahFlag[ch][sfbGrp + sfb] != AH_ACTIVE)) {
1010 /* threshold reduction formula:
1011 float tmp = thrExp[ch][sfb]+redVal;
1012 tmp *= tmp;
1013 sfbThrReduced = tmp*tmp;
1014 */
1015 int minScale = fixMin(CountLeadingBits(sfbThrExp),
1016 CountLeadingBits(redVal_m) - redVal_e) -
1017 1;
1018
1019 /* 4*log( sfbThrExp + redVal ) */
1020 sfbThrReducedLdData =
1021 CalcLdData(fAbs(scaleValue(sfbThrExp, minScale) +
1022 scaleValue(redVal_m, redVal_e + minScale))) -
1023 (FIXP_DBL)(minScale << (DFRACT_BITS - 1 - LD_DATA_SHIFT));
1024 sfbThrReducedLdData <<= 2;
1025
1026 /* avoid holes */
1027 if ((sfbThrReducedLdData >
1028 (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData)) &&
1029 (ahFlag[ch][sfbGrp + sfb] != NO_AH)) {
1030 if (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] >
1031 (FL2FXCONST_DBL(-1.0f) - sfbEnLdData)) {
1032 sfbThrReducedLdData = fixMax(
1033 (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData),
1034 sfbThrLdData);
1035 } else
1036 sfbThrReducedLdData = sfbThrLdData;
1037 ahFlag[ch][sfbGrp + sfb] = AH_ACTIVE;
1038 }
1039
1040 /* minimum of 29 dB Ratio for Thresholds */
1041 if ((sfbEnLdData + (FIXP_DBL)MAXVAL_DBL) >
1042 FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING)) {
1043 sfbThrReducedLdData = fixMax(
1044 sfbThrReducedLdData,
1045 (sfbEnLdData - FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING)));
1046 }
1047
1048 qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData;
1049 }
1050 }
1051 }
1052 }
1053 }
1054
1055 /* similar to prepareSfbPe1() */
FDKaacEnc_calcChaosMeasure(const PSY_OUT_CHANNEL * const psyOutChannel,const FIXP_DBL * const sfbFormFactorLdData)1056 static FIXP_DBL FDKaacEnc_calcChaosMeasure(
1057 const PSY_OUT_CHANNEL *const psyOutChannel,
1058 const FIXP_DBL *const sfbFormFactorLdData) {
1059 #define SCALE_FORM_FAC \
1060 (4) /* (SCALE_FORM_FAC+FORM_FAC_SHIFT) >= ld(FRAME_LENGTH)*/
1061 #define SCALE_NRGS (8)
1062 #define SCALE_NLINES (16)
1063 #define SCALE_NRGS_SQRT4 (2) /* 0.25 * SCALE_NRGS */
1064 #define SCALE_NLINES_P34 (12) /* 0.75 * SCALE_NLINES */
1065
1066 INT sfbGrp, sfb;
1067 FIXP_DBL chaosMeasure;
1068 INT frameNLines = 0;
1069 FIXP_DBL frameFormFactor = FL2FXCONST_DBL(0.f);
1070 FIXP_DBL frameEnergy = FL2FXCONST_DBL(0.f);
1071
1072 for (sfbGrp = 0; sfbGrp < psyOutChannel->sfbCnt;
1073 sfbGrp += psyOutChannel->sfbPerGroup) {
1074 for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) {
1075 if (psyOutChannel->sfbEnergyLdData[sfbGrp + sfb] >
1076 psyOutChannel->sfbThresholdLdData[sfbGrp + sfb]) {
1077 frameFormFactor += (CalcInvLdData(sfbFormFactorLdData[sfbGrp + sfb]) >>
1078 SCALE_FORM_FAC);
1079 frameNLines += (psyOutChannel->sfbOffsets[sfbGrp + sfb + 1] -
1080 psyOutChannel->sfbOffsets[sfbGrp + sfb]);
1081 frameEnergy += (psyOutChannel->sfbEnergy[sfbGrp + sfb] >> SCALE_NRGS);
1082 }
1083 }
1084 }
1085
1086 if (frameNLines > 0) {
1087 /* frameNActiveLines = frameFormFactor*2^FORM_FAC_SHIFT * ((frameEnergy
1088 *2^SCALE_NRGS)/frameNLines)^-0.25 chaosMeasure = frameNActiveLines /
1089 frameNLines */
1090 chaosMeasure = CalcInvLdData(
1091 (((CalcLdData(frameFormFactor) >> 1) -
1092 (CalcLdData(frameEnergy) >> (2 + 1))) -
1093 (fMultDiv2(FL2FXCONST_DBL(0.75f),
1094 CalcLdData((FIXP_DBL)frameNLines
1095 << (DFRACT_BITS - 1 - SCALE_NLINES))) -
1096 (((FIXP_DBL)(-((-SCALE_FORM_FAC + SCALE_NRGS_SQRT4 - FORM_FAC_SHIFT +
1097 SCALE_NLINES_P34)
1098 << (DFRACT_BITS - 1 - LD_DATA_SHIFT)))) >>
1099 1)))
1100 << 1);
1101 } else {
1102 /* assuming total chaos, if no sfb is above thresholds */
1103 chaosMeasure = FL2FXCONST_DBL(1.f);
1104 }
1105
1106 return chaosMeasure;
1107 }
1108
1109 /* apply reduction formula for VBR-mode */
FDKaacEnc_reduceThresholdsVBR(QC_OUT_CHANNEL * const qcOutChannel[(2)],const PSY_OUT_CHANNEL * const psyOutChannel[(2)],UCHAR ahFlag[(2)][MAX_GROUPED_SFB],const FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB],const INT nChannels,const FIXP_DBL vbrQualFactor,FIXP_DBL * const chaosMeasureOld)1110 static void FDKaacEnc_reduceThresholdsVBR(
1111 QC_OUT_CHANNEL *const qcOutChannel[(2)],
1112 const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
1113 UCHAR ahFlag[(2)][MAX_GROUPED_SFB],
1114 const FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], const INT nChannels,
1115 const FIXP_DBL vbrQualFactor, FIXP_DBL *const chaosMeasureOld) {
1116 INT ch, sfbGrp, sfb;
1117 FIXP_DBL chGroupEnergy[TRANS_FAC][2]; /*energy for each group and channel*/
1118 FIXP_DBL chChaosMeasure[2];
1119 FIXP_DBL frameEnergy = FL2FXCONST_DBL(1e-10f);
1120 FIXP_DBL chaosMeasure = FL2FXCONST_DBL(0.f);
1121 FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrExp;
1122 FIXP_DBL sfbThrReducedLdData;
1123 FIXP_DBL chaosMeasureAvg;
1124 INT groupCnt; /* loop counter */
1125 FIXP_DBL redVal[TRANS_FAC]; /* reduction values; in short-block case one
1126 redVal for each group */
1127 QC_OUT_CHANNEL *qcOutChan = NULL;
1128 const PSY_OUT_CHANNEL *psyOutChan = NULL;
1129
1130 #define SCALE_GROUP_ENERGY (8)
1131
1132 #define CONST_CHAOS_MEAS_AVG_FAC_0 (FL2FXCONST_DBL(0.25f))
1133 #define CONST_CHAOS_MEAS_AVG_FAC_1 (FL2FXCONST_DBL(1.f - 0.25f))
1134
1135 #define MIN_LDTHRESH (FL2FXCONST_DBL(-0.515625f))
1136
1137 for (ch = 0; ch < nChannels; ch++) {
1138 psyOutChan = psyOutChannel[ch];
1139
1140 /* adding up energy for each channel and each group separately */
1141 FIXP_DBL chEnergy = FL2FXCONST_DBL(0.f);
1142 groupCnt = 0;
1143
1144 for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
1145 sfbGrp += psyOutChan->sfbPerGroup, groupCnt++) {
1146 chGroupEnergy[groupCnt][ch] = FL2FXCONST_DBL(0.f);
1147 for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
1148 chGroupEnergy[groupCnt][ch] +=
1149 (psyOutChan->sfbEnergy[sfbGrp + sfb] >> SCALE_GROUP_ENERGY);
1150 }
1151 chEnergy += chGroupEnergy[groupCnt][ch];
1152 }
1153 frameEnergy += chEnergy;
1154
1155 /* chaosMeasure */
1156 if (psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) {
1157 chChaosMeasure[ch] = FL2FXCONST_DBL(
1158 0.5f); /* assume a constant chaos measure of 0.5f for short blocks */
1159 } else {
1160 chChaosMeasure[ch] = FDKaacEnc_calcChaosMeasure(
1161 psyOutChannel[ch], qcOutChannel[ch]->sfbFormFactorLdData);
1162 }
1163 chaosMeasure += fMult(chChaosMeasure[ch], chEnergy);
1164 }
1165
1166 if (frameEnergy > chaosMeasure) {
1167 INT scale = CntLeadingZeros(frameEnergy) - 1;
1168 FIXP_DBL num = chaosMeasure << scale;
1169 FIXP_DBL denum = frameEnergy << scale;
1170 chaosMeasure = schur_div(num, denum, 16);
1171 } else {
1172 chaosMeasure = FL2FXCONST_DBL(1.f);
1173 }
1174
1175 chaosMeasureAvg = fMult(CONST_CHAOS_MEAS_AVG_FAC_0, chaosMeasure) +
1176 fMult(CONST_CHAOS_MEAS_AVG_FAC_1,
1177 *chaosMeasureOld); /* averaging chaos measure */
1178 *chaosMeasureOld = chaosMeasure = (fixMin(
1179 chaosMeasure, chaosMeasureAvg)); /* use min-value, safe for next frame */
1180
1181 /* characteristic curve
1182 chaosMeasure = 0.2f + 0.7f/0.3f * (chaosMeasure - 0.2f);
1183 chaosMeasure = fixMin(1.0f, fixMax(0.1f, chaosMeasure));
1184 constants scaled by 4.f
1185 */
1186 chaosMeasure = ((FL2FXCONST_DBL(0.2f) >> 2) +
1187 fMult(FL2FXCONST_DBL(0.7f / (4.f * 0.3f)),
1188 (chaosMeasure - FL2FXCONST_DBL(0.2f))));
1189 chaosMeasure =
1190 (fixMin((FIXP_DBL)(FL2FXCONST_DBL(1.0f) >> 2),
1191 fixMax((FIXP_DBL)(FL2FXCONST_DBL(0.1f) >> 2), chaosMeasure)))
1192 << 2;
1193
1194 /* calculation of reduction value */
1195 if (psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) { /* short-blocks */
1196 FDK_ASSERT(TRANS_FAC == 8);
1197 #define WIN_TYPE_SCALE (3)
1198
1199 groupCnt = 0;
1200 for (sfbGrp = 0; sfbGrp < psyOutChannel[0]->sfbCnt;
1201 sfbGrp += psyOutChannel[0]->sfbPerGroup, groupCnt++) {
1202 FIXP_DBL groupEnergy = FL2FXCONST_DBL(0.f);
1203
1204 for (ch = 0; ch < nChannels; ch++) {
1205 groupEnergy +=
1206 chGroupEnergy[groupCnt]
1207 [ch]; /* adding up the channels groupEnergy */
1208 }
1209
1210 FDK_ASSERT(psyOutChannel[0]->groupLen[groupCnt] <= INV_INT_TAB_SIZE);
1211 groupEnergy = fMult(
1212 groupEnergy,
1213 invInt[psyOutChannel[0]->groupLen[groupCnt]]); /* correction of
1214 group energy */
1215 groupEnergy = fixMin(groupEnergy,
1216 frameEnergy >> WIN_TYPE_SCALE); /* do not allow an
1217 higher redVal as
1218 calculated
1219 framewise */
1220
1221 groupEnergy >>=
1222 2; /* 2*WIN_TYPE_SCALE = 6 => 6+2 = 8 ==> 8/4 = int number */
1223
1224 redVal[groupCnt] =
1225 fMult(fMult(vbrQualFactor, chaosMeasure),
1226 CalcInvLdData(CalcLdData(groupEnergy) >> 2))
1227 << (int)((2 + (2 * WIN_TYPE_SCALE) + SCALE_GROUP_ENERGY) >> 2);
1228 }
1229 } else { /* long-block */
1230
1231 redVal[0] = fMult(fMult(vbrQualFactor, chaosMeasure),
1232 CalcInvLdData(CalcLdData(frameEnergy) >> 2))
1233 << (int)(SCALE_GROUP_ENERGY >> 2);
1234 }
1235
1236 for (ch = 0; ch < nChannels; ch++) {
1237 qcOutChan = qcOutChannel[ch];
1238 psyOutChan = psyOutChannel[ch];
1239
1240 for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
1241 sfbGrp += psyOutChan->sfbPerGroup) {
1242 for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
1243 sfbEnLdData = (qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb]);
1244 sfbThrLdData = (qcOutChan->sfbThresholdLdData[sfbGrp + sfb]);
1245 sfbThrExp = thrExp[ch][sfbGrp + sfb];
1246
1247 if ((sfbThrLdData >= MIN_LDTHRESH) && (sfbEnLdData > sfbThrLdData) &&
1248 (ahFlag[ch][sfbGrp + sfb] != AH_ACTIVE)) {
1249 /* Short-Window */
1250 if (psyOutChannel[ch]->lastWindowSequence == SHORT_WINDOW) {
1251 const int groupNumber = (int)sfb / psyOutChan->sfbPerGroup;
1252
1253 FDK_ASSERT(INV_SQRT4_TAB_SIZE > psyOutChan->groupLen[groupNumber]);
1254
1255 sfbThrExp =
1256 fMult(sfbThrExp,
1257 fMult(FL2FXCONST_DBL(2.82f / 4.f),
1258 invSqrt4[psyOutChan->groupLen[groupNumber]]))
1259 << 2;
1260
1261 if (sfbThrExp <= (limitThrReducedLdData - redVal[groupNumber])) {
1262 sfbThrReducedLdData = FL2FXCONST_DBL(-1.0f);
1263 } else {
1264 if ((FIXP_DBL)redVal[groupNumber] >=
1265 FL2FXCONST_DBL(1.0f) - sfbThrExp)
1266 sfbThrReducedLdData = FL2FXCONST_DBL(0.0f);
1267 else {
1268 /* threshold reduction formula */
1269 sfbThrReducedLdData =
1270 CalcLdData(sfbThrExp + redVal[groupNumber]);
1271 sfbThrReducedLdData <<= 2;
1272 }
1273 }
1274 sfbThrReducedLdData +=
1275 (CalcLdInt(psyOutChan->groupLen[groupNumber]) -
1276 ((FIXP_DBL)6 << (DFRACT_BITS - 1 - LD_DATA_SHIFT)));
1277 }
1278
1279 /* Long-Window */
1280 else {
1281 if ((FIXP_DBL)redVal[0] >= FL2FXCONST_DBL(1.0f) - sfbThrExp) {
1282 sfbThrReducedLdData = FL2FXCONST_DBL(0.0f);
1283 } else {
1284 /* threshold reduction formula */
1285 sfbThrReducedLdData = CalcLdData(sfbThrExp + redVal[0]);
1286 sfbThrReducedLdData <<= 2;
1287 }
1288 }
1289
1290 /* avoid holes */
1291 if (((sfbThrReducedLdData - sfbEnLdData) >
1292 qcOutChan->sfbMinSnrLdData[sfbGrp + sfb]) &&
1293 (ahFlag[ch][sfbGrp + sfb] != NO_AH)) {
1294 if (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] >
1295 (FL2FXCONST_DBL(-1.0f) - sfbEnLdData)) {
1296 sfbThrReducedLdData = fixMax(
1297 (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData),
1298 sfbThrLdData);
1299 } else
1300 sfbThrReducedLdData = sfbThrLdData;
1301 ahFlag[ch][sfbGrp + sfb] = AH_ACTIVE;
1302 }
1303
1304 if (sfbThrReducedLdData < FL2FXCONST_DBL(-0.5f))
1305 sfbThrReducedLdData = FL2FXCONST_DBL(-1.f);
1306
1307 /* minimum of 29 dB Ratio for Thresholds */
1308 if ((sfbEnLdData + FL2FXCONST_DBL(1.0f)) >
1309 FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING)) {
1310 sfbThrReducedLdData = fixMax(
1311 sfbThrReducedLdData,
1312 sfbEnLdData - FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING));
1313 }
1314
1315 sfbThrReducedLdData = fixMax(MIN_LDTHRESH, sfbThrReducedLdData);
1316
1317 qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData;
1318 }
1319 }
1320 }
1321 }
1322 }
1323
1324 /*****************************************************************************
1325 functionname: FDKaacEnc_correctThresh
1326 description: if pe difference deltaPe between desired pe and real pe is small
1327 enough, the difference can be distributed among the scale factor bands. New
1328 thresholds can be derived from this pe-difference
1329 *****************************************************************************/
FDKaacEnc_correctThresh(const CHANNEL_MAPPING * const cm,QC_OUT_ELEMENT * const qcElement[((8))],const PSY_OUT_ELEMENT * const psyOutElement[((8))],UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB],const FIXP_DBL thrExp[((8))][(2)][MAX_GROUPED_SFB],const FIXP_DBL redVal_m,const SCHAR redVal_e,const INT deltaPe,const INT processElements,const INT elementOffset)1330 static void FDKaacEnc_correctThresh(
1331 const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
1332 const PSY_OUT_ELEMENT *const psyOutElement[((8))],
1333 UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB],
1334 const FIXP_DBL thrExp[((8))][(2)][MAX_GROUPED_SFB], const FIXP_DBL redVal_m,
1335 const SCHAR redVal_e, const INT deltaPe, const INT processElements,
1336 const INT elementOffset) {
1337 INT ch, sfb, sfbGrp;
1338 QC_OUT_CHANNEL *qcOutChan;
1339 PSY_OUT_CHANNEL *psyOutChan;
1340 PE_CHANNEL_DATA *peChanData;
1341 FIXP_DBL thrFactorLdData;
1342 FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData;
1343 FIXP_DBL *sfbPeFactorsLdData[((8))][(2)];
1344 FIXP_DBL(*sfbNActiveLinesLdData)[(2)][MAX_GROUPED_SFB];
1345
1346 INT normFactorInt;
1347 FIXP_DBL normFactorLdData;
1348
1349 INT nElements = elementOffset + processElements;
1350 INT elementId;
1351
1352 /* scratch is empty; use temporal memory from quantSpec in QC_OUT_CHANNEL */
1353 for (elementId = elementOffset; elementId < nElements; elementId++) {
1354 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1355 /* The reinterpret_cast is used to suppress a compiler warning. We know
1356 * that qcElement[elementId]->qcOutChannel[ch]->quantSpec is sufficiently
1357 * aligned, so the cast is safe */
1358 sfbPeFactorsLdData[elementId][ch] =
1359 reinterpret_cast<FIXP_DBL *>(reinterpret_cast<void *>(
1360 qcElement[elementId]->qcOutChannel[ch]->quantSpec));
1361 }
1362 }
1363 /* The reinterpret_cast is used to suppress a compiler warning. We know that
1364 * qcElement[0]->dynMem_SfbNActiveLinesLdData is sufficiently aligned, so the
1365 * cast is safe */
1366 sfbNActiveLinesLdData = reinterpret_cast<FIXP_DBL(*)[(2)][MAX_GROUPED_SFB]>(
1367 reinterpret_cast<void *>(qcElement[0]->dynMem_SfbNActiveLinesLdData));
1368
1369 /* for each sfb calc relative factors for pe changes */
1370 normFactorInt = 0;
1371
1372 for (elementId = elementOffset; elementId < nElements; elementId++) {
1373 if (cm->elInfo[elementId].elType != ID_DSE) {
1374 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1375 psyOutChan = psyOutElement[elementId]->psyOutChannel[ch];
1376 peChanData = &qcElement[elementId]->peData.peChannelData[ch];
1377
1378 for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
1379 sfbGrp += psyOutChan->sfbPerGroup) {
1380 for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
1381 if (peChanData->sfbNActiveLines[sfbGrp + sfb] == 0) {
1382 sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] =
1383 FL2FXCONST_DBL(-1.0f);
1384 } else {
1385 /* Both CalcLdInt and CalcLdData can be used!
1386 * No offset has to be subtracted, because sfbNActiveLinesLdData
1387 * is shorted while thrFactor calculation */
1388 sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] =
1389 CalcLdInt(peChanData->sfbNActiveLines[sfbGrp + sfb]);
1390 }
1391 if (((ahFlag[elementId][ch][sfbGrp + sfb] < AH_ACTIVE) ||
1392 (deltaPe > 0)) &&
1393 peChanData->sfbNActiveLines[sfbGrp + sfb] != 0) {
1394 if (thrExp[elementId][ch][sfbGrp + sfb] > -redVal_m) {
1395 /* sfbPeFactors[ch][sfbGrp+sfb] =
1396 peChanData->sfbNActiveLines[sfbGrp+sfb] /
1397 (thrExp[elementId][ch][sfbGrp+sfb] +
1398 redVal[elementId]); */
1399
1400 int minScale =
1401 fixMin(
1402 CountLeadingBits(thrExp[elementId][ch][sfbGrp + sfb]),
1403 CountLeadingBits(redVal_m) - redVal_e) -
1404 1;
1405
1406 /* sumld = ld64( sfbThrExp + redVal ) */
1407 FIXP_DBL sumLd =
1408 CalcLdData(scaleValue(thrExp[elementId][ch][sfbGrp + sfb],
1409 minScale) +
1410 scaleValue(redVal_m, redVal_e + minScale)) -
1411 (FIXP_DBL)(minScale << (DFRACT_BITS - 1 - LD_DATA_SHIFT));
1412
1413 if (sumLd < FL2FXCONST_DBL(0.f)) {
1414 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1415 sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
1416 sumLd;
1417 } else {
1418 if (sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] >
1419 (FL2FXCONST_DBL(-1.f) + sumLd)) {
1420 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1421 sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
1422 sumLd;
1423 } else {
1424 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1425 sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb];
1426 }
1427 }
1428
1429 normFactorInt += (INT)CalcInvLdData(
1430 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb]);
1431 } else
1432 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1433 FL2FXCONST_DBL(1.0f);
1434 } else
1435 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1436 FL2FXCONST_DBL(-1.0f);
1437 }
1438 }
1439 }
1440 }
1441 }
1442
1443 /* normFactorLdData = ld64(deltaPe/normFactorInt) */
1444 normFactorLdData =
1445 CalcLdData((FIXP_DBL)((deltaPe < 0) ? (-deltaPe) : (deltaPe))) -
1446 CalcLdData((FIXP_DBL)normFactorInt);
1447
1448 /* distribute the pe difference to the scalefactors
1449 and calculate the according thresholds */
1450 for (elementId = elementOffset; elementId < nElements; elementId++) {
1451 if (cm->elInfo[elementId].elType != ID_DSE) {
1452 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1453 qcOutChan = qcElement[elementId]->qcOutChannel[ch];
1454 psyOutChan = psyOutElement[elementId]->psyOutChannel[ch];
1455 peChanData = &qcElement[elementId]->peData.peChannelData[ch];
1456
1457 for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
1458 sfbGrp += psyOutChan->sfbPerGroup) {
1459 for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
1460 if (peChanData->sfbNActiveLines[sfbGrp + sfb] > 0) {
1461 /* pe difference for this sfb */
1462 if ((sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] ==
1463 FL2FXCONST_DBL(-1.0f)) ||
1464 (deltaPe == 0)) {
1465 thrFactorLdData = FL2FXCONST_DBL(0.f);
1466 } else {
1467 /* new threshold */
1468 FIXP_DBL tmp = CalcInvLdData(
1469 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] +
1470 normFactorLdData -
1471 sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
1472 FL2FXCONST_DBL((float)LD_DATA_SHIFT / LD_DATA_SCALING));
1473
1474 /* limit thrFactor to 60dB */
1475 tmp = (deltaPe < 0) ? tmp : (-tmp);
1476 thrFactorLdData =
1477 fMin(tmp, FL2FXCONST_DBL(20.f / LD_DATA_SCALING));
1478 }
1479
1480 /* new threshold */
1481 sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp + sfb];
1482 sfbEnLdData = qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb];
1483
1484 if (thrFactorLdData < FL2FXCONST_DBL(0.f)) {
1485 if (sfbThrLdData > (FL2FXCONST_DBL(-1.f) - thrFactorLdData)) {
1486 sfbThrReducedLdData = sfbThrLdData + thrFactorLdData;
1487 } else {
1488 sfbThrReducedLdData = FL2FXCONST_DBL(-1.f);
1489 }
1490 } else {
1491 sfbThrReducedLdData = sfbThrLdData + thrFactorLdData;
1492 }
1493
1494 /* avoid hole */
1495 if ((sfbThrReducedLdData - sfbEnLdData >
1496 qcOutChan->sfbMinSnrLdData[sfbGrp + sfb]) &&
1497 (ahFlag[elementId][ch][sfbGrp + sfb] == AH_INACTIVE)) {
1498 /* sfbThrReduced = max(psyOutChan[ch]->sfbMinSnr[i] * sfbEn,
1499 * sfbThr); */
1500 if (sfbEnLdData >
1501 (sfbThrLdData - qcOutChan->sfbMinSnrLdData[sfbGrp + sfb])) {
1502 sfbThrReducedLdData =
1503 qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData;
1504 } else {
1505 sfbThrReducedLdData = sfbThrLdData;
1506 }
1507 ahFlag[elementId][ch][sfbGrp + sfb] = AH_ACTIVE;
1508 }
1509
1510 qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData;
1511 }
1512 }
1513 }
1514 }
1515 }
1516 }
1517 }
1518
1519 /*****************************************************************************
1520 functionname: FDKaacEnc_reduceMinSnr
1521 description: if the desired pe can not be reached, reduce pe by
1522 reducing minSnr
1523 *****************************************************************************/
FDKaacEnc_reduceMinSnr(const CHANNEL_MAPPING * const cm,QC_OUT_ELEMENT * const qcElement[((8))],const PSY_OUT_ELEMENT * const psyOutElement[((8))],const UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB],const INT desiredPe,INT * const redPeGlobal,const INT processElements,const INT elementOffset)1524 static void FDKaacEnc_reduceMinSnr(
1525 const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
1526 const PSY_OUT_ELEMENT *const psyOutElement[((8))],
1527 const UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], const INT desiredPe,
1528 INT *const redPeGlobal, const INT processElements, const INT elementOffset)
1529
1530 {
1531 INT ch, elementId, globalMaxSfb = 0;
1532 const INT nElements = elementOffset + processElements;
1533 INT newGlobalPe = *redPeGlobal;
1534
1535 if (newGlobalPe <= desiredPe) {
1536 goto bail;
1537 }
1538
1539 /* global maximum of maxSfbPerGroup */
1540 for (elementId = elementOffset; elementId < nElements; elementId++) {
1541 if (cm->elInfo[elementId].elType != ID_DSE) {
1542 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1543 globalMaxSfb =
1544 fMax(globalMaxSfb,
1545 psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup);
1546 }
1547 }
1548 }
1549
1550 /* as long as globalPE is above desirePE reduce SNR to 1.0 dB, starting at
1551 * highest SFB */
1552 while ((newGlobalPe > desiredPe) && (--globalMaxSfb >= 0)) {
1553 for (elementId = elementOffset; elementId < nElements; elementId++) {
1554 if (cm->elInfo[elementId].elType != ID_DSE) {
1555 PE_DATA *peData = &qcElement[elementId]->peData;
1556
1557 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1558 QC_OUT_CHANNEL *qcOutChan = qcElement[elementId]->qcOutChannel[ch];
1559 PSY_OUT_CHANNEL *psyOutChan =
1560 psyOutElement[elementId]->psyOutChannel[ch];
1561
1562 /* try to reduce SNR of channel's uppermost SFB(s) */
1563 if (globalMaxSfb < psyOutChan->maxSfbPerGroup) {
1564 INT sfb, deltaPe = 0;
1565
1566 for (sfb = globalMaxSfb; sfb < psyOutChan->sfbCnt;
1567 sfb += psyOutChan->sfbPerGroup) {
1568 if (ahFlag[elementId][ch][sfb] != NO_AH &&
1569 qcOutChan->sfbMinSnrLdData[sfb] < SnrLdFac &&
1570 (qcOutChan->sfbWeightedEnergyLdData[sfb] >
1571 qcOutChan->sfbThresholdLdData[sfb] - SnrLdFac)) {
1572 /* increase threshold to new minSnr of 1dB */
1573 qcOutChan->sfbMinSnrLdData[sfb] = SnrLdFac;
1574 qcOutChan->sfbThresholdLdData[sfb] =
1575 qcOutChan->sfbWeightedEnergyLdData[sfb] + SnrLdFac;
1576
1577 /* calc new pe */
1578 /* C2 + C3*ld(1/0.8) = 1.5 */
1579 deltaPe -= peData->peChannelData[ch].sfbPe[sfb];
1580
1581 /* sfbPe = 1.5 * sfbNLines */
1582 peData->peChannelData[ch].sfbPe[sfb] =
1583 (3 * peData->peChannelData[ch].sfbNLines[sfb])
1584 << (PE_CONSTPART_SHIFT - 1);
1585 deltaPe += peData->peChannelData[ch].sfbPe[sfb];
1586 }
1587
1588 } /* sfb loop */
1589
1590 deltaPe >>= PE_CONSTPART_SHIFT;
1591 peData->pe += deltaPe;
1592 peData->peChannelData[ch].pe += deltaPe;
1593 newGlobalPe += deltaPe;
1594
1595 } /* if globalMaxSfb < maxSfbPerGroup */
1596
1597 /* stop if enough has been saved */
1598 if (newGlobalPe <= desiredPe) {
1599 goto bail;
1600 }
1601
1602 } /* ch loop */
1603 } /* != ID_DSE */
1604 } /* elementId loop */
1605 } /* while ( newGlobalPe > desiredPe) && (--globalMaxSfb >= 0) ) */
1606
1607 bail:
1608 /* update global PE */
1609 *redPeGlobal = newGlobalPe;
1610 }
1611
1612 /*****************************************************************************
1613 functionname: FDKaacEnc_allowMoreHoles
1614 description: if the desired pe can not be reached, some more scalefactor
1615 bands have to be quantized to zero
1616 *****************************************************************************/
FDKaacEnc_allowMoreHoles(const CHANNEL_MAPPING * const cm,QC_OUT_ELEMENT * const qcElement[((8))],const PSY_OUT_ELEMENT * const psyOutElement[((8))],const ATS_ELEMENT * const AdjThrStateElement[((8))],UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB],const INT desiredPe,const INT currentPe,const int processElements,const int elementOffset)1617 static void FDKaacEnc_allowMoreHoles(
1618 const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
1619 const PSY_OUT_ELEMENT *const psyOutElement[((8))],
1620 const ATS_ELEMENT *const AdjThrStateElement[((8))],
1621 UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], const INT desiredPe,
1622 const INT currentPe, const int processElements, const int elementOffset) {
1623 INT elementId;
1624 INT nElements = elementOffset + processElements;
1625 INT actPe = currentPe;
1626
1627 if (actPe <= desiredPe) {
1628 return; /* nothing to do */
1629 }
1630
1631 for (elementId = elementOffset; elementId < nElements; elementId++) {
1632 if (cm->elInfo[elementId].elType != ID_DSE) {
1633 INT ch, sfb, sfbGrp;
1634
1635 PE_DATA *peData = &qcElement[elementId]->peData;
1636 const INT nChannels = cm->elInfo[elementId].nChannelsInEl;
1637
1638 QC_OUT_CHANNEL *qcOutChannel[(2)] = {NULL};
1639 PSY_OUT_CHANNEL *psyOutChannel[(2)] = {NULL};
1640
1641 for (ch = 0; ch < nChannels; ch++) {
1642 /* init pointers */
1643 qcOutChannel[ch] = qcElement[elementId]->qcOutChannel[ch];
1644 psyOutChannel[ch] = psyOutElement[elementId]->psyOutChannel[ch];
1645
1646 for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
1647 sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
1648 for (sfb = psyOutChannel[ch]->maxSfbPerGroup;
1649 sfb < psyOutChannel[ch]->sfbPerGroup; sfb++) {
1650 peData->peChannelData[ch].sfbPe[sfbGrp + sfb] = 0;
1651 }
1652 }
1653 }
1654
1655 /* for MS allow hole in the channel with less energy */
1656 if (nChannels == 2 && psyOutChannel[0]->lastWindowSequence ==
1657 psyOutChannel[1]->lastWindowSequence) {
1658 for (sfb = psyOutChannel[0]->maxSfbPerGroup - 1; sfb >= 0; sfb--) {
1659 for (sfbGrp = 0; sfbGrp < psyOutChannel[0]->sfbCnt;
1660 sfbGrp += psyOutChannel[0]->sfbPerGroup) {
1661 if (psyOutElement[elementId]->toolsInfo.msMask[sfbGrp + sfb]) {
1662 FIXP_DBL EnergyLd_L =
1663 qcOutChannel[0]->sfbWeightedEnergyLdData[sfbGrp + sfb];
1664 FIXP_DBL EnergyLd_R =
1665 qcOutChannel[1]->sfbWeightedEnergyLdData[sfbGrp + sfb];
1666
1667 /* allow hole in side channel ? */
1668 if ((ahFlag[elementId][1][sfbGrp + sfb] != NO_AH) &&
1669 (((FL2FXCONST_DBL(-0.02065512648f) >> 1) +
1670 (qcOutChannel[0]->sfbMinSnrLdData[sfbGrp + sfb] >> 1)) >
1671 ((EnergyLd_R >> 1) - (EnergyLd_L >> 1)))) {
1672 ahFlag[elementId][1][sfbGrp + sfb] = NO_AH;
1673 qcOutChannel[1]->sfbThresholdLdData[sfbGrp + sfb] =
1674 FL2FXCONST_DBL(0.015625f) + EnergyLd_R;
1675 actPe -= peData->peChannelData[1].sfbPe[sfbGrp + sfb] >>
1676 PE_CONSTPART_SHIFT;
1677 }
1678 /* allow hole in mid channel ? */
1679 else if ((ahFlag[elementId][0][sfbGrp + sfb] != NO_AH) &&
1680 (((FL2FXCONST_DBL(-0.02065512648f) >> 1) +
1681 (qcOutChannel[1]->sfbMinSnrLdData[sfbGrp + sfb] >>
1682 1)) > ((EnergyLd_L >> 1) - (EnergyLd_R >> 1)))) {
1683 ahFlag[elementId][0][sfbGrp + sfb] = NO_AH;
1684 qcOutChannel[0]->sfbThresholdLdData[sfbGrp + sfb] =
1685 FL2FXCONST_DBL(0.015625f) + EnergyLd_L;
1686 actPe -= peData->peChannelData[0].sfbPe[sfbGrp + sfb] >>
1687 PE_CONSTPART_SHIFT;
1688 } /* if (ahFlag) */
1689 } /* if MS */
1690 } /* sfbGrp */
1691 if (actPe <= desiredPe) {
1692 return; /* stop if enough has been saved */
1693 }
1694 } /* sfb */
1695 } /* MS possible ? */
1696
1697 } /* EOF DSE-suppression */
1698 } /* EOF for all elements... */
1699
1700 if (actPe > desiredPe) {
1701 /* more holes necessary? subsequently erase bands starting with low energies
1702 */
1703 INT ch, sfb, sfbGrp;
1704 INT minSfb, maxSfb;
1705 INT enIdx, ahCnt, done;
1706 INT startSfb[(8)];
1707 INT sfbCnt[(8)];
1708 INT sfbPerGroup[(8)];
1709 INT maxSfbPerGroup[(8)];
1710 FIXP_DBL avgEn;
1711 FIXP_DBL minEnLD64;
1712 FIXP_DBL avgEnLD64;
1713 FIXP_DBL enLD64[NUM_NRG_LEVS];
1714 INT avgEn_e;
1715
1716 /* get the scaling factor over all audio elements and channels */
1717 maxSfb = 0;
1718 for (elementId = elementOffset; elementId < nElements; elementId++) {
1719 if (cm->elInfo[elementId].elType != ID_DSE) {
1720 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1721 for (sfbGrp = 0;
1722 sfbGrp < psyOutElement[elementId]->psyOutChannel[ch]->sfbCnt;
1723 sfbGrp +=
1724 psyOutElement[elementId]->psyOutChannel[ch]->sfbPerGroup) {
1725 maxSfb +=
1726 psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup;
1727 }
1728 }
1729 }
1730 }
1731 avgEn_e =
1732 (DFRACT_BITS - fixnormz_D((LONG)fMax(0, maxSfb - 1))); /* ilog2() */
1733
1734 ahCnt = 0;
1735 maxSfb = 0;
1736 minSfb = MAX_SFB;
1737 avgEn = FL2FXCONST_DBL(0.0f);
1738 minEnLD64 = FL2FXCONST_DBL(0.0f);
1739
1740 for (elementId = elementOffset; elementId < nElements; elementId++) {
1741 if (cm->elInfo[elementId].elType != ID_DSE) {
1742 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1743 const INT chIdx = cm->elInfo[elementId].ChannelIndex[ch];
1744 QC_OUT_CHANNEL *qcOutChannel = qcElement[elementId]->qcOutChannel[ch];
1745 PSY_OUT_CHANNEL *psyOutChannel =
1746 psyOutElement[elementId]->psyOutChannel[ch];
1747
1748 maxSfbPerGroup[chIdx] = psyOutChannel->maxSfbPerGroup;
1749 sfbCnt[chIdx] = psyOutChannel->sfbCnt;
1750 sfbPerGroup[chIdx] = psyOutChannel->sfbPerGroup;
1751
1752 maxSfb = fMax(maxSfb, psyOutChannel->maxSfbPerGroup);
1753
1754 if (psyOutChannel->lastWindowSequence != SHORT_WINDOW) {
1755 startSfb[chIdx] = AdjThrStateElement[elementId]->ahParam.startSfbL;
1756 } else {
1757 startSfb[chIdx] = AdjThrStateElement[elementId]->ahParam.startSfbS;
1758 }
1759
1760 minSfb = fMin(minSfb, startSfb[chIdx]);
1761
1762 sfbGrp = 0;
1763 sfb = startSfb[chIdx];
1764
1765 do {
1766 for (; sfb < psyOutChannel->maxSfbPerGroup; sfb++) {
1767 if ((ahFlag[elementId][ch][sfbGrp + sfb] != NO_AH) &&
1768 (qcOutChannel->sfbWeightedEnergyLdData[sfbGrp + sfb] >
1769 qcOutChannel->sfbThresholdLdData[sfbGrp + sfb])) {
1770 minEnLD64 = fixMin(minEnLD64,
1771 qcOutChannel->sfbEnergyLdData[sfbGrp + sfb]);
1772 avgEn += qcOutChannel->sfbEnergy[sfbGrp + sfb] >> avgEn_e;
1773 ahCnt++;
1774 }
1775 }
1776
1777 sfbGrp += psyOutChannel->sfbPerGroup;
1778 sfb = startSfb[chIdx];
1779
1780 } while (sfbGrp < psyOutChannel->sfbCnt);
1781 }
1782 } /* (cm->elInfo[elementId].elType != ID_DSE) */
1783 } /* (elementId = elementOffset;elementId<nElements;elementId++) */
1784
1785 if ((avgEn == FL2FXCONST_DBL(0.0f)) || (ahCnt == 0)) {
1786 avgEnLD64 = FL2FXCONST_DBL(0.0f);
1787 } else {
1788 avgEnLD64 = CalcLdData(avgEn) +
1789 (FIXP_DBL)(avgEn_e << (DFRACT_BITS - 1 - LD_DATA_SHIFT)) -
1790 CalcLdInt(ahCnt);
1791 }
1792
1793 /* calc some energy borders between minEn and avgEn */
1794
1795 /* for (enIdx = 0; enIdx < NUM_NRG_LEVS; enIdx++) {
1796 en[enIdx] = (2.0f*enIdx+1.0f)/(2.0f*NUM_NRG_LEVS-1.0f);
1797 } */
1798 enLD64[0] =
1799 minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.06666667f));
1800 enLD64[1] =
1801 minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.20000000f));
1802 enLD64[2] =
1803 minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.33333334f));
1804 enLD64[3] =
1805 minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.46666667f));
1806 enLD64[4] =
1807 minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.60000002f));
1808 enLD64[5] =
1809 minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.73333335f));
1810 enLD64[6] =
1811 minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.86666667f));
1812 enLD64[7] = minEnLD64 + (avgEnLD64 - minEnLD64);
1813
1814 done = 0;
1815 enIdx = 0;
1816 sfb = maxSfb - 1;
1817
1818 while (!done) {
1819 for (elementId = elementOffset; elementId < nElements; elementId++) {
1820 if (cm->elInfo[elementId].elType != ID_DSE) {
1821 PE_DATA *peData = &qcElement[elementId]->peData;
1822 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1823 const INT chIdx = cm->elInfo[elementId].ChannelIndex[ch];
1824 QC_OUT_CHANNEL *qcOutChannel =
1825 qcElement[elementId]->qcOutChannel[ch];
1826 if (sfb >= startSfb[chIdx] && sfb < maxSfbPerGroup[chIdx]) {
1827 for (sfbGrp = 0; sfbGrp < sfbCnt[chIdx];
1828 sfbGrp += sfbPerGroup[chIdx]) {
1829 /* sfb energy below border ? */
1830 if (ahFlag[elementId][ch][sfbGrp + sfb] != NO_AH &&
1831 qcOutChannel->sfbEnergyLdData[sfbGrp + sfb] <
1832 enLD64[enIdx]) {
1833 /* allow hole */
1834 ahFlag[elementId][ch][sfbGrp + sfb] = NO_AH;
1835 qcOutChannel->sfbThresholdLdData[sfbGrp + sfb] =
1836 FL2FXCONST_DBL(0.015625f) +
1837 qcOutChannel->sfbWeightedEnergyLdData[sfbGrp + sfb];
1838 actPe -= peData->peChannelData[ch].sfbPe[sfbGrp + sfb] >>
1839 PE_CONSTPART_SHIFT;
1840 }
1841 if (actPe <= desiredPe) {
1842 return; /* stop if enough has been saved */
1843 }
1844 } /* sfbGrp */
1845 } /* sfb */
1846 } /* nChannelsInEl */
1847 } /* ID_DSE */
1848 } /* elementID */
1849
1850 sfb--;
1851 if (sfb < minSfb) {
1852 /* restart with next energy border */
1853 sfb = maxSfb;
1854 enIdx++;
1855 if (enIdx >= NUM_NRG_LEVS) {
1856 done = 1;
1857 }
1858 }
1859 } /* done */
1860 } /* (actPe <= desiredPe) */
1861 }
1862
1863 /* reset avoid hole flags from AH_ACTIVE to AH_INACTIVE */
FDKaacEnc_resetAHFlags(UCHAR ahFlag[(2)][MAX_GROUPED_SFB],const INT nChannels,const PSY_OUT_CHANNEL * const psyOutChannel[(2)])1864 static void FDKaacEnc_resetAHFlags(
1865 UCHAR ahFlag[(2)][MAX_GROUPED_SFB], const INT nChannels,
1866 const PSY_OUT_CHANNEL *const psyOutChannel[(2)]) {
1867 int ch, sfb, sfbGrp;
1868
1869 for (ch = 0; ch < nChannels; ch++) {
1870 for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
1871 sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
1872 for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
1873 if (ahFlag[ch][sfbGrp + sfb] == AH_ACTIVE) {
1874 ahFlag[ch][sfbGrp + sfb] = AH_INACTIVE;
1875 }
1876 }
1877 }
1878 }
1879 }
1880
CalcRedValPower(FIXP_DBL num,FIXP_DBL denum,INT * scaling)1881 static FIXP_DBL CalcRedValPower(FIXP_DBL num, FIXP_DBL denum, INT *scaling) {
1882 FIXP_DBL value = FL2FXCONST_DBL(0.f);
1883
1884 if (num >= FL2FXCONST_DBL(0.f)) {
1885 value = fDivNorm(num, denum, scaling);
1886 } else {
1887 value = -fDivNorm(-num, denum, scaling);
1888 }
1889 value = f2Pow(value, *scaling, scaling);
1890
1891 return value;
1892 }
1893
1894 /*****************************************************************************
1895 functionname: FDKaacEnc_adaptThresholdsToPe
1896 description: two guesses for the reduction value and one final correction of
1897 the thresholds
1898 *****************************************************************************/
FDKaacEnc_adaptThresholdsToPe(const CHANNEL_MAPPING * const cm,ATS_ELEMENT * const AdjThrStateElement[((8))],QC_OUT_ELEMENT * const qcElement[((8))],const PSY_OUT_ELEMENT * const psyOutElement[((8))],const INT desiredPe,const INT maxIter2ndGuess,const INT processElements,const INT elementOffset)1899 static void FDKaacEnc_adaptThresholdsToPe(
1900 const CHANNEL_MAPPING *const cm,
1901 ATS_ELEMENT *const AdjThrStateElement[((8))],
1902 QC_OUT_ELEMENT *const qcElement[((8))],
1903 const PSY_OUT_ELEMENT *const psyOutElement[((8))], const INT desiredPe,
1904 const INT maxIter2ndGuess, const INT processElements,
1905 const INT elementOffset) {
1906 FIXP_DBL reductionValue_m;
1907 SCHAR reductionValue_e;
1908 UCHAR(*pAhFlag)[(2)][MAX_GROUPED_SFB];
1909 FIXP_DBL(*pThrExp)[(2)][MAX_GROUPED_SFB];
1910 int iter;
1911
1912 INT constPartGlobal, noRedPeGlobal, nActiveLinesGlobal, redPeGlobal;
1913 constPartGlobal = noRedPeGlobal = nActiveLinesGlobal = redPeGlobal = 0;
1914
1915 int elementId;
1916
1917 int nElements = elementOffset + processElements;
1918 if (nElements > cm->nElements) {
1919 nElements = cm->nElements;
1920 }
1921
1922 /* The reinterpret_cast is used to suppress a compiler warning. We know that
1923 * qcElement[0]->dynMem_Ah_Flag is sufficiently aligned, so the cast is safe
1924 */
1925 pAhFlag = reinterpret_cast<UCHAR(*)[(2)][MAX_GROUPED_SFB]>(
1926 reinterpret_cast<void *>(qcElement[0]->dynMem_Ah_Flag));
1927 /* The reinterpret_cast is used to suppress a compiler warning. We know that
1928 * qcElement[0]->dynMem_Thr_Exp is sufficiently aligned, so the cast is safe
1929 */
1930 pThrExp = reinterpret_cast<FIXP_DBL(*)[(2)][MAX_GROUPED_SFB]>(
1931 reinterpret_cast<void *>(qcElement[0]->dynMem_Thr_Exp));
1932
1933 /* ------------------------------------------------------- */
1934 /* Part I: Initialize data structures and variables... */
1935 /* ------------------------------------------------------- */
1936 for (elementId = elementOffset; elementId < nElements; elementId++) {
1937 if (cm->elInfo[elementId].elType != ID_DSE) {
1938 INT nChannels = cm->elInfo[elementId].nChannelsInEl;
1939 PE_DATA *peData = &qcElement[elementId]->peData;
1940
1941 /* thresholds to the power of redExp */
1942 FDKaacEnc_calcThreshExp(
1943 pThrExp[elementId], qcElement[elementId]->qcOutChannel,
1944 psyOutElement[elementId]->psyOutChannel, nChannels);
1945
1946 /* lower the minSnr requirements for low energies compared to the average
1947 energy in this frame */
1948 FDKaacEnc_adaptMinSnr(qcElement[elementId]->qcOutChannel,
1949 psyOutElement[elementId]->psyOutChannel,
1950 &AdjThrStateElement[elementId]->minSnrAdaptParam,
1951 nChannels);
1952
1953 /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
1954 FDKaacEnc_initAvoidHoleFlag(
1955 qcElement[elementId]->qcOutChannel,
1956 psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
1957 &psyOutElement[elementId]->toolsInfo, nChannels,
1958 &AdjThrStateElement[elementId]->ahParam);
1959
1960 /* sum up */
1961 constPartGlobal += peData->constPart;
1962 noRedPeGlobal += peData->pe;
1963 nActiveLinesGlobal += fixMax((INT)peData->nActiveLines, 1);
1964
1965 } /* EOF DSE-suppression */
1966 } /* EOF for all elements... */
1967
1968 /*
1969 First guess of reduction value:
1970 avgThrExp = (float)pow(2.0f, (constPartGlobal - noRedPeGlobal)/(4.0f *
1971 nActiveLinesGlobal)); redVal = (float)pow(2.0f, (constPartGlobal -
1972 desiredPe)/(4.0f * nActiveLinesGlobal)) - avgThrExp; redVal = max(0.f,
1973 redVal);
1974 */
1975 int redVal_e, avgThrExp_e, result_e;
1976 FIXP_DBL redVal_m, avgThrExp_m;
1977
1978 redVal_m = CalcRedValPower(constPartGlobal - desiredPe,
1979 4 * nActiveLinesGlobal, &redVal_e);
1980 avgThrExp_m = CalcRedValPower(constPartGlobal - noRedPeGlobal,
1981 4 * nActiveLinesGlobal, &avgThrExp_e);
1982 result_e = fMax(redVal_e, avgThrExp_e) + 1;
1983
1984 reductionValue_m = fMax(FL2FXCONST_DBL(0.f),
1985 scaleValue(redVal_m, redVal_e - result_e) -
1986 scaleValue(avgThrExp_m, avgThrExp_e - result_e));
1987 reductionValue_e = result_e;
1988
1989 /* ----------------------------------------------------------------------- */
1990 /* Part II: Calculate bit consumption of initial bit constraints setup */
1991 /* ----------------------------------------------------------------------- */
1992 for (elementId = elementOffset; elementId < nElements; elementId++) {
1993 if (cm->elInfo[elementId].elType != ID_DSE) {
1994 INT nChannels = cm->elInfo[elementId].nChannelsInEl;
1995 PE_DATA *peData = &qcElement[elementId]->peData;
1996
1997 /* reduce thresholds */
1998 FDKaacEnc_reduceThresholdsCBR(
1999 qcElement[elementId]->qcOutChannel,
2000 psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
2001 pThrExp[elementId], nChannels, reductionValue_m, reductionValue_e);
2002
2003 /* pe after first guess */
2004 FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
2005 qcElement[elementId]->qcOutChannel, peData, nChannels);
2006
2007 redPeGlobal += peData->pe;
2008 } /* EOF DSE-suppression */
2009 } /* EOF for all elements... */
2010
2011 /* -------------------------------------------------- */
2012 /* Part III: Iterate until bit constraints are met */
2013 /* -------------------------------------------------- */
2014 iter = 0;
2015 while ((fixp_abs(redPeGlobal - desiredPe) >
2016 fMultI(FL2FXCONST_DBL(0.05f), desiredPe)) &&
2017 (iter < maxIter2ndGuess)) {
2018 INT desiredPeNoAHGlobal;
2019 INT redPeNoAHGlobal = 0;
2020 INT constPartNoAHGlobal = 0;
2021 INT nActiveLinesNoAHGlobal = 0;
2022
2023 for (elementId = elementOffset; elementId < nElements; elementId++) {
2024 if (cm->elInfo[elementId].elType != ID_DSE) {
2025 INT redPeNoAH, constPartNoAH, nActiveLinesNoAH;
2026 INT nChannels = cm->elInfo[elementId].nChannelsInEl;
2027 PE_DATA *peData = &qcElement[elementId]->peData;
2028
2029 /* pe for bands where avoid hole is inactive */
2030 FDKaacEnc_FDKaacEnc_calcPeNoAH(
2031 &redPeNoAH, &constPartNoAH, &nActiveLinesNoAH, peData,
2032 pAhFlag[elementId], psyOutElement[elementId]->psyOutChannel,
2033 nChannels);
2034
2035 redPeNoAHGlobal += redPeNoAH;
2036 constPartNoAHGlobal += constPartNoAH;
2037 nActiveLinesNoAHGlobal += nActiveLinesNoAH;
2038 } /* EOF DSE-suppression */
2039 } /* EOF for all elements... */
2040
2041 /* Calculate new redVal ... */
2042 if (desiredPe < redPeGlobal) {
2043 /* new desired pe without bands where avoid hole is active */
2044 desiredPeNoAHGlobal = desiredPe - (redPeGlobal - redPeNoAHGlobal);
2045
2046 /* limit desiredPeNoAH to positive values, as the PE can not become
2047 * negative */
2048 desiredPeNoAHGlobal = fMax(0, desiredPeNoAHGlobal);
2049
2050 /* second guess (only if there are bands left where avoid hole is
2051 * inactive)*/
2052 if (nActiveLinesNoAHGlobal > 0) {
2053 /*
2054 avgThrExp = (float)pow(2.0f, (constPartNoAHGlobal - redPeNoAHGlobal) /
2055 (4.0f * nActiveLinesNoAHGlobal)); redVal += (float)pow(2.0f,
2056 (constPartNoAHGlobal - desiredPeNoAHGlobal) / (4.0f *
2057 nActiveLinesNoAHGlobal)) - avgThrExp; redVal = max(0.0f, redVal);
2058 */
2059
2060 redVal_m = CalcRedValPower(constPartNoAHGlobal - desiredPeNoAHGlobal,
2061 4 * nActiveLinesNoAHGlobal, &redVal_e);
2062 avgThrExp_m = CalcRedValPower(constPartNoAHGlobal - redPeNoAHGlobal,
2063 4 * nActiveLinesNoAHGlobal, &avgThrExp_e);
2064 result_e = fMax(reductionValue_e, fMax(redVal_e, avgThrExp_e) + 1) + 1;
2065
2066 reductionValue_m =
2067 fMax(FL2FXCONST_DBL(0.f),
2068 scaleValue(reductionValue_m, reductionValue_e - result_e) +
2069 scaleValue(redVal_m, redVal_e - result_e) -
2070 scaleValue(avgThrExp_m, avgThrExp_e - result_e));
2071 reductionValue_e = result_e;
2072
2073 } /* nActiveLinesNoAHGlobal > 0 */
2074 } else {
2075 /* redVal *= redPeGlobal/desiredPe; */
2076 int sc0, sc1;
2077 reductionValue_m = fMultNorm(
2078 reductionValue_m,
2079 fDivNorm((FIXP_DBL)redPeGlobal, (FIXP_DBL)desiredPe, &sc0), &sc1);
2080 reductionValue_e += sc0 + sc1;
2081
2082 for (elementId = elementOffset; elementId < nElements; elementId++) {
2083 if (cm->elInfo[elementId].elType != ID_DSE) {
2084 FDKaacEnc_resetAHFlags(pAhFlag[elementId],
2085 cm->elInfo[elementId].nChannelsInEl,
2086 psyOutElement[elementId]->psyOutChannel);
2087 } /* EOF DSE-suppression */
2088 } /* EOF for all elements... */
2089 }
2090
2091 redPeGlobal = 0;
2092 /* Calculate new redVal's PE... */
2093 for (elementId = elementOffset; elementId < nElements; elementId++) {
2094 if (cm->elInfo[elementId].elType != ID_DSE) {
2095 INT nChannels = cm->elInfo[elementId].nChannelsInEl;
2096 PE_DATA *peData = &qcElement[elementId]->peData;
2097
2098 /* reduce thresholds */
2099 FDKaacEnc_reduceThresholdsCBR(
2100 qcElement[elementId]->qcOutChannel,
2101 psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
2102 pThrExp[elementId], nChannels, reductionValue_m, reductionValue_e);
2103
2104 /* pe after second guess */
2105 FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
2106 qcElement[elementId]->qcOutChannel, peData, nChannels);
2107 redPeGlobal += peData->pe;
2108
2109 } /* EOF DSE-suppression */
2110 } /* EOF for all elements... */
2111
2112 iter++;
2113 } /* EOF while */
2114
2115 /* ------------------------------------------------------- */
2116 /* Part IV: if still required, further reduce constraints */
2117 /* ------------------------------------------------------- */
2118 /* 1.0* 1.15* 1.20*
2119 * desiredPe desiredPe desiredPe
2120 * | | |
2121 * ...XXXXXXXXXXXXXXXXXXXXXXXXXXX| |
2122 * | | |XXXXXXXXXXX...
2123 * | |XXXXXXXXXXX|
2124 * --- A --- | --- B --- | --- C ---
2125 *
2126 * (X): redPeGlobal
2127 * (A): FDKaacEnc_correctThresh()
2128 * (B): FDKaacEnc_allowMoreHoles()
2129 * (C): FDKaacEnc_reduceMinSnr()
2130 */
2131
2132 /* correct thresholds to get closer to the desired pe */
2133 if (redPeGlobal > desiredPe) {
2134 FDKaacEnc_correctThresh(cm, qcElement, psyOutElement, pAhFlag, pThrExp,
2135 reductionValue_m, reductionValue_e,
2136 desiredPe - redPeGlobal, processElements,
2137 elementOffset);
2138
2139 /* update PE */
2140 redPeGlobal = 0;
2141 for (elementId = elementOffset; elementId < nElements; elementId++) {
2142 if (cm->elInfo[elementId].elType != ID_DSE) {
2143 INT nChannels = cm->elInfo[elementId].nChannelsInEl;
2144 PE_DATA *peData = &qcElement[elementId]->peData;
2145
2146 /* pe after correctThresh */
2147 FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
2148 qcElement[elementId]->qcOutChannel, peData, nChannels);
2149 redPeGlobal += peData->pe;
2150
2151 } /* EOF DSE-suppression */
2152 } /* EOF for all elements... */
2153 }
2154
2155 if (redPeGlobal > desiredPe) {
2156 /* reduce pe by reducing minSnr requirements */
2157 FDKaacEnc_reduceMinSnr(
2158 cm, qcElement, psyOutElement, pAhFlag,
2159 (fMultI(FL2FXCONST_DBL(0.15f), desiredPe) + desiredPe), &redPeGlobal,
2160 processElements, elementOffset);
2161
2162 /* reduce pe by allowing additional spectral holes */
2163 FDKaacEnc_allowMoreHoles(cm, qcElement, psyOutElement, AdjThrStateElement,
2164 pAhFlag, desiredPe, redPeGlobal, processElements,
2165 elementOffset);
2166 }
2167 }
2168
2169 /* similar to FDKaacEnc_adaptThresholdsToPe(), for VBR-mode */
FDKaacEnc_AdaptThresholdsVBR(QC_OUT_CHANNEL * const qcOutChannel[(2)],const PSY_OUT_CHANNEL * const psyOutChannel[(2)],ATS_ELEMENT * const AdjThrStateElement,const struct TOOLSINFO * const toolsInfo,const INT nChannels)2170 static void FDKaacEnc_AdaptThresholdsVBR(
2171 QC_OUT_CHANNEL *const qcOutChannel[(2)],
2172 const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
2173 ATS_ELEMENT *const AdjThrStateElement,
2174 const struct TOOLSINFO *const toolsInfo, const INT nChannels) {
2175 UCHAR(*pAhFlag)[MAX_GROUPED_SFB];
2176 FIXP_DBL(*pThrExp)[MAX_GROUPED_SFB];
2177
2178 /* allocate scratch memory */
2179 C_ALLOC_SCRATCH_START(_pAhFlag, UCHAR, (2) * MAX_GROUPED_SFB)
2180 C_ALLOC_SCRATCH_START(_pThrExp, FIXP_DBL, (2) * MAX_GROUPED_SFB)
2181 pAhFlag = (UCHAR(*)[MAX_GROUPED_SFB])_pAhFlag;
2182 pThrExp = (FIXP_DBL(*)[MAX_GROUPED_SFB])_pThrExp;
2183
2184 /* thresholds to the power of redExp */
2185 FDKaacEnc_calcThreshExp(pThrExp, qcOutChannel, psyOutChannel, nChannels);
2186
2187 /* lower the minSnr requirements for low energies compared to the average
2188 energy in this frame */
2189 FDKaacEnc_adaptMinSnr(qcOutChannel, psyOutChannel,
2190 &AdjThrStateElement->minSnrAdaptParam, nChannels);
2191
2192 /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
2193 FDKaacEnc_initAvoidHoleFlag(qcOutChannel, psyOutChannel, pAhFlag, toolsInfo,
2194 nChannels, &AdjThrStateElement->ahParam);
2195
2196 /* reduce thresholds */
2197 FDKaacEnc_reduceThresholdsVBR(qcOutChannel, psyOutChannel, pAhFlag, pThrExp,
2198 nChannels, AdjThrStateElement->vbrQualFactor,
2199 &AdjThrStateElement->chaosMeasureOld);
2200
2201 /* free scratch memory */
2202 C_ALLOC_SCRATCH_END(_pThrExp, FIXP_DBL, (2) * MAX_GROUPED_SFB)
2203 C_ALLOC_SCRATCH_END(_pAhFlag, UCHAR, (2) * MAX_GROUPED_SFB)
2204 }
2205
2206 /*****************************************************************************
2207
2208 functionname: FDKaacEnc_calcBitSave
2209 description: Calculates percentage of bit save, see figure below
2210 returns:
2211 input: parameters and bitres-fullness
2212 output: percentage of bit save
2213
2214 *****************************************************************************/
2215 /*
2216 bitsave
2217 maxBitSave(%)| clipLow
2218 |---\
2219 | \
2220 | \
2221 | \
2222 | \
2223 |--------\--------------> bitres
2224 | \
2225 minBitSave(%)| \------------
2226 clipHigh maxBitres
2227 */
FDKaacEnc_calcBitSave(FIXP_DBL fillLevel,const FIXP_DBL clipLow,const FIXP_DBL clipHigh,const FIXP_DBL minBitSave,const FIXP_DBL maxBitSave,const FIXP_DBL bitsave_slope)2228 static FIXP_DBL FDKaacEnc_calcBitSave(FIXP_DBL fillLevel,
2229 const FIXP_DBL clipLow,
2230 const FIXP_DBL clipHigh,
2231 const FIXP_DBL minBitSave,
2232 const FIXP_DBL maxBitSave,
2233 const FIXP_DBL bitsave_slope) {
2234 FIXP_DBL bitsave;
2235
2236 fillLevel = fixMax(fillLevel, clipLow);
2237 fillLevel = fixMin(fillLevel, clipHigh);
2238
2239 bitsave = maxBitSave - fMult((fillLevel - clipLow), bitsave_slope);
2240
2241 return (bitsave);
2242 }
2243
2244 /*****************************************************************************
2245
2246 functionname: FDKaacEnc_calcBitSpend
2247 description: Calculates percentage of bit spend, see figure below
2248 returns:
2249 input: parameters and bitres-fullness
2250 output: percentage of bit spend
2251
2252 *****************************************************************************/
2253 /*
2254 bitspend clipHigh
2255 maxBitSpend(%)| /-----------maxBitres
2256 | /
2257 | /
2258 | /
2259 | /
2260 | /
2261 |----/-----------------> bitres
2262 | /
2263 minBitSpend(%)|--/
2264 clipLow
2265 */
FDKaacEnc_calcBitSpend(FIXP_DBL fillLevel,const FIXP_DBL clipLow,const FIXP_DBL clipHigh,const FIXP_DBL minBitSpend,const FIXP_DBL maxBitSpend,const FIXP_DBL bitspend_slope)2266 static FIXP_DBL FDKaacEnc_calcBitSpend(FIXP_DBL fillLevel,
2267 const FIXP_DBL clipLow,
2268 const FIXP_DBL clipHigh,
2269 const FIXP_DBL minBitSpend,
2270 const FIXP_DBL maxBitSpend,
2271 const FIXP_DBL bitspend_slope) {
2272 FIXP_DBL bitspend;
2273
2274 fillLevel = fixMax(fillLevel, clipLow);
2275 fillLevel = fixMin(fillLevel, clipHigh);
2276
2277 bitspend = minBitSpend + fMult(fillLevel - clipLow, bitspend_slope);
2278
2279 return (bitspend);
2280 }
2281
2282 /*****************************************************************************
2283
2284 functionname: FDKaacEnc_adjustPeMinMax()
2285 description: adjusts peMin and peMax parameters over time
2286 returns:
2287 input: current pe, peMin, peMax, bitres size
2288 output: adjusted peMin/peMax
2289
2290 *****************************************************************************/
FDKaacEnc_adjustPeMinMax(const INT currPe,INT * peMin,INT * peMax)2291 static void FDKaacEnc_adjustPeMinMax(const INT currPe, INT *peMin, INT *peMax) {
2292 FIXP_DBL minFacHi = FL2FXCONST_DBL(0.3f), maxFacHi = (FIXP_DBL)MAXVAL_DBL,
2293 minFacLo = FL2FXCONST_DBL(0.14f), maxFacLo = FL2FXCONST_DBL(0.07f);
2294 INT diff;
2295
2296 INT minDiff_fix = fMultI(FL2FXCONST_DBL(0.1666666667f), currPe);
2297
2298 if (currPe > *peMax) {
2299 diff = (currPe - *peMax);
2300 *peMin += fMultI(minFacHi, diff);
2301 *peMax += fMultI(maxFacHi, diff);
2302 } else if (currPe < *peMin) {
2303 diff = (*peMin - currPe);
2304 *peMin -= fMultI(minFacLo, diff);
2305 *peMax -= fMultI(maxFacLo, diff);
2306 } else {
2307 *peMin += fMultI(minFacHi, (currPe - *peMin));
2308 *peMax -= fMultI(maxFacLo, (*peMax - currPe));
2309 }
2310
2311 if ((*peMax - *peMin) < minDiff_fix) {
2312 INT peMax_fix = *peMax, peMin_fix = *peMin;
2313 FIXP_DBL partLo_fix, partHi_fix;
2314
2315 partLo_fix = (FIXP_DBL)fixMax(0, currPe - peMin_fix);
2316 partHi_fix = (FIXP_DBL)fixMax(0, peMax_fix - currPe);
2317
2318 peMax_fix =
2319 (INT)(currPe + fMultI(fDivNorm(partHi_fix, (partLo_fix + partHi_fix)),
2320 minDiff_fix));
2321 peMin_fix =
2322 (INT)(currPe - fMultI(fDivNorm(partLo_fix, (partLo_fix + partHi_fix)),
2323 minDiff_fix));
2324 peMin_fix = fixMax(0, peMin_fix);
2325
2326 *peMax = peMax_fix;
2327 *peMin = peMin_fix;
2328 }
2329 }
2330
2331 /*****************************************************************************
2332
2333 functionname: BitresCalcBitFac
2334 description: calculates factor of spending bits for one frame
2335 1.0 : take all frame dynpart bits
2336 >1.0 : take all frame dynpart bits + bitres
2337 <1.0 : put bits in bitreservoir
2338 returns: BitFac
2339 input: bitres-fullness, pe, blockType, parameter-settings
2340 output:
2341
2342 *****************************************************************************/
2343 /*
2344 bitfac(%) pemax
2345 bitspend(%) | /-----------maxBitres
2346 | /
2347 | /
2348 | /
2349 | /
2350 | /
2351 |----/-----------------> pe
2352 | /
2353 bitsave(%) |--/
2354 pemin
2355 */
2356
FDKaacEnc_bitresCalcBitFac(const INT bitresBits,const INT maxBitresBits,const INT pe,const INT lastWindowSequence,const INT avgBits,const FIXP_DBL maxBitFac,const ADJ_THR_STATE * const AdjThr,ATS_ELEMENT * const adjThrChan,FIXP_DBL * const pBitresFac,INT * const pBitresFac_e)2357 void FDKaacEnc_bitresCalcBitFac(const INT bitresBits, const INT maxBitresBits,
2358 const INT pe, const INT lastWindowSequence,
2359 const INT avgBits, const FIXP_DBL maxBitFac,
2360 const ADJ_THR_STATE *const AdjThr,
2361 ATS_ELEMENT *const adjThrChan,
2362 FIXP_DBL *const pBitresFac,
2363 INT *const pBitresFac_e) {
2364 const BRES_PARAM *bresParam;
2365 INT pex;
2366 FIXP_DBL fillLevel;
2367 INT fillLevel_e = 0;
2368
2369 FIXP_DBL bitresFac;
2370 INT bitresFac_e;
2371
2372 FIXP_DBL bitSave, bitSpend;
2373 FIXP_DBL bitsave_slope, bitspend_slope;
2374 FIXP_DBL fillLevel_fix = MAXVAL_DBL;
2375
2376 FIXP_DBL slope = MAXVAL_DBL;
2377
2378 if (lastWindowSequence != SHORT_WINDOW) {
2379 bresParam = &(AdjThr->bresParamLong);
2380 bitsave_slope = FL2FXCONST_DBL(0.466666666);
2381 bitspend_slope = FL2FXCONST_DBL(0.666666666);
2382 } else {
2383 bresParam = &(AdjThr->bresParamShort);
2384 bitsave_slope = (FIXP_DBL)0x2E8BA2E9;
2385 bitspend_slope = (FIXP_DBL)0x7fffffff;
2386 }
2387
2388 // fillLevel = (float)(bitresBits+avgBits) / (float)(maxBitresBits + avgBits);
2389 if (bitresBits < maxBitresBits) {
2390 fillLevel_fix = fDivNorm(bitresBits, maxBitresBits);
2391 }
2392
2393 pex = fMax(pe, adjThrChan->peMin);
2394 pex = fMin(pex, adjThrChan->peMax);
2395
2396 bitSave = FDKaacEnc_calcBitSave(
2397 fillLevel_fix, bresParam->clipSaveLow, bresParam->clipSaveHigh,
2398 bresParam->minBitSave, bresParam->maxBitSave, bitsave_slope);
2399
2400 bitSpend = FDKaacEnc_calcBitSpend(
2401 fillLevel_fix, bresParam->clipSpendLow, bresParam->clipSpendHigh,
2402 bresParam->minBitSpend, bresParam->maxBitSpend, bitspend_slope);
2403
2404 slope = schur_div((pex - adjThrChan->peMin),
2405 (adjThrChan->peMax - adjThrChan->peMin), 31);
2406
2407 /* scale down by 1 bit because the result of the following addition can be
2408 * bigger than 1 (though smaller than 2) */
2409 bitresFac = ((FIXP_DBL)(MAXVAL_DBL >> 1) - (bitSave >> 1));
2410 bitresFac_e = 1; /* exp=1 */
2411 bitresFac = fMultAddDiv2(bitresFac, slope, bitSpend + bitSave); /* exp=1 */
2412
2413 /*** limit bitresFac for small bitreservoir ***/
2414 fillLevel = fDivNorm(bitresBits, avgBits, &fillLevel_e);
2415 if (fillLevel_e < 0) {
2416 fillLevel = scaleValue(fillLevel, fillLevel_e);
2417 fillLevel_e = 0;
2418 }
2419 /* shift down value by 1 because of summation, ... */
2420 fillLevel >>= 1;
2421 fillLevel_e += 1;
2422 /* ..., this summation: */
2423 fillLevel += scaleValue(FL2FXCONST_DBL(0.7f), -fillLevel_e);
2424 /* set bitresfactor to same exponent as fillLevel */
2425 if (scaleValue(bitresFac, -fillLevel_e + 1) > fillLevel) {
2426 bitresFac = fillLevel;
2427 bitresFac_e = fillLevel_e;
2428 }
2429
2430 /* limit bitresFac for high bitrates */
2431 if (scaleValue(bitresFac, bitresFac_e - (DFRACT_BITS - 1 - 24)) > maxBitFac) {
2432 bitresFac = maxBitFac;
2433 bitresFac_e = (DFRACT_BITS - 1 - 24);
2434 }
2435
2436 FDKaacEnc_adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax);
2437
2438 /* output values */
2439 *pBitresFac = bitresFac;
2440 *pBitresFac_e = bitresFac_e;
2441 }
2442
2443 /*****************************************************************************
2444 functionname: FDKaacEnc_AdjThrNew
2445 description: allocate ADJ_THR_STATE
2446 *****************************************************************************/
FDKaacEnc_AdjThrNew(ADJ_THR_STATE ** phAdjThr,INT nElements)2447 INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE **phAdjThr, INT nElements) {
2448 INT err = 0;
2449 INT i;
2450 ADJ_THR_STATE *hAdjThr = GetRam_aacEnc_AdjustThreshold();
2451 if (hAdjThr == NULL) {
2452 err = 1;
2453 goto bail;
2454 }
2455
2456 for (i = 0; i < nElements; i++) {
2457 hAdjThr->adjThrStateElem[i] = GetRam_aacEnc_AdjThrStateElement(i);
2458 if (hAdjThr->adjThrStateElem[i] == NULL) {
2459 err = 1;
2460 goto bail;
2461 }
2462 }
2463
2464 bail:
2465 *phAdjThr = hAdjThr;
2466 return err;
2467 }
2468
2469 /*****************************************************************************
2470 functionname: FDKaacEnc_AdjThrInit
2471 description: initialize ADJ_THR_STATE
2472 *****************************************************************************/
FDKaacEnc_AdjThrInit(ADJ_THR_STATE * const hAdjThr,const INT meanPe,const INT invQuant,const CHANNEL_MAPPING * const channelMapping,const INT sampleRate,const INT totalBitrate,const INT isLowDelay,const AACENC_BITRES_MODE bitResMode,const INT dZoneQuantEnable,const INT bitDistributionMode,const FIXP_DBL vbrQualFactor)2473 void FDKaacEnc_AdjThrInit(
2474 ADJ_THR_STATE *const hAdjThr, const INT meanPe, const INT invQuant,
2475 const CHANNEL_MAPPING *const channelMapping, const INT sampleRate,
2476 const INT totalBitrate, const INT isLowDelay,
2477 const AACENC_BITRES_MODE bitResMode, const INT dZoneQuantEnable,
2478 const INT bitDistributionMode, const FIXP_DBL vbrQualFactor) {
2479 INT i;
2480
2481 FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f);
2482 FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f);
2483
2484 if (bitDistributionMode == 1) {
2485 hAdjThr->bitDistributionMode = AACENC_BD_MODE_INTRA_ELEMENT;
2486 } else {
2487 hAdjThr->bitDistributionMode = AACENC_BD_MODE_INTER_ELEMENT;
2488 }
2489
2490 /* Max number of iterations in second guess is 3 for lowdelay aot and for
2491 configurations with multiple audio elements in general, otherwise iteration
2492 value is always 1. */
2493 hAdjThr->maxIter2ndGuess =
2494 (isLowDelay != 0 || channelMapping->nElements > 1) ? 3 : 1;
2495
2496 /* common for all elements: */
2497 /* parameters for bitres control */
2498 hAdjThr->bresParamLong.clipSaveLow =
2499 (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
2500 hAdjThr->bresParamLong.clipSaveHigh =
2501 (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
2502 hAdjThr->bresParamLong.minBitSave =
2503 (FIXP_DBL)0xf999999a; /* FL2FXCONST_DBL(-0.05f); */
2504 hAdjThr->bresParamLong.maxBitSave =
2505 (FIXP_DBL)0x26666666; /* FL2FXCONST_DBL(0.3f); */
2506 hAdjThr->bresParamLong.clipSpendLow =
2507 (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
2508 hAdjThr->bresParamLong.clipSpendHigh =
2509 (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
2510 hAdjThr->bresParamLong.minBitSpend =
2511 (FIXP_DBL)0xf3333333; /* FL2FXCONST_DBL(-0.10f); */
2512 hAdjThr->bresParamLong.maxBitSpend =
2513 (FIXP_DBL)0x33333333; /* FL2FXCONST_DBL(0.4f); */
2514
2515 hAdjThr->bresParamShort.clipSaveLow =
2516 (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
2517 hAdjThr->bresParamShort.clipSaveHigh =
2518 (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
2519 hAdjThr->bresParamShort.minBitSave =
2520 (FIXP_DBL)0x00000000; /* FL2FXCONST_DBL(0.0f); */
2521 hAdjThr->bresParamShort.maxBitSave =
2522 (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
2523 hAdjThr->bresParamShort.clipSpendLow =
2524 (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
2525 hAdjThr->bresParamShort.clipSpendHigh =
2526 (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
2527 hAdjThr->bresParamShort.minBitSpend =
2528 (FIXP_DBL)0xf9999998; /* FL2FXCONST_DBL(-0.05f); */
2529 hAdjThr->bresParamShort.maxBitSpend =
2530 (FIXP_DBL)0x40000000; /* FL2FXCONST_DBL(0.5f); */
2531
2532 /* specific for each element: */
2533 for (i = 0; i < channelMapping->nElements; i++) {
2534 const FIXP_DBL relativeBits = channelMapping->elInfo[i].relativeBits;
2535 const INT nChannelsInElement = channelMapping->elInfo[i].nChannelsInEl;
2536 const INT bitrateInElement =
2537 (relativeBits != (FIXP_DBL)MAXVAL_DBL)
2538 ? (INT)fMultNorm(relativeBits, (FIXP_DBL)totalBitrate)
2539 : totalBitrate;
2540 const INT chBitrate = bitrateInElement >> (nChannelsInElement == 1 ? 0 : 1);
2541
2542 ATS_ELEMENT *atsElem = hAdjThr->adjThrStateElem[i];
2543 MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam;
2544
2545 /* parameters for bitres control */
2546 if (isLowDelay) {
2547 atsElem->peMin = fMultI(POINT8, meanPe);
2548 atsElem->peMax = fMultI(POINT6, meanPe) << 1;
2549 } else {
2550 atsElem->peMin = fMultI(POINT8, meanPe) >> 1;
2551 atsElem->peMax = fMultI(POINT6, meanPe);
2552 }
2553
2554 /* for use in FDKaacEnc_reduceThresholdsVBR */
2555 atsElem->chaosMeasureOld = FL2FXCONST_DBL(0.3f);
2556
2557 /* additional pe offset to correct pe2bits for low bitrates */
2558 /* ---- no longer necessary, set by table ----- */
2559 atsElem->peOffset = 0;
2560
2561 /* vbr initialisation */
2562 atsElem->vbrQualFactor = vbrQualFactor;
2563 if (chBitrate < 32000) {
2564 atsElem->peOffset =
2565 fixMax(50, 100 - fMultI((FIXP_DBL)0x666667, chBitrate));
2566 }
2567
2568 /* avoid hole parameters */
2569 if (chBitrate >= 20000) {
2570 atsElem->ahParam.modifyMinSnr = TRUE;
2571 atsElem->ahParam.startSfbL = 15;
2572 atsElem->ahParam.startSfbS = 3;
2573 } else {
2574 atsElem->ahParam.modifyMinSnr = FALSE;
2575 atsElem->ahParam.startSfbL = 0;
2576 atsElem->ahParam.startSfbS = 0;
2577 }
2578
2579 /* minSnr adaptation */
2580 msaParam->maxRed = FL2FXCONST_DBL(0.00390625f); /* 0.25f/64.0f */
2581 /* start adaptation of minSnr for avgEn/sfbEn > startRatio */
2582 msaParam->startRatio = FL2FXCONST_DBL(0.05190512648f); /* ld64(10.0f) */
2583 /* maximum minSnr reduction to minSnr^maxRed is reached for
2584 avgEn/sfbEn >= maxRatio */
2585 /* msaParam->maxRatio = 1000.0f; */
2586 /*msaParam->redRatioFac = ((float)1.0f - msaParam->maxRed) /
2587 * ((float)10.0f*log10(msaParam->startRatio/msaParam->maxRatio)/log10(2.0f)*(float)0.3010299956f);*/
2588 msaParam->redRatioFac = FL2FXCONST_DBL(-0.375f); /* -0.0375f * 10.0f */
2589 /*msaParam->redOffs = (float)1.0f - msaParam->redRatioFac * (float)10.0f *
2590 * log10(msaParam->startRatio)/log10(2.0f) * (float)0.3010299956f;*/
2591 msaParam->redOffs = FL2FXCONST_DBL(0.021484375); /* 1.375f/64.0f */
2592
2593 /* init pe correction */
2594 atsElem->peCorrectionFactor_m = FL2FXCONST_DBL(0.5f); /* 1.0 */
2595 atsElem->peCorrectionFactor_e = 1;
2596
2597 atsElem->dynBitsLast = -1;
2598 atsElem->peLast = 0;
2599
2600 /* init bits to pe factor */
2601
2602 /* init bits2PeFactor */
2603 FDKaacEnc_InitBits2PeFactor(
2604 &atsElem->bits2PeFactor_m, &atsElem->bits2PeFactor_e, bitrateInElement,
2605 nChannelsInElement, sampleRate, isLowDelay, dZoneQuantEnable, invQuant);
2606
2607 } /* for nElements */
2608 }
2609
2610 /*****************************************************************************
2611 functionname: FDKaacEnc_FDKaacEnc_calcPeCorrection
2612 description: calc desired pe
2613 *****************************************************************************/
FDKaacEnc_FDKaacEnc_calcPeCorrection(FIXP_DBL * const correctionFac_m,INT * const correctionFac_e,const INT peAct,const INT peLast,const INT bitsLast,const FIXP_DBL bits2PeFactor_m,const INT bits2PeFactor_e)2614 static void FDKaacEnc_FDKaacEnc_calcPeCorrection(
2615 FIXP_DBL *const correctionFac_m, INT *const correctionFac_e,
2616 const INT peAct, const INT peLast, const INT bitsLast,
2617 const FIXP_DBL bits2PeFactor_m, const INT bits2PeFactor_e) {
2618 if ((bitsLast > 0) && (peAct < 1.5f * peLast) && (peAct > 0.7f * peLast) &&
2619 (FDKaacEnc_bits2pe2(bitsLast,
2620 fMult(FL2FXCONST_DBL(1.2f / 2.f), bits2PeFactor_m),
2621 bits2PeFactor_e + 1) > peLast) &&
2622 (FDKaacEnc_bits2pe2(bitsLast,
2623 fMult(FL2FXCONST_DBL(0.65f), bits2PeFactor_m),
2624 bits2PeFactor_e) < peLast)) {
2625 FIXP_DBL corrFac = *correctionFac_m;
2626
2627 int scaling = 0;
2628 FIXP_DBL denum = (FIXP_DBL)FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m,
2629 bits2PeFactor_e);
2630 FIXP_DBL newFac = fDivNorm((FIXP_DBL)peLast, denum, &scaling);
2631
2632 /* dead zone, newFac and corrFac are scaled by 0.5 */
2633 if ((FIXP_DBL)peLast <= denum) { /* ratio <= 1.f */
2634 newFac = fixMax(
2635 scaleValue(fixMin(fMult(FL2FXCONST_DBL(1.1f / 2.f), newFac),
2636 scaleValue(FL2FXCONST_DBL(1.f / 2.f), -scaling)),
2637 scaling),
2638 FL2FXCONST_DBL(0.85f / 2.f));
2639 } else { /* ratio < 1.f */
2640 newFac = fixMax(
2641 fixMin(scaleValue(fMult(FL2FXCONST_DBL(0.9f / 2.f), newFac), scaling),
2642 FL2FXCONST_DBL(1.15f / 2.f)),
2643 FL2FXCONST_DBL(1.f / 2.f));
2644 }
2645
2646 if (((newFac > FL2FXCONST_DBL(1.f / 2.f)) &&
2647 (corrFac < FL2FXCONST_DBL(1.f / 2.f))) ||
2648 ((newFac < FL2FXCONST_DBL(1.f / 2.f)) &&
2649 (corrFac > FL2FXCONST_DBL(1.f / 2.f)))) {
2650 corrFac = FL2FXCONST_DBL(1.f / 2.f);
2651 }
2652
2653 /* faster adaptation towards 1.0, slower in the other direction */
2654 if ((corrFac < FL2FXCONST_DBL(1.f / 2.f) && newFac < corrFac) ||
2655 (corrFac > FL2FXCONST_DBL(1.f / 2.f) && newFac > corrFac)) {
2656 corrFac = fMult(FL2FXCONST_DBL(0.85f), corrFac) +
2657 fMult(FL2FXCONST_DBL(0.15f), newFac);
2658 } else {
2659 corrFac = fMult(FL2FXCONST_DBL(0.7f), corrFac) +
2660 fMult(FL2FXCONST_DBL(0.3f), newFac);
2661 }
2662
2663 corrFac = fixMax(fixMin(corrFac, FL2FXCONST_DBL(1.15f / 2.f)),
2664 FL2FXCONST_DBL(0.85 / 2.f));
2665
2666 *correctionFac_m = corrFac;
2667 *correctionFac_e = 1;
2668 } else {
2669 *correctionFac_m = FL2FXCONST_DBL(1.f / 2.f);
2670 *correctionFac_e = 1;
2671 }
2672 }
2673
FDKaacEnc_calcPeCorrectionLowBitRes(FIXP_DBL * const correctionFac_m,INT * const correctionFac_e,const INT peLast,const INT bitsLast,const INT bitresLevel,const INT nChannels,const FIXP_DBL bits2PeFactor_m,const INT bits2PeFactor_e)2674 static void FDKaacEnc_calcPeCorrectionLowBitRes(
2675 FIXP_DBL *const correctionFac_m, INT *const correctionFac_e,
2676 const INT peLast, const INT bitsLast, const INT bitresLevel,
2677 const INT nChannels, const FIXP_DBL bits2PeFactor_m,
2678 const INT bits2PeFactor_e) {
2679 /* tuning params */
2680 const FIXP_DBL amp = FL2FXCONST_DBL(0.005);
2681 const FIXP_DBL maxDiff = FL2FXCONST_DBL(0.25f);
2682
2683 if (bitsLast > 0) {
2684 /* Estimate deviation of granted and used dynamic bits in previous frame, in
2685 * PE units */
2686 const int bitsBalLast =
2687 peLast - FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m, bits2PeFactor_e);
2688
2689 /* reserve n bits per channel */
2690 int headroom = (bitresLevel >= 50 * nChannels) ? 0 : (100 * nChannels);
2691
2692 /* in PE units */
2693 headroom = FDKaacEnc_bits2pe2(headroom, bits2PeFactor_m, bits2PeFactor_e);
2694
2695 /*
2696 * diff = amp * ((bitsBalLast - headroom) / (bitresLevel + headroom)
2697 * diff = max ( min ( diff, maxDiff, -maxDiff)) / 2
2698 */
2699 FIXP_DBL denominator = (FIXP_DBL)FDKaacEnc_bits2pe2(
2700 bitresLevel, bits2PeFactor_m, bits2PeFactor_e) +
2701 (FIXP_DBL)headroom;
2702
2703 int scaling = 0;
2704 FIXP_DBL diff =
2705 (bitsBalLast >= headroom)
2706 ? fMult(amp, fDivNorm((FIXP_DBL)(bitsBalLast - headroom),
2707 denominator, &scaling))
2708 : -fMult(amp, fDivNorm(-(FIXP_DBL)(bitsBalLast - headroom),
2709 denominator, &scaling));
2710
2711 scaling -= 1; /* divide by 2 */
2712
2713 diff = (scaling <= 0)
2714 ? fMax(fMin(diff >> (-scaling), maxDiff >> 1), -maxDiff >> 1)
2715 : fMax(fMin(diff, maxDiff >> (1 + scaling)),
2716 -maxDiff >> (1 + scaling))
2717 << scaling;
2718
2719 /*
2720 * corrFac += diff
2721 * corrFac = max ( min ( corrFac/2.f, 1.f/2.f, 0.75f/2.f ) )
2722 */
2723 *correctionFac_m =
2724 fMax(fMin((*correctionFac_m) + diff, FL2FXCONST_DBL(1.0f / 2.f)),
2725 FL2FXCONST_DBL(0.75f / 2.f));
2726 *correctionFac_e = 1;
2727 } else {
2728 *correctionFac_m = FL2FXCONST_DBL(0.75 / 2.f);
2729 *correctionFac_e = 1;
2730 }
2731 }
2732
FDKaacEnc_DistributeBits(ADJ_THR_STATE * adjThrState,ATS_ELEMENT * AdjThrStateElement,PSY_OUT_CHANNEL * psyOutChannel[(2)],PE_DATA * peData,INT * grantedPe,INT * grantedPeCorr,const INT nChannels,const INT commonWindow,const INT grantedDynBits,const INT bitresBits,const INT maxBitresBits,const FIXP_DBL maxBitFac,const AACENC_BITRES_MODE bitResMode)2733 void FDKaacEnc_DistributeBits(
2734 ADJ_THR_STATE *adjThrState, ATS_ELEMENT *AdjThrStateElement,
2735 PSY_OUT_CHANNEL *psyOutChannel[(2)], PE_DATA *peData, INT *grantedPe,
2736 INT *grantedPeCorr, const INT nChannels, const INT commonWindow,
2737 const INT grantedDynBits, const INT bitresBits, const INT maxBitresBits,
2738 const FIXP_DBL maxBitFac, const AACENC_BITRES_MODE bitResMode) {
2739 FIXP_DBL bitFactor;
2740 INT bitFactor_e;
2741 INT noRedPe = peData->pe;
2742
2743 /* prefer short windows for calculation of bitFactor */
2744 INT curWindowSequence = LONG_WINDOW;
2745 if (nChannels == 2) {
2746 if ((psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) ||
2747 (psyOutChannel[1]->lastWindowSequence == SHORT_WINDOW)) {
2748 curWindowSequence = SHORT_WINDOW;
2749 }
2750 } else {
2751 curWindowSequence = psyOutChannel[0]->lastWindowSequence;
2752 }
2753
2754 if (grantedDynBits >= 1) {
2755 if (bitResMode != AACENC_BR_MODE_FULL) {
2756 /* small or disabled bitreservoir */
2757 *grantedPe = FDKaacEnc_bits2pe2(grantedDynBits,
2758 AdjThrStateElement->bits2PeFactor_m,
2759 AdjThrStateElement->bits2PeFactor_e);
2760 } else {
2761 /* factor dependend on current fill level and pe */
2762 FDKaacEnc_bitresCalcBitFac(
2763 bitresBits, maxBitresBits, noRedPe, curWindowSequence, grantedDynBits,
2764 maxBitFac, adjThrState, AdjThrStateElement, &bitFactor, &bitFactor_e);
2765
2766 /* desired pe for actual frame */
2767 /* Worst case max of grantedDynBits is = 1024 * 5.27 * 2 */
2768 *grantedPe = FDKaacEnc_bits2pe2(
2769 grantedDynBits, fMult(bitFactor, AdjThrStateElement->bits2PeFactor_m),
2770 AdjThrStateElement->bits2PeFactor_e + bitFactor_e);
2771 }
2772 } else {
2773 *grantedPe = 0; /* prevent divsion by 0 */
2774 }
2775
2776 /* correction of pe value */
2777 switch (bitResMode) {
2778 case AACENC_BR_MODE_DISABLED:
2779 case AACENC_BR_MODE_REDUCED:
2780 /* correction of pe value for low bitres */
2781 FDKaacEnc_calcPeCorrectionLowBitRes(
2782 &AdjThrStateElement->peCorrectionFactor_m,
2783 &AdjThrStateElement->peCorrectionFactor_e, AdjThrStateElement->peLast,
2784 AdjThrStateElement->dynBitsLast, bitresBits, nChannels,
2785 AdjThrStateElement->bits2PeFactor_m,
2786 AdjThrStateElement->bits2PeFactor_e);
2787 break;
2788 case AACENC_BR_MODE_FULL:
2789 default:
2790 /* correction of pe value for high bitres */
2791 FDKaacEnc_FDKaacEnc_calcPeCorrection(
2792 &AdjThrStateElement->peCorrectionFactor_m,
2793 &AdjThrStateElement->peCorrectionFactor_e,
2794 fixMin(*grantedPe, noRedPe), AdjThrStateElement->peLast,
2795 AdjThrStateElement->dynBitsLast, AdjThrStateElement->bits2PeFactor_m,
2796 AdjThrStateElement->bits2PeFactor_e);
2797 break;
2798 }
2799
2800 *grantedPeCorr =
2801 (INT)(fMult((FIXP_DBL)(*grantedPe << Q_AVGBITS),
2802 AdjThrStateElement->peCorrectionFactor_m) >>
2803 (Q_AVGBITS - AdjThrStateElement->peCorrectionFactor_e));
2804
2805 /* update last pe */
2806 AdjThrStateElement->peLast = *grantedPe;
2807 AdjThrStateElement->dynBitsLast = -1;
2808 }
2809
2810 /*****************************************************************************
2811 functionname: FDKaacEnc_AdjustThresholds
2812 description: adjust thresholds
2813 *****************************************************************************/
FDKaacEnc_AdjustThresholds(ADJ_THR_STATE * const hAdjThr,QC_OUT_ELEMENT * const qcElement[((8))],QC_OUT * const qcOut,const PSY_OUT_ELEMENT * const psyOutElement[((8))],const INT CBRbitrateMode,const CHANNEL_MAPPING * const cm)2814 void FDKaacEnc_AdjustThresholds(
2815 ADJ_THR_STATE *const hAdjThr, QC_OUT_ELEMENT *const qcElement[((8))],
2816 QC_OUT *const qcOut, const PSY_OUT_ELEMENT *const psyOutElement[((8))],
2817 const INT CBRbitrateMode, const CHANNEL_MAPPING *const cm) {
2818 int i;
2819
2820 if (CBRbitrateMode) {
2821 /* In case, no bits must be shifted between different elements, */
2822 /* an element-wise execution of the pe-dependent threshold- */
2823 /* adaption becomes necessary... */
2824 if (hAdjThr->bitDistributionMode == AACENC_BD_MODE_INTRA_ELEMENT) {
2825 for (i = 0; i < cm->nElements; i++) {
2826 ELEMENT_INFO elInfo = cm->elInfo[i];
2827
2828 if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
2829 (elInfo.elType == ID_LFE)) {
2830 /* qcElement[i]->grantedPe = 2000; */ /* Use this only for debugging
2831 */
2832 // if (totalGrantedPeCorr < totalNoRedPe) {
2833 if (qcElement[i]->grantedPeCorr < qcElement[i]->peData.pe) {
2834 /* calc threshold necessary for desired pe */
2835 FDKaacEnc_adaptThresholdsToPe(
2836 cm, hAdjThr->adjThrStateElem, qcElement, psyOutElement,
2837 qcElement[i]->grantedPeCorr, hAdjThr->maxIter2ndGuess,
2838 1, /* Process only 1 element */
2839 i /* Process exactly THIS element */
2840 );
2841 }
2842 } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */
2843 } /* -end- element loop */
2844 } /* AACENC_BD_MODE_INTRA_ELEMENT */
2845 else if (hAdjThr->bitDistributionMode == AACENC_BD_MODE_INTER_ELEMENT) {
2846 /* Use global Pe to obtain the thresholds? */
2847 if (qcOut->totalGrantedPeCorr < qcOut->totalNoRedPe) {
2848 /* add equal loadness quantization noise to match the */
2849 /* desired pe calc threshold necessary for desired pe */
2850 /* Now carried out globally to cover all(!) channels. */
2851 FDKaacEnc_adaptThresholdsToPe(cm, hAdjThr->adjThrStateElem, qcElement,
2852 psyOutElement, qcOut->totalGrantedPeCorr,
2853 hAdjThr->maxIter2ndGuess,
2854 cm->nElements, /* Process all elements */
2855 0); /* Process exactly THIS element */
2856 } else {
2857 /* In case global pe doesn't need to be reduced check each element to
2858 hold estimated bitrate below maximum element bitrate. */
2859 for (i = 0; i < cm->nElements; i++) {
2860 if ((cm->elInfo[i].elType == ID_SCE) ||
2861 (cm->elInfo[i].elType == ID_CPE) ||
2862 (cm->elInfo[i].elType == ID_LFE)) {
2863 /* Element pe applies to dynamic bits of maximum element bitrate. */
2864 const int maxElementPe = FDKaacEnc_bits2pe2(
2865 (cm->elInfo[i].nChannelsInEl * MIN_BUFSIZE_PER_EFF_CHAN) -
2866 qcElement[i]->staticBitsUsed - qcElement[i]->extBitsUsed,
2867 hAdjThr->adjThrStateElem[i]->bits2PeFactor_m,
2868 hAdjThr->adjThrStateElem[i]->bits2PeFactor_e);
2869
2870 if (maxElementPe < qcElement[i]->peData.pe) {
2871 FDKaacEnc_adaptThresholdsToPe(
2872 cm, hAdjThr->adjThrStateElem, qcElement, psyOutElement,
2873 maxElementPe, hAdjThr->maxIter2ndGuess, 1, i);
2874 }
2875 } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */
2876 } /* -end- element loop */
2877 } /* (qcOut->totalGrantedPeCorr < qcOut->totalNoRedPe) */
2878 } /* AACENC_BD_MODE_INTER_ELEMENT */
2879 } else {
2880 for (i = 0; i < cm->nElements; i++) {
2881 ELEMENT_INFO elInfo = cm->elInfo[i];
2882
2883 if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
2884 (elInfo.elType == ID_LFE)) {
2885 /* for VBR-mode */
2886 FDKaacEnc_AdaptThresholdsVBR(
2887 qcElement[i]->qcOutChannel, psyOutElement[i]->psyOutChannel,
2888 hAdjThr->adjThrStateElem[i], &psyOutElement[i]->toolsInfo,
2889 cm->elInfo[i].nChannelsInEl);
2890 } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */
2891
2892 } /* -end- element loop */
2893 }
2894 for (i = 0; i < cm->nElements; i++) {
2895 int ch, sfb, sfbGrp;
2896 /* no weighting of threholds and energies for mlout */
2897 /* weight energies and thresholds */
2898 for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) {
2899 QC_OUT_CHANNEL *pQcOutCh = qcElement[i]->qcOutChannel[ch];
2900 for (sfbGrp = 0; sfbGrp < psyOutElement[i]->psyOutChannel[ch]->sfbCnt;
2901 sfbGrp += psyOutElement[i]->psyOutChannel[ch]->sfbPerGroup) {
2902 for (sfb = 0; sfb < psyOutElement[i]->psyOutChannel[ch]->maxSfbPerGroup;
2903 sfb++) {
2904 pQcOutCh->sfbThresholdLdData[sfb + sfbGrp] +=
2905 pQcOutCh->sfbEnFacLd[sfb + sfbGrp];
2906 }
2907 }
2908 }
2909 }
2910 }
2911
FDKaacEnc_AdjThrClose(ADJ_THR_STATE ** phAdjThr)2912 void FDKaacEnc_AdjThrClose(ADJ_THR_STATE **phAdjThr) {
2913 INT i;
2914 ADJ_THR_STATE *hAdjThr = *phAdjThr;
2915
2916 if (hAdjThr != NULL) {
2917 for (i = 0; i < ((8)); i++) {
2918 if (hAdjThr->adjThrStateElem[i] != NULL) {
2919 FreeRam_aacEnc_AdjThrStateElement(&hAdjThr->adjThrStateElem[i]);
2920 }
2921 }
2922 FreeRam_aacEnc_AdjustThreshold(phAdjThr);
2923 }
2924 }
2925