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