xref: /aosp_15_r20/external/aac/libAACenc/src/adj_thr.cpp (revision e54365361535b070c2db7374cec45c159c7d0e7a)
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 [email protected]
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           sfbThrReducedLdData = fixMax(MIN_LDTHRESH, sfbThrReducedLdData);
1306 
1307           qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData;
1308         }
1309       }
1310     }
1311   }
1312 }
1313 
1314 /*****************************************************************************
1315 functionname: FDKaacEnc_correctThresh
1316 description:  if pe difference deltaPe between desired pe and real pe is small
1317 enough, the difference can be distributed among the scale factor bands. New
1318 thresholds can be derived from this pe-difference
1319 *****************************************************************************/
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)1320 static void FDKaacEnc_correctThresh(
1321     const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
1322     const PSY_OUT_ELEMENT *const psyOutElement[((8))],
1323     UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB],
1324     const FIXP_DBL thrExp[((8))][(2)][MAX_GROUPED_SFB], const FIXP_DBL redVal_m,
1325     const SCHAR redVal_e, const INT deltaPe, const INT processElements,
1326     const INT elementOffset) {
1327   INT ch, sfb, sfbGrp;
1328   QC_OUT_CHANNEL *qcOutChan;
1329   PSY_OUT_CHANNEL *psyOutChan;
1330   PE_CHANNEL_DATA *peChanData;
1331   FIXP_DBL thrFactorLdData;
1332   FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData;
1333   FIXP_DBL *sfbPeFactorsLdData[((8))][(2)];
1334   FIXP_DBL(*sfbNActiveLinesLdData)[(2)][MAX_GROUPED_SFB];
1335 
1336   INT normFactorInt;
1337   FIXP_DBL normFactorLdData;
1338 
1339   INT nElements = elementOffset + processElements;
1340   INT elementId;
1341 
1342   /* scratch is empty; use temporal memory from quantSpec in QC_OUT_CHANNEL */
1343   for (elementId = elementOffset; elementId < nElements; elementId++) {
1344     for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1345       /* The reinterpret_cast is used to suppress a compiler warning. We know
1346        * that qcElement[elementId]->qcOutChannel[ch]->quantSpec is sufficiently
1347        * aligned, so the cast is safe */
1348       sfbPeFactorsLdData[elementId][ch] =
1349           reinterpret_cast<FIXP_DBL *>(reinterpret_cast<void *>(
1350               qcElement[elementId]->qcOutChannel[ch]->quantSpec));
1351     }
1352   }
1353   /* The reinterpret_cast is used to suppress a compiler warning. We know that
1354    * qcElement[0]->dynMem_SfbNActiveLinesLdData is sufficiently aligned, so the
1355    * cast is safe */
1356   sfbNActiveLinesLdData = reinterpret_cast<FIXP_DBL(*)[(2)][MAX_GROUPED_SFB]>(
1357       reinterpret_cast<void *>(qcElement[0]->dynMem_SfbNActiveLinesLdData));
1358 
1359   /* for each sfb calc relative factors for pe changes */
1360   normFactorInt = 0;
1361 
1362   for (elementId = elementOffset; elementId < nElements; elementId++) {
1363     if (cm->elInfo[elementId].elType != ID_DSE) {
1364       for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1365         psyOutChan = psyOutElement[elementId]->psyOutChannel[ch];
1366         peChanData = &qcElement[elementId]->peData.peChannelData[ch];
1367 
1368         for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
1369              sfbGrp += psyOutChan->sfbPerGroup) {
1370           for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
1371             if (peChanData->sfbNActiveLines[sfbGrp + sfb] == 0) {
1372               sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] =
1373                   FL2FXCONST_DBL(-1.0f);
1374             } else {
1375               /* Both CalcLdInt and CalcLdData can be used!
1376                * No offset has to be subtracted, because sfbNActiveLinesLdData
1377                * is shorted while thrFactor calculation */
1378               sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] =
1379                   CalcLdInt(peChanData->sfbNActiveLines[sfbGrp + sfb]);
1380             }
1381             if (((ahFlag[elementId][ch][sfbGrp + sfb] < AH_ACTIVE) ||
1382                  (deltaPe > 0)) &&
1383                 peChanData->sfbNActiveLines[sfbGrp + sfb] != 0) {
1384               if (thrExp[elementId][ch][sfbGrp + sfb] > -redVal_m) {
1385                 /* sfbPeFactors[ch][sfbGrp+sfb] =
1386                    peChanData->sfbNActiveLines[sfbGrp+sfb] /
1387                                   (thrExp[elementId][ch][sfbGrp+sfb] +
1388                    redVal[elementId]); */
1389 
1390                 int minScale =
1391                     fixMin(
1392                         CountLeadingBits(thrExp[elementId][ch][sfbGrp + sfb]),
1393                         CountLeadingBits(redVal_m) - redVal_e) -
1394                     1;
1395 
1396                 /* sumld = ld64( sfbThrExp + redVal ) */
1397                 FIXP_DBL sumLd =
1398                     CalcLdData(scaleValue(thrExp[elementId][ch][sfbGrp + sfb],
1399                                           minScale) +
1400                                scaleValue(redVal_m, redVal_e + minScale)) -
1401                     (FIXP_DBL)(minScale << (DFRACT_BITS - 1 - LD_DATA_SHIFT));
1402 
1403                 if (sumLd < FL2FXCONST_DBL(0.f)) {
1404                   sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1405                       sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
1406                       sumLd;
1407                 } else {
1408                   if (sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] >
1409                       (FL2FXCONST_DBL(-1.f) + sumLd)) {
1410                     sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1411                         sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
1412                         sumLd;
1413                   } else {
1414                     sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1415                         sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb];
1416                   }
1417                 }
1418 
1419                 normFactorInt += (INT)CalcInvLdData(
1420                     sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb]);
1421               } else
1422                 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1423                     FL2FXCONST_DBL(1.0f);
1424             } else
1425               sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1426                   FL2FXCONST_DBL(-1.0f);
1427           }
1428         }
1429       }
1430     }
1431   }
1432 
1433   /* normFactorLdData = ld64(deltaPe/normFactorInt) */
1434   normFactorLdData =
1435       CalcLdData((FIXP_DBL)((deltaPe < 0) ? (-deltaPe) : (deltaPe))) -
1436       CalcLdData((FIXP_DBL)normFactorInt);
1437 
1438   /* distribute the pe difference to the scalefactors
1439      and calculate the according thresholds */
1440   for (elementId = elementOffset; elementId < nElements; elementId++) {
1441     if (cm->elInfo[elementId].elType != ID_DSE) {
1442       for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1443         qcOutChan = qcElement[elementId]->qcOutChannel[ch];
1444         psyOutChan = psyOutElement[elementId]->psyOutChannel[ch];
1445         peChanData = &qcElement[elementId]->peData.peChannelData[ch];
1446 
1447         for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
1448              sfbGrp += psyOutChan->sfbPerGroup) {
1449           for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
1450             if (peChanData->sfbNActiveLines[sfbGrp + sfb] > 0) {
1451               /* pe difference for this sfb */
1452               if ((sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] ==
1453                    FL2FXCONST_DBL(-1.0f)) ||
1454                   (deltaPe == 0)) {
1455                 thrFactorLdData = FL2FXCONST_DBL(0.f);
1456               } else {
1457                 /* new threshold */
1458                 FIXP_DBL tmp = CalcInvLdData(
1459                     sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] +
1460                     normFactorLdData -
1461                     sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
1462                     FL2FXCONST_DBL((float)LD_DATA_SHIFT / LD_DATA_SCALING));
1463 
1464                 /* limit thrFactor to 60dB */
1465                 tmp = (deltaPe < 0) ? tmp : (-tmp);
1466                 thrFactorLdData =
1467                     fMin(tmp, FL2FXCONST_DBL(20.f / LD_DATA_SCALING));
1468               }
1469 
1470               /* new threshold */
1471               sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp + sfb];
1472               sfbEnLdData = qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb];
1473 
1474               if (thrFactorLdData < FL2FXCONST_DBL(0.f)) {
1475                 if (sfbThrLdData > (FL2FXCONST_DBL(-1.f) - thrFactorLdData)) {
1476                   sfbThrReducedLdData = sfbThrLdData + thrFactorLdData;
1477                 } else {
1478                   sfbThrReducedLdData = FL2FXCONST_DBL(-1.f);
1479                 }
1480               } else {
1481                 sfbThrReducedLdData = sfbThrLdData + thrFactorLdData;
1482               }
1483 
1484               /* avoid hole */
1485               if ((sfbThrReducedLdData - sfbEnLdData >
1486                    qcOutChan->sfbMinSnrLdData[sfbGrp + sfb]) &&
1487                   (ahFlag[elementId][ch][sfbGrp + sfb] == AH_INACTIVE)) {
1488                 /* sfbThrReduced = max(psyOutChan[ch]->sfbMinSnr[i] * sfbEn,
1489                  * sfbThr); */
1490                 if (sfbEnLdData >
1491                     (sfbThrLdData - qcOutChan->sfbMinSnrLdData[sfbGrp + sfb])) {
1492                   sfbThrReducedLdData =
1493                       qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData;
1494                 } else {
1495                   sfbThrReducedLdData = sfbThrLdData;
1496                 }
1497                 ahFlag[elementId][ch][sfbGrp + sfb] = AH_ACTIVE;
1498               }
1499 
1500               qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData;
1501             }
1502           }
1503         }
1504       }
1505     }
1506   }
1507 }
1508 
1509 /*****************************************************************************
1510     functionname: FDKaacEnc_reduceMinSnr
1511     description:  if the desired pe can not be reached, reduce pe by
1512                   reducing minSnr
1513 *****************************************************************************/
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)1514 static void FDKaacEnc_reduceMinSnr(
1515     const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
1516     const PSY_OUT_ELEMENT *const psyOutElement[((8))],
1517     const UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], const INT desiredPe,
1518     INT *const redPeGlobal, const INT processElements, const INT elementOffset)
1519 
1520 {
1521   INT ch, elementId, globalMaxSfb = 0;
1522   const INT nElements = elementOffset + processElements;
1523   INT newGlobalPe = *redPeGlobal;
1524 
1525   if (newGlobalPe <= desiredPe) {
1526     goto bail;
1527   }
1528 
1529   /* global maximum of maxSfbPerGroup */
1530   for (elementId = elementOffset; elementId < nElements; elementId++) {
1531     if (cm->elInfo[elementId].elType != ID_DSE) {
1532       for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1533         globalMaxSfb =
1534             fMax(globalMaxSfb,
1535                  psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup);
1536       }
1537     }
1538   }
1539 
1540   /* as long as globalPE is above desirePE reduce SNR to 1.0 dB, starting at
1541    * highest SFB */
1542   while ((newGlobalPe > desiredPe) && (--globalMaxSfb >= 0)) {
1543     for (elementId = elementOffset; elementId < nElements; elementId++) {
1544       if (cm->elInfo[elementId].elType != ID_DSE) {
1545         PE_DATA *peData = &qcElement[elementId]->peData;
1546 
1547         for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1548           QC_OUT_CHANNEL *qcOutChan = qcElement[elementId]->qcOutChannel[ch];
1549           PSY_OUT_CHANNEL *psyOutChan =
1550               psyOutElement[elementId]->psyOutChannel[ch];
1551 
1552           /* try to reduce SNR of channel's uppermost SFB(s) */
1553           if (globalMaxSfb < psyOutChan->maxSfbPerGroup) {
1554             INT sfb, deltaPe = 0;
1555 
1556             for (sfb = globalMaxSfb; sfb < psyOutChan->sfbCnt;
1557                  sfb += psyOutChan->sfbPerGroup) {
1558               if (ahFlag[elementId][ch][sfb] != NO_AH &&
1559                   qcOutChan->sfbMinSnrLdData[sfb] < SnrLdFac &&
1560                   (qcOutChan->sfbWeightedEnergyLdData[sfb] >
1561                    qcOutChan->sfbThresholdLdData[sfb] - SnrLdFac)) {
1562                 /* increase threshold to new minSnr of 1dB */
1563                 qcOutChan->sfbMinSnrLdData[sfb] = SnrLdFac;
1564                 qcOutChan->sfbThresholdLdData[sfb] =
1565                     qcOutChan->sfbWeightedEnergyLdData[sfb] + SnrLdFac;
1566 
1567                 /* calc new pe */
1568                 /* C2 + C3*ld(1/0.8) = 1.5 */
1569                 deltaPe -= peData->peChannelData[ch].sfbPe[sfb];
1570 
1571                 /* sfbPe = 1.5 * sfbNLines */
1572                 peData->peChannelData[ch].sfbPe[sfb] =
1573                     (3 * peData->peChannelData[ch].sfbNLines[sfb])
1574                     << (PE_CONSTPART_SHIFT - 1);
1575                 deltaPe += peData->peChannelData[ch].sfbPe[sfb];
1576               }
1577 
1578             } /* sfb loop */
1579 
1580             deltaPe >>= PE_CONSTPART_SHIFT;
1581             peData->pe += deltaPe;
1582             peData->peChannelData[ch].pe += deltaPe;
1583             newGlobalPe += deltaPe;
1584 
1585           } /* if globalMaxSfb < maxSfbPerGroup */
1586 
1587           /* stop if enough has been saved */
1588           if (newGlobalPe <= desiredPe) {
1589             goto bail;
1590           }
1591 
1592         } /* ch loop */
1593       }   /* != ID_DSE */
1594     }     /* elementId loop */
1595   }       /* while ( newGlobalPe > desiredPe) && (--globalMaxSfb >= 0) ) */
1596 
1597 bail:
1598   /* update global PE */
1599   *redPeGlobal = newGlobalPe;
1600 }
1601 
1602 /*****************************************************************************
1603     functionname: FDKaacEnc_allowMoreHoles
1604     description:  if the desired pe can not be reached, some more scalefactor
1605                   bands have to be quantized to zero
1606 *****************************************************************************/
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)1607 static void FDKaacEnc_allowMoreHoles(
1608     const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
1609     const PSY_OUT_ELEMENT *const psyOutElement[((8))],
1610     const ATS_ELEMENT *const AdjThrStateElement[((8))],
1611     UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], const INT desiredPe,
1612     const INT currentPe, const int processElements, const int elementOffset) {
1613   INT elementId;
1614   INT nElements = elementOffset + processElements;
1615   INT actPe = currentPe;
1616 
1617   if (actPe <= desiredPe) {
1618     return; /* nothing to do */
1619   }
1620 
1621   for (elementId = elementOffset; elementId < nElements; elementId++) {
1622     if (cm->elInfo[elementId].elType != ID_DSE) {
1623       INT ch, sfb, sfbGrp;
1624 
1625       PE_DATA *peData = &qcElement[elementId]->peData;
1626       const INT nChannels = cm->elInfo[elementId].nChannelsInEl;
1627 
1628       QC_OUT_CHANNEL *qcOutChannel[(2)] = {NULL};
1629       PSY_OUT_CHANNEL *psyOutChannel[(2)] = {NULL};
1630 
1631       for (ch = 0; ch < nChannels; ch++) {
1632         /* init pointers */
1633         qcOutChannel[ch] = qcElement[elementId]->qcOutChannel[ch];
1634         psyOutChannel[ch] = psyOutElement[elementId]->psyOutChannel[ch];
1635 
1636         for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
1637              sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
1638           for (sfb = psyOutChannel[ch]->maxSfbPerGroup;
1639                sfb < psyOutChannel[ch]->sfbPerGroup; sfb++) {
1640             peData->peChannelData[ch].sfbPe[sfbGrp + sfb] = 0;
1641           }
1642         }
1643       }
1644 
1645       /* for MS allow hole in the channel with less energy */
1646       if (nChannels == 2 && psyOutChannel[0]->lastWindowSequence ==
1647                                 psyOutChannel[1]->lastWindowSequence) {
1648         for (sfb = psyOutChannel[0]->maxSfbPerGroup - 1; sfb >= 0; sfb--) {
1649           for (sfbGrp = 0; sfbGrp < psyOutChannel[0]->sfbCnt;
1650                sfbGrp += psyOutChannel[0]->sfbPerGroup) {
1651             if (psyOutElement[elementId]->toolsInfo.msMask[sfbGrp + sfb]) {
1652               FIXP_DBL EnergyLd_L =
1653                   qcOutChannel[0]->sfbWeightedEnergyLdData[sfbGrp + sfb];
1654               FIXP_DBL EnergyLd_R =
1655                   qcOutChannel[1]->sfbWeightedEnergyLdData[sfbGrp + sfb];
1656 
1657               /* allow hole in side channel ? */
1658               if ((ahFlag[elementId][1][sfbGrp + sfb] != NO_AH) &&
1659                   (((FL2FXCONST_DBL(-0.02065512648f) >> 1) +
1660                     (qcOutChannel[0]->sfbMinSnrLdData[sfbGrp + sfb] >> 1)) >
1661                    ((EnergyLd_R >> 1) - (EnergyLd_L >> 1)))) {
1662                 ahFlag[elementId][1][sfbGrp + sfb] = NO_AH;
1663                 qcOutChannel[1]->sfbThresholdLdData[sfbGrp + sfb] =
1664                     FL2FXCONST_DBL(0.015625f) + EnergyLd_R;
1665                 actPe -= peData->peChannelData[1].sfbPe[sfbGrp + sfb] >>
1666                          PE_CONSTPART_SHIFT;
1667               }
1668               /* allow hole in mid channel ? */
1669               else if ((ahFlag[elementId][0][sfbGrp + sfb] != NO_AH) &&
1670                        (((FL2FXCONST_DBL(-0.02065512648f) >> 1) +
1671                          (qcOutChannel[1]->sfbMinSnrLdData[sfbGrp + sfb] >>
1672                           1)) > ((EnergyLd_L >> 1) - (EnergyLd_R >> 1)))) {
1673                 ahFlag[elementId][0][sfbGrp + sfb] = NO_AH;
1674                 qcOutChannel[0]->sfbThresholdLdData[sfbGrp + sfb] =
1675                     FL2FXCONST_DBL(0.015625f) + EnergyLd_L;
1676                 actPe -= peData->peChannelData[0].sfbPe[sfbGrp + sfb] >>
1677                          PE_CONSTPART_SHIFT;
1678               } /* if (ahFlag) */
1679             }   /* if MS */
1680           }     /* sfbGrp */
1681           if (actPe <= desiredPe) {
1682             return; /* stop if enough has been saved */
1683           }
1684         } /* sfb */
1685       }   /* MS possible ? */
1686 
1687     } /* EOF DSE-suppression */
1688   }   /* EOF for all elements... */
1689 
1690   if (actPe > desiredPe) {
1691     /* more holes necessary? subsequently erase bands starting with low energies
1692      */
1693     INT ch, sfb, sfbGrp;
1694     INT minSfb, maxSfb;
1695     INT enIdx, ahCnt, done;
1696     INT startSfb[(8)];
1697     INT sfbCnt[(8)];
1698     INT sfbPerGroup[(8)];
1699     INT maxSfbPerGroup[(8)];
1700     FIXP_DBL avgEn;
1701     FIXP_DBL minEnLD64;
1702     FIXP_DBL avgEnLD64;
1703     FIXP_DBL enLD64[NUM_NRG_LEVS];
1704     INT avgEn_e;
1705 
1706     /* get the scaling factor over all audio elements and channels */
1707     maxSfb = 0;
1708     for (elementId = elementOffset; elementId < nElements; elementId++) {
1709       if (cm->elInfo[elementId].elType != ID_DSE) {
1710         for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1711           for (sfbGrp = 0;
1712                sfbGrp < psyOutElement[elementId]->psyOutChannel[ch]->sfbCnt;
1713                sfbGrp +=
1714                psyOutElement[elementId]->psyOutChannel[ch]->sfbPerGroup) {
1715             maxSfb +=
1716                 psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup;
1717           }
1718         }
1719       }
1720     }
1721     avgEn_e =
1722         (DFRACT_BITS - fixnormz_D((LONG)fMax(0, maxSfb - 1))); /* ilog2() */
1723 
1724     ahCnt = 0;
1725     maxSfb = 0;
1726     minSfb = MAX_SFB;
1727     avgEn = FL2FXCONST_DBL(0.0f);
1728     minEnLD64 = FL2FXCONST_DBL(0.0f);
1729 
1730     for (elementId = elementOffset; elementId < nElements; elementId++) {
1731       if (cm->elInfo[elementId].elType != ID_DSE) {
1732         for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1733           const INT chIdx = cm->elInfo[elementId].ChannelIndex[ch];
1734           QC_OUT_CHANNEL *qcOutChannel = qcElement[elementId]->qcOutChannel[ch];
1735           PSY_OUT_CHANNEL *psyOutChannel =
1736               psyOutElement[elementId]->psyOutChannel[ch];
1737 
1738           maxSfbPerGroup[chIdx] = psyOutChannel->maxSfbPerGroup;
1739           sfbCnt[chIdx] = psyOutChannel->sfbCnt;
1740           sfbPerGroup[chIdx] = psyOutChannel->sfbPerGroup;
1741 
1742           maxSfb = fMax(maxSfb, psyOutChannel->maxSfbPerGroup);
1743 
1744           if (psyOutChannel->lastWindowSequence != SHORT_WINDOW) {
1745             startSfb[chIdx] = AdjThrStateElement[elementId]->ahParam.startSfbL;
1746           } else {
1747             startSfb[chIdx] = AdjThrStateElement[elementId]->ahParam.startSfbS;
1748           }
1749 
1750           minSfb = fMin(minSfb, startSfb[chIdx]);
1751 
1752           sfbGrp = 0;
1753           sfb = startSfb[chIdx];
1754 
1755           do {
1756             for (; sfb < psyOutChannel->maxSfbPerGroup; sfb++) {
1757               if ((ahFlag[elementId][ch][sfbGrp + sfb] != NO_AH) &&
1758                   (qcOutChannel->sfbWeightedEnergyLdData[sfbGrp + sfb] >
1759                    qcOutChannel->sfbThresholdLdData[sfbGrp + sfb])) {
1760                 minEnLD64 = fixMin(minEnLD64,
1761                                    qcOutChannel->sfbEnergyLdData[sfbGrp + sfb]);
1762                 avgEn += qcOutChannel->sfbEnergy[sfbGrp + sfb] >> avgEn_e;
1763                 ahCnt++;
1764               }
1765             }
1766 
1767             sfbGrp += psyOutChannel->sfbPerGroup;
1768             sfb = startSfb[chIdx];
1769 
1770           } while (sfbGrp < psyOutChannel->sfbCnt);
1771         }
1772       } /* (cm->elInfo[elementId].elType != ID_DSE) */
1773     }   /* (elementId = elementOffset;elementId<nElements;elementId++) */
1774 
1775     if ((avgEn == FL2FXCONST_DBL(0.0f)) || (ahCnt == 0)) {
1776       avgEnLD64 = FL2FXCONST_DBL(0.0f);
1777     } else {
1778       avgEnLD64 = CalcLdData(avgEn) +
1779                   (FIXP_DBL)(avgEn_e << (DFRACT_BITS - 1 - LD_DATA_SHIFT)) -
1780                   CalcLdInt(ahCnt);
1781     }
1782 
1783     /* calc some energy borders between minEn and avgEn */
1784 
1785     /* for (enIdx = 0; enIdx < NUM_NRG_LEVS; enIdx++) {
1786          en[enIdx] = (2.0f*enIdx+1.0f)/(2.0f*NUM_NRG_LEVS-1.0f);
1787        } */
1788     enLD64[0] =
1789         minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.06666667f));
1790     enLD64[1] =
1791         minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.20000000f));
1792     enLD64[2] =
1793         minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.33333334f));
1794     enLD64[3] =
1795         minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.46666667f));
1796     enLD64[4] =
1797         minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.60000002f));
1798     enLD64[5] =
1799         minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.73333335f));
1800     enLD64[6] =
1801         minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.86666667f));
1802     enLD64[7] = minEnLD64 + (avgEnLD64 - minEnLD64);
1803 
1804     done = 0;
1805     enIdx = 0;
1806     sfb = maxSfb - 1;
1807 
1808     while (!done) {
1809       for (elementId = elementOffset; elementId < nElements; elementId++) {
1810         if (cm->elInfo[elementId].elType != ID_DSE) {
1811           PE_DATA *peData = &qcElement[elementId]->peData;
1812           for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1813             const INT chIdx = cm->elInfo[elementId].ChannelIndex[ch];
1814             QC_OUT_CHANNEL *qcOutChannel =
1815                 qcElement[elementId]->qcOutChannel[ch];
1816             if (sfb >= startSfb[chIdx] && sfb < maxSfbPerGroup[chIdx]) {
1817               for (sfbGrp = 0; sfbGrp < sfbCnt[chIdx];
1818                    sfbGrp += sfbPerGroup[chIdx]) {
1819                 /* sfb energy below border ? */
1820                 if (ahFlag[elementId][ch][sfbGrp + sfb] != NO_AH &&
1821                     qcOutChannel->sfbEnergyLdData[sfbGrp + sfb] <
1822                         enLD64[enIdx]) {
1823                   /* allow hole */
1824                   ahFlag[elementId][ch][sfbGrp + sfb] = NO_AH;
1825                   qcOutChannel->sfbThresholdLdData[sfbGrp + sfb] =
1826                       FL2FXCONST_DBL(0.015625f) +
1827                       qcOutChannel->sfbWeightedEnergyLdData[sfbGrp + sfb];
1828                   actPe -= peData->peChannelData[ch].sfbPe[sfbGrp + sfb] >>
1829                            PE_CONSTPART_SHIFT;
1830                 }
1831                 if (actPe <= desiredPe) {
1832                   return; /* stop if enough has been saved */
1833                 }
1834               } /* sfbGrp */
1835             }   /* sfb */
1836           }     /* nChannelsInEl */
1837         }       /* ID_DSE */
1838       }         /* elementID */
1839 
1840       sfb--;
1841       if (sfb < minSfb) {
1842         /* restart with next energy border */
1843         sfb = maxSfb;
1844         enIdx++;
1845         if (enIdx >= NUM_NRG_LEVS) {
1846           done = 1;
1847         }
1848       }
1849     } /* done */
1850   }   /* (actPe <= desiredPe) */
1851 }
1852 
1853 /* 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)])1854 static void FDKaacEnc_resetAHFlags(
1855     UCHAR ahFlag[(2)][MAX_GROUPED_SFB], const INT nChannels,
1856     const PSY_OUT_CHANNEL *const psyOutChannel[(2)]) {
1857   int ch, sfb, sfbGrp;
1858 
1859   for (ch = 0; ch < nChannels; ch++) {
1860     for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
1861          sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
1862       for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
1863         if (ahFlag[ch][sfbGrp + sfb] == AH_ACTIVE) {
1864           ahFlag[ch][sfbGrp + sfb] = AH_INACTIVE;
1865         }
1866       }
1867     }
1868   }
1869 }
1870 
CalcRedValPower(FIXP_DBL num,FIXP_DBL denum,INT * scaling)1871 static FIXP_DBL CalcRedValPower(FIXP_DBL num, FIXP_DBL denum, INT *scaling) {
1872   FIXP_DBL value = FL2FXCONST_DBL(0.f);
1873 
1874   if (num >= FL2FXCONST_DBL(0.f)) {
1875     value = fDivNorm(num, denum, scaling);
1876   } else {
1877     value = -fDivNorm(-num, denum, scaling);
1878   }
1879   value = f2Pow(value, *scaling, scaling);
1880 
1881   return value;
1882 }
1883 
1884 /*****************************************************************************
1885 functionname: FDKaacEnc_adaptThresholdsToPe
1886 description:  two guesses for the reduction value and one final correction of
1887 the thresholds
1888 *****************************************************************************/
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)1889 static void FDKaacEnc_adaptThresholdsToPe(
1890     const CHANNEL_MAPPING *const cm,
1891     ATS_ELEMENT *const AdjThrStateElement[((8))],
1892     QC_OUT_ELEMENT *const qcElement[((8))],
1893     const PSY_OUT_ELEMENT *const psyOutElement[((8))], const INT desiredPe,
1894     const INT maxIter2ndGuess, const INT processElements,
1895     const INT elementOffset) {
1896   FIXP_DBL reductionValue_m;
1897   SCHAR reductionValue_e;
1898   UCHAR(*pAhFlag)[(2)][MAX_GROUPED_SFB];
1899   FIXP_DBL(*pThrExp)[(2)][MAX_GROUPED_SFB];
1900   int iter;
1901 
1902   INT constPartGlobal, noRedPeGlobal, nActiveLinesGlobal, redPeGlobal;
1903   constPartGlobal = noRedPeGlobal = nActiveLinesGlobal = redPeGlobal = 0;
1904 
1905   int elementId;
1906 
1907   int nElements = elementOffset + processElements;
1908   if (nElements > cm->nElements) {
1909     nElements = cm->nElements;
1910   }
1911 
1912   /* The reinterpret_cast is used to suppress a compiler warning. We know that
1913    * qcElement[0]->dynMem_Ah_Flag is sufficiently aligned, so the cast is safe
1914    */
1915   pAhFlag = reinterpret_cast<UCHAR(*)[(2)][MAX_GROUPED_SFB]>(
1916       reinterpret_cast<void *>(qcElement[0]->dynMem_Ah_Flag));
1917   /* The reinterpret_cast is used to suppress a compiler warning. We know that
1918    * qcElement[0]->dynMem_Thr_Exp is sufficiently aligned, so the cast is safe
1919    */
1920   pThrExp = reinterpret_cast<FIXP_DBL(*)[(2)][MAX_GROUPED_SFB]>(
1921       reinterpret_cast<void *>(qcElement[0]->dynMem_Thr_Exp));
1922 
1923   /* ------------------------------------------------------- */
1924   /* Part I: Initialize data structures and variables... */
1925   /* ------------------------------------------------------- */
1926   for (elementId = elementOffset; elementId < nElements; elementId++) {
1927     if (cm->elInfo[elementId].elType != ID_DSE) {
1928       INT nChannels = cm->elInfo[elementId].nChannelsInEl;
1929       PE_DATA *peData = &qcElement[elementId]->peData;
1930 
1931       /* thresholds to the power of redExp */
1932       FDKaacEnc_calcThreshExp(
1933           pThrExp[elementId], qcElement[elementId]->qcOutChannel,
1934           psyOutElement[elementId]->psyOutChannel, nChannels);
1935 
1936       /* lower the minSnr requirements for low energies compared to the average
1937          energy in this frame */
1938       FDKaacEnc_adaptMinSnr(qcElement[elementId]->qcOutChannel,
1939                             psyOutElement[elementId]->psyOutChannel,
1940                             &AdjThrStateElement[elementId]->minSnrAdaptParam,
1941                             nChannels);
1942 
1943       /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
1944       FDKaacEnc_initAvoidHoleFlag(
1945           qcElement[elementId]->qcOutChannel,
1946           psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
1947           &psyOutElement[elementId]->toolsInfo, nChannels,
1948           &AdjThrStateElement[elementId]->ahParam);
1949 
1950       /* sum up */
1951       constPartGlobal += peData->constPart;
1952       noRedPeGlobal += peData->pe;
1953       nActiveLinesGlobal += fixMax((INT)peData->nActiveLines, 1);
1954 
1955     } /* EOF DSE-suppression */
1956   }   /* EOF for all elements... */
1957 
1958   /*
1959      First guess of reduction value:
1960      avgThrExp = (float)pow(2.0f, (constPartGlobal - noRedPeGlobal)/(4.0f *
1961      nActiveLinesGlobal)); redVal    = (float)pow(2.0f, (constPartGlobal -
1962      desiredPe)/(4.0f * nActiveLinesGlobal)) - avgThrExp; redVal    = max(0.f,
1963      redVal);
1964   */
1965   int redVal_e, avgThrExp_e, result_e;
1966   FIXP_DBL redVal_m, avgThrExp_m;
1967 
1968   redVal_m = CalcRedValPower(constPartGlobal - desiredPe,
1969                              4 * nActiveLinesGlobal, &redVal_e);
1970   avgThrExp_m = CalcRedValPower(constPartGlobal - noRedPeGlobal,
1971                                 4 * nActiveLinesGlobal, &avgThrExp_e);
1972   result_e = fMax(redVal_e, avgThrExp_e) + 1;
1973 
1974   reductionValue_m = fMax(FL2FXCONST_DBL(0.f),
1975                           scaleValue(redVal_m, redVal_e - result_e) -
1976                               scaleValue(avgThrExp_m, avgThrExp_e - result_e));
1977   reductionValue_e = result_e;
1978 
1979   /* ----------------------------------------------------------------------- */
1980   /* Part II: Calculate bit consumption of initial bit constraints setup */
1981   /* ----------------------------------------------------------------------- */
1982   for (elementId = elementOffset; elementId < nElements; elementId++) {
1983     if (cm->elInfo[elementId].elType != ID_DSE) {
1984       INT nChannels = cm->elInfo[elementId].nChannelsInEl;
1985       PE_DATA *peData = &qcElement[elementId]->peData;
1986 
1987       /* reduce thresholds */
1988       FDKaacEnc_reduceThresholdsCBR(
1989           qcElement[elementId]->qcOutChannel,
1990           psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
1991           pThrExp[elementId], nChannels, reductionValue_m, reductionValue_e);
1992 
1993       /* pe after first guess */
1994       FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
1995                        qcElement[elementId]->qcOutChannel, peData, nChannels);
1996 
1997       redPeGlobal += peData->pe;
1998     } /* EOF DSE-suppression */
1999   }   /* EOF for all elements... */
2000 
2001   /* -------------------------------------------------- */
2002   /* Part III: Iterate until bit constraints are met */
2003   /* -------------------------------------------------- */
2004   iter = 0;
2005   while ((fixp_abs(redPeGlobal - desiredPe) >
2006           fMultI(FL2FXCONST_DBL(0.05f), desiredPe)) &&
2007          (iter < maxIter2ndGuess)) {
2008     INT desiredPeNoAHGlobal;
2009     INT redPeNoAHGlobal = 0;
2010     INT constPartNoAHGlobal = 0;
2011     INT nActiveLinesNoAHGlobal = 0;
2012 
2013     for (elementId = elementOffset; elementId < nElements; elementId++) {
2014       if (cm->elInfo[elementId].elType != ID_DSE) {
2015         INT redPeNoAH, constPartNoAH, nActiveLinesNoAH;
2016         INT nChannels = cm->elInfo[elementId].nChannelsInEl;
2017         PE_DATA *peData = &qcElement[elementId]->peData;
2018 
2019         /* pe for bands where avoid hole is inactive */
2020         FDKaacEnc_FDKaacEnc_calcPeNoAH(
2021             &redPeNoAH, &constPartNoAH, &nActiveLinesNoAH, peData,
2022             pAhFlag[elementId], psyOutElement[elementId]->psyOutChannel,
2023             nChannels);
2024 
2025         redPeNoAHGlobal += redPeNoAH;
2026         constPartNoAHGlobal += constPartNoAH;
2027         nActiveLinesNoAHGlobal += nActiveLinesNoAH;
2028       } /* EOF DSE-suppression */
2029     }   /* EOF for all elements... */
2030 
2031     /* Calculate new redVal ... */
2032     if (desiredPe < redPeGlobal) {
2033       /* new desired pe without bands where avoid hole is active */
2034       desiredPeNoAHGlobal = desiredPe - (redPeGlobal - redPeNoAHGlobal);
2035 
2036       /* limit desiredPeNoAH to positive values, as the PE can not become
2037        * negative */
2038       desiredPeNoAHGlobal = fMax(0, desiredPeNoAHGlobal);
2039 
2040       /* second guess (only if there are bands left where avoid hole is
2041        * inactive)*/
2042       if (nActiveLinesNoAHGlobal > 0) {
2043         /*
2044           avgThrExp = (float)pow(2.0f, (constPartNoAHGlobal - redPeNoAHGlobal) /
2045           (4.0f * nActiveLinesNoAHGlobal)); redVal   += (float)pow(2.0f,
2046           (constPartNoAHGlobal - desiredPeNoAHGlobal) / (4.0f *
2047           nActiveLinesNoAHGlobal)) - avgThrExp; redVal    = max(0.0f, redVal);
2048         */
2049 
2050         redVal_m = CalcRedValPower(constPartNoAHGlobal - desiredPeNoAHGlobal,
2051                                    4 * nActiveLinesNoAHGlobal, &redVal_e);
2052         avgThrExp_m = CalcRedValPower(constPartNoAHGlobal - redPeNoAHGlobal,
2053                                       4 * nActiveLinesNoAHGlobal, &avgThrExp_e);
2054         result_e = fMax(reductionValue_e, fMax(redVal_e, avgThrExp_e) + 1) + 1;
2055 
2056         reductionValue_m =
2057             fMax(FL2FXCONST_DBL(0.f),
2058                  scaleValue(reductionValue_m, reductionValue_e - result_e) +
2059                      scaleValue(redVal_m, redVal_e - result_e) -
2060                      scaleValue(avgThrExp_m, avgThrExp_e - result_e));
2061         reductionValue_e = result_e;
2062 
2063       } /* nActiveLinesNoAHGlobal > 0 */
2064     } else {
2065       /* redVal *= redPeGlobal/desiredPe; */
2066       int sc0, sc1;
2067       reductionValue_m = fMultNorm(
2068           reductionValue_m,
2069           fDivNorm((FIXP_DBL)redPeGlobal, (FIXP_DBL)desiredPe, &sc0), &sc1);
2070       reductionValue_e += sc0 + sc1;
2071 
2072       for (elementId = elementOffset; elementId < nElements; elementId++) {
2073         if (cm->elInfo[elementId].elType != ID_DSE) {
2074           FDKaacEnc_resetAHFlags(pAhFlag[elementId],
2075                                  cm->elInfo[elementId].nChannelsInEl,
2076                                  psyOutElement[elementId]->psyOutChannel);
2077         } /* EOF DSE-suppression */
2078       }   /* EOF for all elements... */
2079     }
2080 
2081     redPeGlobal = 0;
2082     /* Calculate new redVal's PE... */
2083     for (elementId = elementOffset; elementId < nElements; elementId++) {
2084       if (cm->elInfo[elementId].elType != ID_DSE) {
2085         INT nChannels = cm->elInfo[elementId].nChannelsInEl;
2086         PE_DATA *peData = &qcElement[elementId]->peData;
2087 
2088         /* reduce thresholds */
2089         FDKaacEnc_reduceThresholdsCBR(
2090             qcElement[elementId]->qcOutChannel,
2091             psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
2092             pThrExp[elementId], nChannels, reductionValue_m, reductionValue_e);
2093 
2094         /* pe after second guess */
2095         FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
2096                          qcElement[elementId]->qcOutChannel, peData, nChannels);
2097         redPeGlobal += peData->pe;
2098 
2099       } /* EOF DSE-suppression */
2100     }   /* EOF for all elements... */
2101 
2102     iter++;
2103   } /* EOF while */
2104 
2105   /* ------------------------------------------------------- */
2106   /* Part IV: if still required, further reduce constraints  */
2107   /* ------------------------------------------------------- */
2108   /*                  1.0*        1.15*       1.20*
2109    *               desiredPe   desiredPe   desiredPe
2110    *                   |           |           |
2111    * ...XXXXXXXXXXXXXXXXXXXXXXXXXXX|           |
2112    *                   |           |           |XXXXXXXXXXX...
2113    *                   |           |XXXXXXXXXXX|
2114    *            --- A ---          | --- B --- | --- C ---
2115    *
2116    * (X): redPeGlobal
2117    * (A): FDKaacEnc_correctThresh()
2118    * (B): FDKaacEnc_allowMoreHoles()
2119    * (C): FDKaacEnc_reduceMinSnr()
2120    */
2121 
2122   /* correct thresholds to get closer to the desired pe */
2123   if (redPeGlobal > desiredPe) {
2124     FDKaacEnc_correctThresh(cm, qcElement, psyOutElement, pAhFlag, pThrExp,
2125                             reductionValue_m, reductionValue_e,
2126                             desiredPe - redPeGlobal, processElements,
2127                             elementOffset);
2128 
2129     /* update PE */
2130     redPeGlobal = 0;
2131     for (elementId = elementOffset; elementId < nElements; elementId++) {
2132       if (cm->elInfo[elementId].elType != ID_DSE) {
2133         INT nChannels = cm->elInfo[elementId].nChannelsInEl;
2134         PE_DATA *peData = &qcElement[elementId]->peData;
2135 
2136         /* pe after correctThresh */
2137         FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
2138                          qcElement[elementId]->qcOutChannel, peData, nChannels);
2139         redPeGlobal += peData->pe;
2140 
2141       } /* EOF DSE-suppression */
2142     }   /* EOF for all elements... */
2143   }
2144 
2145   if (redPeGlobal > desiredPe) {
2146     /* reduce pe by reducing minSnr requirements */
2147     FDKaacEnc_reduceMinSnr(
2148         cm, qcElement, psyOutElement, pAhFlag,
2149         (fMultI(FL2FXCONST_DBL(0.15f), desiredPe) + desiredPe), &redPeGlobal,
2150         processElements, elementOffset);
2151 
2152     /* reduce pe by allowing additional spectral holes */
2153     FDKaacEnc_allowMoreHoles(cm, qcElement, psyOutElement, AdjThrStateElement,
2154                              pAhFlag, desiredPe, redPeGlobal, processElements,
2155                              elementOffset);
2156   }
2157 }
2158 
2159 /* 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)2160 static void FDKaacEnc_AdaptThresholdsVBR(
2161     QC_OUT_CHANNEL *const qcOutChannel[(2)],
2162     const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
2163     ATS_ELEMENT *const AdjThrStateElement,
2164     const struct TOOLSINFO *const toolsInfo, const INT nChannels) {
2165   UCHAR(*pAhFlag)[MAX_GROUPED_SFB];
2166   FIXP_DBL(*pThrExp)[MAX_GROUPED_SFB];
2167 
2168   /* allocate scratch memory */
2169   C_ALLOC_SCRATCH_START(_pAhFlag, UCHAR, (2) * MAX_GROUPED_SFB)
2170   C_ALLOC_SCRATCH_START(_pThrExp, FIXP_DBL, (2) * MAX_GROUPED_SFB)
2171   pAhFlag = (UCHAR(*)[MAX_GROUPED_SFB])_pAhFlag;
2172   pThrExp = (FIXP_DBL(*)[MAX_GROUPED_SFB])_pThrExp;
2173 
2174   /* thresholds to the power of redExp */
2175   FDKaacEnc_calcThreshExp(pThrExp, qcOutChannel, psyOutChannel, nChannels);
2176 
2177   /* lower the minSnr requirements for low energies compared to the average
2178      energy in this frame */
2179   FDKaacEnc_adaptMinSnr(qcOutChannel, psyOutChannel,
2180                         &AdjThrStateElement->minSnrAdaptParam, nChannels);
2181 
2182   /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
2183   FDKaacEnc_initAvoidHoleFlag(qcOutChannel, psyOutChannel, pAhFlag, toolsInfo,
2184                               nChannels, &AdjThrStateElement->ahParam);
2185 
2186   /* reduce thresholds */
2187   FDKaacEnc_reduceThresholdsVBR(qcOutChannel, psyOutChannel, pAhFlag, pThrExp,
2188                                 nChannels, AdjThrStateElement->vbrQualFactor,
2189                                 &AdjThrStateElement->chaosMeasureOld);
2190 
2191   /* free scratch memory */
2192   C_ALLOC_SCRATCH_END(_pThrExp, FIXP_DBL, (2) * MAX_GROUPED_SFB)
2193   C_ALLOC_SCRATCH_END(_pAhFlag, UCHAR, (2) * MAX_GROUPED_SFB)
2194 }
2195 
2196 /*****************************************************************************
2197 
2198   functionname: FDKaacEnc_calcBitSave
2199   description:  Calculates percentage of bit save, see figure below
2200   returns:
2201   input:        parameters and bitres-fullness
2202   output:       percentage of bit save
2203 
2204 *****************************************************************************/
2205 /*
2206         bitsave
2207                     maxBitSave(%)|   clipLow
2208                                  |---\
2209                                  |    \
2210                                  |     \
2211                                  |      \
2212                                  |       \
2213                                  |--------\--------------> bitres
2214                                  |         \
2215                     minBitSave(%)|          \------------
2216                                           clipHigh      maxBitres
2217 */
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)2218 static FIXP_DBL FDKaacEnc_calcBitSave(FIXP_DBL fillLevel,
2219                                       const FIXP_DBL clipLow,
2220                                       const FIXP_DBL clipHigh,
2221                                       const FIXP_DBL minBitSave,
2222                                       const FIXP_DBL maxBitSave,
2223                                       const FIXP_DBL bitsave_slope) {
2224   FIXP_DBL bitsave;
2225 
2226   fillLevel = fixMax(fillLevel, clipLow);
2227   fillLevel = fixMin(fillLevel, clipHigh);
2228 
2229   bitsave = maxBitSave - fMult((fillLevel - clipLow), bitsave_slope);
2230 
2231   return (bitsave);
2232 }
2233 
2234 /*****************************************************************************
2235 
2236   functionname: FDKaacEnc_calcBitSpend
2237   description:  Calculates percentage of bit spend, see figure below
2238   returns:
2239   input:        parameters and bitres-fullness
2240   output:       percentage of bit spend
2241 
2242 *****************************************************************************/
2243 /*
2244                               bitspend      clipHigh
2245                    maxBitSpend(%)|          /-----------maxBitres
2246                                  |         /
2247                                  |        /
2248                                  |       /
2249                                  |      /
2250                                  |     /
2251                                  |----/-----------------> bitres
2252                                  |   /
2253                    minBitSpend(%)|--/
2254                                    clipLow
2255 */
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)2256 static FIXP_DBL FDKaacEnc_calcBitSpend(FIXP_DBL fillLevel,
2257                                        const FIXP_DBL clipLow,
2258                                        const FIXP_DBL clipHigh,
2259                                        const FIXP_DBL minBitSpend,
2260                                        const FIXP_DBL maxBitSpend,
2261                                        const FIXP_DBL bitspend_slope) {
2262   FIXP_DBL bitspend;
2263 
2264   fillLevel = fixMax(fillLevel, clipLow);
2265   fillLevel = fixMin(fillLevel, clipHigh);
2266 
2267   bitspend = minBitSpend + fMult(fillLevel - clipLow, bitspend_slope);
2268 
2269   return (bitspend);
2270 }
2271 
2272 /*****************************************************************************
2273 
2274   functionname: FDKaacEnc_adjustPeMinMax()
2275   description:  adjusts peMin and peMax parameters over time
2276   returns:
2277   input:        current pe, peMin, peMax, bitres size
2278   output:       adjusted peMin/peMax
2279 
2280 *****************************************************************************/
FDKaacEnc_adjustPeMinMax(const INT currPe,INT * peMin,INT * peMax)2281 static void FDKaacEnc_adjustPeMinMax(const INT currPe, INT *peMin, INT *peMax) {
2282   FIXP_DBL minFacHi = FL2FXCONST_DBL(0.3f), maxFacHi = (FIXP_DBL)MAXVAL_DBL,
2283            minFacLo = FL2FXCONST_DBL(0.14f), maxFacLo = FL2FXCONST_DBL(0.07f);
2284   INT diff;
2285 
2286   INT minDiff_fix = fMultI(FL2FXCONST_DBL(0.1666666667f), currPe);
2287 
2288   if (currPe > *peMax) {
2289     diff = (currPe - *peMax);
2290     *peMin += fMultI(minFacHi, diff);
2291     *peMax += fMultI(maxFacHi, diff);
2292   } else if (currPe < *peMin) {
2293     diff = (*peMin - currPe);
2294     *peMin -= fMultI(minFacLo, diff);
2295     *peMax -= fMultI(maxFacLo, diff);
2296   } else {
2297     *peMin += fMultI(minFacHi, (currPe - *peMin));
2298     *peMax -= fMultI(maxFacLo, (*peMax - currPe));
2299   }
2300 
2301   if ((*peMax - *peMin) < minDiff_fix) {
2302     INT peMax_fix = *peMax, peMin_fix = *peMin;
2303     FIXP_DBL partLo_fix, partHi_fix;
2304 
2305     partLo_fix = (FIXP_DBL)fixMax(0, currPe - peMin_fix);
2306     partHi_fix = (FIXP_DBL)fixMax(0, peMax_fix - currPe);
2307 
2308     peMax_fix =
2309         (INT)(currPe + fMultI(fDivNorm(partHi_fix, (partLo_fix + partHi_fix)),
2310                               minDiff_fix));
2311     peMin_fix =
2312         (INT)(currPe - fMultI(fDivNorm(partLo_fix, (partLo_fix + partHi_fix)),
2313                               minDiff_fix));
2314     peMin_fix = fixMax(0, peMin_fix);
2315 
2316     *peMax = peMax_fix;
2317     *peMin = peMin_fix;
2318   }
2319 }
2320 
2321 /*****************************************************************************
2322 
2323   functionname: BitresCalcBitFac
2324   description:  calculates factor of spending bits for one frame
2325   1.0 : take all frame dynpart bits
2326   >1.0 : take all frame dynpart bits + bitres
2327   <1.0 : put bits in bitreservoir
2328   returns:      BitFac
2329   input:        bitres-fullness, pe, blockType, parameter-settings
2330   output:
2331 
2332 *****************************************************************************/
2333 /*
2334                      bitfac(%)            pemax
2335                    bitspend(%)   |          /-----------maxBitres
2336                                  |         /
2337                                  |        /
2338                                  |       /
2339                                  |      /
2340                                  |     /
2341                                  |----/-----------------> pe
2342                                  |   /
2343                    bitsave(%)    |--/
2344                                     pemin
2345 */
2346 
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)2347 void FDKaacEnc_bitresCalcBitFac(const INT bitresBits, const INT maxBitresBits,
2348                                 const INT pe, const INT lastWindowSequence,
2349                                 const INT avgBits, const FIXP_DBL maxBitFac,
2350                                 const ADJ_THR_STATE *const AdjThr,
2351                                 ATS_ELEMENT *const adjThrChan,
2352                                 FIXP_DBL *const pBitresFac,
2353                                 INT *const pBitresFac_e) {
2354   const BRES_PARAM *bresParam;
2355   INT pex;
2356   FIXP_DBL fillLevel;
2357   INT fillLevel_e = 0;
2358 
2359   FIXP_DBL bitresFac;
2360   INT bitresFac_e;
2361 
2362   FIXP_DBL bitSave, bitSpend;
2363   FIXP_DBL bitsave_slope, bitspend_slope;
2364   FIXP_DBL fillLevel_fix = MAXVAL_DBL;
2365 
2366   FIXP_DBL slope = MAXVAL_DBL;
2367 
2368   if (lastWindowSequence != SHORT_WINDOW) {
2369     bresParam = &(AdjThr->bresParamLong);
2370     bitsave_slope = FL2FXCONST_DBL(0.466666666);
2371     bitspend_slope = FL2FXCONST_DBL(0.666666666);
2372   } else {
2373     bresParam = &(AdjThr->bresParamShort);
2374     bitsave_slope = (FIXP_DBL)0x2E8BA2E9;
2375     bitspend_slope = (FIXP_DBL)0x7fffffff;
2376   }
2377 
2378   // fillLevel = (float)(bitresBits+avgBits) / (float)(maxBitresBits + avgBits);
2379   if (bitresBits < maxBitresBits) {
2380     fillLevel_fix = fDivNorm(bitresBits, maxBitresBits);
2381   }
2382 
2383   pex = fMax(pe, adjThrChan->peMin);
2384   pex = fMin(pex, adjThrChan->peMax);
2385 
2386   bitSave = FDKaacEnc_calcBitSave(
2387       fillLevel_fix, bresParam->clipSaveLow, bresParam->clipSaveHigh,
2388       bresParam->minBitSave, bresParam->maxBitSave, bitsave_slope);
2389 
2390   bitSpend = FDKaacEnc_calcBitSpend(
2391       fillLevel_fix, bresParam->clipSpendLow, bresParam->clipSpendHigh,
2392       bresParam->minBitSpend, bresParam->maxBitSpend, bitspend_slope);
2393 
2394   slope = schur_div((pex - adjThrChan->peMin),
2395                     (adjThrChan->peMax - adjThrChan->peMin), 31);
2396 
2397   /* scale down by 1 bit because the result of the following addition can be
2398    * bigger than 1 (though smaller than 2) */
2399   bitresFac = ((FIXP_DBL)(MAXVAL_DBL >> 1) - (bitSave >> 1));
2400   bitresFac_e = 1;                                                /* exp=1 */
2401   bitresFac = fMultAddDiv2(bitresFac, slope, bitSpend + bitSave); /* exp=1 */
2402 
2403   /*** limit bitresFac for small bitreservoir ***/
2404   fillLevel = fDivNorm(bitresBits, avgBits, &fillLevel_e);
2405   if (fillLevel_e < 0) {
2406     fillLevel = scaleValue(fillLevel, fillLevel_e);
2407     fillLevel_e = 0;
2408   }
2409   /* shift down value by 1 because of summation, ... */
2410   fillLevel >>= 1;
2411   fillLevel_e += 1;
2412   /* ..., this summation: */
2413   fillLevel += scaleValue(FL2FXCONST_DBL(0.7f), -fillLevel_e);
2414   /* set bitresfactor to same exponent as fillLevel */
2415   if (scaleValue(bitresFac, -fillLevel_e + 1) > fillLevel) {
2416     bitresFac = fillLevel;
2417     bitresFac_e = fillLevel_e;
2418   }
2419 
2420   /* limit bitresFac for high bitrates */
2421   if (scaleValue(bitresFac, bitresFac_e - (DFRACT_BITS - 1 - 24)) > maxBitFac) {
2422     bitresFac = maxBitFac;
2423     bitresFac_e = (DFRACT_BITS - 1 - 24);
2424   }
2425 
2426   FDKaacEnc_adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax);
2427 
2428   /* output values */
2429   *pBitresFac = bitresFac;
2430   *pBitresFac_e = bitresFac_e;
2431 }
2432 
2433 /*****************************************************************************
2434 functionname: FDKaacEnc_AdjThrNew
2435 description:  allocate ADJ_THR_STATE
2436 *****************************************************************************/
FDKaacEnc_AdjThrNew(ADJ_THR_STATE ** phAdjThr,INT nElements)2437 INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE **phAdjThr, INT nElements) {
2438   INT err = 0;
2439   INT i;
2440   ADJ_THR_STATE *hAdjThr = GetRam_aacEnc_AdjustThreshold();
2441   if (hAdjThr == NULL) {
2442     err = 1;
2443     goto bail;
2444   }
2445 
2446   for (i = 0; i < nElements; i++) {
2447     hAdjThr->adjThrStateElem[i] = GetRam_aacEnc_AdjThrStateElement(i);
2448     if (hAdjThr->adjThrStateElem[i] == NULL) {
2449       err = 1;
2450       goto bail;
2451     }
2452   }
2453 
2454 bail:
2455   *phAdjThr = hAdjThr;
2456   return err;
2457 }
2458 
2459 /*****************************************************************************
2460 functionname: FDKaacEnc_AdjThrInit
2461 description:  initialize ADJ_THR_STATE
2462 *****************************************************************************/
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)2463 void FDKaacEnc_AdjThrInit(
2464     ADJ_THR_STATE *const hAdjThr, const INT meanPe, const INT invQuant,
2465     const CHANNEL_MAPPING *const channelMapping, const INT sampleRate,
2466     const INT totalBitrate, const INT isLowDelay,
2467     const AACENC_BITRES_MODE bitResMode, const INT dZoneQuantEnable,
2468     const INT bitDistributionMode, const FIXP_DBL vbrQualFactor) {
2469   INT i;
2470 
2471   FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f);
2472   FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f);
2473 
2474   if (bitDistributionMode == 1) {
2475     hAdjThr->bitDistributionMode = AACENC_BD_MODE_INTRA_ELEMENT;
2476   } else {
2477     hAdjThr->bitDistributionMode = AACENC_BD_MODE_INTER_ELEMENT;
2478   }
2479 
2480   /* Max number of iterations in second guess is 3 for lowdelay aot and for
2481      configurations with multiple audio elements in general, otherwise iteration
2482      value is always 1. */
2483   hAdjThr->maxIter2ndGuess =
2484       (isLowDelay != 0 || channelMapping->nElements > 1) ? 3 : 1;
2485 
2486   /* common for all elements: */
2487   /* parameters for bitres control */
2488   hAdjThr->bresParamLong.clipSaveLow =
2489       (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
2490   hAdjThr->bresParamLong.clipSaveHigh =
2491       (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
2492   hAdjThr->bresParamLong.minBitSave =
2493       (FIXP_DBL)0xf999999a; /* FL2FXCONST_DBL(-0.05f); */
2494   hAdjThr->bresParamLong.maxBitSave =
2495       (FIXP_DBL)0x26666666; /* FL2FXCONST_DBL(0.3f); */
2496   hAdjThr->bresParamLong.clipSpendLow =
2497       (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
2498   hAdjThr->bresParamLong.clipSpendHigh =
2499       (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
2500   hAdjThr->bresParamLong.minBitSpend =
2501       (FIXP_DBL)0xf3333333; /* FL2FXCONST_DBL(-0.10f); */
2502   hAdjThr->bresParamLong.maxBitSpend =
2503       (FIXP_DBL)0x33333333; /* FL2FXCONST_DBL(0.4f); */
2504 
2505   hAdjThr->bresParamShort.clipSaveLow =
2506       (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
2507   hAdjThr->bresParamShort.clipSaveHigh =
2508       (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
2509   hAdjThr->bresParamShort.minBitSave =
2510       (FIXP_DBL)0x00000000; /* FL2FXCONST_DBL(0.0f); */
2511   hAdjThr->bresParamShort.maxBitSave =
2512       (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
2513   hAdjThr->bresParamShort.clipSpendLow =
2514       (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
2515   hAdjThr->bresParamShort.clipSpendHigh =
2516       (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
2517   hAdjThr->bresParamShort.minBitSpend =
2518       (FIXP_DBL)0xf9999998; /* FL2FXCONST_DBL(-0.05f); */
2519   hAdjThr->bresParamShort.maxBitSpend =
2520       (FIXP_DBL)0x40000000; /* FL2FXCONST_DBL(0.5f); */
2521 
2522   /* specific for each element: */
2523   for (i = 0; i < channelMapping->nElements; i++) {
2524     const FIXP_DBL relativeBits = channelMapping->elInfo[i].relativeBits;
2525     const INT nChannelsInElement = channelMapping->elInfo[i].nChannelsInEl;
2526     const INT bitrateInElement =
2527         (relativeBits != (FIXP_DBL)MAXVAL_DBL)
2528             ? (INT)fMultNorm(relativeBits, (FIXP_DBL)totalBitrate)
2529             : totalBitrate;
2530     const INT chBitrate = bitrateInElement >> (nChannelsInElement == 1 ? 0 : 1);
2531 
2532     ATS_ELEMENT *atsElem = hAdjThr->adjThrStateElem[i];
2533     MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam;
2534 
2535     /* parameters for bitres control */
2536     if (isLowDelay) {
2537       atsElem->peMin = fMultI(POINT8, meanPe);
2538       atsElem->peMax = fMultI(POINT6, meanPe) << 1;
2539     } else {
2540       atsElem->peMin = fMultI(POINT8, meanPe) >> 1;
2541       atsElem->peMax = fMultI(POINT6, meanPe);
2542     }
2543 
2544     /* for use in FDKaacEnc_reduceThresholdsVBR */
2545     atsElem->chaosMeasureOld = FL2FXCONST_DBL(0.3f);
2546 
2547     /* additional pe offset to correct pe2bits for low bitrates */
2548     /* ---- no longer necessary, set by table ----- */
2549     atsElem->peOffset = 0;
2550 
2551     /* vbr initialisation */
2552     atsElem->vbrQualFactor = vbrQualFactor;
2553     if (chBitrate < 32000) {
2554       atsElem->peOffset =
2555           fixMax(50, 100 - fMultI((FIXP_DBL)0x666667, chBitrate));
2556     }
2557 
2558     /* avoid hole parameters */
2559     if (chBitrate >= 20000) {
2560       atsElem->ahParam.modifyMinSnr = TRUE;
2561       atsElem->ahParam.startSfbL = 15;
2562       atsElem->ahParam.startSfbS = 3;
2563     } else {
2564       atsElem->ahParam.modifyMinSnr = FALSE;
2565       atsElem->ahParam.startSfbL = 0;
2566       atsElem->ahParam.startSfbS = 0;
2567     }
2568 
2569     /* minSnr adaptation */
2570     msaParam->maxRed = FL2FXCONST_DBL(0.00390625f); /* 0.25f/64.0f */
2571     /* start adaptation of minSnr for avgEn/sfbEn > startRatio */
2572     msaParam->startRatio = FL2FXCONST_DBL(0.05190512648f); /* ld64(10.0f) */
2573     /* maximum minSnr reduction to minSnr^maxRed is reached for
2574        avgEn/sfbEn >= maxRatio */
2575     /* msaParam->maxRatio = 1000.0f; */
2576     /*msaParam->redRatioFac = ((float)1.0f - msaParam->maxRed) /
2577      * ((float)10.0f*log10(msaParam->startRatio/msaParam->maxRatio)/log10(2.0f)*(float)0.3010299956f);*/
2578     msaParam->redRatioFac = FL2FXCONST_DBL(-0.375f); /* -0.0375f * 10.0f */
2579     /*msaParam->redOffs = (float)1.0f - msaParam->redRatioFac * (float)10.0f *
2580      * log10(msaParam->startRatio)/log10(2.0f) * (float)0.3010299956f;*/
2581     msaParam->redOffs = FL2FXCONST_DBL(0.021484375); /* 1.375f/64.0f */
2582 
2583     /* init pe correction */
2584     atsElem->peCorrectionFactor_m = FL2FXCONST_DBL(0.5f); /* 1.0 */
2585     atsElem->peCorrectionFactor_e = 1;
2586 
2587     atsElem->dynBitsLast = -1;
2588     atsElem->peLast = 0;
2589 
2590     /* init bits to pe factor */
2591 
2592     /* init bits2PeFactor */
2593     FDKaacEnc_InitBits2PeFactor(
2594         &atsElem->bits2PeFactor_m, &atsElem->bits2PeFactor_e, bitrateInElement,
2595         nChannelsInElement, sampleRate, isLowDelay, dZoneQuantEnable, invQuant);
2596 
2597   } /* for nElements */
2598 }
2599 
2600 /*****************************************************************************
2601     functionname: FDKaacEnc_FDKaacEnc_calcPeCorrection
2602     description:  calc desired pe
2603 *****************************************************************************/
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)2604 static void FDKaacEnc_FDKaacEnc_calcPeCorrection(
2605     FIXP_DBL *const correctionFac_m, INT *const correctionFac_e,
2606     const INT peAct, const INT peLast, const INT bitsLast,
2607     const FIXP_DBL bits2PeFactor_m, const INT bits2PeFactor_e) {
2608   if ((bitsLast > 0) && (peAct < 1.5f * peLast) && (peAct > 0.7f * peLast) &&
2609       (FDKaacEnc_bits2pe2(bitsLast,
2610                           fMult(FL2FXCONST_DBL(1.2f / 2.f), bits2PeFactor_m),
2611                           bits2PeFactor_e + 1) > peLast) &&
2612       (FDKaacEnc_bits2pe2(bitsLast,
2613                           fMult(FL2FXCONST_DBL(0.65f), bits2PeFactor_m),
2614                           bits2PeFactor_e) < peLast)) {
2615     FIXP_DBL corrFac = *correctionFac_m;
2616 
2617     int scaling = 0;
2618     FIXP_DBL denum = (FIXP_DBL)FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m,
2619                                                   bits2PeFactor_e);
2620     FIXP_DBL newFac = fDivNorm((FIXP_DBL)peLast, denum, &scaling);
2621 
2622     /* dead zone, newFac and corrFac are scaled by 0.5 */
2623     if ((FIXP_DBL)peLast <= denum) { /* ratio <= 1.f */
2624       newFac = fixMax(
2625           scaleValue(fixMin(fMult(FL2FXCONST_DBL(1.1f / 2.f), newFac),
2626                             scaleValue(FL2FXCONST_DBL(1.f / 2.f), -scaling)),
2627                      scaling),
2628           FL2FXCONST_DBL(0.85f / 2.f));
2629     } else { /* ratio < 1.f */
2630       newFac = fixMax(
2631           fixMin(scaleValue(fMult(FL2FXCONST_DBL(0.9f / 2.f), newFac), scaling),
2632                  FL2FXCONST_DBL(1.15f / 2.f)),
2633           FL2FXCONST_DBL(1.f / 2.f));
2634     }
2635 
2636     if (((newFac > FL2FXCONST_DBL(1.f / 2.f)) &&
2637          (corrFac < FL2FXCONST_DBL(1.f / 2.f))) ||
2638         ((newFac < FL2FXCONST_DBL(1.f / 2.f)) &&
2639          (corrFac > FL2FXCONST_DBL(1.f / 2.f)))) {
2640       corrFac = FL2FXCONST_DBL(1.f / 2.f);
2641     }
2642 
2643     /* faster adaptation towards 1.0, slower in the other direction */
2644     if ((corrFac < FL2FXCONST_DBL(1.f / 2.f) && newFac < corrFac) ||
2645         (corrFac > FL2FXCONST_DBL(1.f / 2.f) && newFac > corrFac)) {
2646       corrFac = fMult(FL2FXCONST_DBL(0.85f), corrFac) +
2647                 fMult(FL2FXCONST_DBL(0.15f), newFac);
2648     } else {
2649       corrFac = fMult(FL2FXCONST_DBL(0.7f), corrFac) +
2650                 fMult(FL2FXCONST_DBL(0.3f), newFac);
2651     }
2652 
2653     corrFac = fixMax(fixMin(corrFac, FL2FXCONST_DBL(1.15f / 2.f)),
2654                      FL2FXCONST_DBL(0.85 / 2.f));
2655 
2656     *correctionFac_m = corrFac;
2657     *correctionFac_e = 1;
2658   } else {
2659     *correctionFac_m = FL2FXCONST_DBL(1.f / 2.f);
2660     *correctionFac_e = 1;
2661   }
2662 }
2663 
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)2664 static void FDKaacEnc_calcPeCorrectionLowBitRes(
2665     FIXP_DBL *const correctionFac_m, INT *const correctionFac_e,
2666     const INT peLast, const INT bitsLast, const INT bitresLevel,
2667     const INT nChannels, const FIXP_DBL bits2PeFactor_m,
2668     const INT bits2PeFactor_e) {
2669   /* tuning params */
2670   const FIXP_DBL amp = FL2FXCONST_DBL(0.005);
2671   const FIXP_DBL maxDiff = FL2FXCONST_DBL(0.25f);
2672 
2673   if (bitsLast > 0) {
2674     /* Estimate deviation of granted and used dynamic bits in previous frame, in
2675      * PE units */
2676     const int bitsBalLast =
2677         peLast - FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m, bits2PeFactor_e);
2678 
2679     /* reserve n bits per channel */
2680     int headroom = (bitresLevel >= 50 * nChannels) ? 0 : (100 * nChannels);
2681 
2682     /* in PE units */
2683     headroom = FDKaacEnc_bits2pe2(headroom, bits2PeFactor_m, bits2PeFactor_e);
2684 
2685     /*
2686      * diff = amp * ((bitsBalLast - headroom) / (bitresLevel + headroom)
2687      * diff = max ( min ( diff, maxDiff, -maxDiff)) / 2
2688      */
2689     FIXP_DBL denominator = (FIXP_DBL)FDKaacEnc_bits2pe2(
2690                                bitresLevel, bits2PeFactor_m, bits2PeFactor_e) +
2691                            (FIXP_DBL)headroom;
2692 
2693     int scaling = 0;
2694     FIXP_DBL diff =
2695         (bitsBalLast >= headroom)
2696             ? fMult(amp, fDivNorm((FIXP_DBL)(bitsBalLast - headroom),
2697                                   denominator, &scaling))
2698             : -fMult(amp, fDivNorm(-(FIXP_DBL)(bitsBalLast - headroom),
2699                                    denominator, &scaling));
2700 
2701     scaling -= 1; /* divide by 2 */
2702 
2703     diff = (scaling <= 0)
2704                ? fMax(fMin(diff >> (-scaling), maxDiff >> 1), -maxDiff >> 1)
2705                : fMax(fMin(diff, maxDiff >> (1 + scaling)),
2706                       -maxDiff >> (1 + scaling))
2707                      << scaling;
2708 
2709     /*
2710      * corrFac += diff
2711      * corrFac = max ( min ( corrFac/2.f, 1.f/2.f, 0.75f/2.f ) )
2712      */
2713     *correctionFac_m =
2714         fMax(fMin((*correctionFac_m) + diff, FL2FXCONST_DBL(1.0f / 2.f)),
2715              FL2FXCONST_DBL(0.75f / 2.f));
2716     *correctionFac_e = 1;
2717   } else {
2718     *correctionFac_m = FL2FXCONST_DBL(0.75 / 2.f);
2719     *correctionFac_e = 1;
2720   }
2721 }
2722 
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)2723 void FDKaacEnc_DistributeBits(
2724     ADJ_THR_STATE *adjThrState, ATS_ELEMENT *AdjThrStateElement,
2725     PSY_OUT_CHANNEL *psyOutChannel[(2)], PE_DATA *peData, INT *grantedPe,
2726     INT *grantedPeCorr, const INT nChannels, const INT commonWindow,
2727     const INT grantedDynBits, const INT bitresBits, const INT maxBitresBits,
2728     const FIXP_DBL maxBitFac, const AACENC_BITRES_MODE bitResMode) {
2729   FIXP_DBL bitFactor;
2730   INT bitFactor_e;
2731   INT noRedPe = peData->pe;
2732 
2733   /* prefer short windows for calculation of bitFactor */
2734   INT curWindowSequence = LONG_WINDOW;
2735   if (nChannels == 2) {
2736     if ((psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) ||
2737         (psyOutChannel[1]->lastWindowSequence == SHORT_WINDOW)) {
2738       curWindowSequence = SHORT_WINDOW;
2739     }
2740   } else {
2741     curWindowSequence = psyOutChannel[0]->lastWindowSequence;
2742   }
2743 
2744   if (grantedDynBits >= 1) {
2745     if (bitResMode != AACENC_BR_MODE_FULL) {
2746       /* small or disabled bitreservoir */
2747       *grantedPe = FDKaacEnc_bits2pe2(grantedDynBits,
2748                                       AdjThrStateElement->bits2PeFactor_m,
2749                                       AdjThrStateElement->bits2PeFactor_e);
2750     } else {
2751       /* factor dependend on current fill level and pe */
2752       FDKaacEnc_bitresCalcBitFac(
2753           bitresBits, maxBitresBits, noRedPe, curWindowSequence, grantedDynBits,
2754           maxBitFac, adjThrState, AdjThrStateElement, &bitFactor, &bitFactor_e);
2755 
2756       /* desired pe for actual frame */
2757       /* Worst case max of grantedDynBits is = 1024 * 5.27 * 2 */
2758       *grantedPe = FDKaacEnc_bits2pe2(
2759           grantedDynBits, fMult(bitFactor, AdjThrStateElement->bits2PeFactor_m),
2760           AdjThrStateElement->bits2PeFactor_e + bitFactor_e);
2761     }
2762   } else {
2763     *grantedPe = 0; /* prevent divsion by 0 */
2764   }
2765 
2766   /* correction of pe value */
2767   switch (bitResMode) {
2768     case AACENC_BR_MODE_DISABLED:
2769     case AACENC_BR_MODE_REDUCED:
2770       /* correction of pe value for low bitres */
2771       FDKaacEnc_calcPeCorrectionLowBitRes(
2772           &AdjThrStateElement->peCorrectionFactor_m,
2773           &AdjThrStateElement->peCorrectionFactor_e, AdjThrStateElement->peLast,
2774           AdjThrStateElement->dynBitsLast, bitresBits, nChannels,
2775           AdjThrStateElement->bits2PeFactor_m,
2776           AdjThrStateElement->bits2PeFactor_e);
2777       break;
2778     case AACENC_BR_MODE_FULL:
2779     default:
2780       /* correction of pe value for high bitres */
2781       FDKaacEnc_FDKaacEnc_calcPeCorrection(
2782           &AdjThrStateElement->peCorrectionFactor_m,
2783           &AdjThrStateElement->peCorrectionFactor_e,
2784           fixMin(*grantedPe, noRedPe), AdjThrStateElement->peLast,
2785           AdjThrStateElement->dynBitsLast, AdjThrStateElement->bits2PeFactor_m,
2786           AdjThrStateElement->bits2PeFactor_e);
2787       break;
2788   }
2789 
2790   *grantedPeCorr =
2791       (INT)(fMult((FIXP_DBL)(*grantedPe << Q_AVGBITS),
2792                   AdjThrStateElement->peCorrectionFactor_m) >>
2793             (Q_AVGBITS - AdjThrStateElement->peCorrectionFactor_e));
2794 
2795   /* update last pe */
2796   AdjThrStateElement->peLast = *grantedPe;
2797   AdjThrStateElement->dynBitsLast = -1;
2798 }
2799 
2800 /*****************************************************************************
2801 functionname: FDKaacEnc_AdjustThresholds
2802 description:  adjust thresholds
2803 *****************************************************************************/
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)2804 void FDKaacEnc_AdjustThresholds(
2805     ADJ_THR_STATE *const hAdjThr, QC_OUT_ELEMENT *const qcElement[((8))],
2806     QC_OUT *const qcOut, const PSY_OUT_ELEMENT *const psyOutElement[((8))],
2807     const INT CBRbitrateMode, const CHANNEL_MAPPING *const cm) {
2808   int i;
2809 
2810   if (CBRbitrateMode) {
2811     /* In case, no bits must be shifted between different elements, */
2812     /* an element-wise execution of the pe-dependent threshold- */
2813     /* adaption becomes necessary... */
2814     if (hAdjThr->bitDistributionMode == AACENC_BD_MODE_INTRA_ELEMENT) {
2815       for (i = 0; i < cm->nElements; i++) {
2816         ELEMENT_INFO elInfo = cm->elInfo[i];
2817 
2818         if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
2819             (elInfo.elType == ID_LFE)) {
2820           /* qcElement[i]->grantedPe = 2000; */ /* Use this only for debugging
2821                                                  */
2822           // if (totalGrantedPeCorr < totalNoRedPe) {
2823           if (qcElement[i]->grantedPeCorr < qcElement[i]->peData.pe) {
2824             /* calc threshold necessary for desired pe */
2825             FDKaacEnc_adaptThresholdsToPe(
2826                 cm, hAdjThr->adjThrStateElem, qcElement, psyOutElement,
2827                 qcElement[i]->grantedPeCorr, hAdjThr->maxIter2ndGuess,
2828                 1, /* Process only 1 element */
2829                 i  /* Process exactly THIS element */
2830             );
2831           }
2832         } /*  -end- if(ID_SCE || ID_CPE || ID_LFE) */
2833       }   /* -end- element loop */
2834     }     /* AACENC_BD_MODE_INTRA_ELEMENT */
2835     else if (hAdjThr->bitDistributionMode == AACENC_BD_MODE_INTER_ELEMENT) {
2836       /* Use global Pe to obtain the thresholds? */
2837       if (qcOut->totalGrantedPeCorr < qcOut->totalNoRedPe) {
2838         /* add equal loadness quantization noise to match the */
2839         /* desired pe calc threshold necessary for desired pe */
2840         /* Now carried out globally to cover all(!) channels. */
2841         FDKaacEnc_adaptThresholdsToPe(cm, hAdjThr->adjThrStateElem, qcElement,
2842                                       psyOutElement, qcOut->totalGrantedPeCorr,
2843                                       hAdjThr->maxIter2ndGuess,
2844                                       cm->nElements, /* Process all elements */
2845                                       0); /* Process exactly THIS element */
2846       } else {
2847         /* In case global pe doesn't need to be reduced check each element to
2848            hold estimated bitrate below maximum element bitrate. */
2849         for (i = 0; i < cm->nElements; i++) {
2850           if ((cm->elInfo[i].elType == ID_SCE) ||
2851               (cm->elInfo[i].elType == ID_CPE) ||
2852               (cm->elInfo[i].elType == ID_LFE)) {
2853             /* Element pe applies to dynamic bits of maximum element bitrate. */
2854             const int maxElementPe = FDKaacEnc_bits2pe2(
2855                 (cm->elInfo[i].nChannelsInEl * MIN_BUFSIZE_PER_EFF_CHAN) -
2856                     qcElement[i]->staticBitsUsed - qcElement[i]->extBitsUsed,
2857                 hAdjThr->adjThrStateElem[i]->bits2PeFactor_m,
2858                 hAdjThr->adjThrStateElem[i]->bits2PeFactor_e);
2859 
2860             if (maxElementPe < qcElement[i]->peData.pe) {
2861               FDKaacEnc_adaptThresholdsToPe(
2862                   cm, hAdjThr->adjThrStateElem, qcElement, psyOutElement,
2863                   maxElementPe, hAdjThr->maxIter2ndGuess, 1, i);
2864             }
2865           } /*  -end- if(ID_SCE || ID_CPE || ID_LFE) */
2866         }   /* -end- element loop */
2867       }     /* (qcOut->totalGrantedPeCorr < qcOut->totalNoRedPe) */
2868     }       /* AACENC_BD_MODE_INTER_ELEMENT */
2869   } else {
2870     for (i = 0; i < cm->nElements; i++) {
2871       ELEMENT_INFO elInfo = cm->elInfo[i];
2872 
2873       if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
2874           (elInfo.elType == ID_LFE)) {
2875         /* for VBR-mode */
2876         FDKaacEnc_AdaptThresholdsVBR(
2877             qcElement[i]->qcOutChannel, psyOutElement[i]->psyOutChannel,
2878             hAdjThr->adjThrStateElem[i], &psyOutElement[i]->toolsInfo,
2879             cm->elInfo[i].nChannelsInEl);
2880       } /*  -end- if(ID_SCE || ID_CPE || ID_LFE) */
2881 
2882     } /* -end- element loop */
2883   }
2884   for (i = 0; i < cm->nElements; i++) {
2885     int ch, sfb, sfbGrp;
2886     /* no weighting of threholds and energies for mlout */
2887     /* weight energies and thresholds */
2888     for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) {
2889       QC_OUT_CHANNEL *pQcOutCh = qcElement[i]->qcOutChannel[ch];
2890       for (sfbGrp = 0; sfbGrp < psyOutElement[i]->psyOutChannel[ch]->sfbCnt;
2891            sfbGrp += psyOutElement[i]->psyOutChannel[ch]->sfbPerGroup) {
2892         for (sfb = 0; sfb < psyOutElement[i]->psyOutChannel[ch]->maxSfbPerGroup;
2893              sfb++) {
2894           pQcOutCh->sfbThresholdLdData[sfb + sfbGrp] +=
2895               pQcOutCh->sfbEnFacLd[sfb + sfbGrp];
2896         }
2897       }
2898     }
2899   }
2900 }
2901 
FDKaacEnc_AdjThrClose(ADJ_THR_STATE ** phAdjThr)2902 void FDKaacEnc_AdjThrClose(ADJ_THR_STATE **phAdjThr) {
2903   INT i;
2904   ADJ_THR_STATE *hAdjThr = *phAdjThr;
2905 
2906   if (hAdjThr != NULL) {
2907     for (i = 0; i < ((8)); i++) {
2908       if (hAdjThr->adjThrStateElem[i] != NULL) {
2909         FreeRam_aacEnc_AdjThrStateElement(&hAdjThr->adjThrStateElem[i]);
2910       }
2911     }
2912     FreeRam_aacEnc_AdjustThreshold(phAdjThr);
2913   }
2914 }
2915