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