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