2 /* -----------------------------------------------------------------------------------------------------------
3 Software License for The Fraunhofer FDK AAC Codec Library for Android
5 © Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
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.
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.
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.
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.
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:
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.
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.
42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43 prior written permission.
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.
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."
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.
59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60 by appropriate patent licenses.
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.
73 5. CONTACT INFORMATION
75 Fraunhofer Institute for Integrated Circuits IIS
76 Attention: Audio and Multimedia Departments - FDK AAC LL
78 91058 Erlangen, Germany
80 www.iis.fraunhofer.de/amm
81 amm-info@iis.fraunhofer.de
82 ----------------------------------------------------------------------------------------------------------- */
84 /******************************** MPEG Audio Encoder **************************
86 Initial author: M. Werner
87 contents/description: Threshold compensation
89 ******************************************************************************/
91 #include "common_fix.h"
93 #include "adj_thr_data.h"
97 #include "aacEnc_ram.h"
102 #define INV_INT_TAB_SIZE (8)
103 static const FIXP_DBL invInt
[INV_INT_TAB_SIZE
] =
105 0x7fffffff, 0x7fffffff, 0x40000000, 0x2aaaaaaa, 0x20000000, 0x19999999, 0x15555555, 0x12492492
109 #define INV_SQRT4_TAB_SIZE (8)
110 static const FIXP_DBL invSqrt4
[INV_SQRT4_TAB_SIZE
] =
112 0x7fffffff, 0x7fffffff, 0x6ba27e65, 0x61424bb5, 0x5a827999, 0x55994845, 0x51c8e33c, 0x4eb160d1
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);*/
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);*/
127 The bits2Pe factors are choosen for the case that some times
128 the crash recovery strategy will be activated once.
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
;
145 const INT sampleRate
;
146 const BIT_PE_SFAC
* pPeTab
;
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}
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}
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}
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}
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}
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}
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
) }
237 /* values for avoid hole flag */
238 enum _avoid_hole_state
{
245 /* Q format definitions */
246 #define Q_BITFAC (24) /* Q scaling used in FDKaacEnc_bitresCalcBitFac() calculation */
247 #define Q_AVGBITS (17) /* scale bit values */
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
,
259 const INT sampleRate
,
260 const INT advancedBitsToPe
,
264 /* default bits2pe factor */
265 FIXP_DBL bit2PE_m
= FL2FXCONST_DBL(1.18f
/(1<<(1)));
268 /* make use of advanced bits to pe factor table */
269 if (advancedBitsToPe
) {
272 const BIT_PE_SFAC
*peTab
= NULL
;
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
;
284 if ( (peTab
!=NULL
) && (size
!=0) ) {
290 /* stereo or mono mode and invQuant used or not */
291 for (i
=0; i
<size
-1; i
++)
293 if ((peTab
[i
].bitrate
<=bitRate
) && ((peTab
[i
+1].bitrate
>bitRate
) || ((i
==size
-2)) ))
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
;
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
;
316 /* if a configuration is available */
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 */
322 /* sanity check if bits2pe value is high enough */
323 if ( bit2PE
>= (FL2FXCONST_DBL(0.35f
) >> 2) ) {
325 bit2PE_e
= 2; /* table is fixed scaled */
329 } /* advancedBitsToPe */
332 /* return bits2pe factor */
333 *bits2PeFactor_m
= bit2PE_m
;
334 *bits2PeFactor_e
= bit2PE_e
;
338 /*****************************************************************************
339 functionname: FDKaacEnc_bits2pe2
340 description: convert from bits to pe
341 *****************************************************************************/
342 static INT
FDKaacEnc_bits2pe2(
344 const FIXP_DBL factor_m
,
348 return (INT
)(fMult(factor_m
, (FIXP_DBL
)(bits
<<Q_AVGBITS
)) >> (Q_AVGBITS
-factor_e
));
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)],
361 FIXP_DBL thrExpLdData
;
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
);
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
,
383 INT ch
, sfb
, sfbGrp
, nSfb
;
384 FIXP_DBL avgEnLD64
, dbRatio
, minSnrRed
;
385 FIXP_DBL minSnrLimitLD64
= FL2FXCONST_DBL(-0.00503012648262f
); /* ld64(0.8f) */
389 for (ch
=0; ch
<nChannels
; ch
++) {
390 /* calc average energy per scalefactor band */
392 accu
= FL2FXCONST_DBL(0.0f
);
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;
401 if ((accu
== FL2FXCONST_DBL(0.0f
)) || (nSfb
== 0)) {
402 avgEnLD64
= FL2FXCONST_DBL(-1.0f
);
405 nSfbLD64
= CalcLdInt(nSfb
);
406 avgEnLD64
= CalcLdData(accu
);
407 avgEnLD64
= avgEnLD64
+ FL2FXCONST_DBL(0.09375f
) - nSfbLD64
; /* 0.09375f: compensate shift with 6 */
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
]);
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
,
435 const PE_DATA
*peData
,
439 FIXP_DBL sfbEn
, sfbEnm1
;
440 FIXP_DBL sfbEnLdData
;
441 FIXP_DBL avgEnLdData
;
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
++) {
447 QC_OUT_CHANNEL
* qcOutChan
= qcOutChannel
[ch
];
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 ;
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
]) ;
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
;
471 sfbEnm1
= qcOutChan
->sfbEnergy
[sfbGrp
+sfb
-1];
473 sfbEnm1
= qcOutChan
->sfbEnergy
[sfbGrp
+sfb
];
475 if (sfb
< psyOutChannel
[ch
]->maxSfbPerGroup
-1)
476 sfbEnp1
= qcOutChan
->sfbEnergy
[sfbGrp
+sfb
+1];
478 sfbEnp1
= qcOutChan
->sfbEnergy
[sfbGrp
+sfb
];
480 avgEn
= (sfbEnm1
>>1) + (sfbEnp1
>>1);
481 avgEnLdData
= CalcLdData(avgEn
);
482 sfbEn
= qcOutChan
->sfbEnergy
[sfbGrp
+sfb
];
483 sfbEnLdData
= qcOutChan
->sfbEnergyLdData
[sfbGrp
+sfb
];
486 FIXP_DBL tmpMinSnrLdData
;
487 if (psyOutChannel
[ch
]->lastWindowSequence
==LONG_WINDOW
)
488 tmpMinSnrLdData
= fixMax( SnrLdFac
+ (FIXP_DBL
)(avgEnLdData
- sfbEnLdData
), (FIXP_DBL
)SnrLdMin1
) ;
490 tmpMinSnrLdData
= fixMax( SnrLdFac
+ (FIXP_DBL
)(avgEnLdData
- sfbEnLdData
), (FIXP_DBL
)SnrLdMin3
) ;
492 qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
] =
493 fixMin(qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
], tmpMinSnrLdData
);
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
));
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
;
519 if ( ((SnrLdMin5
>>1) + (maxSfbEnLd
>>1) + (qcOutChanM
->sfbMinSnrLdData
[sfbGrp
+sfb
]>>1)) <= FL2FXCONST_DBL(-0.5f
))
520 maxThrLd
= FL2FXCONST_DBL(-1.0f
) ;
522 maxThrLd
= SnrLdMin5
+ maxSfbEnLd
+ qcOutChanM
->sfbMinSnrLdData
[sfbGrp
+sfb
];
524 if (qcOutChanM
->sfbEnergy
[sfbGrp
+sfb
] > FL2FXCONST_DBL(0.0f
))
525 sfbMinSnrTmpLd
= maxThrLd
- qcOutChanM
->sfbEnergyLdData
[sfbGrp
+sfb
];
527 sfbMinSnrTmpLd
= FL2FXCONST_DBL(0.0f
);
529 qcOutChanM
->sfbMinSnrLdData
[sfbGrp
+sfb
] = fixMax(qcOutChanM
->sfbMinSnrLdData
[sfbGrp
+sfb
],sfbMinSnrTmpLd
);
531 if (qcOutChanM
->sfbMinSnrLdData
[sfbGrp
+sfb
] <= FL2FXCONST_DBL(0.0f
))
532 qcOutChanM
->sfbMinSnrLdData
[sfbGrp
+sfb
] = fixMin(qcOutChanM
->sfbMinSnrLdData
[sfbGrp
+sfb
], (FIXP_DBL
)SnrLdFac
);
534 if (qcOutChanS
->sfbEnergy
[sfbGrp
+sfb
] > FL2FXCONST_DBL(0.0f
))
535 sfbMinSnrTmpLd
= maxThrLd
- qcOutChanS
->sfbEnergyLdData
[sfbGrp
+sfb
];
537 sfbMinSnrTmpLd
= FL2FXCONST_DBL(0.0f
);
539 qcOutChanS
->sfbMinSnrLdData
[sfbGrp
+sfb
] = fixMax(qcOutChanS
->sfbMinSnrLdData
[sfbGrp
+sfb
],sfbMinSnrTmpLd
);
541 if (qcOutChanS
->sfbMinSnrLdData
[sfbGrp
+sfb
] <= FL2FXCONST_DBL(0.0f
))
542 qcOutChanS
->sfbMinSnrLdData
[sfbGrp
+sfb
] = fixMin(qcOutChanS
->sfbMinSnrLdData
[sfbGrp
+sfb
],(FIXP_DBL
)SnrLdFac
);
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
));
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
));
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
;
567 ahFlag
[ch
][sfbGrp
+sfb
] = AH_INACTIVE
;
577 * \brief Calculate constants that do not change during successive pe calculations.
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.
588 void FDKaacEnc_preparePe(PE_DATA
*peData
,
589 PSY_OUT_CHANNEL
* psyOutChannel
[(2)],
590 QC_OUT_CHANNEL
* qcOutChannel
[(2)],
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
,
604 psyOutChan
->sfbPerGroup
,
605 psyOutChan
->maxSfbPerGroup
);
607 peData
->offset
= peOffset
;
611 * \brief Calculate weighting factor for threshold adjustment.
613 * Calculate weighting factor to be applied at energies and thresholds in ld64 format.
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).
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
,
632 const INT usePatchTool
)
634 int ch
, noShortWindowInFrame
= TRUE
;
637 for (ch
=0; ch
<nChannels
; ch
++) {
638 if (psyOutChannel
[ch
]->lastWindowSequence
== SHORT_WINDOW
) {
639 noShortWindowInFrame
= FALSE
;
641 FDKmemclear(qcOutChannel
[ch
]->sfbEnFacLd
, MAX_GROUPED_SFB
*sizeof(FIXP_DBL
));
644 if (usePatchTool
==0) {
645 return; /* tool is disabled */
648 for (ch
=0; ch
<nChannels
; ch
++) {
650 PSY_OUT_CHANNEL
*psyOutChan
= psyOutChannel
[ch
];
652 if (noShortWindowInFrame
) { /* retain energy ratio between blocks of different length */
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;
659 nrgSum14
= nrgSum12
= nrgSum34
= nrgTotal
= FL2FXCONST_DBL(0.f
);
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) */
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) */
676 nrgTotal
= CalcLdData(nrgTotal
); /* get ld64 of total nrg */
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) */
682 adjThrStateElement
->chaosMeasureEnFac
[ch
] = FDKmax( FL2FXCONST_DBL(0.1875f
), fDivNorm(nLinesSum
,psyOutChan
->sfbOffsets
[psyOutChan
->sfbCnt
]) );
684 usePatch
= (adjThrStateElement
->chaosMeasureEnFac
[ch
] > FL2FXCONST_DBL(0.78125f
));
685 exePatch
= ((usePatch
) && (adjThrStateElement
->lastEnFacPatch
[ch
]));
687 for (sfbGrp
= 0;sfbGrp
< psyOutChannel
[ch
]->sfbCnt
; sfbGrp
+=psyOutChannel
[ch
]->sfbPerGroup
) {
688 for (sfb
=0; sfb
<psyOutChannel
[ch
]->maxSfbPerGroup
; sfb
++) {
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
;
697 sfbExePatch
= exePatch
;
700 if ( (sfbExePatch
) && (psyOutChan
->sfbEnergy
[sfbGrp
+sfb
]>FL2FXCONST_DBL(0.f
)) )
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) */
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) */
710 qcOutChannel
[ch
]->sfbEnFacLd
[sfbGrp
+sfb
] = ( (nrgFacLd_34
+ (psyOutChan
->sfbEnergyLdData
[sfbGrp
+sfb
]>>1))>>1 ); /* sfbEnergy^(1/4) */
712 qcOutChannel
[ch
]->sfbEnFacLd
[sfbGrp
+sfb
] = fixMin(qcOutChannel
[ch
]->sfbEnFacLd
[sfbGrp
+sfb
],(FIXP_DBL
)0);
718 adjThrStateElement
->lastEnFacPatch
[ch
] = usePatch
;
719 exePatchM
= exePatch
;
722 /* !noShortWindowInFrame */
723 adjThrStateElement
->chaosMeasureEnFac
[ch
] = FL2FXCONST_DBL(0.75f
);
724 adjThrStateElement
->lastEnFacPatch
[ch
] = TRUE
; /* allow use of sfbEnFac patch in upcoming frame */
734 /*****************************************************************************
735 functionname: FDKaacEnc_calcPe
736 description: calculate pe for both channels
737 *****************************************************************************/
739 void FDKaacEnc_calcPe(PSY_OUT_CHANNEL
* psyOutChannel
[(2)],
740 QC_OUT_CHANNEL
* qcOutChannel
[(2)],
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
);
760 peData
->pe
+= peChanData
->pe
;
761 peData
->constPart
+= peChanData
->constPart
;
762 peData
->nActiveLines
+= peChanData
->nActiveLines
;
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
,
773 /* constants that will not change during successive pe calculations */
774 FDKaacEnc_preparePe(peData
, psyOutChannel
, qcOutChannel
, nChannels
, adjThrStateElement
->peOffset
);
776 /* calculate weighting factor for threshold adjustment */
777 FDKaacEnc_calcWeighting(peData
, psyOutChannel
, qcOutChannel
, toolsInfo
, adjThrStateElement
, nChannels
, 1);
779 /* no weighting of threholds and energies for mlout */
780 /* weight energies and thresholds */
782 for (ch
=0; ch
<nChannels
; ch
++) {
785 QC_OUT_CHANNEL
* pQcOutCh
= qcOutChannel
[ch
];
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
];
796 /* pe without reduction */
797 FDKaacEnc_calcPe(psyOutChannel
, qcOutChannel
, peData
, nChannels
);
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
,
810 UCHAR ahFlag
[(2)][MAX_GROUPED_SFB
],
811 PSY_OUT_CHANNEL
* psyOutChannel
[(2)],
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
];
831 /* correct scaled pe and constPart values */
832 *pe
= pe_tmp
>> PE_CONSTPART_SHIFT
;
833 *constPart
= constPart_tmp
>> PE_CONSTPART_SHIFT
;
835 *nActiveLines
= nActiveLines_tmp
;
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));*/
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
],
850 const FIXP_DBL redVal
,
851 const SCHAR redValScaling
)
854 FIXP_DBL sfbEnLdData
, sfbThrLdData
, sfbThrReducedLdData
;
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
)) {
866 /* threshold reduction formula:
867 float tmp = thrExp[ch][sfb]+redVal;
869 sfbThrReduced = tmp*tmp;
871 int minScale
= fixMin(CountLeadingBits(sfbThrExp
), CountLeadingBits(redVal
) - (DFRACT_BITS
-1-redValScaling
) )-1;
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;
879 if ( ((sfbThrReducedLdData
- sfbEnLdData
) > qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
] )
880 && (ahFlag
[ch
][sfbGrp
+sfb
] != NO_AH
) )
882 if (qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
] > (FL2FXCONST_DBL(-1.0f
) - sfbEnLdData
) ){
883 sfbThrReducedLdData
= fixMax((qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
] + sfbEnLdData
), sfbThrLdData
);
885 else sfbThrReducedLdData
= sfbThrLdData
;
886 ahFlag
[ch
][sfbGrp
+sfb
] = AH_ACTIVE
;
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
)));
894 qcOutChan
->sfbThresholdLdData
[sfbGrp
+sfb
] = sfbThrReducedLdData
;
901 /* similar to prepareSfbPe1() */
902 static FIXP_DBL
FDKaacEnc_calcChaosMeasure(PSY_OUT_CHANNEL
*psyOutChannel
,
903 const FIXP_DBL
*sfbFormFactorLdData
)
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 */
912 FIXP_DBL chaosMeasure
;
914 FIXP_DBL frameFormFactor
= FL2FXCONST_DBL(0.f
);
915 FIXP_DBL frameEnergy
= FL2FXCONST_DBL(0.f
);
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
);
929 /* frameNActiveLines = frameFormFactor*2^FORM_FAC_SHIFT * ((frameEnergy *2^SCALE_NRGS)/frameNLines)^-0.25
930 chaosMeasure = frameNActiveLines / frameNLines */
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))
939 /* assuming total chaos, if no sfb is above thresholds */
940 chaosMeasure
= FL2FXCONST_DBL(1.f
);
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
],
952 const FIXP_DBL vbrQualFactor
,
953 FIXP_DBL
* chaosMeasureOld
)
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
;
968 #define SCALE_GROUP_ENERGY (8)
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))
973 #define MIN_LDTHRESH (FL2FXCONST_DBL(-0.515625f))
976 for(ch
=0; ch
<nChannels
; ch
++){
977 qcOutChan
= qcOutChannel
[ch
];
978 psyOutChan
= psyOutChannel
[ch
];
980 /* adding up energy for each channel and each group separately */
981 FIXP_DBL chEnergy
= FL2FXCONST_DBL(0.f
);
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
);
989 chEnergy
+= chGroupEnergy
[groupCnt
][ch
];
991 frameEnergy
+= chEnergy
;
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 */
997 chChaosMeasure
[ch
] = FDKaacEnc_calcChaosMeasure(psyOutChannel
[ch
], qcOutChannel
[ch
]->sfbFormFactorLdData
);
999 chaosMeasure
+= fMult(chChaosMeasure
[ch
], chEnergy
);
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);
1009 chaosMeasure
= FL2FXCONST_DBL(1.f
);
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 */
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
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;
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)
1029 INT sfbGrp
, groupCnt
=0;
1030 for (sfbGrp
=0; sfbGrp
<psyOutChan
->sfbCnt
; sfbGrp
+=psyOutChan
->sfbPerGroup
,groupCnt
++) {
1032 FIXP_DBL groupEnergy
= FL2FXCONST_DBL(0.f
);
1034 for(ch
=0;ch
<nChannels
;ch
++){
1035 groupEnergy
+= chGroupEnergy
[groupCnt
][ch
]; /* adding up the channels groupEnergy */
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 */
1042 groupEnergy
>>=2; /* 2*WIN_TYPE_SCALE = 6 => 6+2 = 8 ==> 8/4 = int number */
1044 redVal
[groupCnt
] = fMult(fMult(vbrQualFactor
,chaosMeasure
),
1045 CalcInvLdData(CalcLdData(groupEnergy
)>>2) )
1046 << (int)( ( 2 + (2*WIN_TYPE_SCALE
) + SCALE_GROUP_ENERGY
)>>2 ) ;
1049 } else { /* long-block */
1051 redVal
[0] = fMult( fMult(vbrQualFactor
,chaosMeasure
),
1052 CalcInvLdData(CalcLdData(frameEnergy
)>>2) )
1053 << (int)( SCALE_GROUP_ENERGY
>>2 ) ;
1056 for(ch
=0; ch
<nChannels
; ch
++) {
1057 qcOutChan
= qcOutChannel
[ch
];
1058 psyOutChan
= psyOutChannel
[ch
];
1060 for (sfbGrp
=0; sfbGrp
<psyOutChan
->sfbCnt
; sfbGrp
+=psyOutChan
->sfbPerGroup
) {
1061 for (sfb
=0; sfb
<psyOutChan
->maxSfbPerGroup
; sfb
++){
1063 sfbEnLdData
= (qcOutChan
->sfbWeightedEnergyLdData
[sfbGrp
+sfb
]);
1064 sfbThrLdData
= (qcOutChan
->sfbThresholdLdData
[sfbGrp
+sfb
]);
1065 sfbThrExp
= thrExp
[ch
][sfbGrp
+sfb
];
1067 if ( (sfbThrLdData
>=MIN_LDTHRESH
) && (sfbEnLdData
> sfbThrLdData
) && (ahFlag
[ch
][sfbGrp
+sfb
] != AH_ACTIVE
)) {
1070 if (psyOutChannel
[ch
]->lastWindowSequence
== SHORT_WINDOW
) {
1071 const int groupNumber
= (int) sfb
/psyOutChan
->sfbPerGroup
;
1073 FDK_ASSERT(INV_SQRT4_TAB_SIZE
>psyOutChan
->groupLen
[groupNumber
]);
1075 sfbThrExp
= fMult(sfbThrExp
, fMult( FL2FXCONST_DBL(2.82f
/4.f
), invSqrt4
[psyOutChan
->groupLen
[groupNumber
]]))<<2 ;
1077 if ( sfbThrExp
<= (limitThrReducedLdData
-redVal
[groupNumber
]) ) {
1078 sfbThrReducedLdData
= FL2FXCONST_DBL(-1.0f
);
1081 if ((FIXP_DBL
)redVal
[groupNumber
] >= FL2FXCONST_DBL(1.0f
)-sfbThrExp
)
1082 sfbThrReducedLdData
= FL2FXCONST_DBL(0.0f
);
1084 /* threshold reduction formula */
1085 sfbThrReducedLdData
= CalcLdData(sfbThrExp
+ redVal
[groupNumber
]);
1086 sfbThrReducedLdData
<<= 2;
1089 sfbThrReducedLdData
+= ( CalcLdInt(psyOutChan
->groupLen
[groupNumber
]) -
1090 ((FIXP_DBL
)6<<(DFRACT_BITS
-1-LD_DATA_SHIFT
)) );
1095 if ((FIXP_DBL
)redVal
[0] >= FL2FXCONST_DBL(1.0f
)-sfbThrExp
) {
1096 sfbThrReducedLdData
= FL2FXCONST_DBL(0.0f
);
1099 /* threshold reduction formula */
1100 sfbThrReducedLdData
= CalcLdData(sfbThrExp
+ redVal
[0]);
1101 sfbThrReducedLdData
<<= 2;
1106 if ( ((sfbThrReducedLdData
- sfbEnLdData
) > qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
] )
1107 && (ahFlag
[ch
][sfbGrp
+sfb
] != NO_AH
) )
1109 if (qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
] > (FL2FXCONST_DBL(-1.0f
) - sfbEnLdData
) ){
1110 sfbThrReducedLdData
= fixMax((qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
] + sfbEnLdData
), sfbThrLdData
);
1112 else sfbThrReducedLdData
= sfbThrLdData
;
1113 ahFlag
[ch
][sfbGrp
+sfb
] = AH_ACTIVE
;
1116 if (sfbThrReducedLdData
<FL2FXCONST_DBL(-0.5f
))
1117 sfbThrReducedLdData
= FL2FXCONST_DBL(-1.f
);
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
));
1124 sfbThrReducedLdData
= fixMax(MIN_LDTHRESH
,sfbThrReducedLdData
);
1126 qcOutChan
->sfbThresholdLdData
[sfbGrp
+sfb
] = sfbThrReducedLdData
;
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)],
1147 const INT processElements
,
1148 const INT elementOffset
)
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
];
1159 FIXP_DBL normFactorLdData
;
1161 INT nElements
= elementOffset
+processElements
;
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
;
1172 /* for each sfb calc relative factors for pe changes */
1175 for(elementId
=elementOffset
;elementId
<nElements
;elementId
++) {
1176 if (cm
->elInfo
[elementId
].elType
!= ID_DSE
) {
1178 for(ch
=0; ch
<cm
->elInfo
[elementId
].nChannelsInEl
; ch
++) {
1180 qcOutChan
= qcElement
[elementId
]->qcOutChannel
[ch
];
1181 psyOutChan
= psyOutElement
[elementId
]->psyOutChannel
[ch
];
1182 peChanData
= &qcElement
[elementId
]->peData
.peChannelData
[ch
];
1184 for(sfbGrp
= 0; sfbGrp
< psyOutChan
->sfbCnt
; sfbGrp
+= psyOutChan
->sfbPerGroup
){
1185 for (sfb
=0; sfb
<psyOutChan
->maxSfbPerGroup
; sfb
++) {
1187 if ( peChanData
->sfbNActiveLines
[sfbGrp
+sfb
] == 0 ) {
1188 sfbNActiveLinesLdData
[elementId
][ch
][sfbGrp
+sfb
] = FL2FXCONST_DBL(-1.0f
);
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
]);
1196 if ( ((ahFlag
[elementId
][ch
][sfbGrp
+sfb
] < AH_ACTIVE
) || (deltaPe
> 0)) &&
1197 peChanData
->sfbNActiveLines
[sfbGrp
+sfb
] != 0 )
1199 if (thrExp
[elementId
][ch
][sfbGrp
+sfb
] > -redVal
[elementId
]) {
1201 /* sfbPeFactors[ch][sfbGrp+sfb] = peChanData->sfbNActiveLines[sfbGrp+sfb] /
1202 (thrExp[elementId][ch][sfbGrp+sfb] + redVal[elementId]); */
1204 int minScale
= fixMin(CountLeadingBits(thrExp
[elementId
][ch
][sfbGrp
+sfb
]), CountLeadingBits(redVal
[elementId
]) - (DFRACT_BITS
-1-redValScaling
[elementId
]) ) - 1;
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
));
1210 if (sumLd
< FL2FXCONST_DBL(0.f
)) {
1211 sfbPeFactorsLdData
[elementId
][ch
][sfbGrp
+sfb
] = sfbNActiveLinesLdData
[elementId
][ch
][sfbGrp
+sfb
] - sumLd
;
1214 if ( sfbNActiveLinesLdData
[elementId
][ch
][sfbGrp
+sfb
] > (FL2FXCONST_DBL(-1.f
) + sumLd
) ) {
1215 sfbPeFactorsLdData
[elementId
][ch
][sfbGrp
+sfb
] = sfbNActiveLinesLdData
[elementId
][ch
][sfbGrp
+sfb
] - sumLd
;
1218 sfbPeFactorsLdData
[elementId
][ch
][sfbGrp
+sfb
] = sfbNActiveLinesLdData
[elementId
][ch
][sfbGrp
+sfb
];
1222 normFactorInt
+= (INT
)CalcInvLdData(sfbPeFactorsLdData
[elementId
][ch
][sfbGrp
+sfb
]);
1224 else sfbPeFactorsLdData
[elementId
][ch
][sfbGrp
+sfb
] = FL2FXCONST_DBL(1.0f
);
1226 else sfbPeFactorsLdData
[elementId
][ch
][sfbGrp
+sfb
] = FL2FXCONST_DBL(-1.0f
);
1233 /* normFactorLdData = ld64(deltaPe/normFactorInt) */
1234 normFactorLdData
= CalcLdData((FIXP_DBL
)((deltaPe
<0) ? (-deltaPe
) : (deltaPe
))) - CalcLdData((FIXP_DBL
)normFactorInt
);
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
) {
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
];
1246 for(sfbGrp
= 0;sfbGrp
< psyOutChan
->sfbCnt
;sfbGrp
+= psyOutChan
->sfbPerGroup
){
1247 for (sfb
=0; sfb
<psyOutChan
->maxSfbPerGroup
; sfb
++) {
1249 if (peChanData
->sfbNActiveLines
[sfbGrp
+sfb
] > 0) {
1251 /* pe difference for this sfb */
1252 if ( (sfbPeFactorsLdData
[elementId
][ch
][sfbGrp
+sfb
]==FL2FXCONST_DBL(-1.0f
)) ||
1255 thrFactorLdData
= FL2FXCONST_DBL(0.f
);
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
));
1261 /* limit thrFactor to 60dB */
1262 tmp
= (deltaPe
<0) ? tmp
: (-tmp
);
1263 thrFactorLdData
= FDKmin(tmp
, FL2FXCONST_DBL(20.f
/LD_DATA_SCALING
));
1267 sfbThrLdData
= qcOutChan
->sfbThresholdLdData
[sfbGrp
+sfb
];
1268 sfbEnLdData
= qcOutChan
->sfbWeightedEnergyLdData
[sfbGrp
+sfb
];
1270 if (thrFactorLdData
< FL2FXCONST_DBL(0.f
)) {
1271 if( sfbThrLdData
> (FL2FXCONST_DBL(-1.f
)-thrFactorLdData
) ) {
1272 sfbThrReducedLdData
= sfbThrLdData
+ thrFactorLdData
;
1275 sfbThrReducedLdData
= FL2FXCONST_DBL(-1.f
);
1279 sfbThrReducedLdData
= sfbThrLdData
+ thrFactorLdData
;
1283 if ( (sfbThrReducedLdData
- sfbEnLdData
> qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
]) &&
1284 (ahFlag
[elementId
][ch
][sfbGrp
+sfb
] == AH_INACTIVE
) )
1286 /* sfbThrReduced = max(psyOutChan[ch]->sfbMinSnr[i] * sfbEn, sfbThr); */
1287 if ( sfbEnLdData
> (sfbThrLdData
-qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
]) ) {
1288 sfbThrReducedLdData
= qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
] + sfbEnLdData
;
1291 sfbThrReducedLdData
= sfbThrLdData
;
1293 ahFlag
[elementId
][ch
][sfbGrp
+sfb
] = AH_ACTIVE
;
1296 qcOutChan
->sfbThresholdLdData
[sfbGrp
+sfb
] = sfbThrReducedLdData
;
1305 /*****************************************************************************
1306 functionname: FDKaacEnc_reduceMinSnr
1307 description: if the desired pe can not be reached, reduce pe by
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
,
1316 const INT processElements
,
1317 const INT elementOffset
)
1321 INT nElements
= elementOffset
+processElements
;
1323 INT newGlobalPe
= *redPeGlobal
;
1325 for(elementId
=elementOffset
;elementId
<nElements
;elementId
++) {
1326 if (cm
->elInfo
[elementId
].elType
!= ID_DSE
) {
1328 INT maxSfbPerGroup
[2];
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
;
1338 PE_DATA
*peData
= &qcElement
[elementId
]->peData
;
1342 for(ch
=0; ch
<cm
->elInfo
[elementId
].nChannelsInEl
; ch
++) {
1345 QC_OUT_CHANNEL
*qcOutChan
= qcElement
[elementId
]->qcOutChannel
[ch
];
1346 INT noReduction
= 1;
1348 if (maxSfbPerGroup
[ch
]>=0) { /* sfb in next channel */
1350 sfb
= maxSfbPerGroup
[ch
]--;
1353 for (sfbGrp
= 0; sfbGrp
< sfbCnt
[ch
]; sfbGrp
+= sfbPerGroup
[ch
]) {
1355 if (ahFlag
[elementId
][ch
][sfbGrp
+sfb
] != NO_AH
&&
1356 qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
] < SnrLdFac
)
1358 /* increase threshold to new minSnr of 1dB */
1359 qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
] = SnrLdFac
;
1361 /* sfbThrReduced = max(psyOutChan[ch]->sfbMinSnr[i] * sfbEn, sfbThr); */
1362 if ( qcOutChan
->sfbWeightedEnergyLdData
[sfbGrp
+sfb
] >= qcOutChan
->sfbThresholdLdData
[sfbGrp
+sfb
] - qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
] ) {
1364 qcOutChan
->sfbThresholdLdData
[sfbGrp
+sfb
] = qcOutChan
->sfbWeightedEnergyLdData
[sfbGrp
+sfb
] + qcOutChan
->sfbMinSnrLdData
[sfbGrp
+sfb
];
1367 /* C2 + C3*ld(1/0.8) = 1.5 */
1368 deltaPe
-= (peData
->peChannelData
[ch
].sfbPe
[sfbGrp
+sfb
]>>PE_CONSTPART_SHIFT
);
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
);
1378 peData
->pe
+= deltaPe
;
1379 peData
->peChannelData
[ch
].pe
+= deltaPe
;
1380 newGlobalPe
+= deltaPe
;
1382 /* stop if enough has been saved */
1383 if (peData
->pe
<= desiredPe
) {
1389 if ( (ch
==(cm
->elInfo
[elementId
].nChannelsInEl
-1)) && noReduction
) {
1395 } while ( peData
->pe
> desiredPe
);
1398 } /* element loop */
1402 /* update global PE */
1403 *redPeGlobal
= newGlobalPe
;
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
)
1423 INT nElements
= elementOffset
+processElements
;
1424 INT actPe
= currentPe
;
1426 if (actPe
<= desiredPe
) {
1427 return; /* nothing to do */
1430 for (elementId
= elementOffset
;elementId
<nElements
;elementId
++) {
1431 if (cm
->elInfo
[elementId
].elType
!= ID_DSE
) {
1433 INT ch
, sfb
, sfbGrp
;
1435 PE_DATA
*peData
= &qcElement
[elementId
]->peData
;
1436 const INT nChannels
= cm
->elInfo
[elementId
].nChannelsInEl
;
1438 QC_OUT_CHANNEL
* qcOutChannel
[(2)] = {NULL
};
1439 PSY_OUT_CHANNEL
* psyOutChannel
[(2)] = {NULL
};
1441 for (ch
=0; ch
<nChannels
; ch
++) {
1444 qcOutChannel
[ch
] = qcElement
[elementId
]->qcOutChannel
[ch
];
1445 psyOutChannel
[ch
] = psyOutElement
[elementId
]->psyOutChannel
[ch
];
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;
1454 /* for MS allow hole in the channel with less energy */
1455 if ( nChannels
==2 && psyOutChannel
[0]->lastWindowSequence
==psyOutChannel
[1]->lastWindowSequence
) {
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
];
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))) )
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
;
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))) )
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
;
1483 if (actPe
<= desiredPe
) {
1484 return; /* stop if enough has been saved */
1487 } /* MS possible ? */
1489 /* more holes necessary? subsequently erase bands
1490 starting with low energies */
1492 FIXP_DBL avgEnLD64
,minEnLD64
;
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
;
1504 startSfb
[ch
] = AdjThrStateElement
[elementId
]->ahParam
.startSfbS
;
1507 /* calc avg and min energies of bands that avoid holes */
1508 avgEn
= FL2FXCONST_DBL(0.0f
);
1509 minEnLD64
= FL2FXCONST_DBL(0.0f
);
1512 for (ch
=0; ch
<nChannels
; ch
++) {
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;
1527 sfbGrp
+= psyOutChannel
[ch
]->sfbPerGroup
;
1530 } while (sfbGrp
< psyOutChannel
[ch
]->sfbCnt
);
1533 if ( (avgEn
== FL2FXCONST_DBL(0.0f
)) || (ahCnt
== 0) ) {
1534 avgEnLD64
= FL2FXCONST_DBL(0.0f
);
1537 avgEnLD64
= CalcLdData(avgEn
);
1538 ahCntLD64
= CalcLdInt(ahCnt
);
1539 avgEnLD64
= avgEnLD64
+ FL2FXCONST_DBL(0.09375f
) - ahCntLD64
; /* compensate shift with 6 */
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
);
1550 for (enIdx
=0; enIdx
<4; enIdx
++) {
1551 INT noReduction
= 1;
1553 INT maxSfbPerGroup
[2];
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
;
1567 for(ch
=0; ch
<cm
->elInfo
[elementId
].nChannelsInEl
; ch
++) {
1571 /* start with lowest energy border at highest sfb */
1572 if (maxSfbPerGroup
[ch
]>=startSfb
[ch
]) { /* sfb in next channel */
1573 sfb
= maxSfbPerGroup
[ch
]--;
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
]) {
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
;
1586 if (actPe
<= desiredPe
) {
1587 return; /* stop if enough has been saved */
1592 } while( (noReduction
== 0) && (actPe
> desiredPe
) );
1594 if (actPe
<= desiredPe
) {
1595 return; /* stop if enough has been saved */
1600 } /* EOF DSE-suppression */
1601 } /* EOF for all elements... */
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)])
1610 int ch
, sfb
, sfbGrp
;
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
;
1624 static FIXP_DBL
CalcRedValPower(FIXP_DBL num
,
1628 FIXP_DBL value
= FL2FXCONST_DBL(0.f
);
1630 if (num
>=FL2FXCONST_DBL(0.f
)) {
1631 value
= fDivNorm( num
, denum
, scaling
);
1634 value
= -fDivNorm( -num
, denum
, scaling
);
1636 value
= f2Pow(value
, *scaling
, scaling
);
1637 *scaling
= DFRACT_BITS
-1-*scaling
;
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
)
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
];
1661 INT constPartGlobal
, noRedPeGlobal
, nActiveLinesGlobal
, redPeGlobal
;
1662 constPartGlobal
= noRedPeGlobal
= nActiveLinesGlobal
= redPeGlobal
= 0;
1666 int nElements
= elementOffset
+processElements
;
1667 if(nElements
> cm
->nElements
) {
1668 nElements
= cm
->nElements
;
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
) {
1677 INT nChannels
= cm
->elInfo
[elementId
].nChannelsInEl
;
1678 PE_DATA
*peData
= &qcElement
[elementId
]->peData
;
1680 /* thresholds to the power of redExp */
1681 FDKaacEnc_calcThreshExp(pThrExp
[elementId
], qcElement
[elementId
]->qcOutChannel
, psyOutElement
[elementId
]->psyOutChannel
, nChannels
);
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
);
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
);
1691 constPartGlobal
+= peData
->constPart
;
1692 noRedPeGlobal
+= peData
->pe
;
1693 nActiveLinesGlobal
+= fixMax((INT
)peData
->nActiveLines
, 1);
1695 } /* EOF DSE-suppression */
1696 } /* EOF for all elements... */
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
) {
1704 redVal = ( 2 ^ ( (constPartGlobal-desiredPe) / (invRedExp*nActiveLinesGlobal) )
1705 - 2 ^ ( (constPartGlobal-noRedPeGlobal) / (invRedExp*nActiveLinesGlobal) ) )
1709 INT nChannels
= cm
->elInfo
[elementId
].nChannelsInEl
;
1710 PE_DATA
*peData
= &qcElement
[elementId
]->peData
;
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
);
1717 int scalMin
= FDKmin(scale0
, scale1
)-1;
1719 redValue
[elementId
] = scaleValue(tmp0
,(scalMin
-scale0
)) - scaleValue(tmp1
,(scalMin
-scale1
));
1720 redValScaling
[elementId
] = scalMin
;
1722 /* reduce thresholds */
1723 FDKaacEnc_reduceThresholdsCBR(qcElement
[elementId
]->qcOutChannel
, psyOutElement
[elementId
]->psyOutChannel
, pAhFlag
[elementId
], pThrExp
[elementId
], nChannels
, redValue
[elementId
], redValScaling
[elementId
]);
1725 /* pe after first guess */
1726 FDKaacEnc_calcPe(psyOutElement
[elementId
]->psyOutChannel
, qcElement
[elementId
]->qcOutChannel
, peData
, nChannels
);
1728 redPeGlobal
+= peData
->pe
;
1729 } /* EOF DSE-suppression */
1730 } /* EOF for all elements... */
1732 /* -------------------------------------------------- */
1733 /* Part III: Iterate until bit constraints are met */
1734 /* -------------------------------------------------- */
1736 while ((fixp_abs(redPeGlobal
- desiredPe
) > fMultI(FL2FXCONST_DBL(0.05f
),desiredPe
)) && (iter
< 1)) {
1738 INT desiredPeNoAHGlobal
;
1739 INT redPeNoAHGlobal
= 0;
1740 INT constPartNoAHGlobal
= 0;
1741 INT nActiveLinesNoAHGlobal
= 0;
1743 for (elementId
= elementOffset
;elementId
<nElements
;elementId
++) {
1744 if (cm
->elInfo
[elementId
].elType
!= ID_DSE
) {
1746 INT redPeNoAH
, constPartNoAH
, nActiveLinesNoAH
;
1747 INT nChannels
= cm
->elInfo
[elementId
].nChannelsInEl
;
1748 PE_DATA
*peData
= &qcElement
[elementId
]->peData
;
1750 /* pe for bands where avoid hole is inactive */
1751 FDKaacEnc_FDKaacEnc_calcPeNoAH(&redPeNoAH
, &constPartNoAH
, &nActiveLinesNoAH
,
1752 peData
, pAhFlag
[elementId
], psyOutElement
[elementId
]->psyOutChannel
, nChannels
);
1754 redPeNoAHGlobal
+= redPeNoAH
;
1755 constPartNoAHGlobal
+= constPartNoAH
;
1756 nActiveLinesNoAHGlobal
+= nActiveLinesNoAH
;
1757 } /* EOF DSE-suppression */
1758 } /* EOF for all elements... */
1760 /* Calculate new redVal ... */
1761 if(desiredPe
< redPeGlobal
) {
1763 /* new desired pe without bands where avoid hole is active */
1764 desiredPeNoAHGlobal
= desiredPe
- (redPeGlobal
- redPeNoAHGlobal
);
1766 /* limit desiredPeNoAH to positive values, as the PE can not become negative */
1767 desiredPeNoAHGlobal
= FDKmax(0,desiredPeNoAHGlobal
);
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
) {
1774 redVal += ( 2 ^ ( (constPartNoAHGlobal-desiredPeNoAHGlobal) / (invRedExp*nActiveLinesNoAHGlobal) )
1775 - 2 ^ ( (constPartNoAHGlobal-redPeNoAHGlobal) / (invRedExp*nActiveLinesNoAHGlobal) ) )
1780 FIXP_DBL tmp0
= CalcRedValPower( constPartNoAHGlobal
-desiredPeNoAHGlobal
, 4*nActiveLinesNoAHGlobal
, &scale0
);
1781 FIXP_DBL tmp1
= CalcRedValPower( constPartNoAHGlobal
-redPeNoAHGlobal
, 4*nActiveLinesNoAHGlobal
, &scale1
);
1783 int scalMin
= FDKmin(scale0
, scale1
)-1;
1785 tmp0
= scaleValue(tmp0
,(scalMin
-scale0
)) - scaleValue(tmp1
,(scalMin
-scale1
));
1788 /* old reduction value */
1789 tmp1
= redValue
[elementId
];
1790 scale1
= redValScaling
[elementId
];
1792 scalMin
= fixMin(scale0
,scale1
)-1;
1794 /* sum up old and new reduction value */
1795 redValue
[elementId
] = scaleValue(tmp0
,(scalMin
-scale0
)) + scaleValue(tmp1
,(scalMin
-scale1
));
1796 redValScaling
[elementId
] = scalMin
;
1798 } /* EOF DSE-suppression */
1799 } /* EOF for all elements... */
1800 } /* nActiveLinesNoAHGlobal > 0 */
1803 /* desiredPe >= redPeGlobal */
1804 for (elementId
= elementOffset
;elementId
<nElements
;elementId
++) {
1805 if (cm
->elInfo
[elementId
].elType
!= ID_DSE
) {
1807 INT redVal_scale
= 0;
1808 FIXP_DBL tmp
= fDivNorm((FIXP_DBL
)redPeGlobal
, (FIXP_DBL
)desiredPe
, &redVal_scale
);
1810 /* redVal *= redPeGlobal/desiredPe; */
1811 redValue
[elementId
] = fMult(redValue
[elementId
], tmp
);
1812 redValScaling
[elementId
] -= redVal_scale
;
1814 FDKaacEnc_resetAHFlags(pAhFlag
[elementId
], cm
->elInfo
[elementId
].nChannelsInEl
, psyOutElement
[elementId
]->psyOutChannel
);
1815 } /* EOF DSE-suppression */
1816 } /* EOF for all elements... */
1820 /* Calculate new redVal's PE... */
1821 for (elementId
= elementOffset
;elementId
<nElements
;elementId
++) {
1822 if (cm
->elInfo
[elementId
].elType
!= ID_DSE
) {
1824 INT nChannels
= cm
->elInfo
[elementId
].nChannelsInEl
;
1825 PE_DATA
*peData
= &qcElement
[elementId
]->peData
;
1827 /* reduce thresholds */
1828 FDKaacEnc_reduceThresholdsCBR(qcElement
[elementId
]->qcOutChannel
, psyOutElement
[elementId
]->psyOutChannel
, pAhFlag
[elementId
], pThrExp
[elementId
], nChannels
, redValue
[elementId
], redValScaling
[elementId
]);
1830 /* pe after second guess */
1831 FDKaacEnc_calcPe(psyOutElement
[elementId
]->psyOutChannel
, qcElement
[elementId
]->qcOutChannel
, peData
, nChannels
);
1832 redPeGlobal
+= peData
->pe
;
1834 } /* EOF DSE-suppression */
1835 } /* EOF for all elements... */
1841 /* ------------------------------------------------------- */
1842 /* Part IV: if still required, further reduce constraints */
1843 /* ------------------------------------------------------- */
1845 * desiredPe desiredPe desiredPe
1847 * ...XXXXXXXXXXXXXXXXXXXXXXXXXXX| |
1848 * | | |XXXXXXXXXXX...
1850 * --- A --- | --- B --- | --- C ---
1853 * (A): FDKaacEnc_correctThresh()
1854 * (B): FDKaacEnc_allowMoreHoles()
1855 * (C): FDKaacEnc_reduceMinSnr()
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
);
1865 for(elementId
=elementOffset
;elementId
<nElements
;elementId
++) {
1866 if (cm
->elInfo
[elementId
].elType
!= ID_DSE
) {
1868 INT nChannels
= cm
->elInfo
[elementId
].nChannelsInEl
;
1869 PE_DATA
*peData
= &qcElement
[elementId
]->peData
;
1871 /* pe after correctThresh */
1872 FDKaacEnc_calcPe(psyOutElement
[elementId
]->psyOutChannel
, qcElement
[elementId
]->qcOutChannel
, peData
, nChannels
);
1873 redPeGlobal
+= peData
->pe
;
1875 } /* EOF DSE-suppression */
1876 } /* EOF for all elements... */
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
);
1885 /* reduce pe by allowing additional spectral holes */
1886 FDKaacEnc_allowMoreHoles(cm
, qcElement
, psyOutElement
, AdjThrStateElement
, pAhFlag
,
1887 desiredPe
, redPeGlobal
, processElements
, elementOffset
);
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
,
1898 const INT nChannels
)
1900 UCHAR (*pAhFlag
)[MAX_GROUPED_SFB
];
1901 FIXP_DBL (*pThrExp
)[MAX_GROUPED_SFB
];
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
;
1909 /* thresholds to the power of redExp */
1910 FDKaacEnc_calcThreshExp(pThrExp
, qcOutChannel
, psyOutChannel
, nChannels
);
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
);
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
);
1920 /* reduce thresholds */
1921 FDKaacEnc_reduceThresholdsVBR(qcOutChannel
, psyOutChannel
, pAhFlag
, pThrExp
, nChannels
,
1922 AdjThrStateElement
->vbrQualFactor
,
1923 &AdjThrStateElement
->chaosMeasureOld
);
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
)
1931 /*****************************************************************************
1933 functionname: FDKaacEnc_calcBitSave
1934 description: Calculates percentage of bit save, see figure below
1936 input: parameters and bitres-fullness
1937 output: percentage of bit save
1939 *****************************************************************************/
1942 maxBitSave(%)| clipLow
1948 |--------\--------------> bitres
1950 minBitSave(%)| \------------
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
)
1962 fillLevel
= fixMax(fillLevel
, clipLow
);
1963 fillLevel
= fixMin(fillLevel
, clipHigh
);
1965 bitsave
= maxBitSave
- fMult((fillLevel
-clipLow
), bitsave_slope
);
1970 /*****************************************************************************
1972 functionname: FDKaacEnc_calcBitSpend
1973 description: Calculates percentage of bit spend, see figure below
1975 input: parameters and bitres-fullness
1976 output: percentage of bit spend
1978 *****************************************************************************/
1981 maxBitSpend(%)| /-----------maxBitres
1987 |----/-----------------> bitres
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
)
2001 fillLevel
= fixMax(fillLevel
, clipLow
);
2002 fillLevel
= fixMin(fillLevel
, clipHigh
);
2004 bitspend
= minBitSpend
+ fMult(fillLevel
-clipLow
, bitspend_slope
);
2010 /*****************************************************************************
2012 functionname: FDKaacEnc_adjustPeMinMax()
2013 description: adjusts peMin and peMax parameters over time
2015 input: current pe, peMin, peMax, bitres size
2016 output: adjusted peMin/peMax
2018 *****************************************************************************/
2019 static void FDKaacEnc_adjustPeMinMax(const INT currPe
,
2023 FIXP_DBL minFacHi
= FL2FXCONST_DBL(0.3f
), maxFacHi
= (FIXP_DBL
)MAXVAL_DBL
, minFacLo
= FL2FXCONST_DBL(0.14f
), maxFacLo
= FL2FXCONST_DBL(0.07f
);
2026 INT minDiff_fix
= fMultI(FL2FXCONST_DBL(0.1666666667f
), currPe
);
2028 if (currPe
> *peMax
)
2030 diff
= (currPe
-*peMax
) ;
2031 *peMin
+= fMultI(minFacHi
,diff
);
2032 *peMax
+= fMultI(maxFacHi
,diff
);
2034 else if (currPe
< *peMin
)
2036 diff
= (*peMin
-currPe
) ;
2037 *peMin
-= fMultI(minFacLo
,diff
);
2038 *peMax
-= fMultI(maxFacLo
,diff
);
2042 *peMin
+= fMultI(minFacHi
, (currPe
- *peMin
));
2043 *peMax
-= fMultI(maxFacLo
, (*peMax
- currPe
));
2046 if ((*peMax
- *peMin
) < minDiff_fix
)
2048 INT peMax_fix
= *peMax
, peMin_fix
= *peMin
;
2049 FIXP_DBL partLo_fix
, partHi_fix
;
2051 partLo_fix
= (FIXP_DBL
)fixMax(0, currPe
- peMin_fix
);
2052 partHi_fix
= (FIXP_DBL
)fixMax(0, peMax_fix
- currPe
);
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
);
2065 /*****************************************************************************
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
2073 input: bitres-fullness, pe, blockType, parameter-settings
2076 *****************************************************************************/
2079 bitspend(%) | /-----------maxBitres
2085 |----/-----------------> pe
2091 static FIXP_DBL
FDKaacEnc_bitresCalcBitFac(const INT bitresBits
,
2092 const INT maxBitresBits
,
2094 const INT lastWindowSequence
,
2096 const FIXP_DBL maxBitFac
,
2097 ADJ_THR_STATE
*AdjThr
,
2098 ATS_ELEMENT
*adjThrChan
)
2100 BRES_PARAM
*bresParam
;
2103 INT qmin
, qbr
, qbres
, qmbr
;
2104 FIXP_DBL bitSave
, bitSpend
;
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;
2113 if (maxBitresBits
> bitresBits
) {
2114 fillLevel_fix
= fDivNorm(bitresBits
, maxBitresBits
);
2117 if (lastWindowSequence
!= SHORT_WINDOW
)
2119 bresParam
= &(AdjThr
->bresParamLong
);
2120 bitsave_slope
= (FIXP_DBL
)0x3BBBBBBC;
2121 bitspend_slope
= (FIXP_DBL
)0x55555555;
2125 bresParam
= &(AdjThr
->bresParamShort
);
2126 bitsave_slope
= (FIXP_DBL
)0x2E8BA2E9;
2127 bitspend_slope
= (FIXP_DBL
)0x7fffffff;
2130 pex
= fixMax(pe
, adjThrChan
->peMin
);
2131 pex
= fixMin(pex
, adjThrChan
->peMax
);
2133 bitSave
= FDKaacEnc_calcBitSave(fillLevel_fix
,
2134 bresParam
->clipSaveLow
, bresParam
->clipSaveHigh
,
2135 bresParam
->minBitSave
, bresParam
->maxBitSave
, bitsave_slope
);
2137 bitSpend
= FDKaacEnc_calcBitSpend(fillLevel_fix
,
2138 bresParam
->clipSpendLow
, bresParam
->clipSpendHigh
,
2139 bresParam
->minBitSpend
, bresParam
->maxBitSpend
, bitspend_slope
);
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);
2145 /* (float)bitresBits/(float)avgBits */
2146 bits_ratio
= fDivNorm(bitresBits
, avgBits
, &qbr
);
2147 qbr
= DFRACT_BITS
-1-qbr
;
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;
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
);
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
)
2166 bitresFac_fix
= maxBitFac
;
2172 bitresFac_fix
= bitresFac_fix
<< (Q_BITFAC
-qmin
);
2176 bitresFac_fix
= bitresFac_fix
>> (qmin
-Q_BITFAC
);
2180 FDKaacEnc_adjustPeMinMax(pe
, &adjThrChan
->peMin
, &adjThrChan
->peMax
);
2182 return bitresFac_fix
;
2186 /*****************************************************************************
2187 functionname: FDKaacEnc_AdjThrNew
2188 description: allocate ADJ_THR_STATE
2189 *****************************************************************************/
2190 INT
FDKaacEnc_AdjThrNew(ADJ_THR_STATE
** phAdjThr
,
2195 ADJ_THR_STATE
* hAdjThr
= GetRam_aacEnc_AdjustThreshold();
2196 if (hAdjThr
==NULL
) {
2201 for (i
=0; i
<nElements
; i
++) {
2202 hAdjThr
->adjThrStateElem
[i
] = GetRam_aacEnc_AdjThrStateElement(i
);
2203 if (hAdjThr
->adjThrStateElem
[i
]==NULL
) {
2210 *phAdjThr
= hAdjThr
;
2215 /*****************************************************************************
2216 functionname: FDKaacEnc_AdjThrInit
2217 description: initialize ADJ_THR_STATE
2218 *****************************************************************************/
2219 void FDKaacEnc_AdjThrInit(
2220 ADJ_THR_STATE
*hAdjThr
,
2222 ELEMENT_BITS
*elBits
[(8)],
2227 INT advancedBitsToPe
,
2228 FIXP_DBL vbrQualFactor
2233 FIXP_DBL POINT8
= FL2FXCONST_DBL(0.8f
);
2234 FIXP_DBL POINT6
= FL2FXCONST_DBL(0.6f
);
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); */
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); */
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
;
2262 /* parameters for bitres control */
2263 atsElem
->peMin
= fMultI(POINT8
, meanPe
) >> 1;
2264 atsElem
->peMax
= fMultI(POINT6
, meanPe
);
2266 /* for use in FDKaacEnc_reduceThresholdsVBR */
2267 atsElem
->chaosMeasureOld
= FL2FXCONST_DBL(0.3f
);
2269 /* additional pe offset to correct pe2bits for low bitrates */
2270 atsElem
->peOffset
= 0;
2272 /* vbr initialisation */
2273 atsElem
->vbrQualFactor
= vbrQualFactor
;
2274 if (chBitrate
< 32000)
2276 atsElem
->peOffset
= fixMax(50, 100-fMultI((FIXP_DBL
)0x666667, chBitrate
));
2279 /* avoid hole parameters */
2280 if (chBitrate
> 20000) {
2281 atsElem
->ahParam
.modifyMinSnr
= TRUE
;
2282 atsElem
->ahParam
.startSfbL
= 15;
2283 atsElem
->ahParam
.startSfbS
= 3;
2286 atsElem
->ahParam
.modifyMinSnr
= FALSE
;
2287 atsElem
->ahParam
.startSfbL
= 0;
2288 atsElem
->ahParam
.startSfbS
= 0;
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 */
2303 /* init pe correction */
2304 atsElem
->peCorrectionFactor_m
= FL2FXCONST_DBL(0.5f
); /* 1.0 */
2305 atsElem
->peCorrectionFactor_e
= 1;
2307 atsElem
->dynBitsLast
= -1;
2308 atsElem
->peLast
= 0;
2310 /* init bits to pe factor */
2312 /* init bits2PeFactor */
2313 FDKaacEnc_InitBits2PeFactor(
2314 &atsElem
->bits2PeFactor_m
,
2315 &atsElem
->bits2PeFactor_e
,
2316 chBitrate
, /* bitrate/channel*/
2317 nChannelsEff
, /* number of channels */
2323 } /* for nElements */
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
,
2338 const FIXP_DBL bits2PeFactor_m
,
2339 const INT bits2PeFactor_e
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
) )
2346 FIXP_DBL corrFac
= *correctionFac_m
;
2349 FIXP_DBL denum
= (FIXP_DBL
)FDKaacEnc_bits2pe2(bitsLast
, bits2PeFactor_m
, bits2PeFactor_e
);
2350 FIXP_DBL newFac
= fDivNorm((FIXP_DBL
)peLast
, denum
, &scaling
);
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
) );
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
) );
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
))))
2363 corrFac
= FL2FXCONST_DBL(1.f
/2.f
);
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
) )
2370 corrFac
= fMult(FL2FXCONST_DBL(0.85f
), corrFac
) + fMult(FL2FXCONST_DBL(0.15f
), newFac
);
2373 corrFac
= fMult(FL2FXCONST_DBL(0.7f
), corrFac
) + fMult(FL2FXCONST_DBL(0.3f
), newFac
);
2376 corrFac
= fixMax( fixMin( corrFac
, FL2FXCONST_DBL(1.15f
/2.f
) ), FL2FXCONST_DBL(0.85/2.f
) );
2378 *correctionFac_m
= corrFac
;
2379 *correctionFac_e
= 1;
2382 *correctionFac_m
= FL2FXCONST_DBL(1.f
/2.f
);
2383 *correctionFac_e
= 1;
2388 static void FDKaacEnc_calcPeCorrectionLowBitRes(
2389 FIXP_DBL
*const correctionFac_m
,
2390 INT
*const correctionFac_e
,
2393 const INT bitresLevel
,
2394 const INT nChannels
,
2395 const FIXP_DBL bits2PeFactor_m
,
2396 const INT bits2PeFactor_e
2400 const FIXP_DBL amp
= FL2FXCONST_DBL(0.005);
2401 const FIXP_DBL maxDiff
= FL2FXCONST_DBL(0.25f
);
2405 /* Estimate deviation of granted and used dynamic bits in previous frame, in PE units */
2406 const int bitsBalLast
= peLast
- FDKaacEnc_bits2pe2(
2411 /* reserve n bits per channel */
2412 int headroom
= (bitresLevel
>=50*nChannels
) ? 0 : (100*nChannels
);
2415 headroom
= FDKaacEnc_bits2pe2(
2421 * diff = amp * ((bitsBalLast - headroom) / (bitresLevel + headroom)
2422 * diff = max ( min ( diff, maxDiff, -maxDiff)) / 2
2424 FIXP_DBL denominator
= (FIXP_DBL
)FDKaacEnc_bits2pe2(bitresLevel
, bits2PeFactor_m
, bits2PeFactor_e
) + (FIXP_DBL
)headroom
;
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
)) ;
2431 scaling
-= 1; /* divide by 2 */
2433 diff
= (scaling
<=0) ? FDKmax( FDKmin (diff
>>(-scaling
), maxDiff
>>1), -maxDiff
>>1)
2434 : FDKmax( FDKmin (diff
, maxDiff
>>(1+scaling
)), -maxDiff
>>(1+scaling
)) << scaling
;
2438 * corrFac = max ( min ( corrFac/2.f, 1.f/2.f, 0.75f/2.f ) )
2440 *correctionFac_m
= FDKmax(FDKmin((*correctionFac_m
)+diff
, FL2FXCONST_DBL(1.0f
/2.f
)), FL2FXCONST_DBL(0.75f
/2.f
)) ;
2441 *correctionFac_e
= 1;
2444 *correctionFac_m
= FL2FXCONST_DBL(0.75/2.f
);
2445 *correctionFac_e
= 1;
2449 void FDKaacEnc_DistributeBits(ADJ_THR_STATE
*adjThrState
,
2450 ATS_ELEMENT
*AdjThrStateElement
,
2451 PSY_OUT_CHANNEL
*psyOutChannel
[(2)],
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
)
2464 INT noRedPe
= peData
->pe
;
2466 /* prefer short windows for calculation of bitFactor */
2467 INT curWindowSequence
= LONG_WINDOW
;
2469 if ((psyOutChannel
[0]->lastWindowSequence
== SHORT_WINDOW
) ||
2470 (psyOutChannel
[1]->lastWindowSequence
== SHORT_WINDOW
)) {
2471 curWindowSequence
= SHORT_WINDOW
;
2475 curWindowSequence
= psyOutChannel
[0]->lastWindowSequence
;
2478 if (grantedDynBits
>= 1) {
2479 if (bitDistributionMode
!=0) {
2480 *grantedPe
= FDKaacEnc_bits2pe2(grantedDynBits
, AdjThrStateElement
->bits2PeFactor_m
, AdjThrStateElement
->bits2PeFactor_e
);
2484 /* factor dependend on current fill level and pe */
2485 bitFactor
= FDKaacEnc_bitresCalcBitFac(bitresBits
, maxBitresBits
, noRedPe
,
2486 curWindowSequence
, grantedDynBits
, maxBitFac
,
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
)
2499 *grantedPe
= 0; /* prevent divsion by 0 */
2502 /* correction of pe value */
2503 switch (bitDistributionMode
) {
2506 FDKaacEnc_calcPeCorrectionLowBitRes(
2507 &AdjThrStateElement
->peCorrectionFactor_m
,
2508 &AdjThrStateElement
->peCorrectionFactor_e
,
2509 AdjThrStateElement
->peLast
,
2510 AdjThrStateElement
->dynBitsLast
,
2513 AdjThrStateElement
->bits2PeFactor_m
,
2514 AdjThrStateElement
->bits2PeFactor_e
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
2531 *grantedPeCorr
= (INT
)(fMult((FIXP_DBL
)(*grantedPe
<<Q_AVGBITS
), AdjThrStateElement
->peCorrectionFactor_m
) >> (Q_AVGBITS
-AdjThrStateElement
->peCorrectionFactor_e
));
2533 /* update last pe */
2534 AdjThrStateElement
->peLast
= *grantedPe
;
2535 AdjThrStateElement
->dynBitsLast
= -1;
2539 /*****************************************************************************
2540 functionname: FDKaacEnc_AdjustThresholds
2541 description: adjust thresholds
2542 *****************************************************************************/
2543 void FDKaacEnc_AdjustThresholds(ATS_ELEMENT
* AdjThrStateElement
[(8)],
2544 QC_OUT_ELEMENT
* qcElement
[(8)],
2546 PSY_OUT_ELEMENT
* psyOutElement
[(8)],
2548 CHANNEL_MAPPING
* cm
)
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
++)
2558 ELEMENT_INFO elInfo
= cm
->elInfo
[i
];
2560 if ((elInfo
.elType
== ID_SCE
) || (elInfo
.elType
== ID_CPE
) ||
2561 (elInfo
.elType
== ID_LFE
))
2563 /* qcElement[i]->grantedPe = 2000; */ /* Use this only for debugging */
2564 //if (totalGrantedPeCorr < totalNoRedPe) {
2565 if (qcElement
[i
]->grantedPe
< qcElement
[i
]->peData
.pe
)
2567 /* calc threshold necessary for desired pe */
2568 FDKaacEnc_adaptThresholdsToPe(cm
,
2572 qcElement
[i
]->grantedPeCorr
,
2573 1, /* Process only 1 element */
2574 i
); /* Process exactly THIS element */
2578 } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */
2580 } /* -end- element loop */
2583 for (i
=0; i
<cm
->nElements
; i
++)
2585 ELEMENT_INFO elInfo
= cm
->elInfo
[i
];
2587 if ((elInfo
.elType
== ID_SCE
) || (elInfo
.elType
== ID_CPE
) ||
2588 (elInfo
.elType
== ID_LFE
))
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) */
2599 } /* -end- element loop */
2602 for (i
=0; i
<cm
->nElements
; i
++) {
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
];
2617 void FDKaacEnc_AdjThrClose(ADJ_THR_STATE
** phAdjThr
)
2620 ADJ_THR_STATE
* hAdjThr
= *phAdjThr
;
2622 if (hAdjThr
!=NULL
) {
2623 for (i
=0; i
<(8); i
++) {
2624 if (hAdjThr
->adjThrStateElem
[i
]!=NULL
) {
2625 FreeRam_aacEnc_AdjThrStateElement(&hAdjThr
->adjThrStateElem
[i
]);
2628 FreeRam_aacEnc_AdjustThreshold(phAdjThr
);