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