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