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