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 - 2013 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 #include "tran_det.h"
     85 
     86 #include "fram_gen.h"
     87 #include "sbr_ram.h"
     88 #include "sbr_misc.h"
     89 
     90 #include "genericStds.h"
     91 
     92 #define NORM_QMF_ENERGY 5.684341886080801486968994140625e-14 /* 2^-44 */
     93 
     94 /* static FIXP_DBL ABS_THRES = fixMax( FL2FXCONST_DBL(1.28e5 *  NORM_QMF_ENERGY), (FIXP_DBL)1)  Minimum threshold for detecting changes */
     95 #define ABS_THRES ((FIXP_DBL)16)
     96 
     97 /*******************************************************************************
     98  Functionname:  spectralChange
     99  *******************************************************************************
    100  \brief   Calculates a measure for the spectral change within the frame
    101 
    102  The function says how good it would be to split the frame at the given border
    103  position into 2 envelopes.
    104 
    105  The return value delta_sum is scaled with the factor 1/64
    106 
    107  \return  calculated value
    108 *******************************************************************************/
    109 static FIXP_DBL spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS],
    110                                INT *scaleEnergies,
    111                                FIXP_DBL EnergyTotal,
    112                                INT nSfb,
    113                                INT start,
    114                                INT border,
    115                                INT stop)
    116 {
    117   INT i,j;
    118   INT len1,len2;
    119   FIXP_DBL delta,tmp0,tmp1,tmp2;
    120   FIXP_DBL accu1,accu2,delta_sum,result;
    121 
    122   FDK_ASSERT(scaleEnergies[0] >= 0);
    123 
    124   /* equal for aac (would be not equal for mp3) */
    125   len1 = border-start;
    126   len2 = stop-border;
    127 
    128   /* prefer borders near the middle of the frame */
    129   FIXP_DBL   pos_weight;
    130   pos_weight = FL2FXCONST_DBL(0.5f) - (len1*GetInvInt(len1+len2));
    131   pos_weight = /*FL2FXCONST_DBL(1.0)*/ (FIXP_DBL)MAXVAL_DBL - (fMult(pos_weight, pos_weight)<<2);
    132 
    133   delta_sum = FL2FXCONST_DBL(0.0f);
    134 
    135   /* Sum up energies of all QMF-timeslots for both halfs */
    136   for (j=0; j<nSfb; j++) {
    137     #define NRG_SCALE  3
    138     /* init with some energy to prevent division by zero
    139        and to prevent splitting for very low levels */
    140     accu1 = ((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY*8.0/32))) << fixMin(scaleEnergies[0],25))>>NRG_SCALE;  /* complex init for compare with original version */
    141     accu2 = ((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY*8.0/32))) << fixMin(scaleEnergies[0],25))>>NRG_SCALE;  /* can be simplified in dsp implementation */
    142 
    143     /* Sum up energies in first half */
    144     for (i=start; i<border; i++) {
    145       accu1 += (Energies[i][j]>>NRG_SCALE);
    146     }
    147 
    148     /* Sum up energies in second half */
    149     for (i=border; i<stop; i++) {
    150       accu2 += (Energies[i][j]>>NRG_SCALE);
    151     }
    152 
    153     /* Energy change in current band */
    154     tmp0 = CalcLdData(accu2);
    155     tmp1 = CalcLdData(accu1);
    156     tmp2 = (tmp0 - tmp1 + CalcLdData(len1)-CalcLdData(len2));
    157     delta = fixp_abs(fMult(tmp2, FL2FXCONST_DBL(0.6931471806f)));
    158 
    159     /* Weighting with amplitude ratio of this band */
    160     result = (EnergyTotal == FL2FXCONST_DBL(0.0f))
    161             ? FL2FXCONST_DBL(0.f)
    162             : FDKsbrEnc_LSI_divide_scale_fract( (accu1+accu2),
    163                                       (EnergyTotal>>NRG_SCALE)+(FIXP_DBL)1,
    164                                       (FIXP_DBL)MAXVAL_DBL >> fixMin(scaleEnergies[0],(DFRACT_BITS-1)) );
    165 
    166     delta_sum += (FIXP_DBL)(fMult(sqrtFixp(result), delta));
    167   }
    168 
    169   return fMult(delta_sum, pos_weight);
    170 }
    171 
    172 
    173 /*******************************************************************************
    174  Functionname:  addLowbandEnergies
    175  *******************************************************************************
    176  \brief   Calculates total lowband energy
    177 
    178  The return value nrgTotal is scaled by the factor (1/32.0)
    179 
    180  \return  total energy in the lowband
    181 *******************************************************************************/
    182 static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies,
    183                                    int       *scaleEnergies,
    184                                    int        YBufferWriteOffset,
    185                                    int        nrgSzShift,
    186                                    int        tran_off,
    187                                    UCHAR     *freqBandTable,
    188                                    int        slots)
    189 {
    190   FIXP_DBL nrgTotal;
    191   FIXP_DBL accu1 = FL2FXCONST_DBL(0.0f);
    192   FIXP_DBL accu2 = FL2FXCONST_DBL(0.0f);
    193   int tran_offdiv2 = tran_off>>nrgSzShift;
    194   int ts,k;
    195 
    196   /* Sum up lowband energy from one frame at offset tran_off */
    197   for (ts=tran_offdiv2; ts<YBufferWriteOffset; ts++) {
    198     for (k = 0; k < freqBandTable[0]; k++) {
    199       accu1 += Energies[ts][k] >> 6;
    200     }
    201   }
    202   for (; ts<tran_offdiv2+(slots>>nrgSzShift); ts++) {
    203     for (k = 0; k < freqBandTable[0]; k++) {
    204       accu2 += Energies[ts][k] >> 6;
    205     }
    206   }
    207 
    208   nrgTotal = ( (accu1 >> fixMin(scaleEnergies[0],(DFRACT_BITS-1)))
    209            +   (accu2 >> fixMin(scaleEnergies[1],(DFRACT_BITS-1))) ) << (2);
    210 
    211   return(nrgTotal);
    212 }
    213 
    214 
    215 /*******************************************************************************
    216  Functionname:  addHighbandEnergies
    217  *******************************************************************************
    218  \brief   Add highband energies
    219 
    220  Highband energies are mapped to an array with smaller dimension:
    221  Its time resolution is only 1 SBR-timeslot and its frequency resolution
    222  is 1 SBR-band. Therefore the data to be fed into the spectralChange
    223  function is reduced.
    224 
    225  The values EnergiesM are scaled by the factor (1/32.0) and scaleEnergies[0]
    226  The return value nrgTotal is scaled by the factor (1/32.0)
    227 
    228  \return  total energy in the highband
    229 *******************************************************************************/
    230 
    231 static FIXP_DBL addHighbandEnergies(FIXP_DBL **RESTRICT Energies, /*!< input */
    232                                     INT       *scaleEnergies,
    233                                     FIXP_DBL   EnergiesM[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS], /*!< Combined output */
    234                                     UCHAR     *RESTRICT freqBandTable,
    235                                     INT        nSfb,
    236                                     INT        sbrSlots,
    237                                     INT        timeStep)
    238 {
    239   INT i,j,k,slotIn,slotOut,scale;
    240   INT li,ui;
    241   FIXP_DBL nrgTotal;
    242   FIXP_DBL accu = FL2FXCONST_DBL(0.0f);
    243 
    244   /* Combine QMF-timeslots to SBR-timeslots,
    245      combine QMF-bands to SBR-bands,
    246      combine Left and Right channel */
    247   for (slotOut=0; slotOut<sbrSlots; slotOut++) {
    248     slotIn = 2*slotOut;
    249 
    250     for (j=0; j<nSfb; j++) {
    251       accu = FL2FXCONST_DBL(0.0f);
    252 
    253       li = freqBandTable[j];
    254       ui = freqBandTable[j + 1];
    255 
    256       for (k=li; k<ui; k++) {
    257         for (i=0; i<timeStep; i++) {
    258          accu += (Energies[(slotIn+i)>>1][k] >> 5);
    259         }
    260       }
    261       EnergiesM[slotOut][j] = accu;
    262     }
    263   }
    264 
    265   scale = fixMin(8,scaleEnergies[0]);      /* scale energies down before add up */
    266 
    267   if ((scaleEnergies[0]-1) > (DFRACT_BITS-1) )
    268     nrgTotal = FL2FXCONST_DBL(0.0f);
    269   else {
    270     /* Now add all energies */
    271     accu = FL2FXCONST_DBL(0.0f);
    272     for (slotOut=0; slotOut<sbrSlots; slotOut++) {
    273       for (j=0; j<nSfb; j++) {
    274         accu += (EnergiesM[slotOut][j] >> scale);
    275       }
    276     }
    277     nrgTotal = accu >> (scaleEnergies[0]-scale);
    278   }
    279 
    280   return(nrgTotal);
    281 }
    282 
    283 
    284 /*******************************************************************************
    285  Functionname:  FDKsbrEnc_frameSplitter
    286  *******************************************************************************
    287  \brief   Decides if a FIXFIX-frame shall be splitted into 2 envelopes
    288 
    289  If no transient has been detected before, the frame can still be splitted
    290  into 2 envelopes.
    291 *******************************************************************************/
    292 void
    293 FDKsbrEnc_frameSplitter(FIXP_DBL **Energies,
    294                         INT *scaleEnergies,
    295                         HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
    296                         UCHAR *freqBandTable,
    297                         UCHAR *tran_vector,
    298                         int YBufferWriteOffset,
    299                         int YBufferSzShift,
    300                         int nSfb,
    301                         int timeStep,
    302                         int no_cols)
    303 {
    304   if (tran_vector[1]==0) /* no transient was detected */
    305   {
    306     FIXP_DBL delta;
    307     FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS];
    308     FIXP_DBL EnergyTotal,newLowbandEnergy,newHighbandEnergy;
    309     INT border;
    310     INT sbrSlots = fMultI(GetInvInt(timeStep),no_cols);
    311 
    312     FDK_ASSERT( sbrSlots * timeStep == no_cols );
    313 
    314     /*
    315       Get Lowband-energy over a range of 2 frames (Look half a frame back and ahead).
    316     */
    317     newLowbandEnergy = addLowbandEnergies(Energies,
    318                                           scaleEnergies,
    319                                           YBufferWriteOffset,
    320                                           YBufferSzShift,
    321                                           h_sbrTransientDetector->tran_off,
    322                                           freqBandTable,
    323                                           no_cols);
    324 
    325     newHighbandEnergy = addHighbandEnergies(Energies,
    326                                             scaleEnergies,
    327                                             EnergiesM,
    328                                             freqBandTable,
    329                                             nSfb,
    330                                             sbrSlots,
    331                                             timeStep);
    332 
    333     if ( h_sbrTransientDetector->frameShift != 0 ) {
    334       if (tran_vector[1]==0)
    335         tran_vector[0] = 0;
    336     } else
    337     {
    338       /* prevLowBandEnergy: Corresponds to 1 frame, starting with half a frame look-behind
    339          newLowbandEnergy:  Corresponds to 1 frame, starting in the middle of the current frame */
    340       EnergyTotal = (newLowbandEnergy + h_sbrTransientDetector->prevLowBandEnergy) >> 1;
    341       EnergyTotal += newHighbandEnergy;
    342       /* The below border should specify the same position as the middle border
    343          of a FIXFIX-frame with 2 envelopes. */
    344       border = (sbrSlots+1) >> 1;
    345 
    346       delta = spectralChange(EnergiesM,
    347                              scaleEnergies,
    348                              EnergyTotal,
    349                              nSfb,
    350                              0,
    351                              border,
    352                              sbrSlots);
    353 
    354       if (delta > (h_sbrTransientDetector->split_thr >> LD_DATA_SHIFT)) /* delta scaled by 1/64 */
    355         tran_vector[0] = 1; /* Set flag for splitting */
    356       else
    357         tran_vector[0] = 0;
    358     }
    359 
    360     /* Update prevLowBandEnergy */
    361     h_sbrTransientDetector->prevLowBandEnergy = newLowbandEnergy;
    362     h_sbrTransientDetector->prevHighBandEnergy = newHighbandEnergy;
    363   }
    364 }
    365 
    366 /*
    367  * Calculate transient energy threshold for each QMF band
    368  */
    369 static void
    370 calculateThresholds(FIXP_DBL **RESTRICT Energies,
    371                     INT       *RESTRICT scaleEnergies,
    372                     FIXP_DBL  *RESTRICT thresholds,
    373                     int        YBufferWriteOffset,
    374                     int        YBufferSzShift,
    375                     int        noCols,
    376                     int        noRows,
    377                     int        tran_off)
    378 {
    379   FIXP_DBL mean_val,std_val,temp;
    380   FIXP_DBL i_noCols;
    381   FIXP_DBL i_noCols1;
    382   FIXP_DBL accu,accu0,accu1;
    383   int scaleFactor0,scaleFactor1,commonScale;
    384   int i,j;
    385 
    386   i_noCols  = GetInvInt(noCols + tran_off ) << YBufferSzShift;
    387   i_noCols1 = GetInvInt(noCols + tran_off - 1) << YBufferSzShift;
    388 
    389   /* calc minimum scale of energies of previous and current frame */
    390   commonScale = fixMin(scaleEnergies[0],scaleEnergies[1]);
    391 
    392   /* calc scalefactors to adapt energies to common scale */
    393   scaleFactor0 = fixMin((scaleEnergies[0]-commonScale), (DFRACT_BITS-1));
    394   scaleFactor1 = fixMin((scaleEnergies[1]-commonScale), (DFRACT_BITS-1));
    395 
    396   FDK_ASSERT((scaleFactor0 >= 0) && (scaleFactor1 >= 0));
    397 
    398   /* calculate standard deviation in every subband */
    399   for (i=0; i<noRows; i++)
    400   {
    401     int startEnergy = (tran_off>>YBufferSzShift);
    402     int endEnergy = ((noCols>>YBufferSzShift)+tran_off);
    403     int shift;
    404 
    405     /* calculate mean value over decimated energy values (downsampled by 2). */
    406     accu0 = accu1 = FL2FXCONST_DBL(0.0f);
    407 
    408     for (j=startEnergy; j<YBufferWriteOffset; j++)
    409       accu0 += fMult(Energies[j][i], i_noCols);
    410     for (; j<endEnergy; j++)
    411       accu1 += fMult(Energies[j][i], i_noCols);
    412 
    413     mean_val = (accu0 >> scaleFactor0) + (accu1 >> scaleFactor1);  /* average */
    414     shift    = fixMax(0,CountLeadingBits(mean_val)-6);             /* -6 to keep room for accumulating upto N = 24 values */
    415 
    416     /* calculate standard deviation */
    417     accu = FL2FXCONST_DBL(0.0f);
    418 
    419     /* summe { ((mean_val-nrg)^2) * i_noCols1 } */
    420     for (j=startEnergy; j<YBufferWriteOffset; j++) {
    421       temp = ((FIXP_DBL)mean_val - ((FIXP_DBL)Energies[j][i] >> scaleFactor0))<<shift;
    422       temp = fPow2(temp);
    423       temp = fMult(temp, i_noCols1);
    424       accu += temp;
    425     }
    426     for (; j<endEnergy; j++) {
    427       temp = ((FIXP_DBL)mean_val - ((FIXP_DBL)Energies[j][i] >> scaleFactor1))<<shift;
    428       temp = fPow2(temp);
    429       temp = fMult(temp, i_noCols1);
    430       accu += temp;
    431     }
    432 
    433     std_val = sqrtFixp(accu)>>shift;     /* standard deviation */
    434 
    435     /*
    436     Take new threshold as average of calculated standard deviation ratio
    437     and old threshold if greater than absolute threshold
    438     */
    439     temp = ( commonScale<=(DFRACT_BITS-1) )
    440             ? fMult(FL2FXCONST_DBL(0.66f), thresholds[i]) + (fMult(FL2FXCONST_DBL(0.34f), std_val) >> commonScale)
    441             : (FIXP_DBL) 0;
    442 
    443     thresholds[i] = fixMax(ABS_THRES,temp);
    444 
    445     FDK_ASSERT(commonScale >= 0);
    446   }
    447 }
    448 
    449 /*
    450  * Calculate transient levels for each QMF time slot.
    451  */
    452 static void
    453 extractTransientCandidates(FIXP_DBL  **RESTRICT Energies,
    454                            INT        *RESTRICT scaleEnergies,
    455                            FIXP_DBL   *RESTRICT thresholds,
    456                            FIXP_DBL   *RESTRICT transients,
    457                            int         YBufferWriteOffset,
    458                            int         YBufferSzShift,
    459                            int         noCols,
    460                            int         start_band,
    461                            int         stop_band,
    462                            int         tran_off,
    463                            int         addPrevSamples)
    464 {
    465   FIXP_DBL i_thres;
    466   C_ALLOC_SCRATCH_START(EnergiesTemp, FIXP_DBL, 2*QMF_MAX_TIME_SLOTS);
    467   FIXP_DBL *RESTRICT pEnergiesTemp = EnergiesTemp;
    468   int tmpScaleEnergies0, tmpScaleEnergies1;
    469   int endCond;
    470   int startEnerg,endEnerg;
    471   int i,j,jIndex,jpBM;
    472 
    473   tmpScaleEnergies0 = scaleEnergies[0];
    474   tmpScaleEnergies1 = scaleEnergies[1];
    475 
    476   /* Scale value for first energies, upto YBufferWriteOffset */
    477   tmpScaleEnergies0 = fixMin(tmpScaleEnergies0, MAX_SHIFT_DBL);
    478   /* Scale value for first energies, from YBufferWriteOffset upwards */
    479   tmpScaleEnergies1 = fixMin(tmpScaleEnergies1, MAX_SHIFT_DBL);
    480 
    481   FDK_ASSERT((tmpScaleEnergies0 >= 0) && (tmpScaleEnergies1 >= 0));
    482 
    483   /* Keep addPrevSamples extra previous transient candidates. */
    484   FDKmemmove(transients, transients + noCols - addPrevSamples, (tran_off+addPrevSamples) * sizeof (FIXP_DBL));
    485   FDKmemclear(transients + tran_off + addPrevSamples, noCols * sizeof (FIXP_DBL));
    486 
    487   endCond = noCols; /* Amount of new transient values to be calculated. */
    488   startEnerg = (tran_off-3)>>YBufferSzShift; /* >>YBufferSzShift because of amount of energy values. -3 because of neighbors being watched. */
    489   endEnerg = ((noCols+ (YBufferWriteOffset<<YBufferSzShift))-1)>>YBufferSzShift; /* YBufferSzShift shifts because of half energy values. */
    490 
    491   /* Compute differential values with two different weightings in every subband */
    492   for (i=start_band; i<stop_band; i++)
    493   {
    494     FIXP_DBL thres = thresholds[i];
    495 
    496     if((LONG)thresholds[i]>=256)
    497       i_thres = (LONG)( (LONG)MAXVAL_DBL / ((((LONG)thresholds[i]))+1) )<<(32-24);
    498     else
    499       i_thres = (LONG)MAXVAL_DBL;
    500 
    501     /* Copy one timeslot and de-scale and de-squish */
    502     if (YBufferSzShift == 1) {
    503       for(j=startEnerg; j<YBufferWriteOffset; j++) {
    504         FIXP_DBL tmp = Energies[j][i];
    505         EnergiesTemp[(j<<1)+1] = EnergiesTemp[j<<1] = tmp>>tmpScaleEnergies0;
    506       }
    507       for(; j<=endEnerg; j++) {
    508         FIXP_DBL tmp = Energies[j][i];
    509         EnergiesTemp[(j<<1)+1] = EnergiesTemp[j<<1] = tmp>>tmpScaleEnergies1;
    510       }
    511     } else {
    512       for(j=startEnerg; j<YBufferWriteOffset; j++) {
    513         FIXP_DBL tmp = Energies[j][i];
    514         EnergiesTemp[j] = tmp>>tmpScaleEnergies0;
    515       }
    516       for(; j<=endEnerg; j++) {
    517         FIXP_DBL tmp = Energies[j][i];
    518         EnergiesTemp[j] = tmp>>tmpScaleEnergies1;
    519       }
    520     }
    521 
    522     /* Detect peaks in energy values. */
    523 
    524     jIndex = tran_off;
    525     jpBM = jIndex+addPrevSamples;
    526 
    527     for (j=endCond; j--; jIndex++, jpBM++)
    528     {
    529 
    530       FIXP_DBL delta, tran;
    531       int d;
    532 
    533       delta = (FIXP_DBL)0;
    534       tran  = (FIXP_DBL)0;
    535 
    536       for (d=1; d<4; d++) {
    537         delta += pEnergiesTemp[jIndex+d]; /* R */
    538         delta -= pEnergiesTemp[jIndex-d]; /* L */
    539         delta -= thres;
    540 
    541         if ( delta > (FIXP_DBL)0 ) {
    542           tran += fMult(i_thres, delta);
    543         }
    544       }
    545       transients[jpBM] += tran;
    546     }
    547   }
    548   C_ALLOC_SCRATCH_END(EnergiesTemp, FIXP_DBL, 2*QMF_MAX_TIME_SLOTS);
    549 }
    550 
    551 void
    552 FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTran,
    553                           FIXP_DBL **Energies,
    554                           INT *scaleEnergies,
    555                           UCHAR *transient_info,
    556                           int YBufferWriteOffset,
    557                           int YBufferSzShift,
    558                           int timeStep,
    559                           int frameMiddleBorder)
    560 {
    561   int no_cols = h_sbrTran->no_cols;
    562   int qmfStartSample;
    563   int addPrevSamples;
    564   int timeStepShift=0;
    565   int i, cond;
    566 
    567   /* Where to start looking for transients in the transient candidate buffer */
    568   qmfStartSample = timeStep * frameMiddleBorder;
    569   /* We need to look one value backwards in the transients, so we might need one more previous value. */
    570   addPrevSamples = (qmfStartSample > 0) ? 0: 1;
    571 
    572   switch (timeStep) {
    573     case 1: timeStepShift = 0; break;
    574     case 2: timeStepShift = 1; break;
    575     case 4: timeStepShift = 2; break;
    576   }
    577 
    578   calculateThresholds(Energies,
    579                       scaleEnergies,
    580                       h_sbrTran->thresholds,
    581                       YBufferWriteOffset,
    582                       YBufferSzShift,
    583                       h_sbrTran->no_cols,
    584                       h_sbrTran->no_rows,
    585                       h_sbrTran->tran_off);
    586 
    587   extractTransientCandidates(Energies,
    588                              scaleEnergies,
    589                              h_sbrTran->thresholds,
    590                              h_sbrTran->transients,
    591                              YBufferWriteOffset,
    592                              YBufferSzShift,
    593                              h_sbrTran->no_cols,
    594                              0,
    595                              h_sbrTran->no_rows,
    596                              h_sbrTran->tran_off,
    597                              addPrevSamples );
    598 
    599   transient_info[0] = 0;
    600   transient_info[1] = 0;
    601   transient_info[2] = 0;
    602 
    603   /* Offset by the amount of additional previous transient candidates being kept. */
    604   qmfStartSample += addPrevSamples;
    605 
    606   /* Check for transients in second granule (pick the last value of subsequent values)  */
    607   for (i=qmfStartSample; i<qmfStartSample + no_cols; i++) {
    608     cond =    (h_sbrTran->transients[i] < fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1]) )
    609            && (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr);
    610 
    611     if (cond) {
    612       transient_info[0] = (i - qmfStartSample)>>timeStepShift;
    613       transient_info[1] = 1;
    614       break;
    615     }
    616   }
    617 
    618   if ( h_sbrTran->frameShift != 0) {
    619       /* transient prediction for LDSBR */
    620       /* Check for transients in first <frameShift> qmf-slots of second frame */
    621       for (i=qmfStartSample+no_cols; i<qmfStartSample + no_cols+h_sbrTran->frameShift; i++) {
    622 
    623         cond =    (h_sbrTran->transients[i] < fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1]) )
    624                && (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr);
    625 
    626         if (cond) {
    627           int pos = (int) ( (i - qmfStartSample-no_cols) >> timeStepShift );
    628           if ((pos < 3) && (transient_info[1]==0)) {
    629             transient_info[2] = 1;
    630           }
    631           break;
    632         }
    633       }
    634   }
    635 }
    636 
    637 int
    638 FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
    639                                    INT   frameSize,
    640                                    INT   sampleFreq,
    641                                    sbrConfigurationPtr params,
    642                                    int   tran_fc,
    643                                    int   no_cols,
    644                                    int   no_rows,
    645                                    int   YBufferWriteOffset,
    646                                    int   YBufferSzShift,
    647                                    int   frameShift,
    648                                    int   tran_off)
    649 {
    650     INT totalBitrate = params->codecSettings.standardBitrate * params->codecSettings.nChannels;
    651     INT codecBitrate = params->codecSettings.bitRate;
    652     FIXP_DBL bitrateFactor_fix, framedur_fix;
    653     INT scale_0, scale_1;
    654 
    655     FDKmemclear(h_sbrTransientDetector,sizeof(SBR_TRANSIENT_DETECTOR));
    656 
    657     h_sbrTransientDetector->frameShift = frameShift;
    658     h_sbrTransientDetector->tran_off = tran_off;
    659 
    660     if(codecBitrate) {
    661       bitrateFactor_fix = fDivNorm((FIXP_DBL)totalBitrate, (FIXP_DBL)(codecBitrate<<2),&scale_0);
    662     }
    663     else {
    664       bitrateFactor_fix = FL2FXCONST_DBL(1.0/4.0);
    665       scale_0 = 0;
    666     }
    667 
    668     framedur_fix = fDivNorm(frameSize, sampleFreq);
    669 
    670     /* The longer the frames, the more often should the FIXFIX-
    671     case transmit 2 envelopes instead of 1.
    672     Frame durations below 10 ms produce the highest threshold
    673     so that practically always only 1 env is transmitted. */
    674     FIXP_DBL tmp = framedur_fix - FL2FXCONST_DBL(0.010);
    675 
    676     tmp = fixMax(tmp, FL2FXCONST_DBL(0.0001));
    677     tmp = fDivNorm(FL2FXCONST_DBL(0.000075), fPow2(tmp), &scale_1);
    678 
    679     scale_1 = -(scale_1 + scale_0 + 2);
    680 
    681     FDK_ASSERT(no_cols <= QMF_MAX_TIME_SLOTS);
    682     FDK_ASSERT(no_rows <= QMF_CHANNELS);
    683 
    684     h_sbrTransientDetector->no_cols = no_cols;
    685     h_sbrTransientDetector->tran_thr = (FIXP_DBL)((params->tran_thr << (32-24-1)) / no_rows);
    686     h_sbrTransientDetector->tran_fc = tran_fc;
    687 
    688     if (scale_1>=0) {
    689       h_sbrTransientDetector->split_thr = fMult(tmp, bitrateFactor_fix) >> scale_1;
    690     }
    691     else {
    692       h_sbrTransientDetector->split_thr = fMult(tmp, bitrateFactor_fix) << (-scale_1);
    693     }
    694 
    695     h_sbrTransientDetector->no_rows = no_rows;
    696     h_sbrTransientDetector->mode = params->tran_det_mode;
    697     h_sbrTransientDetector->prevLowBandEnergy = FL2FXCONST_DBL(0.0f);
    698 
    699     return (0);
    700 }
    701 
    702