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