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