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