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