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