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 - 2015 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 9.31322574615479E-10 /* 2^-30 */
     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 #define NRG_SHIFT  3 /* for energy summation */
    110 
    111 static FIXP_DBL spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS],
    112                                INT *scaleEnergies,
    113                                FIXP_DBL EnergyTotal,
    114                                INT nSfb,
    115                                INT start,
    116                                INT border,
    117                                INT YBufferWriteOffset,
    118                                INT stop,
    119                                INT *result_e)
    120 {
    121   INT i,j;
    122   INT len1,len2;
    123   SCHAR energies_e_diff[NUMBER_TIME_SLOTS_2304], energies_e, energyTotal_e=19, energies_e_add;
    124   SCHAR prevEnergies_e_diff, newEnergies_e_diff;
    125   FIXP_DBL tmp0,tmp1;
    126   FIXP_DBL accu1,accu2,accu1_init,accu2_init;
    127   FIXP_DBL delta, delta_sum;
    128   INT accu_e, tmp_e;
    129 
    130   delta_sum = FL2FXCONST_DBL(0.0f);
    131   *result_e = 0;
    132 
    133   len1 = border-start;
    134   len2 = stop-border;
    135 
    136   /* prefer borders near the middle of the frame */
    137   FIXP_DBL   pos_weight;
    138   pos_weight = FL2FXCONST_DBL(0.5f) - (len1*GetInvInt(len1+len2));
    139   pos_weight = /*FL2FXCONST_DBL(1.0)*/ (FIXP_DBL)MAXVAL_DBL - (fMult(pos_weight, pos_weight)<<2);
    140 
    141   /*** Calc scaling for energies ***/
    142   FDK_ASSERT(scaleEnergies[0] >= 0);
    143   FDK_ASSERT(scaleEnergies[1] >= 0);
    144 
    145   energies_e = 19 - FDKmin(scaleEnergies[0], scaleEnergies[1]);
    146 
    147   /* limit shift for energy accumulation, energies_e can be -10 min. */
    148   if (energies_e < -10) {
    149      energies_e_add = -10 - energies_e;
    150      energies_e = -10;
    151   } else if (energies_e > 17) {
    152      energies_e_add = energies_e - 17;
    153      energies_e = 17;
    154   } else {
    155      energies_e_add = 0;
    156   }
    157 
    158   /* compensate scaling differences between scaleEnergies[0] and scaleEnergies[1]  */
    159   prevEnergies_e_diff = scaleEnergies[0] - FDKmin(scaleEnergies[0], scaleEnergies[1]) + energies_e_add + NRG_SHIFT;
    160   newEnergies_e_diff  = scaleEnergies[1] - FDKmin(scaleEnergies[0], scaleEnergies[1]) + energies_e_add + NRG_SHIFT;
    161 
    162   prevEnergies_e_diff = fMin(prevEnergies_e_diff, DFRACT_BITS-1);
    163   newEnergies_e_diff  = fMin(newEnergies_e_diff,  DFRACT_BITS-1);
    164 
    165   for (i=start; i<YBufferWriteOffset; i++) {
    166     energies_e_diff[i] = prevEnergies_e_diff;
    167   }
    168   for (i=YBufferWriteOffset; i<stop; i++) {
    169     energies_e_diff[i] = newEnergies_e_diff;
    170   }
    171 
    172   /* Sum up energies of all QMF-timeslots for both halfs */
    173   FDK_ASSERT(len1<=8); /* otherwise an overflow is possible */
    174   FDK_ASSERT(len2<=8); /* otherwise an overflow is possible */
    175   /* init with some energy to prevent division by zero
    176       and to prevent splitting for very low levels */
    177   accu1_init = scaleValue((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY))),-energies_e);
    178   accu2_init = scaleValue((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY))),-energies_e);
    179   accu1_init = fMult(accu1_init, (FIXP_DBL)len1<<((DFRACT_BITS-1)-NRG_SHIFT-1))<<1;
    180   accu2_init = fMult(accu2_init, (FIXP_DBL)len2<<((DFRACT_BITS-1)-NRG_SHIFT-1))<<1;
    181 
    182   for (j=0; j<nSfb; j++) {
    183 
    184     accu1 = accu1_init;
    185     accu2 = accu2_init;
    186     accu_e = energies_e+3;
    187 
    188     /* Sum up energies in first half */
    189     for (i=start; i<border; i++) {
    190       accu1 += scaleValue(Energies[i][j], -energies_e_diff[i]);
    191     }
    192 
    193     /* Sum up energies in second half */
    194     for (i=border; i<stop; i++) {
    195       accu2 += scaleValue(Energies[i][j], -energies_e_diff[i]);
    196     }
    197 
    198     /* Energy change in current band */
    199     #define LN2 FL2FXCONST_DBL(0.6931471806f) /* ln(2) */
    200     tmp0 = fLog2(accu2, accu_e) - fLog2(accu1, accu_e);
    201     tmp1 = fLog2((FIXP_DBL)len1, 31) - fLog2((FIXP_DBL)len2, 31);
    202     delta = fMult(LN2, (tmp0 + tmp1));
    203     delta = (FIXP_DBL)FDKabs( delta );
    204 
    205     /* Weighting with amplitude ratio of this band */
    206     accu_e++;
    207     accu1>>=1;
    208     accu2>>=1;
    209     if (accu_e & 1) {
    210       accu_e++;
    211       accu1>>=1;
    212       accu2>>=1;
    213     }
    214 
    215     delta_sum += fMult(sqrtFixp(accu1+accu2), delta);
    216     *result_e = ((accu_e>>1) + LD_DATA_SHIFT);
    217   }
    218 
    219   energyTotal_e+=1; /* for a defined square result exponent, the exponent has to be even */
    220   EnergyTotal<<=1;
    221   delta_sum = fMult(delta_sum, invSqrtNorm2(EnergyTotal, &tmp_e));
    222   *result_e = *result_e + (tmp_e-(energyTotal_e>>1));
    223 
    224   return fMult(delta_sum, pos_weight);
    225 
    226 }
    227 
    228 
    229 /*******************************************************************************
    230  Functionname:  addLowbandEnergies
    231  *******************************************************************************
    232  \brief   Calculates total lowband energy
    233 
    234  The input values Energies[0] (low-band) are scaled by the factor
    235  2^(14-*scaleEnergies[0])
    236  The input values Energies[1] (high-band) are scaled by the factor
    237  2^(14-*scaleEnergies[1])
    238 
    239  \return  total energy in the lowband, scaled by the factor 2^19
    240 *******************************************************************************/
    241 static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies,
    242                                    int       *scaleEnergies,
    243                                    int        YBufferWriteOffset,
    244                                    int        nrgSzShift,
    245                                    int        tran_off,
    246                                    UCHAR     *freqBandTable,
    247                                    int        slots)
    248 {
    249   FIXP_DBL nrgTotal;
    250   FIXP_DBL accu1 = FL2FXCONST_DBL(0.0f);
    251   FIXP_DBL accu2 = FL2FXCONST_DBL(0.0f);
    252   int tran_offdiv2 = tran_off>>nrgSzShift;
    253   int ts,k;
    254 
    255   /* Sum up lowband energy from one frame at offset tran_off */
    256   /* freqBandTable[LORES] has MAX_FREQ_COEFFS/2 +1 coeefs max. */
    257   for (ts=tran_offdiv2; ts<YBufferWriteOffset; ts++) {
    258     for (k = 0; k < freqBandTable[0]; k++) {
    259       accu1 += Energies[ts][k] >> 6;
    260     }
    261   }
    262   for (; ts<tran_offdiv2+(slots>>nrgSzShift); ts++) {
    263     for (k = 0; k < freqBandTable[0]; k++) {
    264       accu2 += Energies[ts][k] >> 9;
    265     }
    266   }
    267 
    268   nrgTotal = ( scaleValueSaturate(accu1, 1-scaleEnergies[0]) )
    269            + ( scaleValueSaturate(accu2, 4-scaleEnergies[1]) );
    270 
    271   return(nrgTotal);
    272 }
    273 
    274 
    275 /*******************************************************************************
    276  Functionname:  addHighbandEnergies
    277  *******************************************************************************
    278  \brief   Add highband energies
    279 
    280  Highband energies are mapped to an array with smaller dimension:
    281  Its time resolution is only 1 SBR-timeslot and its frequency resolution
    282  is 1 SBR-band. Therefore the data to be fed into the spectralChange
    283  function is reduced.
    284 
    285  The values EnergiesM are scaled by the factor (2^19-scaleEnergies[0]) for
    286  slots<YBufferWriteOffset and by the factor (2^19-scaleEnergies[1]) for
    287  slots>=YBufferWriteOffset.
    288 
    289  \return  total energy in the highband, scaled by factor 2^19
    290 *******************************************************************************/
    291 
    292 static FIXP_DBL addHighbandEnergies(FIXP_DBL **RESTRICT Energies, /*!< input */
    293                                     INT       *scaleEnergies,
    294                                     INT        YBufferWriteOffset,
    295                                     FIXP_DBL   EnergiesM[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS], /*!< Combined output */
    296                                     UCHAR     *RESTRICT freqBandTable,
    297                                     INT        nSfb,
    298                                     INT        sbrSlots,
    299                                     INT        timeStep)
    300 {
    301   INT i,j,k,slotIn,slotOut,scale[2];
    302   INT li,ui;
    303   FIXP_DBL nrgTotal;
    304   FIXP_DBL accu = FL2FXCONST_DBL(0.0f);
    305 
    306   /* Combine QMF-timeslots to SBR-timeslots,
    307      combine QMF-bands to SBR-bands,
    308      combine Left and Right channel */
    309   for (slotOut=0; slotOut<sbrSlots; slotOut++) {
    310     slotIn = timeStep*slotOut;
    311 
    312     for (j=0; j<nSfb; j++) {
    313       accu = FL2FXCONST_DBL(0.0f);
    314 
    315       li = freqBandTable[j];
    316       ui = freqBandTable[j + 1];
    317 
    318       for (k=li; k<ui; k++) {
    319         for (i=0; i<timeStep; i++) {
    320          accu += (Energies[(slotIn+i)>>1][k] >> 5);
    321         }
    322       }
    323       EnergiesM[slotOut][j] = accu;
    324     }
    325   }
    326 
    327   /* scale energies down before add up */
    328   scale[0] = fixMin(8,scaleEnergies[0]);
    329   scale[1] = fixMin(8,scaleEnergies[1]);
    330 
    331   if ((scaleEnergies[0]-scale[0]) > (DFRACT_BITS-1) || (scaleEnergies[1]-scale[0]) > (DFRACT_BITS-1))
    332     nrgTotal = FL2FXCONST_DBL(0.0f);
    333   else {
    334     /* Now add all energies */
    335     accu = FL2FXCONST_DBL(0.0f);
    336 
    337     for (slotOut=0; slotOut<YBufferWriteOffset; slotOut++) {
    338       for (j=0; j<nSfb; j++) {
    339         accu += (EnergiesM[slotOut][j] >> scale[0]);
    340       }
    341     }
    342     nrgTotal = accu >> (scaleEnergies[0]-scale[0]);
    343 
    344     for (slotOut=YBufferWriteOffset; slotOut<sbrSlots; slotOut++) {
    345       for (j=0; j<nSfb; j++) {
    346         accu += (EnergiesM[slotOut][j] >> scale[0]);
    347       }
    348     }
    349     nrgTotal = accu >> (scaleEnergies[1]-scale[1]);
    350   }
    351 
    352   return(nrgTotal);
    353 }
    354 
    355 
    356 /*******************************************************************************
    357  Functionname:  FDKsbrEnc_frameSplitter
    358  *******************************************************************************
    359  \brief   Decides if a FIXFIX-frame shall be splitted into 2 envelopes
    360 
    361  If no transient has been detected before, the frame can still be splitted
    362  into 2 envelopes.
    363 *******************************************************************************/
    364 void
    365 FDKsbrEnc_frameSplitter(FIXP_DBL **Energies,
    366                         INT *scaleEnergies,
    367                         HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
    368                         UCHAR *freqBandTable,
    369                         UCHAR *tran_vector,
    370                         int YBufferWriteOffset,
    371                         int YBufferSzShift,
    372                         int nSfb,
    373                         int timeStep,
    374                         int no_cols,
    375                         FIXP_DBL* tonality)
    376 {
    377   if (tran_vector[1]==0) /* no transient was detected */
    378   {
    379     FIXP_DBL delta;
    380     INT delta_e;
    381     FIXP_DBL (*EnergiesM)[MAX_FREQ_COEFFS];
    382     FIXP_DBL EnergyTotal,newLowbandEnergy,newHighbandEnergy;
    383     INT border;
    384     INT sbrSlots = fMultI(GetInvInt(timeStep),no_cols);
    385     C_ALLOC_SCRATCH_START(_EnergiesM, FIXP_DBL, NUMBER_TIME_SLOTS_2304*MAX_FREQ_COEFFS)
    386 
    387     FDK_ASSERT( sbrSlots * timeStep == no_cols );
    388 
    389     EnergiesM = (FIXP_DBL(*)[MAX_FREQ_COEFFS])_EnergiesM;
    390 
    391     /*
    392       Get Lowband-energy over a range of 2 frames (Look half a frame back and ahead).
    393     */
    394     newLowbandEnergy = addLowbandEnergies(Energies,
    395                                           scaleEnergies,
    396                                           YBufferWriteOffset,
    397                                           YBufferSzShift,
    398                                           h_sbrTransientDetector->tran_off,
    399                                           freqBandTable,
    400                                           no_cols);
    401 
    402     newHighbandEnergy = addHighbandEnergies(Energies,
    403                                             scaleEnergies,
    404                                             YBufferWriteOffset,
    405                                             EnergiesM,
    406                                             freqBandTable,
    407                                             nSfb,
    408                                             sbrSlots,
    409                                             timeStep);
    410 
    411     {
    412       /* prevLowBandEnergy: Corresponds to 1 frame, starting with half a frame look-behind
    413          newLowbandEnergy:  Corresponds to 1 frame, starting in the middle of the current frame */
    414       EnergyTotal = (newLowbandEnergy + h_sbrTransientDetector->prevLowBandEnergy) >> 1;
    415       EnergyTotal += newHighbandEnergy;
    416       /* The below border should specify the same position as the middle border
    417          of a FIXFIX-frame with 2 envelopes. */
    418       border = (sbrSlots+1) >> 1;
    419 
    420       if ( (INT)EnergyTotal&0xffffffe0 && (scaleEnergies[0]<32 || scaleEnergies[1]<32) ) /* i.e. > 31 */ {
    421       delta = spectralChange(EnergiesM,
    422                              scaleEnergies,
    423                              EnergyTotal,
    424                              nSfb,
    425                              0,
    426                              border,
    427                              YBufferWriteOffset,
    428                              sbrSlots,
    429                             &delta_e
    430                              );
    431       } else {
    432         delta = FL2FXCONST_DBL(0.0f);
    433         delta_e = 0;
    434 
    435         /* set tonality to 0 when energy is very low, since the amplitude
    436            resolution should then be low as well                          */
    437         *tonality = FL2FXCONST_DBL(0.0f);
    438       }
    439 
    440 
    441       if ( fIsLessThan(h_sbrTransientDetector->split_thr_m, h_sbrTransientDetector->split_thr_e, delta, delta_e) ) {
    442         tran_vector[0] = 1; /* Set flag for splitting */
    443       } else {
    444         tran_vector[0] = 0;
    445       }
    446 
    447     }
    448 
    449     /* Update prevLowBandEnergy */
    450     h_sbrTransientDetector->prevLowBandEnergy = newLowbandEnergy;
    451     h_sbrTransientDetector->prevHighBandEnergy = newHighbandEnergy;
    452     C_ALLOC_SCRATCH_END(_EnergiesM, FIXP_DBL, NUMBER_TIME_SLOTS_2304*MAX_FREQ_COEFFS)
    453   }
    454 }
    455 
    456 /*
    457  * Calculate transient energy threshold for each QMF band
    458  */
    459 static void
    460 calculateThresholds(FIXP_DBL **RESTRICT Energies,
    461                     INT       *RESTRICT scaleEnergies,
    462                     FIXP_DBL  *RESTRICT thresholds,
    463                     int        YBufferWriteOffset,
    464                     int        YBufferSzShift,
    465                     int        noCols,
    466                     int        noRows,
    467                     int        tran_off)
    468 {
    469   FIXP_DBL mean_val,std_val,temp;
    470   FIXP_DBL i_noCols;
    471   FIXP_DBL i_noCols1;
    472   FIXP_DBL accu,accu0,accu1;
    473   int scaleFactor0,scaleFactor1,commonScale;
    474   int i,j;
    475 
    476   i_noCols  = GetInvInt(noCols + tran_off ) << YBufferSzShift;
    477   i_noCols1 = GetInvInt(noCols + tran_off - 1) << YBufferSzShift;
    478 
    479   /* calc minimum scale of energies of previous and current frame */
    480   commonScale = fixMin(scaleEnergies[0],scaleEnergies[1]);
    481 
    482   /* calc scalefactors to adapt energies to common scale */
    483   scaleFactor0 = fixMin((scaleEnergies[0]-commonScale), (DFRACT_BITS-1));
    484   scaleFactor1 = fixMin((scaleEnergies[1]-commonScale), (DFRACT_BITS-1));
    485 
    486   FDK_ASSERT((scaleFactor0 >= 0) && (scaleFactor1 >= 0));
    487 
    488   /* calculate standard deviation in every subband */
    489   for (i=0; i<noRows; i++)
    490   {
    491     int startEnergy = (tran_off>>YBufferSzShift);
    492     int endEnergy = ((noCols>>YBufferSzShift)+tran_off);
    493     int shift;
    494 
    495     /* calculate mean value over decimated energy values (downsampled by 2). */
    496     accu0 = accu1 = FL2FXCONST_DBL(0.0f);
    497 
    498     for (j=startEnergy; j<YBufferWriteOffset; j++)
    499       accu0 += fMult(Energies[j][i], i_noCols);
    500     for (; j<endEnergy; j++)
    501       accu1 += fMult(Energies[j][i], i_noCols);
    502 
    503     mean_val = (accu0 >> scaleFactor0) + (accu1 >> scaleFactor1);  /* average */
    504     shift    = fixMax(0,CountLeadingBits(mean_val)-6);             /* -6 to keep room for accumulating upto N = 24 values */
    505 
    506     /* calculate standard deviation */
    507     accu = FL2FXCONST_DBL(0.0f);
    508 
    509     /* summe { ((mean_val-nrg)^2) * i_noCols1 } */
    510     for (j=startEnergy; j<YBufferWriteOffset; j++) {
    511       temp = ((FIXP_DBL)mean_val - ((FIXP_DBL)Energies[j][i] >> scaleFactor0))<<shift;
    512       temp = fPow2(temp);
    513       temp = fMult(temp, i_noCols1);
    514       accu += temp;
    515     }
    516     for (; j<endEnergy; j++) {
    517       temp = ((FIXP_DBL)mean_val - ((FIXP_DBL)Energies[j][i] >> scaleFactor1))<<shift;
    518       temp = fPow2(temp);
    519       temp = fMult(temp, i_noCols1);
    520       accu += temp;
    521     }
    522 
    523     std_val = sqrtFixp(accu)>>shift;     /* standard deviation */
    524 
    525     /*
    526     Take new threshold as average of calculated standard deviation ratio
    527     and old threshold if greater than absolute threshold
    528     */
    529     temp = ( commonScale<=(DFRACT_BITS-1) )
    530             ? fMult(FL2FXCONST_DBL(0.66f), thresholds[i]) + (fMult(FL2FXCONST_DBL(0.34f), std_val) >> commonScale)
    531             : (FIXP_DBL) 0;
    532 
    533     thresholds[i] = fixMax(ABS_THRES,temp);
    534 
    535     FDK_ASSERT(commonScale >= 0);
    536   }
    537 }
    538 
    539 /*
    540  * Calculate transient levels for each QMF time slot.
    541  */
    542 static void
    543 extractTransientCandidates(FIXP_DBL  **RESTRICT Energies,
    544                            INT        *RESTRICT scaleEnergies,
    545                            FIXP_DBL   *RESTRICT thresholds,
    546                            FIXP_DBL   *RESTRICT transients,
    547                            int         YBufferWriteOffset,
    548                            int         YBufferSzShift,
    549                            int         noCols,
    550                            int         start_band,
    551                            int         stop_band,
    552                            int         tran_off,
    553                            int         addPrevSamples)
    554 {
    555   FIXP_DBL i_thres;
    556   C_ALLOC_SCRATCH_START(EnergiesTemp, FIXP_DBL, 2*QMF_MAX_TIME_SLOTS);
    557   FIXP_DBL *RESTRICT pEnergiesTemp = EnergiesTemp;
    558   int tmpScaleEnergies0, tmpScaleEnergies1;
    559   int endCond;
    560   int startEnerg,endEnerg;
    561   int i,j,jIndex,jpBM;
    562 
    563   tmpScaleEnergies0 = scaleEnergies[0];
    564   tmpScaleEnergies1 = scaleEnergies[1];
    565 
    566   /* Scale value for first energies, upto YBufferWriteOffset */
    567   tmpScaleEnergies0 = fixMin(tmpScaleEnergies0, MAX_SHIFT_DBL);
    568   /* Scale value for first energies, from YBufferWriteOffset upwards */
    569   tmpScaleEnergies1 = fixMin(tmpScaleEnergies1, MAX_SHIFT_DBL);
    570 
    571   FDK_ASSERT((tmpScaleEnergies0 >= 0) && (tmpScaleEnergies1 >= 0));
    572 
    573   /* Keep addPrevSamples extra previous transient candidates. */
    574   FDKmemmove(transients, transients + noCols - addPrevSamples, (tran_off+addPrevSamples) * sizeof (FIXP_DBL));
    575   FDKmemclear(transients + tran_off + addPrevSamples, noCols * sizeof (FIXP_DBL));
    576 
    577   endCond = noCols; /* Amount of new transient values to be calculated. */
    578   startEnerg = (tran_off-3)>>YBufferSzShift; /* >>YBufferSzShift because of amount of energy values. -3 because of neighbors being watched. */
    579   endEnerg = ((noCols+ (YBufferWriteOffset<<YBufferSzShift))-1)>>YBufferSzShift; /* YBufferSzShift shifts because of half energy values. */
    580 
    581   /* Compute differential values with two different weightings in every subband */
    582   for (i=start_band; i<stop_band; i++)
    583   {
    584     FIXP_DBL thres = thresholds[i];
    585 
    586     if((LONG)thresholds[i]>=256)
    587       i_thres = (LONG)( (LONG)MAXVAL_DBL / ((((LONG)thresholds[i]))+1) )<<(32-24);
    588     else
    589       i_thres = (LONG)MAXVAL_DBL;
    590 
    591     /* Copy one timeslot and de-scale and de-squish */
    592     if (YBufferSzShift == 1) {
    593       for(j=startEnerg; j<YBufferWriteOffset; j++) {
    594         FIXP_DBL tmp = Energies[j][i];
    595         EnergiesTemp[(j<<1)+1] = EnergiesTemp[j<<1] = tmp>>tmpScaleEnergies0;
    596       }
    597       for(; j<=endEnerg; j++) {
    598         FIXP_DBL tmp = Energies[j][i];
    599         EnergiesTemp[(j<<1)+1] = EnergiesTemp[j<<1] = tmp>>tmpScaleEnergies1;
    600       }
    601     } else {
    602       for(j=startEnerg; j<YBufferWriteOffset; j++) {
    603         FIXP_DBL tmp = Energies[j][i];
    604         EnergiesTemp[j] = tmp>>tmpScaleEnergies0;
    605       }
    606       for(; j<=endEnerg; j++) {
    607         FIXP_DBL tmp = Energies[j][i];
    608         EnergiesTemp[j] = tmp>>tmpScaleEnergies1;
    609       }
    610     }
    611 
    612     /* Detect peaks in energy values. */
    613 
    614     jIndex = tran_off;
    615     jpBM = jIndex+addPrevSamples;
    616 
    617     for (j=endCond; j--; jIndex++, jpBM++)
    618     {
    619 
    620       FIXP_DBL delta, tran;
    621       int d;
    622 
    623       delta = (FIXP_DBL)0;
    624       tran  = (FIXP_DBL)0;
    625 
    626       for (d=1; d<4; d++) {
    627         delta += pEnergiesTemp[jIndex+d]; /* R */
    628         delta -= pEnergiesTemp[jIndex-d]; /* L */
    629         delta -= thres;
    630 
    631         if ( delta > (FIXP_DBL)0 ) {
    632           tran += fMult(i_thres, delta);
    633         }
    634       }
    635       transients[jpBM] += tran;
    636     }
    637   }
    638   C_ALLOC_SCRATCH_END(EnergiesTemp, FIXP_DBL, 2*QMF_MAX_TIME_SLOTS);
    639 }
    640 
    641 void
    642 FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTran,
    643                           FIXP_DBL **Energies,
    644                           INT *scaleEnergies,
    645                           UCHAR *transient_info,
    646                           int YBufferWriteOffset,
    647                           int YBufferSzShift,
    648                           int timeStep,
    649                           int frameMiddleBorder)
    650 {
    651   int no_cols = h_sbrTran->no_cols;
    652   int qmfStartSample;
    653   int addPrevSamples;
    654   int timeStepShift=0;
    655   int i, cond;
    656 
    657   /* Where to start looking for transients in the transient candidate buffer */
    658   qmfStartSample = timeStep * frameMiddleBorder;
    659   /* We need to look one value backwards in the transients, so we might need one more previous value. */
    660   addPrevSamples = (qmfStartSample > 0) ? 0: 1;
    661 
    662   switch (timeStep) {
    663     case 1: timeStepShift = 0; break;
    664     case 2: timeStepShift = 1; break;
    665     case 4: timeStepShift = 2; break;
    666   }
    667 
    668   calculateThresholds(Energies,
    669                       scaleEnergies,
    670                       h_sbrTran->thresholds,
    671                       YBufferWriteOffset,
    672                       YBufferSzShift,
    673                       h_sbrTran->no_cols,
    674                       h_sbrTran->no_rows,
    675                       h_sbrTran->tran_off);
    676 
    677   extractTransientCandidates(Energies,
    678                              scaleEnergies,
    679                              h_sbrTran->thresholds,
    680                              h_sbrTran->transients,
    681                              YBufferWriteOffset,
    682                              YBufferSzShift,
    683                              h_sbrTran->no_cols,
    684                              0,
    685                              h_sbrTran->no_rows,
    686                              h_sbrTran->tran_off,
    687                              addPrevSamples );
    688 
    689   transient_info[0] = 0;
    690   transient_info[1] = 0;
    691   transient_info[2] = 0;
    692 
    693   /* Offset by the amount of additional previous transient candidates being kept. */
    694   qmfStartSample += addPrevSamples;
    695 
    696   /* Check for transients in second granule (pick the last value of subsequent values)  */
    697   for (i=qmfStartSample; i<qmfStartSample + no_cols; i++) {
    698     cond =    (h_sbrTran->transients[i] < fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1]) )
    699            && (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr);
    700 
    701     if (cond) {
    702       transient_info[0] = (i - qmfStartSample)>>timeStepShift;
    703       transient_info[1] = 1;
    704       break;
    705     }
    706   }
    707 
    708   if ( h_sbrTran->frameShift != 0) {
    709       /* transient prediction for LDSBR */
    710       /* Check for transients in first <frameShift> qmf-slots of second frame */
    711       for (i=qmfStartSample+no_cols; i<qmfStartSample + no_cols+h_sbrTran->frameShift; i++) {
    712 
    713         cond =    (h_sbrTran->transients[i] < fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1]) )
    714                && (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr);
    715 
    716         if (cond) {
    717           int pos = (int) ( (i - qmfStartSample-no_cols) >> timeStepShift );
    718           if ((pos < 3) && (transient_info[1]==0)) {
    719             transient_info[2] = 1;
    720           }
    721           break;
    722         }
    723       }
    724   }
    725 }
    726 
    727 int
    728 FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
    729                                    UINT  sbrSyntaxFlags, /* SBR syntax flags derived from AOT. */
    730                                    INT   frameSize,
    731                                    INT   sampleFreq,
    732                                    sbrConfigurationPtr params,
    733                                    int   tran_fc,
    734                                    int   no_cols,
    735                                    int   no_rows,
    736                                    int   YBufferWriteOffset,
    737                                    int   YBufferSzShift,
    738                                    int   frameShift,
    739                                    int   tran_off)
    740 {
    741     INT totalBitrate = params->codecSettings.standardBitrate * params->codecSettings.nChannels;
    742     INT codecBitrate = params->codecSettings.bitRate;
    743     FIXP_DBL bitrateFactor_m, framedur_fix;
    744     INT bitrateFactor_e, tmp_e;
    745 
    746     FDKmemclear(h_sbrTransientDetector,sizeof(SBR_TRANSIENT_DETECTOR));
    747 
    748     h_sbrTransientDetector->frameShift = frameShift;
    749     h_sbrTransientDetector->tran_off = tran_off;
    750 
    751     if(codecBitrate) {
    752       bitrateFactor_m = fDivNorm((FIXP_DBL)totalBitrate, (FIXP_DBL)(codecBitrate<<2),&bitrateFactor_e);
    753       bitrateFactor_e += 2;
    754     }
    755     else {
    756       bitrateFactor_m = FL2FXCONST_DBL(1.0/4.0);
    757       bitrateFactor_e = 2;
    758     }
    759 
    760     framedur_fix = fDivNorm(frameSize, sampleFreq);
    761 
    762     /* The longer the frames, the more often should the FIXFIX-
    763     case transmit 2 envelopes instead of 1.
    764     Frame durations below 10 ms produce the highest threshold
    765     so that practically always only 1 env is transmitted. */
    766     FIXP_DBL tmp = framedur_fix - FL2FXCONST_DBL(0.010);
    767 
    768     tmp = fixMax(tmp, FL2FXCONST_DBL(0.0001));
    769     tmp = fDivNorm(FL2FXCONST_DBL(0.000075), fPow2(tmp), &tmp_e);
    770 
    771     bitrateFactor_e = (tmp_e + bitrateFactor_e);
    772 
    773   if(sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) {
    774     bitrateFactor_e--; /* divide by 2 */
    775   }
    776 
    777     FDK_ASSERT(no_cols <= QMF_MAX_TIME_SLOTS);
    778     FDK_ASSERT(no_rows <= QMF_CHANNELS);
    779 
    780     h_sbrTransientDetector->no_cols = no_cols;
    781     h_sbrTransientDetector->tran_thr = (FIXP_DBL)((params->tran_thr << (32-24-1)) / no_rows);
    782     h_sbrTransientDetector->tran_fc = tran_fc;
    783     h_sbrTransientDetector->split_thr_m = fMult(tmp, bitrateFactor_m);
    784     h_sbrTransientDetector->split_thr_e = bitrateFactor_e;
    785     h_sbrTransientDetector->no_rows = no_rows;
    786     h_sbrTransientDetector->mode = params->tran_det_mode;
    787     h_sbrTransientDetector->prevLowBandEnergy = FL2FXCONST_DBL(0.0f);
    788 
    789     return (0);
    790 }
    791 
    792 
    793 #define ENERGY_SCALING_SIZE 32
    794 
    795 INT FDKsbrEnc_InitSbrFastTransientDetector(
    796         HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector,
    797         const INT time_slots_per_frame,
    798         const INT bandwidth_qmf_slot,
    799         const INT no_qmf_channels,
    800         const INT sbr_qmf_1st_band
    801         )
    802 {
    803 
    804   int i, e;
    805   int buff_size;
    806   FIXP_DBL myExp;
    807   FIXP_DBL myExpSlot;
    808 
    809   h_sbrFastTransientDetector->lookahead = TRAN_DET_LOOKAHEAD;
    810   h_sbrFastTransientDetector->nTimeSlots = time_slots_per_frame;
    811 
    812   buff_size = h_sbrFastTransientDetector->nTimeSlots + h_sbrFastTransientDetector->lookahead;
    813 
    814   for(i=0; i< buff_size; i++) {
    815     h_sbrFastTransientDetector->delta_energy[i] = FL2FXCONST_DBL(0.0f);
    816     h_sbrFastTransientDetector->energy_timeSlots[i] = FL2FXCONST_DBL(0.0f);
    817     h_sbrFastTransientDetector->lowpass_energy[i] = FL2FXCONST_DBL(0.0f);
    818     h_sbrFastTransientDetector->transientCandidates[i] = 0;
    819   }
    820 
    821   FDK_ASSERT(bandwidth_qmf_slot > 0.f);
    822   h_sbrFastTransientDetector->stopBand  = fMin(TRAN_DET_STOP_FREQ/bandwidth_qmf_slot, no_qmf_channels);
    823   h_sbrFastTransientDetector->startBand = fMin(sbr_qmf_1st_band, h_sbrFastTransientDetector->stopBand - TRAN_DET_MIN_QMFBANDS);
    824 
    825   FDK_ASSERT(h_sbrFastTransientDetector->startBand < no_qmf_channels);
    826   FDK_ASSERT(h_sbrFastTransientDetector->startBand < h_sbrFastTransientDetector->stopBand);
    827   FDK_ASSERT(h_sbrFastTransientDetector->startBand > 1);
    828   FDK_ASSERT(h_sbrFastTransientDetector->stopBand > 1);
    829 
    830   /* the energy weighting and adding up has a headroom of 6 Bits,
    831      so up to 64 bands can be added without potential overflow. */
    832   FDK_ASSERT(h_sbrFastTransientDetector->stopBand - h_sbrFastTransientDetector->startBand <= 64);
    833 
    834   /* QMF_HP_dB_SLOPE_FIX says that we want a 20 dB per 16 kHz HP filter.
    835      The following lines map this to the QMF bandwidth. */
    836   #define EXP_E 7 /* QMF_CHANNELS (=64) multiplications max, max. allowed sum is 0.5 */
    837   myExp = fMultNorm(QMF_HP_dBd_SLOPE_FIX, (FIXP_DBL)bandwidth_qmf_slot, &e);
    838   myExp = scaleValueSaturate(myExp, e+0+DFRACT_BITS-1-EXP_E);
    839   myExpSlot = myExp;
    840 
    841   for(i=0; i<QMF_CHANNELS; i++){
    842     /* Calculate dBf over all qmf bands:
    843        dBf = (10^(0.002266f/10*bw(slot)))^(band) =
    844            = 2^(log2(10)*0.002266f/10*bw(slot)*band) =
    845            = 2^(0.00075275f*bw(slot)*band)                                   */
    846 
    847     FIXP_DBL dBf_m;        /* dBf mantissa        */
    848     INT dBf_e;             /* dBf exponent        */
    849     INT tmp;
    850 
    851     INT dBf_int;           /* dBf integer part    */
    852     FIXP_DBL dBf_fract;    /* dBf fractional part */
    853 
    854     /* myExp*(i+1) = myExp_int - myExp_fract
    855        myExp*(i+1) is split up here for better accuracy of CalcInvLdData(),
    856        for its result can be split up into an integer and a fractional part */
    857 
    858     /* Round up to next integer */
    859     FIXP_DBL myExp_int   = (myExpSlot & (FIXP_DBL)0xfe000000) + (FIXP_DBL)0x02000000;
    860 
    861     /* This is the fractional part that needs to be substracted */
    862     FIXP_DBL myExp_fract = myExp_int - myExpSlot;
    863 
    864     /* Calc integer part */
    865     dBf_int   = CalcInvLdData(myExp_int);
    866     /* The result needs to be re-scaled. The ld(myExp_int) had been scaled by EXP_E,
    867        the CalcInvLdData expects the operand to be scaled by LD_DATA_SHIFT.
    868        Therefore, the correctly scaled result is dBf_int^(2^(EXP_E-LD_DATA_SHIFT)),
    869        which is dBf_int^2 */
    870     dBf_int  *= dBf_int;
    871 
    872     /* Calc fractional part */
    873     dBf_fract = CalcInvLdData(-myExp_fract);
    874     /* The result needs to be re-scaled. The ld(myExp_fract) had been scaled by EXP_E,
    875        the CalcInvLdData expects the operand to be scaled by LD_DATA_SHIFT.
    876        Therefore, the correctly scaled result is dBf_fract^(2^(EXP_E-LD_DATA_SHIFT)),
    877        which is dBf_fract^2 */
    878     dBf_fract = fMultNorm(dBf_fract, dBf_fract, &tmp);
    879 
    880     /* Get worst case scaling of multiplication result */
    881     dBf_e = (DFRACT_BITS-1 - tmp) - CountLeadingBits(dBf_int);
    882 
    883     /* Now multiply integer with fractional part of the result, thus resulting
    884        in the overall accurate fractional result */
    885     dBf_m = fMultNorm(dBf_int, dBf_fract, &e);
    886     dBf_m = scaleValueSaturate(dBf_m, e+DFRACT_BITS-1+tmp-dBf_e);
    887     myExpSlot += myExp;
    888 
    889     /* Keep the results */
    890     h_sbrFastTransientDetector->dBf_m[i] = dBf_m;
    891     h_sbrFastTransientDetector->dBf_e[i] = dBf_e;
    892 
    893   }
    894 
    895   /* Make sure that dBf is greater than 1.0 (because it should be a highpass) */
    896   /* ... */
    897 
    898   return 0;
    899 }
    900 
    901 void FDKsbrEnc_fastTransientDetect(
    902         const HANDLE_FAST_TRAN_DET          h_sbrFastTransientDetector,
    903         const FIXP_DBL              *const *Energies,
    904         const int                   *const  scaleEnergies,
    905         const INT                           YBufferWriteOffset,
    906               UCHAR                 *const  tran_vector
    907         )
    908 {
    909   int timeSlot, band;
    910 
    911   FIXP_DBL max_delta_energy;   /* helper to store maximum energy ratio          */
    912   int max_delta_energy_scale;  /* helper to store scale of maximum energy ratio */
    913   int ind_max             = 0; /* helper to store index of maximum energy ratio */
    914   int isTransientInFrame  = 0;
    915 
    916   const int nTimeSlots         = h_sbrFastTransientDetector->nTimeSlots;
    917   const int lookahead          = h_sbrFastTransientDetector->lookahead;
    918   const int startBand          = h_sbrFastTransientDetector->startBand;
    919   const int stopBand           = h_sbrFastTransientDetector->stopBand;
    920 
    921   int * transientCandidates    = h_sbrFastTransientDetector->transientCandidates;
    922 
    923   FIXP_DBL * energy_timeSlots  = h_sbrFastTransientDetector->energy_timeSlots;
    924   int * energy_timeSlots_scale = h_sbrFastTransientDetector->energy_timeSlots_scale;
    925 
    926   FIXP_DBL * delta_energy      = h_sbrFastTransientDetector->delta_energy;
    927   int * delta_energy_scale     = h_sbrFastTransientDetector->delta_energy_scale;
    928 
    929   const FIXP_DBL thr           = TRAN_DET_THRSHLD;
    930   const INT      thr_scale     = TRAN_DET_THRSHLD_SCALE;
    931 
    932   /*reset transient info*/
    933   tran_vector[2] = 0;
    934 
    935   /* reset transient candidates */
    936   FDKmemclear(transientCandidates+lookahead, nTimeSlots*sizeof(int));
    937 
    938   for(timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) {
    939     int i, norm;
    940     FIXP_DBL tmpE           = FL2FXCONST_DBL(0.0f);
    941     int headroomEnSlot      = DFRACT_BITS-1;
    942 
    943     FIXP_DBL smallNRG = FL2FXCONST_DBL(1e-2f);
    944     FIXP_DBL denominator;
    945     INT denominator_scale;
    946 
    947     /* determine minimum headroom of energy values for this timeslot */
    948     for(band = startBand; band < stopBand; band++) {
    949       int tmp_headroom = fNormz(Energies[timeSlot][band])-1;
    950       if(tmp_headroom < headroomEnSlot){
    951         headroomEnSlot = tmp_headroom;
    952       }
    953     }
    954 
    955     for(i = 0, band = startBand; band < stopBand; band++, i++) {
    956       /* energy is weighted by weightingfactor stored in dBf_m array */
    957       /* dBf_m index runs from 0 to stopBand-startband               */
    958       /* energy shifted by calculated headroom for maximum precision */
    959       FIXP_DBL weightedEnergy = fMult(Energies[timeSlot][band]<<headroomEnSlot, h_sbrFastTransientDetector->dBf_m[i]);
    960 
    961       /* energy is added up                                                */
    962       /* shift by 6 to have a headroom for maximum 64 additions            */
    963       /* shift by dBf_e to handle weighting factor dependent scale factors */
    964       tmpE += weightedEnergy >> (6 + (10 - h_sbrFastTransientDetector->dBf_e[i]));
    965     }
    966 
    967     /* store calculated energy for timeslot */
    968     energy_timeSlots[timeSlot] = tmpE;
    969 
    970     /* calculate overall scale factor for energy of this timeslot                                                             */
    971     /* =   original scale factor of energies (-scaleEnergies[0]+2*QMF_SCALE_OFFSET or -scaleEnergies[1]+2*QMF_SCALE_OFFSET    */
    972     /*     depending on YBufferWriteOffset)                                                                                   */
    973     /*   + weighting factor scale            (10)                                                                             */
    974     /*   + adding up scale factor            ( 6)                                                                             */
    975     /*   - headroom of energy value          (headroomEnSlot)                                                                 */
    976     if(timeSlot < YBufferWriteOffset){
    977       energy_timeSlots_scale[timeSlot] = (-scaleEnergies[0]+2*QMF_SCALE_OFFSET) + (10+6) - headroomEnSlot;
    978     } else {
    979       energy_timeSlots_scale[timeSlot] = (-scaleEnergies[1]+2*QMF_SCALE_OFFSET) + (10+6) - headroomEnSlot;
    980     }
    981 
    982     /* Add a small energy to the denominator, thus making the transient
    983        detection energy-dependent. Loud transients are being detected,
    984        silent ones not. */
    985 
    986     /* make sure that smallNRG does not overflow */
    987     if ( -energy_timeSlots_scale[timeSlot-1] + 1 > 5 )
    988     {
    989       denominator = smallNRG;
    990       denominator_scale = 0;
    991     } else {
    992       /* Leave an additional headroom of 1 bit for this addition. */
    993       smallNRG = scaleValue(smallNRG, -(energy_timeSlots_scale[timeSlot-1] + 1));
    994       denominator = (energy_timeSlots[timeSlot-1]>>1) + smallNRG;
    995       denominator_scale = energy_timeSlots_scale[timeSlot-1]+1;
    996     }
    997 
    998     delta_energy[timeSlot] = fDivNorm(energy_timeSlots[timeSlot], denominator, &norm);
    999     delta_energy_scale[timeSlot] = energy_timeSlots_scale[timeSlot] - denominator_scale + norm;
   1000   }
   1001 
   1002   /*get transient candidates*/
   1003   /* For every timeslot, check if delta(E) exceeds the threshold. If it did,
   1004      it could potentially be marked as a transient candidate. However, the 2
   1005      slots before the current one must not be transients with an energy higher
   1006      than 1.4*E(current). If both aren't transients or if the energy of the
   1007      current timesolot is more than 1.4 times higher than the energy in the
   1008      last or the one before the last slot, it is marked as a transient.*/
   1009 
   1010   FDK_ASSERT(lookahead >= 2);
   1011   for(timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) {
   1012     FIXP_DBL energy_cur_slot_weighted = fMult(energy_timeSlots[timeSlot],FL2FXCONST_DBL(1.0f/1.4f));
   1013     if( !fIsLessThan(delta_energy[timeSlot], delta_energy_scale[timeSlot], thr, thr_scale) &&
   1014         ( ((transientCandidates[timeSlot-2]==0) && (transientCandidates[timeSlot-1]==0)) ||
   1015           !fIsLessThan(energy_cur_slot_weighted, energy_timeSlots_scale[timeSlot], energy_timeSlots[timeSlot-1], energy_timeSlots_scale[timeSlot-1] ) ||
   1016           !fIsLessThan(energy_cur_slot_weighted, energy_timeSlots_scale[timeSlot], energy_timeSlots[timeSlot-2], energy_timeSlots_scale[timeSlot-2] )
   1017         )
   1018       )
   1019 {
   1020       /* in case of strong transients, subsequent
   1021        * qmf slots might be recognized as transients. */
   1022       transientCandidates[timeSlot] = 1;
   1023     }
   1024   }
   1025 
   1026   /*get transient with max energy*/
   1027   max_delta_energy   = FL2FXCONST_DBL(0.0f);
   1028   max_delta_energy_scale = 0;
   1029   ind_max = 0;
   1030   isTransientInFrame = 0;
   1031   for(timeSlot = 0; timeSlot < nTimeSlots; timeSlot++) {
   1032     int scale = fMax(delta_energy_scale[timeSlot], max_delta_energy_scale);
   1033     if(transientCandidates[timeSlot] && ( (delta_energy[timeSlot] >> (scale - delta_energy_scale[timeSlot])) > (max_delta_energy >> (scale - max_delta_energy_scale)) ) ) {
   1034       max_delta_energy   = delta_energy[timeSlot];
   1035       max_delta_energy_scale = scale;
   1036       ind_max            = timeSlot;
   1037       isTransientInFrame = 1;
   1038     }
   1039   }
   1040 
   1041   /*from all transient candidates take the one with the biggest energy*/
   1042   if(isTransientInFrame) {
   1043     tran_vector[0] = ind_max;
   1044     tran_vector[1] = 1;
   1045   } else {
   1046     /*reset transient info*/
   1047     tran_vector[0] = tran_vector[1] = 0;
   1048   }
   1049 
   1050   /*check for transients in lookahead*/
   1051   for(timeSlot = nTimeSlots; timeSlot < nTimeSlots + lookahead; timeSlot++) {
   1052     if(transientCandidates[timeSlot]) {
   1053       tran_vector[2] = 1;
   1054     }
   1055   }
   1056 
   1057   /*update buffers*/
   1058   for(timeSlot = 0; timeSlot < lookahead; timeSlot++) {
   1059     transientCandidates[timeSlot] = transientCandidates[nTimeSlots + timeSlot];
   1060 
   1061     /* fixpoint stuff */
   1062     energy_timeSlots[timeSlot]    = energy_timeSlots[nTimeSlots + timeSlot];
   1063     energy_timeSlots_scale[timeSlot]  = energy_timeSlots_scale[nTimeSlots + timeSlot];
   1064 
   1065     delta_energy[timeSlot]     = delta_energy[nTimeSlots + timeSlot];
   1066     delta_energy_scale[timeSlot]   = delta_energy_scale[nTimeSlots + timeSlot];
   1067   }
   1068 }
   1069 
   1070