1 2 /* ----------------------------------------------------------------------------------------------------------- 3 Software License for The Fraunhofer FDK AAC Codec Library for Android 4 5 Copyright 1995 - 2012 Fraunhofer-Gesellschaft zur Frderung 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 (at) 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 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 *****************************************************************************/ 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 *****************************************************************************/ 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 *****************************************************************************/ 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 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 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 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 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 *****************************************************************************/ 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 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() */ 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 */ 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 *****************************************************************************/ 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 *****************************************************************************/ 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 *****************************************************************************/ 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 */ 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 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 *****************************************************************************/ 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 */ 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 */ 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 */ 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 *****************************************************************************/ 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 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 *****************************************************************************/ 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 *****************************************************************************/ 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 *****************************************************************************/ 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 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 *****************************************************************************/ 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 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