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 amm-info@iis.fraunhofer.de
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 /* minimum of 29 dB Ratio for Thresholds */
1306 if ((sfbEnLdData + FL2FXCONST_DBL(1.0f)) >
1307 FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING)) {
1308 sfbThrReducedLdData = fixMax(
1309 sfbThrReducedLdData,
1310 sfbEnLdData - FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING));
1311 }
1312
1313 sfbThrReducedLdData = fixMax(MIN_LDTHRESH, sfbThrReducedLdData);
1314
1315 qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData;
1316 }
1317 }
1318 }
1319 }
1320 }
1321
1322 /*****************************************************************************
1323 functionname: FDKaacEnc_correctThresh
1324 description: if pe difference deltaPe between desired pe and real pe is small
1325 enough, the difference can be distributed among the scale factor bands. New
1326 thresholds can be derived from this pe-difference
1327 *****************************************************************************/
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)1328 static void FDKaacEnc_correctThresh(
1329 const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
1330 const PSY_OUT_ELEMENT *const psyOutElement[((8))],
1331 UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB],
1332 const FIXP_DBL thrExp[((8))][(2)][MAX_GROUPED_SFB], const FIXP_DBL redVal_m,
1333 const SCHAR redVal_e, const INT deltaPe, const INT processElements,
1334 const INT elementOffset) {
1335 INT ch, sfb, sfbGrp;
1336 QC_OUT_CHANNEL *qcOutChan;
1337 PSY_OUT_CHANNEL *psyOutChan;
1338 PE_CHANNEL_DATA *peChanData;
1339 FIXP_DBL thrFactorLdData;
1340 FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData;
1341 FIXP_DBL *sfbPeFactorsLdData[((8))][(2)];
1342 FIXP_DBL(*sfbNActiveLinesLdData)[(2)][MAX_GROUPED_SFB];
1343
1344 INT normFactorInt;
1345 FIXP_DBL normFactorLdData;
1346
1347 INT nElements = elementOffset + processElements;
1348 INT elementId;
1349
1350 /* scratch is empty; use temporal memory from quantSpec in QC_OUT_CHANNEL */
1351 for (elementId = elementOffset; elementId < nElements; elementId++) {
1352 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1353 /* The reinterpret_cast is used to suppress a compiler warning. We know
1354 * that qcElement[elementId]->qcOutChannel[ch]->quantSpec is sufficiently
1355 * aligned, so the cast is safe */
1356 sfbPeFactorsLdData[elementId][ch] =
1357 reinterpret_cast<FIXP_DBL *>(reinterpret_cast<void *>(
1358 qcElement[elementId]->qcOutChannel[ch]->quantSpec));
1359 }
1360 }
1361 /* The reinterpret_cast is used to suppress a compiler warning. We know that
1362 * qcElement[0]->dynMem_SfbNActiveLinesLdData is sufficiently aligned, so the
1363 * cast is safe */
1364 sfbNActiveLinesLdData = reinterpret_cast<FIXP_DBL(*)[(2)][MAX_GROUPED_SFB]>(
1365 reinterpret_cast<void *>(qcElement[0]->dynMem_SfbNActiveLinesLdData));
1366
1367 /* for each sfb calc relative factors for pe changes */
1368 normFactorInt = 0;
1369
1370 for (elementId = elementOffset; elementId < nElements; elementId++) {
1371 if (cm->elInfo[elementId].elType != ID_DSE) {
1372 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1373 psyOutChan = psyOutElement[elementId]->psyOutChannel[ch];
1374 peChanData = &qcElement[elementId]->peData.peChannelData[ch];
1375
1376 for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
1377 sfbGrp += psyOutChan->sfbPerGroup) {
1378 for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
1379 if (peChanData->sfbNActiveLines[sfbGrp + sfb] == 0) {
1380 sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] =
1381 FL2FXCONST_DBL(-1.0f);
1382 } else {
1383 /* Both CalcLdInt and CalcLdData can be used!
1384 * No offset has to be subtracted, because sfbNActiveLinesLdData
1385 * is shorted while thrFactor calculation */
1386 sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] =
1387 CalcLdInt(peChanData->sfbNActiveLines[sfbGrp + sfb]);
1388 }
1389 if (((ahFlag[elementId][ch][sfbGrp + sfb] < AH_ACTIVE) ||
1390 (deltaPe > 0)) &&
1391 peChanData->sfbNActiveLines[sfbGrp + sfb] != 0) {
1392 if (thrExp[elementId][ch][sfbGrp + sfb] > -redVal_m) {
1393 /* sfbPeFactors[ch][sfbGrp+sfb] =
1394 peChanData->sfbNActiveLines[sfbGrp+sfb] /
1395 (thrExp[elementId][ch][sfbGrp+sfb] +
1396 redVal[elementId]); */
1397
1398 int minScale =
1399 fixMin(
1400 CountLeadingBits(thrExp[elementId][ch][sfbGrp + sfb]),
1401 CountLeadingBits(redVal_m) - redVal_e) -
1402 1;
1403
1404 /* sumld = ld64( sfbThrExp + redVal ) */
1405 FIXP_DBL sumLd =
1406 CalcLdData(scaleValue(thrExp[elementId][ch][sfbGrp + sfb],
1407 minScale) +
1408 scaleValue(redVal_m, redVal_e + minScale)) -
1409 (FIXP_DBL)(minScale << (DFRACT_BITS - 1 - LD_DATA_SHIFT));
1410
1411 if (sumLd < FL2FXCONST_DBL(0.f)) {
1412 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1413 sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
1414 sumLd;
1415 } else {
1416 if (sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] >
1417 (FL2FXCONST_DBL(-1.f) + sumLd)) {
1418 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1419 sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
1420 sumLd;
1421 } else {
1422 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1423 sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb];
1424 }
1425 }
1426
1427 normFactorInt += (INT)CalcInvLdData(
1428 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb]);
1429 } else
1430 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1431 FL2FXCONST_DBL(1.0f);
1432 } else
1433 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1434 FL2FXCONST_DBL(-1.0f);
1435 }
1436 }
1437 }
1438 }
1439 }
1440
1441 /* normFactorLdData = ld64(deltaPe/normFactorInt) */
1442 normFactorLdData =
1443 CalcLdData((FIXP_DBL)((deltaPe < 0) ? (-deltaPe) : (deltaPe))) -
1444 CalcLdData((FIXP_DBL)normFactorInt);
1445
1446 /* distribute the pe difference to the scalefactors
1447 and calculate the according thresholds */
1448 for (elementId = elementOffset; elementId < nElements; elementId++) {
1449 if (cm->elInfo[elementId].elType != ID_DSE) {
1450 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1451 qcOutChan = qcElement[elementId]->qcOutChannel[ch];
1452 psyOutChan = psyOutElement[elementId]->psyOutChannel[ch];
1453 peChanData = &qcElement[elementId]->peData.peChannelData[ch];
1454
1455 for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
1456 sfbGrp += psyOutChan->sfbPerGroup) {
1457 for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
1458 if (peChanData->sfbNActiveLines[sfbGrp + sfb] > 0) {
1459 /* pe difference for this sfb */
1460 if ((sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] ==
1461 FL2FXCONST_DBL(-1.0f)) ||
1462 (deltaPe == 0)) {
1463 thrFactorLdData = FL2FXCONST_DBL(0.f);
1464 } else {
1465 /* new threshold */
1466 FIXP_DBL tmp = CalcInvLdData(
1467 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] +
1468 normFactorLdData -
1469 sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
1470 FL2FXCONST_DBL((float)LD_DATA_SHIFT / LD_DATA_SCALING));
1471
1472 /* limit thrFactor to 60dB */
1473 tmp = (deltaPe < 0) ? tmp : (-tmp);
1474 thrFactorLdData =
1475 fMin(tmp, FL2FXCONST_DBL(20.f / LD_DATA_SCALING));
1476 }
1477
1478 /* new threshold */
1479 sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp + sfb];
1480 sfbEnLdData = qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb];
1481
1482 if (thrFactorLdData < FL2FXCONST_DBL(0.f)) {
1483 if (sfbThrLdData > (FL2FXCONST_DBL(-1.f) - thrFactorLdData)) {
1484 sfbThrReducedLdData = sfbThrLdData + thrFactorLdData;
1485 } else {
1486 sfbThrReducedLdData = FL2FXCONST_DBL(-1.f);
1487 }
1488 } else {
1489 sfbThrReducedLdData = sfbThrLdData + thrFactorLdData;
1490 }
1491
1492 /* avoid hole */
1493 if ((sfbThrReducedLdData - sfbEnLdData >
1494 qcOutChan->sfbMinSnrLdData[sfbGrp + sfb]) &&
1495 (ahFlag[elementId][ch][sfbGrp + sfb] == AH_INACTIVE)) {
1496 /* sfbThrReduced = max(psyOutChan[ch]->sfbMinSnr[i] * sfbEn,
1497 * sfbThr); */
1498 if (sfbEnLdData >
1499 (sfbThrLdData - qcOutChan->sfbMinSnrLdData[sfbGrp + sfb])) {
1500 sfbThrReducedLdData =
1501 qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData;
1502 } else {
1503 sfbThrReducedLdData = sfbThrLdData;
1504 }
1505 ahFlag[elementId][ch][sfbGrp + sfb] = AH_ACTIVE;
1506 }
1507
1508 qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData;
1509 }
1510 }
1511 }
1512 }
1513 }
1514 }
1515 }
1516
1517 /*****************************************************************************
1518 functionname: FDKaacEnc_reduceMinSnr
1519 description: if the desired pe can not be reached, reduce pe by
1520 reducing minSnr
1521 *****************************************************************************/
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)1522 static void FDKaacEnc_reduceMinSnr(
1523 const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
1524 const PSY_OUT_ELEMENT *const psyOutElement[((8))],
1525 const UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], const INT desiredPe,
1526 INT *const redPeGlobal, const INT processElements, const INT elementOffset)
1527
1528 {
1529 INT ch, elementId, globalMaxSfb = 0;
1530 const INT nElements = elementOffset + processElements;
1531 INT newGlobalPe = *redPeGlobal;
1532
1533 if (newGlobalPe <= desiredPe) {
1534 goto bail;
1535 }
1536
1537 /* global maximum of maxSfbPerGroup */
1538 for (elementId = elementOffset; elementId < nElements; elementId++) {
1539 if (cm->elInfo[elementId].elType != ID_DSE) {
1540 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1541 globalMaxSfb =
1542 fMax(globalMaxSfb,
1543 psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup);
1544 }
1545 }
1546 }
1547
1548 /* as long as globalPE is above desirePE reduce SNR to 1.0 dB, starting at
1549 * highest SFB */
1550 while ((newGlobalPe > desiredPe) && (--globalMaxSfb >= 0)) {
1551 for (elementId = elementOffset; elementId < nElements; elementId++) {
1552 if (cm->elInfo[elementId].elType != ID_DSE) {
1553 PE_DATA *peData = &qcElement[elementId]->peData;
1554
1555 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1556 QC_OUT_CHANNEL *qcOutChan = qcElement[elementId]->qcOutChannel[ch];
1557 PSY_OUT_CHANNEL *psyOutChan =
1558 psyOutElement[elementId]->psyOutChannel[ch];
1559
1560 /* try to reduce SNR of channel's uppermost SFB(s) */
1561 if (globalMaxSfb < psyOutChan->maxSfbPerGroup) {
1562 INT sfb, deltaPe = 0;
1563
1564 for (sfb = globalMaxSfb; sfb < psyOutChan->sfbCnt;
1565 sfb += psyOutChan->sfbPerGroup) {
1566 if (ahFlag[elementId][ch][sfb] != NO_AH &&
1567 qcOutChan->sfbMinSnrLdData[sfb] < SnrLdFac &&
1568 (qcOutChan->sfbWeightedEnergyLdData[sfb] >
1569 qcOutChan->sfbThresholdLdData[sfb] - SnrLdFac)) {
1570 /* increase threshold to new minSnr of 1dB */
1571 qcOutChan->sfbMinSnrLdData[sfb] = SnrLdFac;
1572 qcOutChan->sfbThresholdLdData[sfb] =
1573 qcOutChan->sfbWeightedEnergyLdData[sfb] + SnrLdFac;
1574
1575 /* calc new pe */
1576 /* C2 + C3*ld(1/0.8) = 1.5 */
1577 deltaPe -= peData->peChannelData[ch].sfbPe[sfb];
1578
1579 /* sfbPe = 1.5 * sfbNLines */
1580 peData->peChannelData[ch].sfbPe[sfb] =
1581 (3 * peData->peChannelData[ch].sfbNLines[sfb])
1582 << (PE_CONSTPART_SHIFT - 1);
1583 deltaPe += peData->peChannelData[ch].sfbPe[sfb];
1584 }
1585
1586 } /* sfb loop */
1587
1588 deltaPe >>= PE_CONSTPART_SHIFT;
1589 peData->pe += deltaPe;
1590 peData->peChannelData[ch].pe += deltaPe;
1591 newGlobalPe += deltaPe;
1592
1593 } /* if globalMaxSfb < maxSfbPerGroup */
1594
1595 /* stop if enough has been saved */
1596 if (newGlobalPe <= desiredPe) {
1597 goto bail;
1598 }
1599
1600 } /* ch loop */
1601 } /* != ID_DSE */
1602 } /* elementId loop */
1603 } /* while ( newGlobalPe > desiredPe) && (--globalMaxSfb >= 0) ) */
1604
1605 bail:
1606 /* update global PE */
1607 *redPeGlobal = newGlobalPe;
1608 }
1609
1610 /*****************************************************************************
1611 functionname: FDKaacEnc_allowMoreHoles
1612 description: if the desired pe can not be reached, some more scalefactor
1613 bands have to be quantized to zero
1614 *****************************************************************************/
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)1615 static void FDKaacEnc_allowMoreHoles(
1616 const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
1617 const PSY_OUT_ELEMENT *const psyOutElement[((8))],
1618 const ATS_ELEMENT *const AdjThrStateElement[((8))],
1619 UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], const INT desiredPe,
1620 const INT currentPe, const int processElements, const int elementOffset) {
1621 INT elementId;
1622 INT nElements = elementOffset + processElements;
1623 INT actPe = currentPe;
1624
1625 if (actPe <= desiredPe) {
1626 return; /* nothing to do */
1627 }
1628
1629 for (elementId = elementOffset; elementId < nElements; elementId++) {
1630 if (cm->elInfo[elementId].elType != ID_DSE) {
1631 INT ch, sfb, sfbGrp;
1632
1633 PE_DATA *peData = &qcElement[elementId]->peData;
1634 const INT nChannels = cm->elInfo[elementId].nChannelsInEl;
1635
1636 QC_OUT_CHANNEL *qcOutChannel[(2)] = {NULL};
1637 PSY_OUT_CHANNEL *psyOutChannel[(2)] = {NULL};
1638
1639 for (ch = 0; ch < nChannels; ch++) {
1640 /* init pointers */
1641 qcOutChannel[ch] = qcElement[elementId]->qcOutChannel[ch];
1642 psyOutChannel[ch] = psyOutElement[elementId]->psyOutChannel[ch];
1643
1644 for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
1645 sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
1646 for (sfb = psyOutChannel[ch]->maxSfbPerGroup;
1647 sfb < psyOutChannel[ch]->sfbPerGroup; sfb++) {
1648 peData->peChannelData[ch].sfbPe[sfbGrp + sfb] = 0;
1649 }
1650 }
1651 }
1652
1653 /* for MS allow hole in the channel with less energy */
1654 if (nChannels == 2 && psyOutChannel[0]->lastWindowSequence ==
1655 psyOutChannel[1]->lastWindowSequence) {
1656 for (sfb = psyOutChannel[0]->maxSfbPerGroup - 1; sfb >= 0; sfb--) {
1657 for (sfbGrp = 0; sfbGrp < psyOutChannel[0]->sfbCnt;
1658 sfbGrp += psyOutChannel[0]->sfbPerGroup) {
1659 if (psyOutElement[elementId]->toolsInfo.msMask[sfbGrp + sfb]) {
1660 FIXP_DBL EnergyLd_L =
1661 qcOutChannel[0]->sfbWeightedEnergyLdData[sfbGrp + sfb];
1662 FIXP_DBL EnergyLd_R =
1663 qcOutChannel[1]->sfbWeightedEnergyLdData[sfbGrp + sfb];
1664
1665 /* allow hole in side channel ? */
1666 if ((ahFlag[elementId][1][sfbGrp + sfb] != NO_AH) &&
1667 (((FL2FXCONST_DBL(-0.02065512648f) >> 1) +
1668 (qcOutChannel[0]->sfbMinSnrLdData[sfbGrp + sfb] >> 1)) >
1669 ((EnergyLd_R >> 1) - (EnergyLd_L >> 1)))) {
1670 ahFlag[elementId][1][sfbGrp + sfb] = NO_AH;
1671 qcOutChannel[1]->sfbThresholdLdData[sfbGrp + sfb] =
1672 FL2FXCONST_DBL(0.015625f) + EnergyLd_R;
1673 actPe -= peData->peChannelData[1].sfbPe[sfbGrp + sfb] >>
1674 PE_CONSTPART_SHIFT;
1675 }
1676 /* allow hole in mid channel ? */
1677 else if ((ahFlag[elementId][0][sfbGrp + sfb] != NO_AH) &&
1678 (((FL2FXCONST_DBL(-0.02065512648f) >> 1) +
1679 (qcOutChannel[1]->sfbMinSnrLdData[sfbGrp + sfb] >>
1680 1)) > ((EnergyLd_L >> 1) - (EnergyLd_R >> 1)))) {
1681 ahFlag[elementId][0][sfbGrp + sfb] = NO_AH;
1682 qcOutChannel[0]->sfbThresholdLdData[sfbGrp + sfb] =
1683 FL2FXCONST_DBL(0.015625f) + EnergyLd_L;
1684 actPe -= peData->peChannelData[0].sfbPe[sfbGrp + sfb] >>
1685 PE_CONSTPART_SHIFT;
1686 } /* if (ahFlag) */
1687 } /* if MS */
1688 } /* sfbGrp */
1689 if (actPe <= desiredPe) {
1690 return; /* stop if enough has been saved */
1691 }
1692 } /* sfb */
1693 } /* MS possible ? */
1694
1695 } /* EOF DSE-suppression */
1696 } /* EOF for all elements... */
1697
1698 if (actPe > desiredPe) {
1699 /* more holes necessary? subsequently erase bands starting with low energies
1700 */
1701 INT ch, sfb, sfbGrp;
1702 INT minSfb, maxSfb;
1703 INT enIdx, ahCnt, done;
1704 INT startSfb[(8)];
1705 INT sfbCnt[(8)];
1706 INT sfbPerGroup[(8)];
1707 INT maxSfbPerGroup[(8)];
1708 FIXP_DBL avgEn;
1709 FIXP_DBL minEnLD64;
1710 FIXP_DBL avgEnLD64;
1711 FIXP_DBL enLD64[NUM_NRG_LEVS];
1712 INT avgEn_e;
1713
1714 /* get the scaling factor over all audio elements and channels */
1715 maxSfb = 0;
1716 for (elementId = elementOffset; elementId < nElements; elementId++) {
1717 if (cm->elInfo[elementId].elType != ID_DSE) {
1718 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1719 for (sfbGrp = 0;
1720 sfbGrp < psyOutElement[elementId]->psyOutChannel[ch]->sfbCnt;
1721 sfbGrp +=
1722 psyOutElement[elementId]->psyOutChannel[ch]->sfbPerGroup) {
1723 maxSfb +=
1724 psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup;
1725 }
1726 }
1727 }
1728 }
1729 avgEn_e =
1730 (DFRACT_BITS - fixnormz_D((LONG)fMax(0, maxSfb - 1))); /* ilog2() */
1731
1732 ahCnt = 0;
1733 maxSfb = 0;
1734 minSfb = MAX_SFB;
1735 avgEn = FL2FXCONST_DBL(0.0f);
1736 minEnLD64 = FL2FXCONST_DBL(0.0f);
1737
1738 for (elementId = elementOffset; elementId < nElements; elementId++) {
1739 if (cm->elInfo[elementId].elType != ID_DSE) {
1740 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1741 const INT chIdx = cm->elInfo[elementId].ChannelIndex[ch];
1742 QC_OUT_CHANNEL *qcOutChannel = qcElement[elementId]->qcOutChannel[ch];
1743 PSY_OUT_CHANNEL *psyOutChannel =
1744 psyOutElement[elementId]->psyOutChannel[ch];
1745
1746 maxSfbPerGroup[chIdx] = psyOutChannel->maxSfbPerGroup;
1747 sfbCnt[chIdx] = psyOutChannel->sfbCnt;
1748 sfbPerGroup[chIdx] = psyOutChannel->sfbPerGroup;
1749
1750 maxSfb = fMax(maxSfb, psyOutChannel->maxSfbPerGroup);
1751
1752 if (psyOutChannel->lastWindowSequence != SHORT_WINDOW) {
1753 startSfb[chIdx] = AdjThrStateElement[elementId]->ahParam.startSfbL;
1754 } else {
1755 startSfb[chIdx] = AdjThrStateElement[elementId]->ahParam.startSfbS;
1756 }
1757
1758 minSfb = fMin(minSfb, startSfb[chIdx]);
1759
1760 sfbGrp = 0;
1761 sfb = startSfb[chIdx];
1762
1763 do {
1764 for (; sfb < psyOutChannel->maxSfbPerGroup; sfb++) {
1765 if ((ahFlag[elementId][ch][sfbGrp + sfb] != NO_AH) &&
1766 (qcOutChannel->sfbWeightedEnergyLdData[sfbGrp + sfb] >
1767 qcOutChannel->sfbThresholdLdData[sfbGrp + sfb])) {
1768 minEnLD64 = fixMin(minEnLD64,
1769 qcOutChannel->sfbEnergyLdData[sfbGrp + sfb]);
1770 avgEn += qcOutChannel->sfbEnergy[sfbGrp + sfb] >> avgEn_e;
1771 ahCnt++;
1772 }
1773 }
1774
1775 sfbGrp += psyOutChannel->sfbPerGroup;
1776 sfb = startSfb[chIdx];
1777
1778 } while (sfbGrp < psyOutChannel->sfbCnt);
1779 }
1780 } /* (cm->elInfo[elementId].elType != ID_DSE) */
1781 } /* (elementId = elementOffset;elementId<nElements;elementId++) */
1782
1783 if ((avgEn == FL2FXCONST_DBL(0.0f)) || (ahCnt == 0)) {
1784 avgEnLD64 = FL2FXCONST_DBL(0.0f);
1785 } else {
1786 avgEnLD64 = CalcLdData(avgEn) +
1787 (FIXP_DBL)(avgEn_e << (DFRACT_BITS - 1 - LD_DATA_SHIFT)) -
1788 CalcLdInt(ahCnt);
1789 }
1790
1791 /* calc some energy borders between minEn and avgEn */
1792
1793 /* for (enIdx = 0; enIdx < NUM_NRG_LEVS; enIdx++) {
1794 en[enIdx] = (2.0f*enIdx+1.0f)/(2.0f*NUM_NRG_LEVS-1.0f);
1795 } */
1796 enLD64[0] =
1797 minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.06666667f));
1798 enLD64[1] =
1799 minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.20000000f));
1800 enLD64[2] =
1801 minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.33333334f));
1802 enLD64[3] =
1803 minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.46666667f));
1804 enLD64[4] =
1805 minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.60000002f));
1806 enLD64[5] =
1807 minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.73333335f));
1808 enLD64[6] =
1809 minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.86666667f));
1810 enLD64[7] = minEnLD64 + (avgEnLD64 - minEnLD64);
1811
1812 done = 0;
1813 enIdx = 0;
1814 sfb = maxSfb - 1;
1815
1816 while (!done) {
1817 for (elementId = elementOffset; elementId < nElements; elementId++) {
1818 if (cm->elInfo[elementId].elType != ID_DSE) {
1819 PE_DATA *peData = &qcElement[elementId]->peData;
1820 for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1821 const INT chIdx = cm->elInfo[elementId].ChannelIndex[ch];
1822 QC_OUT_CHANNEL *qcOutChannel =
1823 qcElement[elementId]->qcOutChannel[ch];
1824 if (sfb >= startSfb[chIdx] && sfb < maxSfbPerGroup[chIdx]) {
1825 for (sfbGrp = 0; sfbGrp < sfbCnt[chIdx];
1826 sfbGrp += sfbPerGroup[chIdx]) {
1827 /* sfb energy below border ? */
1828 if (ahFlag[elementId][ch][sfbGrp + sfb] != NO_AH &&
1829 qcOutChannel->sfbEnergyLdData[sfbGrp + sfb] <
1830 enLD64[enIdx]) {
1831 /* allow hole */
1832 ahFlag[elementId][ch][sfbGrp + sfb] = NO_AH;
1833 qcOutChannel->sfbThresholdLdData[sfbGrp + sfb] =
1834 FL2FXCONST_DBL(0.015625f) +
1835 qcOutChannel->sfbWeightedEnergyLdData[sfbGrp + sfb];
1836 actPe -= peData->peChannelData[ch].sfbPe[sfbGrp + sfb] >>
1837 PE_CONSTPART_SHIFT;
1838 }
1839 if (actPe <= desiredPe) {
1840 return; /* stop if enough has been saved */
1841 }
1842 } /* sfbGrp */
1843 } /* sfb */
1844 } /* nChannelsInEl */
1845 } /* ID_DSE */
1846 } /* elementID */
1847
1848 sfb--;
1849 if (sfb < minSfb) {
1850 /* restart with next energy border */
1851 sfb = maxSfb;
1852 enIdx++;
1853 if (enIdx >= NUM_NRG_LEVS) {
1854 done = 1;
1855 }
1856 }
1857 } /* done */
1858 } /* (actPe <= desiredPe) */
1859 }
1860
1861 /* 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)])1862 static void FDKaacEnc_resetAHFlags(
1863 UCHAR ahFlag[(2)][MAX_GROUPED_SFB], const INT nChannels,
1864 const PSY_OUT_CHANNEL *const psyOutChannel[(2)]) {
1865 int ch, sfb, sfbGrp;
1866
1867 for (ch = 0; ch < nChannels; ch++) {
1868 for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
1869 sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
1870 for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
1871 if (ahFlag[ch][sfbGrp + sfb] == AH_ACTIVE) {
1872 ahFlag[ch][sfbGrp + sfb] = AH_INACTIVE;
1873 }
1874 }
1875 }
1876 }
1877 }
1878
CalcRedValPower(FIXP_DBL num,FIXP_DBL denum,INT * scaling)1879 static FIXP_DBL CalcRedValPower(FIXP_DBL num, FIXP_DBL denum, INT *scaling) {
1880 FIXP_DBL value = FL2FXCONST_DBL(0.f);
1881
1882 if (num >= FL2FXCONST_DBL(0.f)) {
1883 value = fDivNorm(num, denum, scaling);
1884 } else {
1885 value = -fDivNorm(-num, denum, scaling);
1886 }
1887 value = f2Pow(value, *scaling, scaling);
1888
1889 return value;
1890 }
1891
1892 /*****************************************************************************
1893 functionname: FDKaacEnc_adaptThresholdsToPe
1894 description: two guesses for the reduction value and one final correction of
1895 the thresholds
1896 *****************************************************************************/
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)1897 static void FDKaacEnc_adaptThresholdsToPe(
1898 const CHANNEL_MAPPING *const cm,
1899 ATS_ELEMENT *const AdjThrStateElement[((8))],
1900 QC_OUT_ELEMENT *const qcElement[((8))],
1901 const PSY_OUT_ELEMENT *const psyOutElement[((8))], const INT desiredPe,
1902 const INT maxIter2ndGuess, const INT processElements,
1903 const INT elementOffset) {
1904 FIXP_DBL reductionValue_m;
1905 SCHAR reductionValue_e;
1906 UCHAR(*pAhFlag)[(2)][MAX_GROUPED_SFB];
1907 FIXP_DBL(*pThrExp)[(2)][MAX_GROUPED_SFB];
1908 int iter;
1909
1910 INT constPartGlobal, noRedPeGlobal, nActiveLinesGlobal, redPeGlobal;
1911 constPartGlobal = noRedPeGlobal = nActiveLinesGlobal = redPeGlobal = 0;
1912
1913 int elementId;
1914
1915 int nElements = elementOffset + processElements;
1916 if (nElements > cm->nElements) {
1917 nElements = cm->nElements;
1918 }
1919
1920 /* The reinterpret_cast is used to suppress a compiler warning. We know that
1921 * qcElement[0]->dynMem_Ah_Flag is sufficiently aligned, so the cast is safe
1922 */
1923 pAhFlag = reinterpret_cast<UCHAR(*)[(2)][MAX_GROUPED_SFB]>(
1924 reinterpret_cast<void *>(qcElement[0]->dynMem_Ah_Flag));
1925 /* The reinterpret_cast is used to suppress a compiler warning. We know that
1926 * qcElement[0]->dynMem_Thr_Exp is sufficiently aligned, so the cast is safe
1927 */
1928 pThrExp = reinterpret_cast<FIXP_DBL(*)[(2)][MAX_GROUPED_SFB]>(
1929 reinterpret_cast<void *>(qcElement[0]->dynMem_Thr_Exp));
1930
1931 /* ------------------------------------------------------- */
1932 /* Part I: Initialize data structures and variables... */
1933 /* ------------------------------------------------------- */
1934 for (elementId = elementOffset; elementId < nElements; elementId++) {
1935 if (cm->elInfo[elementId].elType != ID_DSE) {
1936 INT nChannels = cm->elInfo[elementId].nChannelsInEl;
1937 PE_DATA *peData = &qcElement[elementId]->peData;
1938
1939 /* thresholds to the power of redExp */
1940 FDKaacEnc_calcThreshExp(
1941 pThrExp[elementId], qcElement[elementId]->qcOutChannel,
1942 psyOutElement[elementId]->psyOutChannel, nChannels);
1943
1944 /* lower the minSnr requirements for low energies compared to the average
1945 energy in this frame */
1946 FDKaacEnc_adaptMinSnr(qcElement[elementId]->qcOutChannel,
1947 psyOutElement[elementId]->psyOutChannel,
1948 &AdjThrStateElement[elementId]->minSnrAdaptParam,
1949 nChannels);
1950
1951 /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
1952 FDKaacEnc_initAvoidHoleFlag(
1953 qcElement[elementId]->qcOutChannel,
1954 psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
1955 &psyOutElement[elementId]->toolsInfo, nChannels,
1956 &AdjThrStateElement[elementId]->ahParam);
1957
1958 /* sum up */
1959 constPartGlobal += peData->constPart;
1960 noRedPeGlobal += peData->pe;
1961 nActiveLinesGlobal += fixMax((INT)peData->nActiveLines, 1);
1962
1963 } /* EOF DSE-suppression */
1964 } /* EOF for all elements... */
1965
1966 /*
1967 First guess of reduction value:
1968 avgThrExp = (float)pow(2.0f, (constPartGlobal - noRedPeGlobal)/(4.0f *
1969 nActiveLinesGlobal)); redVal = (float)pow(2.0f, (constPartGlobal -
1970 desiredPe)/(4.0f * nActiveLinesGlobal)) - avgThrExp; redVal = max(0.f,
1971 redVal);
1972 */
1973 int redVal_e, avgThrExp_e, result_e;
1974 FIXP_DBL redVal_m, avgThrExp_m;
1975
1976 redVal_m = CalcRedValPower(constPartGlobal - desiredPe,
1977 4 * nActiveLinesGlobal, &redVal_e);
1978 avgThrExp_m = CalcRedValPower(constPartGlobal - noRedPeGlobal,
1979 4 * nActiveLinesGlobal, &avgThrExp_e);
1980 result_e = fMax(redVal_e, avgThrExp_e) + 1;
1981
1982 reductionValue_m = fMax(FL2FXCONST_DBL(0.f),
1983 scaleValue(redVal_m, redVal_e - result_e) -
1984 scaleValue(avgThrExp_m, avgThrExp_e - result_e));
1985 reductionValue_e = result_e;
1986
1987 /* ----------------------------------------------------------------------- */
1988 /* Part II: Calculate bit consumption of initial bit constraints setup */
1989 /* ----------------------------------------------------------------------- */
1990 for (elementId = elementOffset; elementId < nElements; elementId++) {
1991 if (cm->elInfo[elementId].elType != ID_DSE) {
1992 INT nChannels = cm->elInfo[elementId].nChannelsInEl;
1993 PE_DATA *peData = &qcElement[elementId]->peData;
1994
1995 /* reduce thresholds */
1996 FDKaacEnc_reduceThresholdsCBR(
1997 qcElement[elementId]->qcOutChannel,
1998 psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
1999 pThrExp[elementId], nChannels, reductionValue_m, reductionValue_e);
2000
2001 /* pe after first guess */
2002 FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
2003 qcElement[elementId]->qcOutChannel, peData, nChannels);
2004
2005 redPeGlobal += peData->pe;
2006 } /* EOF DSE-suppression */
2007 } /* EOF for all elements... */
2008
2009 /* -------------------------------------------------- */
2010 /* Part III: Iterate until bit constraints are met */
2011 /* -------------------------------------------------- */
2012 iter = 0;
2013 while ((fixp_abs(redPeGlobal - desiredPe) >
2014 fMultI(FL2FXCONST_DBL(0.05f), desiredPe)) &&
2015 (iter < maxIter2ndGuess)) {
2016 INT desiredPeNoAHGlobal;
2017 INT redPeNoAHGlobal = 0;
2018 INT constPartNoAHGlobal = 0;
2019 INT nActiveLinesNoAHGlobal = 0;
2020
2021 for (elementId = elementOffset; elementId < nElements; elementId++) {
2022 if (cm->elInfo[elementId].elType != ID_DSE) {
2023 INT redPeNoAH, constPartNoAH, nActiveLinesNoAH;
2024 INT nChannels = cm->elInfo[elementId].nChannelsInEl;
2025 PE_DATA *peData = &qcElement[elementId]->peData;
2026
2027 /* pe for bands where avoid hole is inactive */
2028 FDKaacEnc_FDKaacEnc_calcPeNoAH(
2029 &redPeNoAH, &constPartNoAH, &nActiveLinesNoAH, peData,
2030 pAhFlag[elementId], psyOutElement[elementId]->psyOutChannel,
2031 nChannels);
2032
2033 redPeNoAHGlobal += redPeNoAH;
2034 constPartNoAHGlobal += constPartNoAH;
2035 nActiveLinesNoAHGlobal += nActiveLinesNoAH;
2036 } /* EOF DSE-suppression */
2037 } /* EOF for all elements... */
2038
2039 /* Calculate new redVal ... */
2040 if (desiredPe < redPeGlobal) {
2041 /* new desired pe without bands where avoid hole is active */
2042 desiredPeNoAHGlobal = desiredPe - (redPeGlobal - redPeNoAHGlobal);
2043
2044 /* limit desiredPeNoAH to positive values, as the PE can not become
2045 * negative */
2046 desiredPeNoAHGlobal = fMax(0, desiredPeNoAHGlobal);
2047
2048 /* second guess (only if there are bands left where avoid hole is
2049 * inactive)*/
2050 if (nActiveLinesNoAHGlobal > 0) {
2051 /*
2052 avgThrExp = (float)pow(2.0f, (constPartNoAHGlobal - redPeNoAHGlobal) /
2053 (4.0f * nActiveLinesNoAHGlobal)); redVal += (float)pow(2.0f,
2054 (constPartNoAHGlobal - desiredPeNoAHGlobal) / (4.0f *
2055 nActiveLinesNoAHGlobal)) - avgThrExp; redVal = max(0.0f, redVal);
2056 */
2057
2058 redVal_m = CalcRedValPower(constPartNoAHGlobal - desiredPeNoAHGlobal,
2059 4 * nActiveLinesNoAHGlobal, &redVal_e);
2060 avgThrExp_m = CalcRedValPower(constPartNoAHGlobal - redPeNoAHGlobal,
2061 4 * nActiveLinesNoAHGlobal, &avgThrExp_e);
2062 result_e = fMax(reductionValue_e, fMax(redVal_e, avgThrExp_e) + 1) + 1;
2063
2064 reductionValue_m =
2065 fMax(FL2FXCONST_DBL(0.f),
2066 scaleValue(reductionValue_m, reductionValue_e - result_e) +
2067 scaleValue(redVal_m, redVal_e - result_e) -
2068 scaleValue(avgThrExp_m, avgThrExp_e - result_e));
2069 reductionValue_e = result_e;
2070
2071 } /* nActiveLinesNoAHGlobal > 0 */
2072 } else {
2073 /* redVal *= redPeGlobal/desiredPe; */
2074 int sc0, sc1;
2075 reductionValue_m = fMultNorm(
2076 reductionValue_m,
2077 fDivNorm((FIXP_DBL)redPeGlobal, (FIXP_DBL)desiredPe, &sc0), &sc1);
2078 reductionValue_e += sc0 + sc1;
2079
2080 for (elementId = elementOffset; elementId < nElements; elementId++) {
2081 if (cm->elInfo[elementId].elType != ID_DSE) {
2082 FDKaacEnc_resetAHFlags(pAhFlag[elementId],
2083 cm->elInfo[elementId].nChannelsInEl,
2084 psyOutElement[elementId]->psyOutChannel);
2085 } /* EOF DSE-suppression */
2086 } /* EOF for all elements... */
2087 }
2088
2089 redPeGlobal = 0;
2090 /* Calculate new redVal's PE... */
2091 for (elementId = elementOffset; elementId < nElements; elementId++) {
2092 if (cm->elInfo[elementId].elType != ID_DSE) {
2093 INT nChannels = cm->elInfo[elementId].nChannelsInEl;
2094 PE_DATA *peData = &qcElement[elementId]->peData;
2095
2096 /* reduce thresholds */
2097 FDKaacEnc_reduceThresholdsCBR(
2098 qcElement[elementId]->qcOutChannel,
2099 psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
2100 pThrExp[elementId], nChannels, reductionValue_m, reductionValue_e);
2101
2102 /* pe after second guess */
2103 FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
2104 qcElement[elementId]->qcOutChannel, peData, nChannels);
2105 redPeGlobal += peData->pe;
2106
2107 } /* EOF DSE-suppression */
2108 } /* EOF for all elements... */
2109
2110 iter++;
2111 } /* EOF while */
2112
2113 /* ------------------------------------------------------- */
2114 /* Part IV: if still required, further reduce constraints */
2115 /* ------------------------------------------------------- */
2116 /* 1.0* 1.15* 1.20*
2117 * desiredPe desiredPe desiredPe
2118 * | | |
2119 * ...XXXXXXXXXXXXXXXXXXXXXXXXXXX| |
2120 * | | |XXXXXXXXXXX...
2121 * | |XXXXXXXXXXX|
2122 * --- A --- | --- B --- | --- C ---
2123 *
2124 * (X): redPeGlobal
2125 * (A): FDKaacEnc_correctThresh()
2126 * (B): FDKaacEnc_allowMoreHoles()
2127 * (C): FDKaacEnc_reduceMinSnr()
2128 */
2129
2130 /* correct thresholds to get closer to the desired pe */
2131 if (redPeGlobal > desiredPe) {
2132 FDKaacEnc_correctThresh(cm, qcElement, psyOutElement, pAhFlag, pThrExp,
2133 reductionValue_m, reductionValue_e,
2134 desiredPe - redPeGlobal, processElements,
2135 elementOffset);
2136
2137 /* update PE */
2138 redPeGlobal = 0;
2139 for (elementId = elementOffset; elementId < nElements; elementId++) {
2140 if (cm->elInfo[elementId].elType != ID_DSE) {
2141 INT nChannels = cm->elInfo[elementId].nChannelsInEl;
2142 PE_DATA *peData = &qcElement[elementId]->peData;
2143
2144 /* pe after correctThresh */
2145 FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
2146 qcElement[elementId]->qcOutChannel, peData, nChannels);
2147 redPeGlobal += peData->pe;
2148
2149 } /* EOF DSE-suppression */
2150 } /* EOF for all elements... */
2151 }
2152
2153 if (redPeGlobal > desiredPe) {
2154 /* reduce pe by reducing minSnr requirements */
2155 FDKaacEnc_reduceMinSnr(
2156 cm, qcElement, psyOutElement, pAhFlag,
2157 (fMultI(FL2FXCONST_DBL(0.15f), desiredPe) + desiredPe), &redPeGlobal,
2158 processElements, elementOffset);
2159
2160 /* reduce pe by allowing additional spectral holes */
2161 FDKaacEnc_allowMoreHoles(cm, qcElement, psyOutElement, AdjThrStateElement,
2162 pAhFlag, desiredPe, redPeGlobal, processElements,
2163 elementOffset);
2164 }
2165 }
2166
2167 /* 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)2168 static void FDKaacEnc_AdaptThresholdsVBR(
2169 QC_OUT_CHANNEL *const qcOutChannel[(2)],
2170 const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
2171 ATS_ELEMENT *const AdjThrStateElement,
2172 const struct TOOLSINFO *const toolsInfo, const INT nChannels) {
2173 UCHAR(*pAhFlag)[MAX_GROUPED_SFB];
2174 FIXP_DBL(*pThrExp)[MAX_GROUPED_SFB];
2175
2176 /* allocate scratch memory */
2177 C_ALLOC_SCRATCH_START(_pAhFlag, UCHAR, (2) * MAX_GROUPED_SFB)
2178 C_ALLOC_SCRATCH_START(_pThrExp, FIXP_DBL, (2) * MAX_GROUPED_SFB)
2179 pAhFlag = (UCHAR(*)[MAX_GROUPED_SFB])_pAhFlag;
2180 pThrExp = (FIXP_DBL(*)[MAX_GROUPED_SFB])_pThrExp;
2181
2182 /* thresholds to the power of redExp */
2183 FDKaacEnc_calcThreshExp(pThrExp, qcOutChannel, psyOutChannel, nChannels);
2184
2185 /* lower the minSnr requirements for low energies compared to the average
2186 energy in this frame */
2187 FDKaacEnc_adaptMinSnr(qcOutChannel, psyOutChannel,
2188 &AdjThrStateElement->minSnrAdaptParam, nChannels);
2189
2190 /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
2191 FDKaacEnc_initAvoidHoleFlag(qcOutChannel, psyOutChannel, pAhFlag, toolsInfo,
2192 nChannels, &AdjThrStateElement->ahParam);
2193
2194 /* reduce thresholds */
2195 FDKaacEnc_reduceThresholdsVBR(qcOutChannel, psyOutChannel, pAhFlag, pThrExp,
2196 nChannels, AdjThrStateElement->vbrQualFactor,
2197 &AdjThrStateElement->chaosMeasureOld);
2198
2199 /* free scratch memory */
2200 C_ALLOC_SCRATCH_END(_pThrExp, FIXP_DBL, (2) * MAX_GROUPED_SFB)
2201 C_ALLOC_SCRATCH_END(_pAhFlag, UCHAR, (2) * MAX_GROUPED_SFB)
2202 }
2203
2204 /*****************************************************************************
2205
2206 functionname: FDKaacEnc_calcBitSave
2207 description: Calculates percentage of bit save, see figure below
2208 returns:
2209 input: parameters and bitres-fullness
2210 output: percentage of bit save
2211
2212 *****************************************************************************/
2213 /*
2214 bitsave
2215 maxBitSave(%)| clipLow
2216 |---\
2217 | \
2218 | \
2219 | \
2220 | \
2221 |--------\--------------> bitres
2222 | \
2223 minBitSave(%)| \------------
2224 clipHigh maxBitres
2225 */
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)2226 static FIXP_DBL FDKaacEnc_calcBitSave(FIXP_DBL fillLevel,
2227 const FIXP_DBL clipLow,
2228 const FIXP_DBL clipHigh,
2229 const FIXP_DBL minBitSave,
2230 const FIXP_DBL maxBitSave,
2231 const FIXP_DBL bitsave_slope) {
2232 FIXP_DBL bitsave;
2233
2234 fillLevel = fixMax(fillLevel, clipLow);
2235 fillLevel = fixMin(fillLevel, clipHigh);
2236
2237 bitsave = maxBitSave - fMult((fillLevel - clipLow), bitsave_slope);
2238
2239 return (bitsave);
2240 }
2241
2242 /*****************************************************************************
2243
2244 functionname: FDKaacEnc_calcBitSpend
2245 description: Calculates percentage of bit spend, see figure below
2246 returns:
2247 input: parameters and bitres-fullness
2248 output: percentage of bit spend
2249
2250 *****************************************************************************/
2251 /*
2252 bitspend clipHigh
2253 maxBitSpend(%)| /-----------maxBitres
2254 | /
2255 | /
2256 | /
2257 | /
2258 | /
2259 |----/-----------------> bitres
2260 | /
2261 minBitSpend(%)|--/
2262 clipLow
2263 */
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)2264 static FIXP_DBL FDKaacEnc_calcBitSpend(FIXP_DBL fillLevel,
2265 const FIXP_DBL clipLow,
2266 const FIXP_DBL clipHigh,
2267 const FIXP_DBL minBitSpend,
2268 const FIXP_DBL maxBitSpend,
2269 const FIXP_DBL bitspend_slope) {
2270 FIXP_DBL bitspend;
2271
2272 fillLevel = fixMax(fillLevel, clipLow);
2273 fillLevel = fixMin(fillLevel, clipHigh);
2274
2275 bitspend = minBitSpend + fMult(fillLevel - clipLow, bitspend_slope);
2276
2277 return (bitspend);
2278 }
2279
2280 /*****************************************************************************
2281
2282 functionname: FDKaacEnc_adjustPeMinMax()
2283 description: adjusts peMin and peMax parameters over time
2284 returns:
2285 input: current pe, peMin, peMax, bitres size
2286 output: adjusted peMin/peMax
2287
2288 *****************************************************************************/
FDKaacEnc_adjustPeMinMax(const INT currPe,INT * peMin,INT * peMax)2289 static void FDKaacEnc_adjustPeMinMax(const INT currPe, INT *peMin, INT *peMax) {
2290 FIXP_DBL minFacHi = FL2FXCONST_DBL(0.3f), maxFacHi = (FIXP_DBL)MAXVAL_DBL,
2291 minFacLo = FL2FXCONST_DBL(0.14f), maxFacLo = FL2FXCONST_DBL(0.07f);
2292 INT diff;
2293
2294 INT minDiff_fix = fMultI(FL2FXCONST_DBL(0.1666666667f), currPe);
2295
2296 if (currPe > *peMax) {
2297 diff = (currPe - *peMax);
2298 *peMin += fMultI(minFacHi, diff);
2299 *peMax += fMultI(maxFacHi, diff);
2300 } else if (currPe < *peMin) {
2301 diff = (*peMin - currPe);
2302 *peMin -= fMultI(minFacLo, diff);
2303 *peMax -= fMultI(maxFacLo, diff);
2304 } else {
2305 *peMin += fMultI(minFacHi, (currPe - *peMin));
2306 *peMax -= fMultI(maxFacLo, (*peMax - currPe));
2307 }
2308
2309 if ((*peMax - *peMin) < minDiff_fix) {
2310 INT peMax_fix = *peMax, peMin_fix = *peMin;
2311 FIXP_DBL partLo_fix, partHi_fix;
2312
2313 partLo_fix = (FIXP_DBL)fixMax(0, currPe - peMin_fix);
2314 partHi_fix = (FIXP_DBL)fixMax(0, peMax_fix - currPe);
2315
2316 peMax_fix =
2317 (INT)(currPe + fMultI(fDivNorm(partHi_fix, (partLo_fix + partHi_fix)),
2318 minDiff_fix));
2319 peMin_fix =
2320 (INT)(currPe - fMultI(fDivNorm(partLo_fix, (partLo_fix + partHi_fix)),
2321 minDiff_fix));
2322 peMin_fix = fixMax(0, peMin_fix);
2323
2324 *peMax = peMax_fix;
2325 *peMin = peMin_fix;
2326 }
2327 }
2328
2329 /*****************************************************************************
2330
2331 functionname: BitresCalcBitFac
2332 description: calculates factor of spending bits for one frame
2333 1.0 : take all frame dynpart bits
2334 >1.0 : take all frame dynpart bits + bitres
2335 <1.0 : put bits in bitreservoir
2336 returns: BitFac
2337 input: bitres-fullness, pe, blockType, parameter-settings
2338 output:
2339
2340 *****************************************************************************/
2341 /*
2342 bitfac(%) pemax
2343 bitspend(%) | /-----------maxBitres
2344 | /
2345 | /
2346 | /
2347 | /
2348 | /
2349 |----/-----------------> pe
2350 | /
2351 bitsave(%) |--/
2352 pemin
2353 */
2354
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)2355 void FDKaacEnc_bitresCalcBitFac(const INT bitresBits, const INT maxBitresBits,
2356 const INT pe, const INT lastWindowSequence,
2357 const INT avgBits, const FIXP_DBL maxBitFac,
2358 const ADJ_THR_STATE *const AdjThr,
2359 ATS_ELEMENT *const adjThrChan,
2360 FIXP_DBL *const pBitresFac,
2361 INT *const pBitresFac_e) {
2362 const BRES_PARAM *bresParam;
2363 INT pex;
2364 FIXP_DBL fillLevel;
2365 INT fillLevel_e = 0;
2366
2367 FIXP_DBL bitresFac;
2368 INT bitresFac_e;
2369
2370 FIXP_DBL bitSave, bitSpend;
2371 FIXP_DBL bitsave_slope, bitspend_slope;
2372 FIXP_DBL fillLevel_fix = MAXVAL_DBL;
2373
2374 FIXP_DBL slope = MAXVAL_DBL;
2375
2376 if (lastWindowSequence != SHORT_WINDOW) {
2377 bresParam = &(AdjThr->bresParamLong);
2378 bitsave_slope = FL2FXCONST_DBL(0.466666666);
2379 bitspend_slope = FL2FXCONST_DBL(0.666666666);
2380 } else {
2381 bresParam = &(AdjThr->bresParamShort);
2382 bitsave_slope = (FIXP_DBL)0x2E8BA2E9;
2383 bitspend_slope = (FIXP_DBL)0x7fffffff;
2384 }
2385
2386 // fillLevel = (float)(bitresBits+avgBits) / (float)(maxBitresBits + avgBits);
2387 if (bitresBits < maxBitresBits) {
2388 fillLevel_fix = fDivNorm(bitresBits, maxBitresBits);
2389 }
2390
2391 pex = fMax(pe, adjThrChan->peMin);
2392 pex = fMin(pex, adjThrChan->peMax);
2393
2394 bitSave = FDKaacEnc_calcBitSave(
2395 fillLevel_fix, bresParam->clipSaveLow, bresParam->clipSaveHigh,
2396 bresParam->minBitSave, bresParam->maxBitSave, bitsave_slope);
2397
2398 bitSpend = FDKaacEnc_calcBitSpend(
2399 fillLevel_fix, bresParam->clipSpendLow, bresParam->clipSpendHigh,
2400 bresParam->minBitSpend, bresParam->maxBitSpend, bitspend_slope);
2401
2402 slope = schur_div((pex - adjThrChan->peMin),
2403 (adjThrChan->peMax - adjThrChan->peMin), 31);
2404
2405 /* scale down by 1 bit because the result of the following addition can be
2406 * bigger than 1 (though smaller than 2) */
2407 bitresFac = ((FIXP_DBL)(MAXVAL_DBL >> 1) - (bitSave >> 1));
2408 bitresFac_e = 1; /* exp=1 */
2409 bitresFac = fMultAddDiv2(bitresFac, slope, bitSpend + bitSave); /* exp=1 */
2410
2411 /*** limit bitresFac for small bitreservoir ***/
2412 fillLevel = fDivNorm(bitresBits, avgBits, &fillLevel_e);
2413 if (fillLevel_e < 0) {
2414 fillLevel = scaleValue(fillLevel, fillLevel_e);
2415 fillLevel_e = 0;
2416 }
2417 /* shift down value by 1 because of summation, ... */
2418 fillLevel >>= 1;
2419 fillLevel_e += 1;
2420 /* ..., this summation: */
2421 fillLevel += scaleValue(FL2FXCONST_DBL(0.7f), -fillLevel_e);
2422 /* set bitresfactor to same exponent as fillLevel */
2423 if (scaleValue(bitresFac, -fillLevel_e + 1) > fillLevel) {
2424 bitresFac = fillLevel;
2425 bitresFac_e = fillLevel_e;
2426 }
2427
2428 /* limit bitresFac for high bitrates */
2429 if (scaleValue(bitresFac, bitresFac_e - (DFRACT_BITS - 1 - 24)) > maxBitFac) {
2430 bitresFac = maxBitFac;
2431 bitresFac_e = (DFRACT_BITS - 1 - 24);
2432 }
2433
2434 FDKaacEnc_adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax);
2435
2436 /* output values */
2437 *pBitresFac = bitresFac;
2438 *pBitresFac_e = bitresFac_e;
2439 }
2440
2441 /*****************************************************************************
2442 functionname: FDKaacEnc_AdjThrNew
2443 description: allocate ADJ_THR_STATE
2444 *****************************************************************************/
FDKaacEnc_AdjThrNew(ADJ_THR_STATE ** phAdjThr,INT nElements)2445 INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE **phAdjThr, INT nElements) {
2446 INT err = 0;
2447 INT i;
2448 ADJ_THR_STATE *hAdjThr = GetRam_aacEnc_AdjustThreshold();
2449 if (hAdjThr == NULL) {
2450 err = 1;
2451 goto bail;
2452 }
2453
2454 for (i = 0; i < nElements; i++) {
2455 hAdjThr->adjThrStateElem[i] = GetRam_aacEnc_AdjThrStateElement(i);
2456 if (hAdjThr->adjThrStateElem[i] == NULL) {
2457 err = 1;
2458 goto bail;
2459 }
2460 }
2461
2462 bail:
2463 *phAdjThr = hAdjThr;
2464 return err;
2465 }
2466
2467 /*****************************************************************************
2468 functionname: FDKaacEnc_AdjThrInit
2469 description: initialize ADJ_THR_STATE
2470 *****************************************************************************/
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)2471 void FDKaacEnc_AdjThrInit(
2472 ADJ_THR_STATE *const hAdjThr, const INT meanPe, const INT invQuant,
2473 const CHANNEL_MAPPING *const channelMapping, const INT sampleRate,
2474 const INT totalBitrate, const INT isLowDelay,
2475 const AACENC_BITRES_MODE bitResMode, const INT dZoneQuantEnable,
2476 const INT bitDistributionMode, const FIXP_DBL vbrQualFactor) {
2477 INT i;
2478
2479 FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f);
2480 FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f);
2481
2482 if (bitDistributionMode == 1) {
2483 hAdjThr->bitDistributionMode = AACENC_BD_MODE_INTRA_ELEMENT;
2484 } else {
2485 hAdjThr->bitDistributionMode = AACENC_BD_MODE_INTER_ELEMENT;
2486 }
2487
2488 /* Max number of iterations in second guess is 3 for lowdelay aot and for
2489 configurations with multiple audio elements in general, otherwise iteration
2490 value is always 1. */
2491 hAdjThr->maxIter2ndGuess =
2492 (isLowDelay != 0 || channelMapping->nElements > 1) ? 3 : 1;
2493
2494 /* common for all elements: */
2495 /* parameters for bitres control */
2496 hAdjThr->bresParamLong.clipSaveLow =
2497 (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
2498 hAdjThr->bresParamLong.clipSaveHigh =
2499 (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
2500 hAdjThr->bresParamLong.minBitSave =
2501 (FIXP_DBL)0xf999999a; /* FL2FXCONST_DBL(-0.05f); */
2502 hAdjThr->bresParamLong.maxBitSave =
2503 (FIXP_DBL)0x26666666; /* FL2FXCONST_DBL(0.3f); */
2504 hAdjThr->bresParamLong.clipSpendLow =
2505 (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
2506 hAdjThr->bresParamLong.clipSpendHigh =
2507 (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
2508 hAdjThr->bresParamLong.minBitSpend =
2509 (FIXP_DBL)0xf3333333; /* FL2FXCONST_DBL(-0.10f); */
2510 hAdjThr->bresParamLong.maxBitSpend =
2511 (FIXP_DBL)0x33333333; /* FL2FXCONST_DBL(0.4f); */
2512
2513 hAdjThr->bresParamShort.clipSaveLow =
2514 (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
2515 hAdjThr->bresParamShort.clipSaveHigh =
2516 (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
2517 hAdjThr->bresParamShort.minBitSave =
2518 (FIXP_DBL)0x00000000; /* FL2FXCONST_DBL(0.0f); */
2519 hAdjThr->bresParamShort.maxBitSave =
2520 (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
2521 hAdjThr->bresParamShort.clipSpendLow =
2522 (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
2523 hAdjThr->bresParamShort.clipSpendHigh =
2524 (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
2525 hAdjThr->bresParamShort.minBitSpend =
2526 (FIXP_DBL)0xf9999998; /* FL2FXCONST_DBL(-0.05f); */
2527 hAdjThr->bresParamShort.maxBitSpend =
2528 (FIXP_DBL)0x40000000; /* FL2FXCONST_DBL(0.5f); */
2529
2530 /* specific for each element: */
2531 for (i = 0; i < channelMapping->nElements; i++) {
2532 const FIXP_DBL relativeBits = channelMapping->elInfo[i].relativeBits;
2533 const INT nChannelsInElement = channelMapping->elInfo[i].nChannelsInEl;
2534 const INT bitrateInElement =
2535 (relativeBits != (FIXP_DBL)MAXVAL_DBL)
2536 ? (INT)fMultNorm(relativeBits, (FIXP_DBL)totalBitrate)
2537 : totalBitrate;
2538 const INT chBitrate = bitrateInElement >> (nChannelsInElement == 1 ? 0 : 1);
2539
2540 ATS_ELEMENT *atsElem = hAdjThr->adjThrStateElem[i];
2541 MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam;
2542
2543 /* parameters for bitres control */
2544 if (isLowDelay) {
2545 atsElem->peMin = fMultI(POINT8, meanPe);
2546 atsElem->peMax = fMultI(POINT6, meanPe) << 1;
2547 } else {
2548 atsElem->peMin = fMultI(POINT8, meanPe) >> 1;
2549 atsElem->peMax = fMultI(POINT6, meanPe);
2550 }
2551
2552 /* for use in FDKaacEnc_reduceThresholdsVBR */
2553 atsElem->chaosMeasureOld = FL2FXCONST_DBL(0.3f);
2554
2555 /* additional pe offset to correct pe2bits for low bitrates */
2556 /* ---- no longer necessary, set by table ----- */
2557 atsElem->peOffset = 0;
2558
2559 /* vbr initialisation */
2560 atsElem->vbrQualFactor = vbrQualFactor;
2561 if (chBitrate < 32000) {
2562 atsElem->peOffset =
2563 fixMax(50, 100 - fMultI((FIXP_DBL)0x666667, chBitrate));
2564 }
2565
2566 /* avoid hole parameters */
2567 if (chBitrate >= 20000) {
2568 atsElem->ahParam.modifyMinSnr = TRUE;
2569 atsElem->ahParam.startSfbL = 15;
2570 atsElem->ahParam.startSfbS = 3;
2571 } else {
2572 atsElem->ahParam.modifyMinSnr = FALSE;
2573 atsElem->ahParam.startSfbL = 0;
2574 atsElem->ahParam.startSfbS = 0;
2575 }
2576
2577 /* minSnr adaptation */
2578 msaParam->maxRed = FL2FXCONST_DBL(0.00390625f); /* 0.25f/64.0f */
2579 /* start adaptation of minSnr for avgEn/sfbEn > startRatio */
2580 msaParam->startRatio = FL2FXCONST_DBL(0.05190512648f); /* ld64(10.0f) */
2581 /* maximum minSnr reduction to minSnr^maxRed is reached for
2582 avgEn/sfbEn >= maxRatio */
2583 /* msaParam->maxRatio = 1000.0f; */
2584 /*msaParam->redRatioFac = ((float)1.0f - msaParam->maxRed) /
2585 * ((float)10.0f*log10(msaParam->startRatio/msaParam->maxRatio)/log10(2.0f)*(float)0.3010299956f);*/
2586 msaParam->redRatioFac = FL2FXCONST_DBL(-0.375f); /* -0.0375f * 10.0f */
2587 /*msaParam->redOffs = (float)1.0f - msaParam->redRatioFac * (float)10.0f *
2588 * log10(msaParam->startRatio)/log10(2.0f) * (float)0.3010299956f;*/
2589 msaParam->redOffs = FL2FXCONST_DBL(0.021484375); /* 1.375f/64.0f */
2590
2591 /* init pe correction */
2592 atsElem->peCorrectionFactor_m = FL2FXCONST_DBL(0.5f); /* 1.0 */
2593 atsElem->peCorrectionFactor_e = 1;
2594
2595 atsElem->dynBitsLast = -1;
2596 atsElem->peLast = 0;
2597
2598 /* init bits to pe factor */
2599
2600 /* init bits2PeFactor */
2601 FDKaacEnc_InitBits2PeFactor(
2602 &atsElem->bits2PeFactor_m, &atsElem->bits2PeFactor_e, bitrateInElement,
2603 nChannelsInElement, sampleRate, isLowDelay, dZoneQuantEnable, invQuant);
2604
2605 } /* for nElements */
2606 }
2607
2608 /*****************************************************************************
2609 functionname: FDKaacEnc_FDKaacEnc_calcPeCorrection
2610 description: calc desired pe
2611 *****************************************************************************/
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)2612 static void FDKaacEnc_FDKaacEnc_calcPeCorrection(
2613 FIXP_DBL *const correctionFac_m, INT *const correctionFac_e,
2614 const INT peAct, const INT peLast, const INT bitsLast,
2615 const FIXP_DBL bits2PeFactor_m, const INT bits2PeFactor_e) {
2616 if ((bitsLast > 0) && (peAct < 1.5f * peLast) && (peAct > 0.7f * peLast) &&
2617 (FDKaacEnc_bits2pe2(bitsLast,
2618 fMult(FL2FXCONST_DBL(1.2f / 2.f), bits2PeFactor_m),
2619 bits2PeFactor_e + 1) > peLast) &&
2620 (FDKaacEnc_bits2pe2(bitsLast,
2621 fMult(FL2FXCONST_DBL(0.65f), bits2PeFactor_m),
2622 bits2PeFactor_e) < peLast)) {
2623 FIXP_DBL corrFac = *correctionFac_m;
2624
2625 int scaling = 0;
2626 FIXP_DBL denum = (FIXP_DBL)FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m,
2627 bits2PeFactor_e);
2628 FIXP_DBL newFac = fDivNorm((FIXP_DBL)peLast, denum, &scaling);
2629
2630 /* dead zone, newFac and corrFac are scaled by 0.5 */
2631 if ((FIXP_DBL)peLast <= denum) { /* ratio <= 1.f */
2632 newFac = fixMax(
2633 scaleValue(fixMin(fMult(FL2FXCONST_DBL(1.1f / 2.f), newFac),
2634 scaleValue(FL2FXCONST_DBL(1.f / 2.f), -scaling)),
2635 scaling),
2636 FL2FXCONST_DBL(0.85f / 2.f));
2637 } else { /* ratio < 1.f */
2638 newFac = fixMax(
2639 fixMin(scaleValue(fMult(FL2FXCONST_DBL(0.9f / 2.f), newFac), scaling),
2640 FL2FXCONST_DBL(1.15f / 2.f)),
2641 FL2FXCONST_DBL(1.f / 2.f));
2642 }
2643
2644 if (((newFac > FL2FXCONST_DBL(1.f / 2.f)) &&
2645 (corrFac < FL2FXCONST_DBL(1.f / 2.f))) ||
2646 ((newFac < FL2FXCONST_DBL(1.f / 2.f)) &&
2647 (corrFac > FL2FXCONST_DBL(1.f / 2.f)))) {
2648 corrFac = FL2FXCONST_DBL(1.f / 2.f);
2649 }
2650
2651 /* faster adaptation towards 1.0, slower in the other direction */
2652 if ((corrFac < FL2FXCONST_DBL(1.f / 2.f) && newFac < corrFac) ||
2653 (corrFac > FL2FXCONST_DBL(1.f / 2.f) && newFac > corrFac)) {
2654 corrFac = fMult(FL2FXCONST_DBL(0.85f), corrFac) +
2655 fMult(FL2FXCONST_DBL(0.15f), newFac);
2656 } else {
2657 corrFac = fMult(FL2FXCONST_DBL(0.7f), corrFac) +
2658 fMult(FL2FXCONST_DBL(0.3f), newFac);
2659 }
2660
2661 corrFac = fixMax(fixMin(corrFac, FL2FXCONST_DBL(1.15f / 2.f)),
2662 FL2FXCONST_DBL(0.85 / 2.f));
2663
2664 *correctionFac_m = corrFac;
2665 *correctionFac_e = 1;
2666 } else {
2667 *correctionFac_m = FL2FXCONST_DBL(1.f / 2.f);
2668 *correctionFac_e = 1;
2669 }
2670 }
2671
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)2672 static void FDKaacEnc_calcPeCorrectionLowBitRes(
2673 FIXP_DBL *const correctionFac_m, INT *const correctionFac_e,
2674 const INT peLast, const INT bitsLast, const INT bitresLevel,
2675 const INT nChannels, const FIXP_DBL bits2PeFactor_m,
2676 const INT bits2PeFactor_e) {
2677 /* tuning params */
2678 const FIXP_DBL amp = FL2FXCONST_DBL(0.005);
2679 const FIXP_DBL maxDiff = FL2FXCONST_DBL(0.25f);
2680
2681 if (bitsLast > 0) {
2682 /* Estimate deviation of granted and used dynamic bits in previous frame, in
2683 * PE units */
2684 const int bitsBalLast =
2685 peLast - FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m, bits2PeFactor_e);
2686
2687 /* reserve n bits per channel */
2688 int headroom = (bitresLevel >= 50 * nChannels) ? 0 : (100 * nChannels);
2689
2690 /* in PE units */
2691 headroom = FDKaacEnc_bits2pe2(headroom, bits2PeFactor_m, bits2PeFactor_e);
2692
2693 /*
2694 * diff = amp * ((bitsBalLast - headroom) / (bitresLevel + headroom)
2695 * diff = max ( min ( diff, maxDiff, -maxDiff)) / 2
2696 */
2697 FIXP_DBL denominator = (FIXP_DBL)FDKaacEnc_bits2pe2(
2698 bitresLevel, bits2PeFactor_m, bits2PeFactor_e) +
2699 (FIXP_DBL)headroom;
2700
2701 int scaling = 0;
2702 FIXP_DBL diff =
2703 (bitsBalLast >= headroom)
2704 ? fMult(amp, fDivNorm((FIXP_DBL)(bitsBalLast - headroom),
2705 denominator, &scaling))
2706 : -fMult(amp, fDivNorm(-(FIXP_DBL)(bitsBalLast - headroom),
2707 denominator, &scaling));
2708
2709 scaling -= 1; /* divide by 2 */
2710
2711 diff = (scaling <= 0)
2712 ? fMax(fMin(diff >> (-scaling), maxDiff >> 1), -maxDiff >> 1)
2713 : fMax(fMin(diff, maxDiff >> (1 + scaling)),
2714 -maxDiff >> (1 + scaling))
2715 << scaling;
2716
2717 /*
2718 * corrFac += diff
2719 * corrFac = max ( min ( corrFac/2.f, 1.f/2.f, 0.75f/2.f ) )
2720 */
2721 *correctionFac_m =
2722 fMax(fMin((*correctionFac_m) + diff, FL2FXCONST_DBL(1.0f / 2.f)),
2723 FL2FXCONST_DBL(0.75f / 2.f));
2724 *correctionFac_e = 1;
2725 } else {
2726 *correctionFac_m = FL2FXCONST_DBL(0.75 / 2.f);
2727 *correctionFac_e = 1;
2728 }
2729 }
2730
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)2731 void FDKaacEnc_DistributeBits(
2732 ADJ_THR_STATE *adjThrState, ATS_ELEMENT *AdjThrStateElement,
2733 PSY_OUT_CHANNEL *psyOutChannel[(2)], PE_DATA *peData, INT *grantedPe,
2734 INT *grantedPeCorr, const INT nChannels, const INT commonWindow,
2735 const INT grantedDynBits, const INT bitresBits, const INT maxBitresBits,
2736 const FIXP_DBL maxBitFac, const AACENC_BITRES_MODE bitResMode) {
2737 FIXP_DBL bitFactor;
2738 INT bitFactor_e;
2739 INT noRedPe = peData->pe;
2740
2741 /* prefer short windows for calculation of bitFactor */
2742 INT curWindowSequence = LONG_WINDOW;
2743 if (nChannels == 2) {
2744 if ((psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) ||
2745 (psyOutChannel[1]->lastWindowSequence == SHORT_WINDOW)) {
2746 curWindowSequence = SHORT_WINDOW;
2747 }
2748 } else {
2749 curWindowSequence = psyOutChannel[0]->lastWindowSequence;
2750 }
2751
2752 if (grantedDynBits >= 1) {
2753 if (bitResMode != AACENC_BR_MODE_FULL) {
2754 /* small or disabled bitreservoir */
2755 *grantedPe = FDKaacEnc_bits2pe2(grantedDynBits,
2756 AdjThrStateElement->bits2PeFactor_m,
2757 AdjThrStateElement->bits2PeFactor_e);
2758 } else {
2759 /* factor dependend on current fill level and pe */
2760 FDKaacEnc_bitresCalcBitFac(
2761 bitresBits, maxBitresBits, noRedPe, curWindowSequence, grantedDynBits,
2762 maxBitFac, adjThrState, AdjThrStateElement, &bitFactor, &bitFactor_e);
2763
2764 /* desired pe for actual frame */
2765 /* Worst case max of grantedDynBits is = 1024 * 5.27 * 2 */
2766 *grantedPe = FDKaacEnc_bits2pe2(
2767 grantedDynBits, fMult(bitFactor, AdjThrStateElement->bits2PeFactor_m),
2768 AdjThrStateElement->bits2PeFactor_e + bitFactor_e);
2769 }
2770 } else {
2771 *grantedPe = 0; /* prevent divsion by 0 */
2772 }
2773
2774 /* correction of pe value */
2775 switch (bitResMode) {
2776 case AACENC_BR_MODE_DISABLED:
2777 case AACENC_BR_MODE_REDUCED:
2778 /* correction of pe value for low bitres */
2779 FDKaacEnc_calcPeCorrectionLowBitRes(
2780 &AdjThrStateElement->peCorrectionFactor_m,
2781 &AdjThrStateElement->peCorrectionFactor_e, AdjThrStateElement->peLast,
2782 AdjThrStateElement->dynBitsLast, bitresBits, nChannels,
2783 AdjThrStateElement->bits2PeFactor_m,
2784 AdjThrStateElement->bits2PeFactor_e);
2785 break;
2786 case AACENC_BR_MODE_FULL:
2787 default:
2788 /* correction of pe value for high bitres */
2789 FDKaacEnc_FDKaacEnc_calcPeCorrection(
2790 &AdjThrStateElement->peCorrectionFactor_m,
2791 &AdjThrStateElement->peCorrectionFactor_e,
2792 fixMin(*grantedPe, noRedPe), AdjThrStateElement->peLast,
2793 AdjThrStateElement->dynBitsLast, AdjThrStateElement->bits2PeFactor_m,
2794 AdjThrStateElement->bits2PeFactor_e);
2795 break;
2796 }
2797
2798 *grantedPeCorr =
2799 (INT)(fMult((FIXP_DBL)(*grantedPe << Q_AVGBITS),
2800 AdjThrStateElement->peCorrectionFactor_m) >>
2801 (Q_AVGBITS - AdjThrStateElement->peCorrectionFactor_e));
2802
2803 /* update last pe */
2804 AdjThrStateElement->peLast = *grantedPe;
2805 AdjThrStateElement->dynBitsLast = -1;
2806 }
2807
2808 /*****************************************************************************
2809 functionname: FDKaacEnc_AdjustThresholds
2810 description: adjust thresholds
2811 *****************************************************************************/
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)2812 void FDKaacEnc_AdjustThresholds(
2813 ADJ_THR_STATE *const hAdjThr, QC_OUT_ELEMENT *const qcElement[((8))],
2814 QC_OUT *const qcOut, const PSY_OUT_ELEMENT *const psyOutElement[((8))],
2815 const INT CBRbitrateMode, const CHANNEL_MAPPING *const cm) {
2816 int i;
2817
2818 if (CBRbitrateMode) {
2819 /* In case, no bits must be shifted between different elements, */
2820 /* an element-wise execution of the pe-dependent threshold- */
2821 /* adaption becomes necessary... */
2822 if (hAdjThr->bitDistributionMode == AACENC_BD_MODE_INTRA_ELEMENT) {
2823 for (i = 0; i < cm->nElements; i++) {
2824 ELEMENT_INFO elInfo = cm->elInfo[i];
2825
2826 if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
2827 (elInfo.elType == ID_LFE)) {
2828 /* qcElement[i]->grantedPe = 2000; */ /* Use this only for debugging
2829 */
2830 // if (totalGrantedPeCorr < totalNoRedPe) {
2831 if (qcElement[i]->grantedPeCorr < qcElement[i]->peData.pe) {
2832 /* calc threshold necessary for desired pe */
2833 FDKaacEnc_adaptThresholdsToPe(
2834 cm, hAdjThr->adjThrStateElem, qcElement, psyOutElement,
2835 qcElement[i]->grantedPeCorr, hAdjThr->maxIter2ndGuess,
2836 1, /* Process only 1 element */
2837 i /* Process exactly THIS element */
2838 );
2839 }
2840 } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */
2841 } /* -end- element loop */
2842 } /* AACENC_BD_MODE_INTRA_ELEMENT */
2843 else if (hAdjThr->bitDistributionMode == AACENC_BD_MODE_INTER_ELEMENT) {
2844 /* Use global Pe to obtain the thresholds? */
2845 if (qcOut->totalGrantedPeCorr < qcOut->totalNoRedPe) {
2846 /* add equal loadness quantization noise to match the */
2847 /* desired pe calc threshold necessary for desired pe */
2848 /* Now carried out globally to cover all(!) channels. */
2849 FDKaacEnc_adaptThresholdsToPe(cm, hAdjThr->adjThrStateElem, qcElement,
2850 psyOutElement, qcOut->totalGrantedPeCorr,
2851 hAdjThr->maxIter2ndGuess,
2852 cm->nElements, /* Process all elements */
2853 0); /* Process exactly THIS element */
2854 } else {
2855 /* In case global pe doesn't need to be reduced check each element to
2856 hold estimated bitrate below maximum element bitrate. */
2857 for (i = 0; i < cm->nElements; i++) {
2858 if ((cm->elInfo[i].elType == ID_SCE) ||
2859 (cm->elInfo[i].elType == ID_CPE) ||
2860 (cm->elInfo[i].elType == ID_LFE)) {
2861 /* Element pe applies to dynamic bits of maximum element bitrate. */
2862 const int maxElementPe = FDKaacEnc_bits2pe2(
2863 (cm->elInfo[i].nChannelsInEl * MIN_BUFSIZE_PER_EFF_CHAN) -
2864 qcElement[i]->staticBitsUsed - qcElement[i]->extBitsUsed,
2865 hAdjThr->adjThrStateElem[i]->bits2PeFactor_m,
2866 hAdjThr->adjThrStateElem[i]->bits2PeFactor_e);
2867
2868 if (maxElementPe < qcElement[i]->peData.pe) {
2869 FDKaacEnc_adaptThresholdsToPe(
2870 cm, hAdjThr->adjThrStateElem, qcElement, psyOutElement,
2871 maxElementPe, hAdjThr->maxIter2ndGuess, 1, i);
2872 }
2873 } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */
2874 } /* -end- element loop */
2875 } /* (qcOut->totalGrantedPeCorr < qcOut->totalNoRedPe) */
2876 } /* AACENC_BD_MODE_INTER_ELEMENT */
2877 } else {
2878 for (i = 0; i < cm->nElements; i++) {
2879 ELEMENT_INFO elInfo = cm->elInfo[i];
2880
2881 if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
2882 (elInfo.elType == ID_LFE)) {
2883 /* for VBR-mode */
2884 FDKaacEnc_AdaptThresholdsVBR(
2885 qcElement[i]->qcOutChannel, psyOutElement[i]->psyOutChannel,
2886 hAdjThr->adjThrStateElem[i], &psyOutElement[i]->toolsInfo,
2887 cm->elInfo[i].nChannelsInEl);
2888 } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */
2889
2890 } /* -end- element loop */
2891 }
2892 for (i = 0; i < cm->nElements; i++) {
2893 int ch, sfb, sfbGrp;
2894 /* no weighting of threholds and energies for mlout */
2895 /* weight energies and thresholds */
2896 for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) {
2897 QC_OUT_CHANNEL *pQcOutCh = qcElement[i]->qcOutChannel[ch];
2898 for (sfbGrp = 0; sfbGrp < psyOutElement[i]->psyOutChannel[ch]->sfbCnt;
2899 sfbGrp += psyOutElement[i]->psyOutChannel[ch]->sfbPerGroup) {
2900 for (sfb = 0; sfb < psyOutElement[i]->psyOutChannel[ch]->maxSfbPerGroup;
2901 sfb++) {
2902 pQcOutCh->sfbThresholdLdData[sfb + sfbGrp] +=
2903 pQcOutCh->sfbEnFacLd[sfb + sfbGrp];
2904 }
2905 }
2906 }
2907 }
2908 }
2909
FDKaacEnc_AdjThrClose(ADJ_THR_STATE ** phAdjThr)2910 void FDKaacEnc_AdjThrClose(ADJ_THR_STATE **phAdjThr) {
2911 INT i;
2912 ADJ_THR_STATE *hAdjThr = *phAdjThr;
2913
2914 if (hAdjThr != NULL) {
2915 for (i = 0; i < ((8)); i++) {
2916 if (hAdjThr->adjThrStateElem[i] != NULL) {
2917 FreeRam_aacEnc_AdjThrStateElement(&hAdjThr->adjThrStateElem[i]);
2918 }
2919 }
2920 FreeRam_aacEnc_AdjustThreshold(phAdjThr);
2921 }
2922 }
2923