Home | History | Annotate | Download | only in src
      1 
      2 /* -----------------------------------------------------------------------------------------------------------
      3 Software License for The Fraunhofer FDK AAC Codec Library for Android
      4 
      5  Copyright  1995 - 2012 Fraunhofer-Gesellschaft zur Frderung 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 (at) iis.fraunhofer.de
     82 ----------------------------------------------------------------------------------------------------------- */
     83 
     84 /*****************************  MPEG Audio Encoder  ***************************
     85 
     86    Initial Authors:      M. Multrus
     87    Contents/Description: PS Wrapper, Downmix
     88 
     89 ******************************************************************************/
     90 
     91 #include "ps_main.h"
     92 
     93 
     94 /* Includes ******************************************************************/
     95 
     96 #include "ps_const.h"
     97 #include "ps_bitenc.h"
     98 
     99 #include "sbr_ram.h"
    100 
    101 /*--------------- function declarations --------------------*/
    102 static void psFindBestScaling(
    103         HANDLE_PARAMETRIC_STEREO  hParametricStereo,
    104         FIXP_DBL                 *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2],
    105         UCHAR                    *dynBandScale,
    106         FIXP_QMF                 *maxBandValue,
    107         SCHAR                    *dmxScale
    108         );
    109 
    110 /*------------- function definitions ----------------*/
    111 FDK_PSENC_ERROR PSEnc_Create(
    112         HANDLE_PARAMETRIC_STEREO *phParametricStereo
    113         )
    114 {
    115   FDK_PSENC_ERROR error = PSENC_OK;
    116 
    117   if (phParametricStereo==NULL) {
    118     error = PSENC_INVALID_HANDLE;
    119   }
    120   else {
    121     int i;
    122     HANDLE_PARAMETRIC_STEREO hParametricStereo = NULL;
    123 
    124     if (NULL==(hParametricStereo = GetRam_ParamStereo())) {
    125       error = PSENC_MEMORY_ERROR;
    126       goto bail;
    127     }
    128     FDKmemclear(hParametricStereo, sizeof(PARAMETRIC_STEREO));
    129 
    130     if (PSENC_OK != (error = FDKsbrEnc_CreatePSEncode(&hParametricStereo->hPsEncode))) {
    131       goto bail;
    132     }
    133 
    134     for (i=0; i<MAX_PS_CHANNELS; i++) {
    135       if (FDKhybridAnalysisOpen(
    136             &hParametricStereo->fdkHybAnaFilter[i],
    137              hParametricStereo->__staticHybAnaStatesLF[i],
    138              sizeof(hParametricStereo->__staticHybAnaStatesLF[i]),
    139              hParametricStereo->__staticHybAnaStatesHF[i],
    140              sizeof(hParametricStereo->__staticHybAnaStatesHF[i])
    141              ) !=0 )
    142       {
    143         error = PSENC_MEMORY_ERROR;
    144         goto bail;
    145       }
    146     }
    147 
    148     *phParametricStereo = hParametricStereo; /* return allocated handle */
    149   }
    150 bail:
    151   return error;
    152 }
    153 
    154 FDK_PSENC_ERROR PSEnc_Init(
    155         HANDLE_PARAMETRIC_STEREO  hParametricStereo,
    156         const HANDLE_PSENC_CONFIG hPsEncConfig,
    157         INT                       noQmfSlots,
    158         INT                       noQmfBands
    159        ,UCHAR                    *dynamic_RAM
    160         )
    161 {
    162   FDK_PSENC_ERROR error = PSENC_OK;
    163 
    164   if ( (NULL==hParametricStereo) || (NULL==hPsEncConfig) ) {
    165     error = PSENC_INVALID_HANDLE;
    166   }
    167   else {
    168     int ch, i;
    169 
    170     hParametricStereo->initPS = 1;
    171     hParametricStereo->noQmfSlots = noQmfSlots;
    172     hParametricStereo->noQmfBands = noQmfBands;
    173 
    174     /* clear delay lines */
    175     FDKmemclear(hParametricStereo->qmfDelayLines, sizeof(hParametricStereo->qmfDelayLines));
    176 
    177     hParametricStereo->qmfDelayScale = FRACT_BITS-1;
    178 
    179     /* create configuration for hybrid filter bank */
    180     for (ch=0; ch<MAX_PS_CHANNELS; ch++) {
    181       FDKhybridAnalysisInit(
    182             &hParametricStereo->fdkHybAnaFilter[ch],
    183              THREE_TO_TEN,
    184              QMF_CHANNELS,
    185              QMF_CHANNELS,
    186              1
    187              );
    188     } /* ch */
    189 
    190     FDKhybridSynthesisInit(
    191           &hParametricStereo->fdkHybSynFilter,
    192            THREE_TO_TEN,
    193            QMF_CHANNELS,
    194            QMF_CHANNELS
    195            );
    196 
    197     /* determine average delay */
    198     hParametricStereo->psDelay = (HYBRID_FILTER_DELAY*hParametricStereo->noQmfBands);
    199 
    200     if ( (hPsEncConfig->maxEnvelopes < PSENC_NENV_1) || (hPsEncConfig->maxEnvelopes > PSENC_NENV_MAX) ) {
    201       hPsEncConfig->maxEnvelopes = PSENC_NENV_DEFAULT;
    202     }
    203     hParametricStereo->maxEnvelopes = hPsEncConfig->maxEnvelopes;
    204 
    205     if (PSENC_OK != (error = FDKsbrEnc_InitPSEncode(hParametricStereo->hPsEncode, (PS_BANDS) hPsEncConfig->nStereoBands, hPsEncConfig->iidQuantErrorThreshold))){
    206       goto bail;
    207     }
    208 
    209     for (ch = 0; ch<MAX_PS_CHANNELS; ch ++) {
    210       FIXP_DBL *pDynReal = GetRam_Sbr_envRBuffer (ch, dynamic_RAM);
    211       FIXP_DBL *pDynImag = GetRam_Sbr_envIBuffer (ch, dynamic_RAM);
    212 
    213       for (i=0; i<HYBRID_FRAMESIZE; i++) {
    214         hParametricStereo->pHybridData[i+HYBRID_READ_OFFSET][ch][0] = &pDynReal[i*MAX_HYBRID_BANDS];
    215         hParametricStereo->pHybridData[i+HYBRID_READ_OFFSET][ch][1] = &pDynImag[i*MAX_HYBRID_BANDS];;
    216       }
    217 
    218       for (i=0; i<HYBRID_READ_OFFSET; i++) {
    219         hParametricStereo->pHybridData[i][ch][0] = hParametricStereo->__staticHybridData[i][ch][0];
    220         hParametricStereo->pHybridData[i][ch][1] = hParametricStereo->__staticHybridData[i][ch][1];
    221       }
    222     } /* ch */
    223 
    224     /* clear static hybrid buffer */
    225     FDKmemclear(hParametricStereo->__staticHybridData, sizeof(hParametricStereo->__staticHybridData));
    226 
    227     /* clear bs buffer */
    228     FDKmemclear(hParametricStereo->psOut, sizeof(hParametricStereo->psOut));
    229 
    230     /* clear scaling buffer */
    231     FDKmemclear(hParametricStereo->dynBandScale, sizeof(UCHAR)*PS_MAX_BANDS);
    232     FDKmemclear(hParametricStereo->maxBandValue, sizeof(FIXP_QMF)*PS_MAX_BANDS);
    233 
    234   } /* valid handle */
    235 bail:
    236   return error;
    237 }
    238 
    239 
    240 FDK_PSENC_ERROR PSEnc_Destroy(
    241         HANDLE_PARAMETRIC_STEREO *phParametricStereo
    242         )
    243 {
    244   FDK_PSENC_ERROR error = PSENC_OK;
    245 
    246   if (NULL!=phParametricStereo) {
    247     HANDLE_PARAMETRIC_STEREO hParametricStereo = *phParametricStereo;
    248     if(hParametricStereo != NULL){
    249       FDKsbrEnc_DestroyPSEncode(&hParametricStereo->hPsEncode);
    250       FreeRam_ParamStereo(phParametricStereo);
    251     }
    252   }
    253 
    254   return error;
    255 }
    256 
    257 static FDK_PSENC_ERROR ExtractPSParameters(
    258         HANDLE_PARAMETRIC_STEREO  hParametricStereo,
    259         const int                 sendHeader,
    260         FIXP_DBL                 *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2]
    261         )
    262 {
    263   FDK_PSENC_ERROR error = PSENC_OK;
    264 
    265   if (hParametricStereo == NULL) {
    266     error = PSENC_INVALID_HANDLE;
    267   }
    268   else {
    269     /* call ps encode function */
    270     if (hParametricStereo->initPS){
    271       hParametricStereo->psOut[1] = hParametricStereo->psOut[0];
    272     }
    273     hParametricStereo->psOut[0] = hParametricStereo->psOut[1];
    274 
    275     if (PSENC_OK != (error = FDKsbrEnc_PSEncode(
    276             hParametricStereo->hPsEncode,
    277            &hParametricStereo->psOut[1],
    278             hParametricStereo->dynBandScale,
    279             hParametricStereo->maxEnvelopes,
    280             hybridData,
    281             hParametricStereo->noQmfSlots,
    282             sendHeader)))
    283     {
    284       goto bail;
    285     }
    286 
    287     if (hParametricStereo->initPS) {
    288       hParametricStereo->psOut[0] = hParametricStereo->psOut[1];
    289       hParametricStereo->initPS = 0;
    290     }
    291   }
    292 bail:
    293   return error;
    294 }
    295 
    296 
    297 static FDK_PSENC_ERROR DownmixPSQmfData(
    298        HANDLE_PARAMETRIC_STEREO  hParametricStereo,
    299        HANDLE_QMF_FILTER_BANK    sbrSynthQmf,
    300        FIXP_QMF       **RESTRICT mixRealQmfData,
    301        FIXP_QMF       **RESTRICT mixImagQmfData,
    302        INT_PCM                  *downsampledOutSignal,
    303        FIXP_DBL                 *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2],
    304        const INT                 noQmfSlots,
    305        const INT                 psQmfScale[MAX_PS_CHANNELS],
    306        SCHAR                    *qmfScale
    307        )
    308 {
    309   FDK_PSENC_ERROR error = PSENC_OK;
    310 
    311   if(hParametricStereo == NULL){
    312     error = PSENC_INVALID_HANDLE;
    313   }
    314   else {
    315     int n, k;
    316     C_ALLOC_SCRATCH_START(pWorkBuffer, FIXP_QMF, QMF_CHANNELS*2);
    317 
    318     /* define scalings */
    319     int dynQmfScale = fixMax(0, hParametricStereo->dmxScale-1); /* scale one bit more for addition of left and right */
    320     int downmixScale = psQmfScale[0] - dynQmfScale;
    321     const FIXP_DBL maxStereoScaleFactor = MAXVAL_DBL; /* 2.f/2.f */
    322 
    323     for (n = 0; n<noQmfSlots; n++) {
    324 
    325       FIXP_DBL tmpHybrid[2][MAX_HYBRID_BANDS];
    326 
    327       for(k = 0; k<71; k++){
    328           int dynScale, sc; /* scaling */
    329           FIXP_QMF tmpLeftReal, tmpRightReal, tmpLeftImag, tmpRightImag;
    330           FIXP_DBL tmpScaleFactor, stereoScaleFactor;
    331 
    332           tmpLeftReal  = hybridData[n][0][0][k];
    333           tmpLeftImag  = hybridData[n][0][1][k];
    334           tmpRightReal = hybridData[n][1][0][k];
    335           tmpRightImag = hybridData[n][1][1][k];
    336 
    337           sc = fixMax(0,CntLeadingZeros( fixMax(fixMax(fixp_abs(tmpLeftReal),fixp_abs(tmpLeftImag)),fixMax(fixp_abs(tmpRightReal),fixp_abs(tmpRightImag))) )-2);
    338 
    339           tmpLeftReal  <<= sc; tmpLeftImag  <<= sc;
    340           tmpRightReal <<= sc; tmpRightImag <<= sc;
    341           dynScale = fixMin(sc-dynQmfScale,DFRACT_BITS-1);
    342 
    343           /* calc stereo scale factor to avoid loss of energy in bands                                                 */
    344           /* stereo scale factor = min(2.0f, sqrt( (abs(l(k, n)^2 + abs(r(k, n)^2 )))/(0.5f*abs(l(k, n) + r(k, n))) )) */
    345           stereoScaleFactor = fPow2Div2(tmpLeftReal)  + fPow2Div2(tmpLeftImag)
    346                             + fPow2Div2(tmpRightReal) + fPow2Div2(tmpRightImag) ;
    347 
    348           /* might be that tmpScaleFactor becomes negative, so fabs(.) */
    349           tmpScaleFactor    = fixp_abs(stereoScaleFactor + fMult(tmpLeftReal,tmpRightReal) + fMult(tmpLeftImag,tmpRightImag));
    350 
    351           /* min(2.0f, sqrt(stereoScaleFactor/(0.5f*tmpScaleFactor)))  */
    352           if ( (stereoScaleFactor>>1) < fMult(maxStereoScaleFactor,tmpScaleFactor) ) {
    353 
    354               int sc_num   = CountLeadingBits(stereoScaleFactor) ;
    355               int sc_denum = CountLeadingBits(tmpScaleFactor) ;
    356               sc       = -(sc_num-sc_denum);
    357 
    358               tmpScaleFactor = schur_div((stereoScaleFactor<<(sc_num))>>1,
    359                                           tmpScaleFactor<<sc_denum,
    360                                           16) ;
    361 
    362               /* prevent odd scaling for next sqrt calculation */
    363               if (sc&0x1) {
    364                 sc++;
    365                 tmpScaleFactor>>=1;
    366               }
    367               stereoScaleFactor = sqrtFixp(tmpScaleFactor);
    368               stereoScaleFactor <<= (sc>>1);
    369           }
    370           else {
    371               stereoScaleFactor = maxStereoScaleFactor;
    372           }
    373 
    374           /* write data to hybrid output */
    375           tmpHybrid[0][k] = fMultDiv2(stereoScaleFactor, (FIXP_QMF)(tmpLeftReal + tmpRightReal))>>dynScale;
    376           tmpHybrid[1][k] = fMultDiv2(stereoScaleFactor, (FIXP_QMF)(tmpLeftImag + tmpRightImag))>>dynScale;
    377 
    378       } /* hybrid bands - k */
    379 
    380       FDKhybridSynthesisApply(
    381             &hParametricStereo->fdkHybSynFilter,
    382              tmpHybrid[0],
    383              tmpHybrid[1],
    384              mixRealQmfData[n],
    385              mixImagQmfData[n]);
    386 
    387       qmfSynthesisFilteringSlot(
    388             sbrSynthQmf,
    389             mixRealQmfData[n],
    390             mixImagQmfData[n],
    391             downmixScale-7,
    392             downmixScale-7,
    393             downsampledOutSignal+(n*sbrSynthQmf->no_channels),
    394             1,
    395             pWorkBuffer);
    396 
    397     } /* slots */
    398 
    399     *qmfScale = -downmixScale + 7;
    400 
    401     C_ALLOC_SCRATCH_END(pWorkBuffer, FIXP_QMF, QMF_CHANNELS*2);
    402 
    403 
    404   {
    405     const INT noQmfSlots2 = hParametricStereo->noQmfSlots>>1;
    406     const int noQmfBands  = hParametricStereo->noQmfBands;
    407 
    408     INT scale, i, j, slotOffset;
    409 
    410     FIXP_QMF tmp[2][QMF_CHANNELS];
    411 
    412     for (i=0; i<noQmfSlots2; i++) {
    413       FDKmemcpy(tmp[0], hParametricStereo->qmfDelayLines[0][i], noQmfBands*sizeof(FIXP_QMF));
    414       FDKmemcpy(tmp[1], hParametricStereo->qmfDelayLines[1][i], noQmfBands*sizeof(FIXP_QMF));
    415 
    416       FDKmemcpy(hParametricStereo->qmfDelayLines[0][i], mixRealQmfData[i+noQmfSlots2], noQmfBands*sizeof(FIXP_QMF));
    417       FDKmemcpy(hParametricStereo->qmfDelayLines[1][i], mixImagQmfData[i+noQmfSlots2], noQmfBands*sizeof(FIXP_QMF));
    418 
    419       FDKmemcpy(mixRealQmfData[i+noQmfSlots2], mixRealQmfData[i], noQmfBands*sizeof(FIXP_QMF));
    420       FDKmemcpy(mixImagQmfData[i+noQmfSlots2], mixImagQmfData[i], noQmfBands*sizeof(FIXP_QMF));
    421 
    422       FDKmemcpy(mixRealQmfData[i], tmp[0], noQmfBands*sizeof(FIXP_QMF));
    423       FDKmemcpy(mixImagQmfData[i], tmp[1], noQmfBands*sizeof(FIXP_QMF));
    424     }
    425 
    426     if (hParametricStereo->qmfDelayScale > *qmfScale) {
    427       scale = hParametricStereo->qmfDelayScale - *qmfScale;
    428       slotOffset = 0;
    429     }
    430     else {
    431       scale = *qmfScale - hParametricStereo->qmfDelayScale;
    432       slotOffset = noQmfSlots2;
    433     }
    434 
    435     for (i=0; i<noQmfSlots2; i++) {
    436       for (j=0; j<noQmfBands; j++) {
    437         mixRealQmfData[i+slotOffset][j] >>= scale;
    438         mixImagQmfData[i+slotOffset][j] >>= scale;
    439       }
    440     }
    441 
    442     scale = *qmfScale;
    443     *qmfScale = FDKmin(*qmfScale, hParametricStereo->qmfDelayScale);
    444     hParametricStereo->qmfDelayScale = scale;
    445   }
    446 
    447   } /* valid handle */
    448 
    449   return error;
    450 }
    451 
    452 
    453 INT FDKsbrEnc_PSEnc_WritePSData(
    454         HANDLE_PARAMETRIC_STEREO  hParametricStereo,
    455         HANDLE_FDK_BITSTREAM      hBitstream
    456         )
    457 {
    458   return ( (hParametricStereo!=NULL) ? FDKsbrEnc_WritePSBitstream(&hParametricStereo->psOut[0], hBitstream) : 0 );
    459 }
    460 
    461 
    462 FDK_PSENC_ERROR FDKsbrEnc_PSEnc_ParametricStereoProcessing(
    463         HANDLE_PARAMETRIC_STEREO  hParametricStereo,
    464         INT_PCM                  *samples[2],
    465         UINT                      timeInStride,
    466         QMF_FILTER_BANK         **hQmfAnalysis,
    467         FIXP_QMF **RESTRICT       downmixedRealQmfData,
    468         FIXP_QMF **RESTRICT       downmixedImagQmfData,
    469         INT_PCM                  *downsampledOutSignal,
    470         HANDLE_QMF_FILTER_BANK    sbrSynthQmf,
    471         SCHAR                    *qmfScale,
    472         const int                 sendHeader
    473         )
    474 {
    475   FDK_PSENC_ERROR error = PSENC_OK;
    476   INT noQmfBands  = hParametricStereo->noQmfBands;
    477   INT psQmfScale[MAX_PS_CHANNELS] = {0};
    478   int psCh, i;
    479   C_ALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, QMF_CHANNELS*4);
    480 
    481   for (psCh = 0; psCh<MAX_PS_CHANNELS; psCh ++) {
    482 
    483     for (i = 0; i < hQmfAnalysis[psCh]->no_col; i++) {
    484 
    485       qmfAnalysisFilteringSlot(
    486           hQmfAnalysis[psCh],
    487          &pWorkBuffer[2*QMF_CHANNELS], /* qmfReal[QMF_CHANNELS] */
    488          &pWorkBuffer[3*QMF_CHANNELS], /* qmfImag[QMF_CHANNELS] */
    489           samples[psCh]+i*(hQmfAnalysis[psCh]->no_channels*timeInStride),
    490           timeInStride,
    491          &pWorkBuffer[0*QMF_CHANNELS]  /* qmf workbuffer 2*QMF_CHANNELS */
    492           );
    493 
    494       FDKhybridAnalysisApply(
    495          &hParametricStereo->fdkHybAnaFilter[psCh],
    496          &pWorkBuffer[2*QMF_CHANNELS],  /* qmfReal[QMF_CHANNELS] */
    497          &pWorkBuffer[3*QMF_CHANNELS],  /* qmfImag[QMF_CHANNELS] */
    498           hParametricStereo->pHybridData[i+HYBRID_READ_OFFSET][psCh][0],
    499           hParametricStereo->pHybridData[i+HYBRID_READ_OFFSET][psCh][1]
    500           );
    501 
    502     } /* no_col loop  i  */
    503 
    504     psQmfScale[psCh] = hQmfAnalysis[psCh]->outScalefactor;
    505 
    506   } /* for psCh */
    507 
    508   C_ALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, QMF_CHANNELS*4);
    509 
    510   /* find best scaling in new QMF and Hybrid data */
    511   psFindBestScaling( hParametricStereo,
    512                     &hParametricStereo->pHybridData[HYBRID_READ_OFFSET],
    513                      hParametricStereo->dynBandScale,
    514                      hParametricStereo->maxBandValue,
    515                     &hParametricStereo->dmxScale ) ;
    516 
    517 
    518   /* extract the ps parameters */
    519   if(PSENC_OK != (error = ExtractPSParameters(hParametricStereo, sendHeader, &hParametricStereo->pHybridData[0]))){
    520     goto bail;
    521   }
    522 
    523   /* save hybrid date for next frame */
    524   for (i=0; i<HYBRID_READ_OFFSET; i++) {
    525     FDKmemcpy(hParametricStereo->pHybridData[i][0][0], hParametricStereo->pHybridData[HYBRID_FRAMESIZE+i][0][0], MAX_HYBRID_BANDS*sizeof(FIXP_DBL)); /* left, real */
    526     FDKmemcpy(hParametricStereo->pHybridData[i][0][1], hParametricStereo->pHybridData[HYBRID_FRAMESIZE+i][0][1], MAX_HYBRID_BANDS*sizeof(FIXP_DBL)); /* left, imag */
    527     FDKmemcpy(hParametricStereo->pHybridData[i][1][0], hParametricStereo->pHybridData[HYBRID_FRAMESIZE+i][1][0], MAX_HYBRID_BANDS*sizeof(FIXP_DBL)); /* right, real */
    528     FDKmemcpy(hParametricStereo->pHybridData[i][1][1], hParametricStereo->pHybridData[HYBRID_FRAMESIZE+i][1][1], MAX_HYBRID_BANDS*sizeof(FIXP_DBL)); /* right, imag */
    529   }
    530 
    531   /* downmix and hybrid synthesis */
    532   if (PSENC_OK != (error = DownmixPSQmfData(hParametricStereo, sbrSynthQmf, downmixedRealQmfData, downmixedImagQmfData, downsampledOutSignal, &hParametricStereo->pHybridData[HYBRID_READ_OFFSET], hParametricStereo->noQmfSlots, psQmfScale, qmfScale))) {
    533     goto bail;
    534   }
    535 
    536 bail:
    537 
    538   return error;
    539 }
    540 
    541 static void psFindBestScaling(
    542         HANDLE_PARAMETRIC_STEREO  hParametricStereo,
    543         FIXP_DBL                 *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2],
    544         UCHAR                    *dynBandScale,
    545         FIXP_QMF                 *maxBandValue,
    546         SCHAR                    *dmxScale
    547         )
    548 {
    549   HANDLE_PS_ENCODE hPsEncode      =  hParametricStereo->hPsEncode;
    550 
    551   INT group, bin, col, band;
    552   const INT frameSize  = hParametricStereo->noQmfSlots;
    553   const INT psBands    = (INT) hPsEncode->psEncMode;
    554   const INT nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups;
    555 
    556   /* group wise scaling */
    557   FIXP_QMF maxVal [2][PS_MAX_BANDS];
    558   FIXP_QMF maxValue = FL2FXCONST_DBL(0.f);
    559 
    560   FDKmemclear(maxVal, sizeof(maxVal));
    561 
    562   /* start with hybrid data */
    563   for (group=0; group < nIidGroups; group++) {
    564     /* Translate group to bin */
    565     bin = hPsEncode->subband2parameterIndex[group];
    566 
    567     /* Translate from 20 bins to 10 bins */
    568     if (hPsEncode->psEncMode == PS_BANDS_COARSE) {
    569       bin >>= 1;
    570     }
    571 
    572     /* QMF downmix scaling */
    573     {
    574       FIXP_QMF tmp = maxVal[0][bin];
    575       int i;
    576       for (col=0; col<frameSize-HYBRID_READ_OFFSET; col++) {
    577         for (i = hPsEncode->iidGroupBorders[group]; i < hPsEncode->iidGroupBorders[group+1]; i++) {
    578           tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][0][0][i]));
    579           tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][0][1][i]));
    580           tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][1][0][i]));
    581           tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][1][1][i]));
    582         }
    583       }
    584       maxVal[0][bin] = tmp;
    585 
    586       tmp = maxVal[1][bin];
    587       for (col=frameSize-HYBRID_READ_OFFSET; col<frameSize; col++) {
    588         for (i = hPsEncode->iidGroupBorders[group]; i < hPsEncode->iidGroupBorders[group+1]; i++) {
    589           tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][0][0][i]));
    590           tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][0][1][i]));
    591           tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][1][0][i]));
    592           tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][1][1][i]));
    593         }
    594       }
    595       maxVal[1][bin] = tmp;
    596     }
    597   } /* nIidGroups */
    598 
    599   /* convert maxSpec to maxScaling, find scaling space */
    600   for (band=0; band<psBands; band++) {
    601 #ifndef MULT_16x16
    602     dynBandScale[band] = CountLeadingBits(fixMax(maxVal[0][band],maxBandValue[band]));
    603 #else
    604     dynBandScale[band] = fixMax(0,CountLeadingBits(fixMax(maxVal[0][band],maxBandValue[band]))-FRACT_BITS);
    605 #endif
    606     maxValue = fixMax(maxValue,fixMax(maxVal[0][band],maxVal[1][band]));
    607     maxBandValue[band] = fixMax(maxVal[0][band], maxVal[1][band]);
    608   }
    609 
    610   /* calculate maximal scaling for QMF downmix */
    611 #ifndef MULT_16x16
    612   *dmxScale = fixMin(DFRACT_BITS, CountLeadingBits(maxValue));
    613 #else
    614   *dmxScale = fixMax(0,fixMin(FRACT_BITS, CountLeadingBits(FX_QMF2FX_DBL(maxValue))));
    615 #endif
    616 
    617 }
    618 
    619