• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5 Forschung e.V. All rights reserved.
6 
7  1.    INTRODUCTION
8 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9 that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10 scheme for digital audio. This FDK AAC Codec software is intended to be used on
11 a wide variety of Android devices.
12 
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14 general perceptual audio codecs. AAC-ELD is considered the best-performing
15 full-bandwidth communications codec by independent studies and is widely
16 deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17 specifications.
18 
19 Patent licenses for necessary patent claims for the FDK AAC Codec (including
20 those of Fraunhofer) may be obtained through Via Licensing
21 (www.vialicensing.com) or through the respective patent owners individually for
22 the purpose of encoding or decoding bit streams in products that are compliant
23 with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24 Android devices already license these patent claims through Via Licensing or
25 directly from the patent owners, and therefore FDK AAC Codec software may
26 already be covered under those patent licenses when it is used for those
27 licensed purposes only.
28 
29 Commercially-licensed AAC software libraries, including floating-point versions
30 with enhanced sound quality, are also available from Fraunhofer. Users are
31 encouraged to check the Fraunhofer website for additional applications
32 information and documentation.
33 
34 2.    COPYRIGHT LICENSE
35 
36 Redistribution and use in source and binary forms, with or without modification,
37 are permitted without payment of copyright license fees provided that you
38 satisfy the following conditions:
39 
40 You must retain the complete text of this software license in redistributions of
41 the FDK AAC Codec or your modifications thereto in source code form.
42 
43 You must retain the complete text of this software license in the documentation
44 and/or other materials provided with redistributions of the FDK AAC Codec or
45 your modifications thereto in binary form. You must make available free of
46 charge copies of the complete source code of the FDK AAC Codec and your
47 modifications thereto to recipients of copies in binary form.
48 
49 The name of Fraunhofer may not be used to endorse or promote products derived
50 from this library without prior written permission.
51 
52 You may not charge copyright license fees for anyone to use, copy or distribute
53 the FDK AAC Codec software or your modifications thereto.
54 
55 Your modified versions of the FDK AAC Codec must carry prominent notices stating
56 that you changed the software and the date of any change. For modified versions
57 of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58 must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59 AAC Codec Library for Android."
60 
61 3.    NO PATENT LICENSE
62 
63 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64 limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65 Fraunhofer provides no warranty of patent non-infringement with respect to this
66 software.
67 
68 You may use this FDK AAC Codec software or modifications thereto only for
69 purposes that are authorized by appropriate patent licenses.
70 
71 4.    DISCLAIMER
72 
73 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74 holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75 including but not limited to the implied warranties of merchantability and
76 fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78 or consequential damages, including but not limited to procurement of substitute
79 goods or services; loss of use, data, or profits, or business interruption,
80 however caused and on any theory of liability, whether in contract, strict
81 liability, or tort (including negligence), arising in any way out of the use of
82 this software, even if advised of the possibility of such damage.
83 
84 5.    CONTACT INFORMATION
85 
86 Fraunhofer Institute for Integrated Circuits IIS
87 Attention: Audio and Multimedia Departments - FDK AAC LL
88 Am Wolfsmantel 33
89 91058 Erlangen, Germany
90 
91 www.iis.fraunhofer.de/amm
92 amm-info@iis.fraunhofer.de
93 ----------------------------------------------------------------------------- */
94 
95 /**************************** AAC encoder library ******************************
96 
97    Author(s):   M.Werner
98 
99    Description: Psychoaccoustic configuration
100 
101 *******************************************************************************/
102 
103 #include "psy_configuration.h"
104 #include "adj_thr.h"
105 #include "aacEnc_rom.h"
106 
107 #include "genericStds.h"
108 
109 #include "FDK_trigFcts.h"
110 
111 typedef struct {
112   LONG sampleRate;
113   const SFB_PARAM_LONG *paramLong;
114   const SFB_PARAM_SHORT *paramShort;
115 } SFB_INFO_TAB;
116 
117 static const SFB_INFO_TAB sfbInfoTab[] = {
118     {8000, &p_FDKaacEnc_8000_long_1024, &p_FDKaacEnc_8000_short_128},
119     {11025, &p_FDKaacEnc_11025_long_1024, &p_FDKaacEnc_11025_short_128},
120     {12000, &p_FDKaacEnc_12000_long_1024, &p_FDKaacEnc_12000_short_128},
121     {16000, &p_FDKaacEnc_16000_long_1024, &p_FDKaacEnc_16000_short_128},
122     {22050, &p_FDKaacEnc_22050_long_1024, &p_FDKaacEnc_22050_short_128},
123     {24000, &p_FDKaacEnc_24000_long_1024, &p_FDKaacEnc_24000_short_128},
124     {32000, &p_FDKaacEnc_32000_long_1024, &p_FDKaacEnc_32000_short_128},
125     {44100, &p_FDKaacEnc_44100_long_1024, &p_FDKaacEnc_44100_short_128},
126     {48000, &p_FDKaacEnc_48000_long_1024, &p_FDKaacEnc_48000_short_128},
127     {64000, &p_FDKaacEnc_64000_long_1024, &p_FDKaacEnc_64000_short_128},
128     {88200, &p_FDKaacEnc_88200_long_1024, &p_FDKaacEnc_88200_short_128},
129     {96000, &p_FDKaacEnc_96000_long_1024, &p_FDKaacEnc_96000_short_128}
130 
131 };
132 
133 /* 22050 and 24000 Hz */
134 static const SFB_PARAM_LONG p_22050_long_512 = {
135     31, {4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  8,  8,  8,  12, 12,
136          12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}};
137 
138 /* 32000 Hz */
139 static const SFB_PARAM_LONG p_32000_long_512 = {
140     37,
141     {4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  8,  8,  8,  8, 8,
142      12, 12, 12, 12, 16, 16, 16, 20, 24, 24, 28, 32, 32, 32, 32, 32, 32, 32}};
143 
144 /* 44100 Hz */
145 static const SFB_PARAM_LONG p_44100_long_512 = {
146     36, {4, 4, 4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  8,  8,  8,
147          8, 8, 12, 12, 12, 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 52}};
148 
149 static const SFB_INFO_TAB sfbInfoTabLD512[] = {
150     {8000, &p_22050_long_512, NULL},   {11025, &p_22050_long_512, NULL},
151     {12000, &p_22050_long_512, NULL},  {16000, &p_22050_long_512, NULL},
152     {22050, &p_22050_long_512, NULL},  {24000, &p_22050_long_512, NULL},
153     {32000, &p_32000_long_512, NULL},  {44100, &p_44100_long_512, NULL},
154     {48000, &p_44100_long_512, NULL},  {64000, &p_44100_long_512, NULL},
155     {88200, &p_44100_long_512, NULL},  {96000, &p_44100_long_512, NULL},
156     {128000, &p_44100_long_512, NULL}, {176400, &p_44100_long_512, NULL},
157     {192000, &p_44100_long_512, NULL}, {256000, &p_44100_long_512, NULL},
158     {352800, &p_44100_long_512, NULL}, {384000, &p_44100_long_512, NULL},
159 };
160 
161 /* 22050 and 24000 Hz */
162 static const SFB_PARAM_LONG p_22050_long_480 = {
163     30, {4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  8,  8,  8,  12,
164          12, 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32}};
165 
166 /* 32000 Hz */
167 static const SFB_PARAM_LONG p_32000_long_480 = {
168     37, {4, 4, 4, 4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  8,  8, 8,
169          8, 8, 8, 12, 12, 12, 16, 16, 20, 24, 32, 32, 32, 32, 32, 32, 32, 32}};
170 
171 /* 44100 Hz */
172 static const SFB_PARAM_LONG p_44100_long_480 = {
173     35, {4, 4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  8,  8,  8, 8,
174          8, 12, 12, 12, 12, 12, 16, 16, 24, 28, 32, 32, 32, 32, 32, 32, 48}};
175 
176 static const SFB_INFO_TAB sfbInfoTabLD480[] = {
177     {8000, &p_22050_long_480, NULL},   {11025, &p_22050_long_480, NULL},
178     {12000, &p_22050_long_480, NULL},  {16000, &p_22050_long_480, NULL},
179     {22050, &p_22050_long_480, NULL},  {24000, &p_22050_long_480, NULL},
180     {32000, &p_32000_long_480, NULL},  {44100, &p_44100_long_480, NULL},
181     {48000, &p_44100_long_480, NULL},  {64000, &p_44100_long_480, NULL},
182     {88200, &p_44100_long_480, NULL},  {96000, &p_44100_long_480, NULL},
183     {128000, &p_44100_long_480, NULL}, {176400, &p_44100_long_480, NULL},
184     {192000, &p_44100_long_480, NULL}, {256000, &p_44100_long_480, NULL},
185     {352800, &p_44100_long_480, NULL}, {384000, &p_44100_long_480, NULL},
186 };
187 
188 /* Fixed point precision definitions */
189 #define Q_BARCVAL (25)
190 
FDKaacEnc_initSfbTable(const LONG sampleRate,const INT blockType,const INT granuleLength,INT * const sfbOffset,INT * const sfbCnt)191 AAC_ENCODER_ERROR FDKaacEnc_initSfbTable(const LONG sampleRate,
192                                          const INT blockType,
193                                          const INT granuleLength,
194                                          INT *const sfbOffset,
195                                          INT *const sfbCnt) {
196   INT i, specStartOffset = 0;
197   INT granuleLengthWindow = granuleLength;
198   const UCHAR *sfbWidth = NULL;
199   const SFB_INFO_TAB *sfbInfo = NULL;
200   int size;
201 
202   /*
203     select table
204   */
205   switch (granuleLength) {
206     case 1024:
207     case 960:
208       sfbInfo = sfbInfoTab;
209       size = (INT)(sizeof(sfbInfoTab) / sizeof(SFB_INFO_TAB));
210       break;
211     case 512:
212       sfbInfo = sfbInfoTabLD512;
213       size = sizeof(sfbInfoTabLD512);
214       break;
215     case 480:
216       sfbInfo = sfbInfoTabLD480;
217       size = sizeof(sfbInfoTabLD480);
218       break;
219     default:
220       return AAC_ENC_INVALID_FRAME_LENGTH;
221   }
222 
223   for (i = 0; i < size; i++) {
224     if (sfbInfo[i].sampleRate == sampleRate) {
225       switch (blockType) {
226         case LONG_WINDOW:
227         case START_WINDOW:
228         case STOP_WINDOW:
229           sfbWidth = sfbInfo[i].paramLong->sfbWidth;
230           *sfbCnt = sfbInfo[i].paramLong->sfbCnt;
231           break;
232         case SHORT_WINDOW:
233           sfbWidth = sfbInfo[i].paramShort->sfbWidth;
234           *sfbCnt = sfbInfo[i].paramShort->sfbCnt;
235           granuleLengthWindow /= TRANS_FAC;
236           break;
237       }
238       break;
239     }
240   }
241   if (i == size) {
242     return AAC_ENC_UNSUPPORTED_SAMPLINGRATE;
243   }
244 
245   /*
246     calc sfb offsets
247   */
248   for (i = 0; i < *sfbCnt; i++) {
249     sfbOffset[i] = specStartOffset;
250     specStartOffset += sfbWidth[i];
251     if (specStartOffset >= granuleLengthWindow) {
252       i++;
253       break;
254     }
255   }
256   *sfbCnt = fixMin(i, *sfbCnt);
257   sfbOffset[*sfbCnt] = fixMin(specStartOffset, granuleLengthWindow);
258   return AAC_ENC_OK;
259 }
260 
261 /*****************************************************************************
262 
263     functionname: FDKaacEnc_BarcLineValue
264     description:  Calculates barc value for one frequency line
265     returns:      barc value of line
266     input:        number of lines in transform, index of line to check, Fs
267     output:
268 
269 *****************************************************************************/
FDKaacEnc_BarcLineValue(INT noOfLines,INT fftLine,LONG samplingFreq)270 static FIXP_DBL FDKaacEnc_BarcLineValue(INT noOfLines, INT fftLine,
271                                         LONG samplingFreq) {
272   FIXP_DBL FOURBY3EM4 = (FIXP_DBL)0x45e7b273; /* 4.0/3 * 0.0001 in q43 */
273   FIXP_DBL PZZZ76 = (FIXP_DBL)0x639d5e4a;     /* 0.00076 in q41 */
274   FIXP_DBL ONE3P3 = (FIXP_DBL)0x35333333;     /* 13.3 in q26 */
275   FIXP_DBL THREEP5 = (FIXP_DBL)0x1c000000;    /* 3.5 in q27 */
276   FIXP_DBL INV480 = (FIXP_DBL)0x44444444;     // 1/480 in q39
277 
278   FIXP_DBL center_freq, x1, x2;
279   FIXP_DBL bvalFFTLine, atan1, atan2;
280 
281   /* Theoritical maximum of center_freq (samp_freq*0.5) is 96khz * 0.5 = 48000
282    */
283   /* Theoritical maximum of x1 is 1.3333333e-4f * center_freq = 6.4, can keep in
284    * q28  */
285   /* Theoritical maximum of x2 is 0.00076f * center_freq = 36.48, can keep in
286    * q25     */
287 
288   center_freq = fftLine * samplingFreq; /* q11 or q8 */
289 
290   switch (noOfLines) {
291     case 1024:
292       center_freq = center_freq << 2; /* q13 */
293       break;
294     case 128:
295       center_freq = center_freq << 5; /* q13 */
296       break;
297     case 512:
298       center_freq = (fftLine * samplingFreq) << 3;  // q13
299       break;
300     case 480:
301       center_freq = fMult(center_freq, INV480) << 4;  // q13
302       break;
303     default:
304       center_freq = (FIXP_DBL)0;
305   }
306 
307   x1 = fMult(center_freq, FOURBY3EM4); /* q13 * q43 - (DFRACT_BITS-1) = q25 */
308   x2 = fMult(center_freq, PZZZ76)
309        << 2; /* q13 * q41 - (DFRACT_BITS-1) + 2 = q25 */
310 
311   atan1 = fixp_atan(x1);
312   atan2 = fixp_atan(x2);
313 
314   /* q25 (q26 * q30 - (DFRACT_BITS-1)) + q25 (q27 * q30 * q30) */
315   bvalFFTLine = fMult(ONE3P3, atan2) + fMult(THREEP5, fMult(atan1, atan1));
316   return (bvalFFTLine);
317 }
318 
319 /*
320    do not consider energies below a certain input signal level,
321    i.e. of -96dB or 1 bit at 16 bit PCM resolution,
322    might need to be configurable to e.g. 24 bit PCM Input or a lower
323    resolution for low bit rates
324 */
FDKaacEnc_InitMinPCMResolution(int numPb,int * pbOffset,FIXP_DBL * sfbPCMquantThreshold)325 static void FDKaacEnc_InitMinPCMResolution(int numPb, int *pbOffset,
326                                            FIXP_DBL *sfbPCMquantThreshold) {
327 /* PCM_QUANT_NOISE = FDKpow(10.0f, - 20.f / 10.0f) * ABS_LOW * NORM_PCM_ENERGY *
328  * FDKpow(2,PCM_QUANT_THR_SCALE) */
329 #define PCM_QUANT_NOISE ((FIXP_DBL)0x00547062)
330 
331   for (int i = 0; i < numPb; i++) {
332     sfbPCMquantThreshold[i] = (pbOffset[i + 1] - pbOffset[i]) * PCM_QUANT_NOISE;
333   }
334 }
335 
getMaskFactor(const FIXP_DBL dbVal_fix,const INT dbVal_e,const FIXP_DBL ten_fix,const INT ten_e)336 static FIXP_DBL getMaskFactor(const FIXP_DBL dbVal_fix, const INT dbVal_e,
337                               const FIXP_DBL ten_fix, const INT ten_e) {
338   INT q_msk;
339   FIXP_DBL mask_factor;
340 
341   mask_factor = fPow(ten_fix, DFRACT_BITS - 1 - ten_e, -dbVal_fix,
342                      DFRACT_BITS - 1 - dbVal_e, &q_msk);
343   q_msk = fixMin(DFRACT_BITS - 1, fixMax(-(DFRACT_BITS - 1), q_msk));
344 
345   if ((q_msk > 0) && (mask_factor > (FIXP_DBL)MAXVAL_DBL >> q_msk)) {
346     mask_factor = (FIXP_DBL)MAXVAL_DBL;
347   } else {
348     mask_factor = scaleValue(mask_factor, q_msk);
349   }
350 
351   return (mask_factor);
352 }
353 
FDKaacEnc_initSpreading(INT numPb,FIXP_DBL * pbBarcValue,FIXP_DBL * pbMaskLoFactor,FIXP_DBL * pbMaskHiFactor,FIXP_DBL * pbMaskLoFactorSprEn,FIXP_DBL * pbMaskHiFactorSprEn,const LONG bitrate,const INT blockType)354 static void FDKaacEnc_initSpreading(INT numPb, FIXP_DBL *pbBarcValue,
355                                     FIXP_DBL *pbMaskLoFactor,
356                                     FIXP_DBL *pbMaskHiFactor,
357                                     FIXP_DBL *pbMaskLoFactorSprEn,
358                                     FIXP_DBL *pbMaskHiFactorSprEn,
359                                     const LONG bitrate, const INT blockType)
360 
361 {
362   INT i;
363   FIXP_DBL MASKLOWSPREN, MASKHIGHSPREN;
364 
365   FIXP_DBL MASKHIGH = (FIXP_DBL)0x30000000;               /* 1.5 in q29 */
366   FIXP_DBL MASKLOW = (FIXP_DBL)0x60000000;                /* 3.0 in q29 */
367   FIXP_DBL MASKLOWSPRENLONG = (FIXP_DBL)0x60000000;       /* 3.0 in q29 */
368   FIXP_DBL MASKHIGHSPRENLONG = (FIXP_DBL)0x40000000;      /* 2.0 in q29 */
369   FIXP_DBL MASKHIGHSPRENLONGLOWBR = (FIXP_DBL)0x30000000; /* 1.5 in q29 */
370   FIXP_DBL MASKLOWSPRENSHORT = (FIXP_DBL)0x40000000;      /* 2.0 in q29 */
371   FIXP_DBL MASKHIGHSPRENSHORT = (FIXP_DBL)0x30000000;     /* 1.5 in q29 */
372   FIXP_DBL TEN = (FIXP_DBL)0x50000000;                    /* 10.0 in q27 */
373 
374   if (blockType != SHORT_WINDOW) {
375     MASKLOWSPREN = MASKLOWSPRENLONG;
376     MASKHIGHSPREN =
377         (bitrate > 20000) ? MASKHIGHSPRENLONG : MASKHIGHSPRENLONGLOWBR;
378   } else {
379     MASKLOWSPREN = MASKLOWSPRENSHORT;
380     MASKHIGHSPREN = MASKHIGHSPRENSHORT;
381   }
382 
383   for (i = 0; i < numPb; i++) {
384     if (i > 0) {
385       pbMaskHiFactor[i] = getMaskFactor(
386           fMult(MASKHIGH, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, 27);
387 
388       pbMaskLoFactor[i - 1] = getMaskFactor(
389           fMult(MASKLOW, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, 27);
390 
391       pbMaskHiFactorSprEn[i] = getMaskFactor(
392           fMult(MASKHIGHSPREN, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN,
393           27);
394 
395       pbMaskLoFactorSprEn[i - 1] = getMaskFactor(
396           fMult(MASKLOWSPREN, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN,
397           27);
398     } else {
399       pbMaskHiFactor[i] = (FIXP_DBL)0;
400       pbMaskLoFactor[numPb - 1] = (FIXP_DBL)0;
401       pbMaskHiFactorSprEn[i] = (FIXP_DBL)0;
402       pbMaskLoFactorSprEn[numPb - 1] = (FIXP_DBL)0;
403     }
404   }
405 }
406 
FDKaacEnc_initBarcValues(INT numPb,INT * pbOffset,INT numLines,INT samplingFrequency,FIXP_DBL * pbBval)407 static void FDKaacEnc_initBarcValues(INT numPb, INT *pbOffset, INT numLines,
408                                      INT samplingFrequency, FIXP_DBL *pbBval) {
409   INT i;
410   FIXP_DBL MAX_BARC = (FIXP_DBL)0x30000000; /* 24.0 in q25 */
411 
412   for (i = 0; i < numPb; i++) {
413     FIXP_DBL v1, v2, cur_bark;
414     v1 = FDKaacEnc_BarcLineValue(numLines, pbOffset[i], samplingFrequency);
415     v2 = FDKaacEnc_BarcLineValue(numLines, pbOffset[i + 1], samplingFrequency);
416     cur_bark = (v1 >> 1) + (v2 >> 1);
417     pbBval[i] = fixMin(cur_bark, MAX_BARC);
418   }
419 }
420 
FDKaacEnc_initMinSnr(const LONG bitrate,const LONG samplerate,const INT numLines,const INT * sfbOffset,const INT sfbActive,const INT blockType,FIXP_DBL * sfbMinSnrLdData)421 static void FDKaacEnc_initMinSnr(const LONG bitrate, const LONG samplerate,
422                                  const INT numLines, const INT *sfbOffset,
423                                  const INT sfbActive, const INT blockType,
424                                  FIXP_DBL *sfbMinSnrLdData) {
425   INT sfb;
426 
427   /* Fix conversion variables */
428   INT qbfac, qperwin, qdiv, qpeprt_const, qpeprt;
429   INT qtmp, qsnr, sfbWidth;
430 
431   FIXP_DBL MAX_BARC = (FIXP_DBL)0x30000000;   /* 24.0 in q25 */
432   FIXP_DBL MAX_BARCP1 = (FIXP_DBL)0x32000000; /* 25.0 in q25 */
433   FIXP_DBL BITS2PEFAC = (FIXP_DBL)0x4b851eb8; /* 1.18 in q30 */
434   FIXP_DBL PERS2P4 = (FIXP_DBL)0x624dd2f2;    /* 0.024 in q36 */
435   FIXP_DBL ONEP5 = (FIXP_DBL)0x60000000;      /* 1.5 in q30 */
436   FIXP_DBL MAX_SNR = (FIXP_DBL)0x33333333;    /* 0.8 in q30 */
437   FIXP_DBL MIN_SNR = (FIXP_DBL)0x003126e9;    /* 0.003 in q30 */
438 
439   FIXP_DBL barcFactor, pePerWindow, pePart, barcWidth;
440   FIXP_DBL pePart_const, tmp, snr, one_qsnr, one_point5;
441 
442   /* relative number of active barks */
443   barcFactor = fDivNorm(fixMin(FDKaacEnc_BarcLineValue(
444                                    numLines, sfbOffset[sfbActive], samplerate),
445                                MAX_BARC),
446                         MAX_BARCP1, &qbfac);
447 
448   qbfac = DFRACT_BITS - 1 - qbfac;
449 
450   pePerWindow = fDivNorm(bitrate, samplerate, &qperwin);
451   qperwin = DFRACT_BITS - 1 - qperwin;
452   pePerWindow = fMult(pePerWindow, BITS2PEFAC);
453   qperwin = qperwin + 30 - (DFRACT_BITS - 1);
454   pePerWindow = fMult(pePerWindow, PERS2P4);
455   qperwin = qperwin + 36 - (DFRACT_BITS - 1);
456 
457   switch (numLines) {
458     case 1024:
459       qperwin = qperwin - 10;
460       break;
461     case 128:
462       qperwin = qperwin - 7;
463       break;
464     case 512:
465       qperwin = qperwin - 9;
466       break;
467     case 480:
468       qperwin = qperwin - 9;
469       pePerWindow = fMult(pePerWindow, FL2FXCONST_DBL(480.f / 512.f));
470       break;
471   }
472 
473   /* for short blocks it is assumed that more bits are available */
474   if (blockType == SHORT_WINDOW) {
475     pePerWindow = fMult(pePerWindow, ONEP5);
476     qperwin = qperwin + 30 - (DFRACT_BITS - 1);
477   }
478   pePart_const = fDivNorm(pePerWindow, barcFactor, &qdiv);
479   qpeprt_const = qperwin - qbfac + DFRACT_BITS - 1 - qdiv;
480 
481   for (sfb = 0; sfb < sfbActive; sfb++) {
482     barcWidth =
483         FDKaacEnc_BarcLineValue(numLines, sfbOffset[sfb + 1], samplerate) -
484         FDKaacEnc_BarcLineValue(numLines, sfbOffset[sfb], samplerate);
485 
486     /* adapt to sfb bands */
487     pePart = fMult(pePart_const, barcWidth);
488     qpeprt = qpeprt_const + 25 - (DFRACT_BITS - 1);
489 
490     /* pe -> snr calculation */
491     sfbWidth = (sfbOffset[sfb + 1] - sfbOffset[sfb]);
492     pePart = fDivNorm(pePart, sfbWidth, &qdiv);
493     qpeprt += DFRACT_BITS - 1 - qdiv;
494 
495     tmp = f2Pow(pePart, DFRACT_BITS - 1 - qpeprt, &qtmp);
496     qtmp = DFRACT_BITS - 1 - qtmp;
497 
498     /* Subtract 1.5 */
499     qsnr = fixMin(qtmp, 30);
500     tmp = tmp >> (qtmp - qsnr);
501 
502     if ((30 + 1 - qsnr) > (DFRACT_BITS - 1))
503       one_point5 = (FIXP_DBL)0;
504     else
505       one_point5 = (FIXP_DBL)(ONEP5 >> (30 + 1 - qsnr));
506 
507     snr = (tmp >> 1) - (one_point5);
508     qsnr -= 1;
509 
510     /* max(snr, 1.0) */
511     if (qsnr > 0)
512       one_qsnr = (FIXP_DBL)(1 << qsnr);
513     else
514       one_qsnr = (FIXP_DBL)0;
515 
516     snr = fixMax(one_qsnr, snr);
517 
518     /* 1/snr */
519     snr = fDivNorm(one_qsnr, snr, &qsnr);
520     qsnr = DFRACT_BITS - 1 - qsnr;
521     snr = (qsnr > 30) ? (snr >> (qsnr - 30)) : snr;
522 
523     /* upper limit is -1 dB */
524     snr = (snr > MAX_SNR) ? MAX_SNR : snr;
525 
526     /* lower limit is -25 dB */
527     snr = (snr < MIN_SNR) ? MIN_SNR : snr;
528     snr = snr << 1;
529 
530     sfbMinSnrLdData[sfb] = CalcLdData(snr);
531   }
532 }
533 
FDKaacEnc_InitPsyConfiguration(INT bitrate,INT samplerate,INT bandwidth,INT blocktype,INT granuleLength,INT useIS,INT useMS,PSY_CONFIGURATION * psyConf,FB_TYPE filterbank)534 AAC_ENCODER_ERROR FDKaacEnc_InitPsyConfiguration(INT bitrate, INT samplerate,
535                                                  INT bandwidth, INT blocktype,
536                                                  INT granuleLength, INT useIS,
537                                                  INT useMS,
538                                                  PSY_CONFIGURATION *psyConf,
539                                                  FB_TYPE filterbank) {
540   AAC_ENCODER_ERROR ErrorStatus;
541   INT sfb;
542   FIXP_DBL sfbBarcVal[MAX_SFB];
543   const INT frameLengthLong = granuleLength;
544   const INT frameLengthShort = granuleLength / TRANS_FAC;
545   INT downscaleFactor = 1;
546 
547   switch (granuleLength) {
548     case 256:
549     case 240:
550       downscaleFactor = 2;
551       break;
552     case 128:
553     case 120:
554       downscaleFactor = 4;
555       break;
556     default:
557       downscaleFactor = 1;
558       break;
559   }
560 
561   FDKmemclear(psyConf, sizeof(PSY_CONFIGURATION));
562   psyConf->granuleLength = granuleLength;
563   psyConf->filterbank = filterbank;
564 
565   psyConf->allowIS = (useIS) && ((bitrate / bandwidth) < 5);
566   psyConf->allowMS = useMS;
567 
568   /* init sfb table */
569   ErrorStatus = FDKaacEnc_initSfbTable(samplerate * downscaleFactor, blocktype,
570                                        granuleLength * downscaleFactor,
571                                        psyConf->sfbOffset, &psyConf->sfbCnt);
572 
573   if (ErrorStatus != AAC_ENC_OK) return ErrorStatus;
574 
575   /* calculate barc values for each pb */
576   FDKaacEnc_initBarcValues(psyConf->sfbCnt, psyConf->sfbOffset,
577                            psyConf->sfbOffset[psyConf->sfbCnt], samplerate,
578                            sfbBarcVal);
579 
580   FDKaacEnc_InitMinPCMResolution(psyConf->sfbCnt, psyConf->sfbOffset,
581                                  psyConf->sfbPcmQuantThreshold);
582 
583   /* calculate spreading function */
584   FDKaacEnc_initSpreading(psyConf->sfbCnt, sfbBarcVal,
585                           psyConf->sfbMaskLowFactor, psyConf->sfbMaskHighFactor,
586                           psyConf->sfbMaskLowFactorSprEn,
587                           psyConf->sfbMaskHighFactorSprEn, bitrate, blocktype);
588 
589   /* init ratio */
590 
591   psyConf->maxAllowedIncreaseFactor = 2; /* integer */
592   psyConf->minRemainingThresholdFactor = (FIXP_SGL)0x0148;
593   /* FL2FXCONST_SGL(0.01f); */ /* fract   */
594 
595   psyConf->clipEnergy =
596       (FIXP_DBL)0x773593ff; /* FL2FXCONST_DBL(1.0e9*NORM_PCM_ENERGY); */
597 
598   if (blocktype != SHORT_WINDOW) {
599     psyConf->lowpassLine =
600         (INT)((2 * bandwidth * frameLengthLong) / samplerate);
601     psyConf->lowpassLineLFE = LFE_LOWPASS_LINE;
602   } else {
603     psyConf->lowpassLine =
604         (INT)((2 * bandwidth * frameLengthShort) / samplerate);
605     psyConf->lowpassLineLFE = 0; /* LFE only in lonf blocks */
606     /* psyConf->clipEnergy /= (TRANS_FAC * TRANS_FAC); */
607     psyConf->clipEnergy >>= 6;
608   }
609 
610   for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) {
611     if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLine) break;
612   }
613   psyConf->sfbActive = fMax(sfb, 1);
614 
615   for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) {
616     if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLineLFE) break;
617   }
618   psyConf->sfbActiveLFE = sfb;
619   psyConf->sfbActive = fMax(psyConf->sfbActive, psyConf->sfbActiveLFE);
620 
621   /* calculate minSnr */
622   FDKaacEnc_initMinSnr(bitrate, samplerate * downscaleFactor,
623                        psyConf->sfbOffset[psyConf->sfbCnt], psyConf->sfbOffset,
624                        psyConf->sfbActive, blocktype, psyConf->sfbMinSnrLdData);
625 
626   return AAC_ENC_OK;
627 }
628