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