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