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