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