Home | History | Annotate | Download | only in src
      1 /* -----------------------------------------------------------------------------
      2 Software License for The Fraunhofer FDK AAC Codec Library for Android
      3 
      4  Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Frderung der angewandten
      5 Forschung e.V. All rights reserved.
      6 
      7  1.    INTRODUCTION
      8 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
      9 that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
     10 scheme for digital audio. This FDK AAC Codec software is intended to be used on
     11 a wide variety of Android devices.
     12 
     13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
     14 general perceptual audio codecs. AAC-ELD is considered the best-performing
     15 full-bandwidth communications codec by independent studies and is widely
     16 deployed. AAC has been standardized by ISO and IEC as part of the MPEG
     17 specifications.
     18 
     19 Patent licenses for necessary patent claims for the FDK AAC Codec (including
     20 those of Fraunhofer) may be obtained through Via Licensing
     21 (www.vialicensing.com) or through the respective patent owners individually for
     22 the purpose of encoding or decoding bit streams in products that are compliant
     23 with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
     24 Android devices already license these patent claims through Via Licensing or
     25 directly from the patent owners, and therefore FDK AAC Codec software may
     26 already be covered under those patent licenses when it is used for those
     27 licensed purposes only.
     28 
     29 Commercially-licensed AAC software libraries, including floating-point versions
     30 with enhanced sound quality, are also available from Fraunhofer. Users are
     31 encouraged to check the Fraunhofer website for additional applications
     32 information and documentation.
     33 
     34 2.    COPYRIGHT LICENSE
     35 
     36 Redistribution and use in source and binary forms, with or without modification,
     37 are permitted without payment of copyright license fees provided that you
     38 satisfy the following conditions:
     39 
     40 You must retain the complete text of this software license in redistributions of
     41 the FDK AAC Codec or your modifications thereto in source code form.
     42 
     43 You must retain the complete text of this software license in the documentation
     44 and/or other materials provided with redistributions of the FDK AAC Codec or
     45 your modifications thereto in binary form. You must make available free of
     46 charge copies of the complete source code of the FDK AAC Codec and your
     47 modifications thereto to recipients of copies in binary form.
     48 
     49 The name of Fraunhofer may not be used to endorse or promote products derived
     50 from this library without prior written permission.
     51 
     52 You may not charge copyright license fees for anyone to use, copy or distribute
     53 the FDK AAC Codec software or your modifications thereto.
     54 
     55 Your modified versions of the FDK AAC Codec must carry prominent notices stating
     56 that you changed the software and the date of any change. For modified versions
     57 of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
     58 must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
     59 AAC Codec Library for Android."
     60 
     61 3.    NO PATENT LICENSE
     62 
     63 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
     64 limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
     65 Fraunhofer provides no warranty of patent non-infringement with respect to this
     66 software.
     67 
     68 You may use this FDK AAC Codec software or modifications thereto only for
     69 purposes that are authorized by appropriate patent licenses.
     70 
     71 4.    DISCLAIMER
     72 
     73 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
     74 holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
     75 including but not limited to the implied warranties of merchantability and
     76 fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     77 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
     78 or consequential damages, including but not limited to procurement of substitute
     79 goods or services; loss of use, data, or profits, or business interruption,
     80 however caused and on any theory of liability, whether in contract, strict
     81 liability, or tort (including negligence), arising in any way out of the use of
     82 this software, even if advised of the possibility of such damage.
     83 
     84 5.    CONTACT INFORMATION
     85 
     86 Fraunhofer Institute for Integrated Circuits IIS
     87 Attention: Audio and Multimedia Departments - FDK AAC LL
     88 Am Wolfsmantel 33
     89 91058 Erlangen, Germany
     90 
     91 www.iis.fraunhofer.de/amm
     92 amm-info (at) iis.fraunhofer.de
     93 ----------------------------------------------------------------------------- */
     94 
     95 /**************************** SBR encoder library ******************************
     96 
     97    Author(s):   Tobias Chalupka
     98 
     99    Description: SBR encoder transient detector
    100 
    101 *******************************************************************************/
    102 
    103 #include "tran_det.h"
    104 
    105 #include "fram_gen.h"
    106 #include "sbrenc_ram.h"
    107 #include "sbr_misc.h"
    108 
    109 #include "genericStds.h"
    110 
    111 #define NORM_QMF_ENERGY 9.31322574615479E-10 /* 2^-30 */
    112 
    113 /* static FIXP_DBL ABS_THRES = fixMax( FL2FXCONST_DBL(1.28e5 *
    114  * NORM_QMF_ENERGY), (FIXP_DBL)1)  Minimum threshold for detecting changes */
    115 #define ABS_THRES ((FIXP_DBL)16)
    116 
    117 /*******************************************************************************
    118  Functionname:  spectralChange
    119  *******************************************************************************
    120  \brief   Calculates a measure for the spectral change within the frame
    121 
    122  The function says how good it would be to split the frame at the given border
    123  position into 2 envelopes.
    124 
    125  The return value delta_sum is scaled with the factor 1/64
    126 
    127  \return  calculated value
    128 *******************************************************************************/
    129 #define NRG_SHIFT 3 /* for energy summation */
    130 
    131 static FIXP_DBL spectralChange(
    132     FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS],
    133     INT *scaleEnergies, FIXP_DBL EnergyTotal, INT nSfb, INT start, INT border,
    134     INT YBufferWriteOffset, INT stop, INT *result_e) {
    135   INT i, j;
    136   INT len1, len2;
    137   SCHAR energies_e_diff[NUMBER_TIME_SLOTS_2304], energies_e, energyTotal_e = 19,
    138                                                              energies_e_add;
    139   SCHAR prevEnergies_e_diff, newEnergies_e_diff;
    140   FIXP_DBL tmp0, tmp1;
    141   FIXP_DBL delta, delta_sum;
    142   INT accu_e, tmp_e;
    143 
    144   delta_sum = FL2FXCONST_DBL(0.0f);
    145   *result_e = 0;
    146 
    147   len1 = border - start;
    148   len2 = stop - border;
    149 
    150   /* prefer borders near the middle of the frame */
    151   FIXP_DBL pos_weight;
    152   pos_weight = FL2FXCONST_DBL(0.5f) - (len1 * GetInvInt(len1 + len2));
    153   pos_weight = /*FL2FXCONST_DBL(1.0)*/ (FIXP_DBL)MAXVAL_DBL -
    154                (fMult(pos_weight, pos_weight) << 2);
    155 
    156   /*** Calc scaling for energies ***/
    157   FDK_ASSERT(scaleEnergies[0] >= 0);
    158   FDK_ASSERT(scaleEnergies[1] >= 0);
    159 
    160   energies_e = 19 - fMin(scaleEnergies[0], scaleEnergies[1]);
    161 
    162   /* limit shift for energy accumulation, energies_e can be -10 min. */
    163   if (energies_e < -10) {
    164     energies_e_add = -10 - energies_e;
    165     energies_e = -10;
    166   } else if (energies_e > 17) {
    167     energies_e_add = energies_e - 17;
    168     energies_e = 17;
    169   } else {
    170     energies_e_add = 0;
    171   }
    172 
    173   /* compensate scaling differences between scaleEnergies[0] and
    174    * scaleEnergies[1]  */
    175   prevEnergies_e_diff = scaleEnergies[0] -
    176                         fMin(scaleEnergies[0], scaleEnergies[1]) +
    177                         energies_e_add + NRG_SHIFT;
    178   newEnergies_e_diff = scaleEnergies[1] -
    179                        fMin(scaleEnergies[0], scaleEnergies[1]) +
    180                        energies_e_add + NRG_SHIFT;
    181 
    182   prevEnergies_e_diff = fMin(prevEnergies_e_diff, DFRACT_BITS - 1);
    183   newEnergies_e_diff = fMin(newEnergies_e_diff, DFRACT_BITS - 1);
    184 
    185   for (i = start; i < YBufferWriteOffset; i++) {
    186     energies_e_diff[i] = prevEnergies_e_diff;
    187   }
    188   for (i = YBufferWriteOffset; i < stop; i++) {
    189     energies_e_diff[i] = newEnergies_e_diff;
    190   }
    191 
    192   /* Sum up energies of all QMF-timeslots for both halfs */
    193   FDK_ASSERT(len1 <= 8); /* otherwise an overflow is possible */
    194   FDK_ASSERT(len2 <= 8); /* otherwise an overflow is possible */
    195 
    196   for (j = 0; j < nSfb; j++) {
    197     FIXP_DBL accu1 = FL2FXCONST_DBL(0.f);
    198     FIXP_DBL accu2 = FL2FXCONST_DBL(0.f);
    199     accu_e = energies_e + 3;
    200 
    201     /* Sum up energies in first half */
    202     for (i = start; i < border; i++) {
    203       accu1 += scaleValue(Energies[i][j], -energies_e_diff[i]);
    204     }
    205 
    206     /* Sum up energies in second half */
    207     for (i = border; i < stop; i++) {
    208       accu2 += scaleValue(Energies[i][j], -energies_e_diff[i]);
    209     }
    210 
    211     /* Ensure certain energy to prevent division by zero and to prevent
    212      * splitting for very low levels */
    213     accu1 = fMax(accu1, (FIXP_DBL)len1);
    214     accu2 = fMax(accu2, (FIXP_DBL)len2);
    215 
    216 /* Energy change in current band */
    217 #define LN2 FL2FXCONST_DBL(0.6931471806f) /* ln(2) */
    218     tmp0 = fLog2(accu2, accu_e) - fLog2(accu1, accu_e);
    219     tmp1 = fLog2((FIXP_DBL)len1, 31) - fLog2((FIXP_DBL)len2, 31);
    220     delta = fMult(LN2, (tmp0 + tmp1));
    221     delta = (FIXP_DBL)fAbs(delta);
    222 
    223     /* Weighting with amplitude ratio of this band */
    224     accu_e++; /* scale at least one bit due to (accu1+accu2) */
    225     accu1 >>= 1;
    226     accu2 >>= 1;
    227 
    228     if (accu_e & 1) {
    229       accu_e++; /* for a defined square result exponent, the exponent has to be
    230                    even */
    231       accu1 >>= 1;
    232       accu2 >>= 1;
    233     }
    234 
    235     delta_sum += fMult(sqrtFixp(accu1 + accu2), delta);
    236     *result_e = ((accu_e >> 1) + LD_DATA_SHIFT);
    237   }
    238 
    239   if (energyTotal_e & 1) {
    240     energyTotal_e += 1; /* for a defined square result exponent, the exponent
    241                            has to be even */
    242     EnergyTotal >>= 1;
    243   }
    244 
    245   delta_sum = fMult(delta_sum, invSqrtNorm2(EnergyTotal, &tmp_e));
    246   *result_e = *result_e + (tmp_e - (energyTotal_e >> 1));
    247 
    248   return fMult(delta_sum, pos_weight);
    249 }
    250 
    251 /*******************************************************************************
    252  Functionname:  addLowbandEnergies
    253  *******************************************************************************
    254  \brief   Calculates total lowband energy
    255 
    256  The input values Energies[0] (low-band) are scaled by the factor
    257  2^(14-*scaleEnergies[0])
    258  The input values Energies[1] (high-band) are scaled by the factor
    259  2^(14-*scaleEnergies[1])
    260 
    261  \return  total energy in the lowband, scaled by the factor 2^19
    262 *******************************************************************************/
    263 static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies, int *scaleEnergies,
    264                                    int YBufferWriteOffset, int nrgSzShift,
    265                                    int tran_off, UCHAR *freqBandTable,
    266                                    int slots) {
    267   INT nrgTotal_e;
    268   FIXP_DBL nrgTotal_m;
    269   FIXP_DBL accu1 = FL2FXCONST_DBL(0.0f);
    270   FIXP_DBL accu2 = FL2FXCONST_DBL(0.0f);
    271   int tran_offdiv2 = tran_off >> nrgSzShift;
    272   const int sc1 =
    273       DFRACT_BITS -
    274       fNormz((FIXP_DBL)fMax(
    275           1, (freqBandTable[0] * (YBufferWriteOffset - tran_offdiv2) - 1)));
    276   const int sc2 =
    277       DFRACT_BITS -
    278       fNormz((FIXP_DBL)fMax(
    279           1, (freqBandTable[0] *
    280                   (tran_offdiv2 + (slots >> nrgSzShift) - YBufferWriteOffset) -
    281               1)));
    282   int ts, k;
    283 
    284   /* Sum up lowband energy from one frame at offset tran_off */
    285   /* freqBandTable[LORES] has MAX_FREQ_COEFFS/2 +1 coeefs max. */
    286   for (ts = tran_offdiv2; ts < YBufferWriteOffset; ts++) {
    287     for (k = 0; k < freqBandTable[0]; k++) {
    288       accu1 += Energies[ts][k] >> sc1;
    289     }
    290   }
    291   for (; ts < tran_offdiv2 + (slots >> nrgSzShift); ts++) {
    292     for (k = 0; k < freqBandTable[0]; k++) {
    293       accu2 += Energies[ts][k] >> sc2;
    294     }
    295   }
    296 
    297   nrgTotal_m = fAddNorm(accu1, (sc1 - 5) - scaleEnergies[0], accu2,
    298                         (sc2 - 5) - scaleEnergies[1], &nrgTotal_e);
    299   nrgTotal_m = scaleValueSaturate(nrgTotal_m, nrgTotal_e);
    300 
    301   return (nrgTotal_m);
    302 }
    303 
    304 /*******************************************************************************
    305  Functionname:  addHighbandEnergies
    306  *******************************************************************************
    307  \brief   Add highband energies
    308 
    309  Highband energies are mapped to an array with smaller dimension:
    310  Its time resolution is only 1 SBR-timeslot and its frequency resolution
    311  is 1 SBR-band. Therefore the data to be fed into the spectralChange
    312  function is reduced.
    313 
    314  The values EnergiesM are scaled by the factor (2^19-scaleEnergies[0]) for
    315  slots<YBufferWriteOffset and by the factor (2^19-scaleEnergies[1]) for
    316  slots>=YBufferWriteOffset.
    317 
    318  \return  total energy in the highband, scaled by factor 2^19
    319 *******************************************************************************/
    320 
    321 static FIXP_DBL addHighbandEnergies(
    322     FIXP_DBL **RESTRICT Energies, /*!< input */
    323     INT *scaleEnergies, INT YBufferWriteOffset,
    324     FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304]
    325                       [MAX_FREQ_COEFFS], /*!< Combined output */
    326     UCHAR *RESTRICT freqBandTable, INT nSfb, INT sbrSlots, INT timeStep) {
    327   INT i, j, k, slotIn, slotOut, scale[2];
    328   INT li, ui;
    329   FIXP_DBL nrgTotal;
    330   FIXP_DBL accu = FL2FXCONST_DBL(0.0f);
    331 
    332   /* Combine QMF-timeslots to SBR-timeslots,
    333      combine QMF-bands to SBR-bands,
    334      combine Left and Right channel */
    335   for (slotOut = 0; slotOut < sbrSlots; slotOut++) {
    336     /* Note: Below slotIn = slotOut and not slotIn = timeStep*slotOut
    337        because the Energies[] time resolution is always the SBR slot resolution
    338        regardless of the timeStep. */
    339     slotIn = slotOut;
    340 
    341     for (j = 0; j < nSfb; j++) {
    342       accu = FL2FXCONST_DBL(0.0f);
    343 
    344       li = freqBandTable[j];
    345       ui = freqBandTable[j + 1];
    346 
    347       for (k = li; k < ui; k++) {
    348         for (i = 0; i < timeStep; i++) {
    349           accu += Energies[slotIn][k] >> 5;
    350         }
    351       }
    352       EnergiesM[slotOut][j] = accu;
    353     }
    354   }
    355 
    356   /* scale energies down before add up */
    357   scale[0] = fixMin(8, scaleEnergies[0]);
    358   scale[1] = fixMin(8, scaleEnergies[1]);
    359 
    360   if ((scaleEnergies[0] - scale[0]) > (DFRACT_BITS - 1) ||
    361       (scaleEnergies[1] - scale[1]) > (DFRACT_BITS - 1))
    362     nrgTotal = FL2FXCONST_DBL(0.0f);
    363   else {
    364     /* Now add all energies */
    365     accu = FL2FXCONST_DBL(0.0f);
    366 
    367     for (slotOut = 0; slotOut < YBufferWriteOffset; slotOut++) {
    368       for (j = 0; j < nSfb; j++) {
    369         accu += (EnergiesM[slotOut][j] >> scale[0]);
    370       }
    371     }
    372     nrgTotal = accu >> (scaleEnergies[0] - scale[0]);
    373 
    374     for (slotOut = YBufferWriteOffset; slotOut < sbrSlots; slotOut++) {
    375       for (j = 0; j < nSfb; j++) {
    376         accu += (EnergiesM[slotOut][j] >> scale[0]);
    377       }
    378     }
    379     nrgTotal = fAddSaturate(nrgTotal, accu >> (scaleEnergies[1] - scale[1]));
    380   }
    381 
    382   return (nrgTotal);
    383 }
    384 
    385 /*******************************************************************************
    386  Functionname:  FDKsbrEnc_frameSplitter
    387  *******************************************************************************
    388  \brief   Decides if a FIXFIX-frame shall be splitted into 2 envelopes
    389 
    390  If no transient has been detected before, the frame can still be splitted
    391  into 2 envelopes.
    392 *******************************************************************************/
    393 void FDKsbrEnc_frameSplitter(
    394     FIXP_DBL **Energies, INT *scaleEnergies,
    395     HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, UCHAR *freqBandTable,
    396     UCHAR *tran_vector, int YBufferWriteOffset, int YBufferSzShift, int nSfb,
    397     int timeStep, int no_cols, FIXP_DBL *tonality) {
    398   if (tran_vector[1] == 0) /* no transient was detected */
    399   {
    400     FIXP_DBL delta;
    401     INT delta_e;
    402     FIXP_DBL(*EnergiesM)[MAX_FREQ_COEFFS];
    403     FIXP_DBL EnergyTotal, newLowbandEnergy, newHighbandEnergy;
    404     INT border;
    405     INT sbrSlots = fMultI(GetInvInt(timeStep), no_cols);
    406     C_ALLOC_SCRATCH_START(_EnergiesM, FIXP_DBL,
    407                           NUMBER_TIME_SLOTS_2304 * MAX_FREQ_COEFFS)
    408 
    409     FDK_ASSERT(sbrSlots * timeStep == no_cols);
    410 
    411     EnergiesM = (FIXP_DBL(*)[MAX_FREQ_COEFFS])_EnergiesM;
    412 
    413     /*
    414       Get Lowband-energy over a range of 2 frames (Look half a frame back and
    415       ahead).
    416     */
    417     newLowbandEnergy = addLowbandEnergies(
    418         Energies, scaleEnergies, YBufferWriteOffset, YBufferSzShift,
    419         h_sbrTransientDetector->tran_off, freqBandTable, no_cols);
    420 
    421     newHighbandEnergy =
    422         addHighbandEnergies(Energies, scaleEnergies, YBufferWriteOffset,
    423                             EnergiesM, freqBandTable, nSfb, sbrSlots, timeStep);
    424 
    425     {
    426       /* prevLowBandEnergy: Corresponds to 1 frame, starting with half a frame
    427          look-behind newLowbandEnergy:  Corresponds to 1 frame, starting in the
    428          middle of the current frame */
    429       EnergyTotal = (newLowbandEnergy >> 1) +
    430                     (h_sbrTransientDetector->prevLowBandEnergy >>
    431                      1); /* mean of new and prev LB NRG */
    432       EnergyTotal =
    433           fAddSaturate(EnergyTotal, newHighbandEnergy); /* Add HB NRG */
    434       /* The below border should specify the same position as the middle border
    435          of a FIXFIX-frame with 2 envelopes. */
    436       border = (sbrSlots + 1) >> 1;
    437 
    438       if ((INT)EnergyTotal & 0xffffffe0 &&
    439           (scaleEnergies[0] < 32 || scaleEnergies[1] < 32)) /* i.e. > 31 */ {
    440         delta = spectralChange(EnergiesM, scaleEnergies, EnergyTotal, nSfb, 0,
    441                                border, YBufferWriteOffset, sbrSlots, &delta_e);
    442       } else {
    443         delta = FL2FXCONST_DBL(0.0f);
    444         delta_e = 0;
    445 
    446         /* set tonality to 0 when energy is very low, since the amplitude
    447            resolution should then be low as well                          */
    448         *tonality = FL2FXCONST_DBL(0.0f);
    449       }
    450 
    451       if (fIsLessThan(h_sbrTransientDetector->split_thr_m,
    452                       h_sbrTransientDetector->split_thr_e, delta, delta_e)) {
    453         tran_vector[0] = 1; /* Set flag for splitting */
    454       } else {
    455         tran_vector[0] = 0;
    456       }
    457     }
    458 
    459     /* Update prevLowBandEnergy */
    460     h_sbrTransientDetector->prevLowBandEnergy = newLowbandEnergy;
    461     h_sbrTransientDetector->prevHighBandEnergy = newHighbandEnergy;
    462     C_ALLOC_SCRATCH_END(_EnergiesM, FIXP_DBL,
    463                         NUMBER_TIME_SLOTS_2304 * MAX_FREQ_COEFFS)
    464   }
    465 }
    466 
    467 /*
    468  * Calculate transient energy threshold for each QMF band
    469  */
    470 static void calculateThresholds(FIXP_DBL **RESTRICT Energies,
    471                                 INT *RESTRICT scaleEnergies,
    472                                 FIXP_DBL *RESTRICT thresholds,
    473                                 int YBufferWriteOffset, int YBufferSzShift,
    474                                 int noCols, int noRows, int tran_off) {
    475   FIXP_DBL mean_val, std_val, temp;
    476   FIXP_DBL i_noCols;
    477   FIXP_DBL i_noCols1;
    478   FIXP_DBL accu, accu0, accu1;
    479   int scaleFactor0, scaleFactor1, commonScale;
    480   int i, j;
    481 
    482   i_noCols = GetInvInt(noCols + tran_off) << YBufferSzShift;
    483   i_noCols1 = GetInvInt(noCols + tran_off - 1) << YBufferSzShift;
    484 
    485   /* calc minimum scale of energies of previous and current frame */
    486   commonScale = fixMin(scaleEnergies[0], scaleEnergies[1]);
    487 
    488   /* calc scalefactors to adapt energies to common scale */
    489   scaleFactor0 = fixMin((scaleEnergies[0] - commonScale), (DFRACT_BITS - 1));
    490   scaleFactor1 = fixMin((scaleEnergies[1] - commonScale), (DFRACT_BITS - 1));
    491 
    492   FDK_ASSERT((scaleFactor0 >= 0) && (scaleFactor1 >= 0));
    493 
    494   /* calculate standard deviation in every subband */
    495   for (i = 0; i < noRows; i++) {
    496     int startEnergy = (tran_off >> YBufferSzShift);
    497     int endEnergy = ((noCols >> YBufferSzShift) + tran_off);
    498     int shift;
    499 
    500     /* calculate mean value over decimated energy values (downsampled by 2). */
    501     accu0 = accu1 = FL2FXCONST_DBL(0.0f);
    502 
    503     for (j = startEnergy; j < YBufferWriteOffset; j++)
    504       accu0 = fMultAddDiv2(accu0, Energies[j][i], i_noCols);
    505     for (; j < endEnergy; j++)
    506       accu1 = fMultAddDiv2(accu1, Energies[j][i], i_noCols);
    507 
    508     mean_val = ((accu0 << 1) >> scaleFactor0) +
    509                ((accu1 << 1) >> scaleFactor1); /* average */
    510     shift = fixMax(
    511         0, CountLeadingBits(mean_val) -
    512                6); /* -6 to keep room for accumulating upto N = 24 values */
    513 
    514     /* calculate standard deviation */
    515     accu = FL2FXCONST_DBL(0.0f);
    516 
    517     /* summe { ((mean_val-nrg)^2) * i_noCols1 } */
    518     for (j = startEnergy; j < YBufferWriteOffset; j++) {
    519       temp = ((FIXP_DBL)mean_val - ((FIXP_DBL)Energies[j][i] >> scaleFactor0))
    520              << shift;
    521       temp = fPow2Div2(temp);
    522       accu = fMultAddDiv2(accu, temp, i_noCols1);
    523     }
    524     for (; j < endEnergy; j++) {
    525       temp = ((FIXP_DBL)mean_val - ((FIXP_DBL)Energies[j][i] >> scaleFactor1))
    526              << shift;
    527       temp = fPow2Div2(temp);
    528       accu = fMultAddDiv2(accu, temp, i_noCols1);
    529     }
    530     accu <<= 2;
    531     std_val = sqrtFixp(accu) >> shift; /* standard deviation */
    532 
    533     /*
    534     Take new threshold as average of calculated standard deviation ratio
    535     and old threshold if greater than absolute threshold
    536     */
    537     temp = (commonScale <= (DFRACT_BITS - 1))
    538                ? fMult(FL2FXCONST_DBL(0.66f), thresholds[i]) +
    539                      (fMult(FL2FXCONST_DBL(0.34f), std_val) >> commonScale)
    540                : (FIXP_DBL)0;
    541 
    542     thresholds[i] = fixMax(ABS_THRES, temp);
    543 
    544     FDK_ASSERT(commonScale >= 0);
    545   }
    546 }
    547 
    548 /*
    549  * Calculate transient levels for each QMF time slot.
    550  */
    551 static void extractTransientCandidates(
    552     FIXP_DBL **RESTRICT Energies, INT *RESTRICT scaleEnergies,
    553     FIXP_DBL *RESTRICT thresholds, FIXP_DBL *RESTRICT transients,
    554     int YBufferWriteOffset, int YBufferSzShift, int noCols, int start_band,
    555     int stop_band, int tran_off, int addPrevSamples) {
    556   FIXP_DBL i_thres;
    557   C_ALLOC_SCRATCH_START(EnergiesTemp, FIXP_DBL, 2 * 32)
    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,
    575              (tran_off + addPrevSamples) * sizeof(FIXP_DBL));
    576   FDKmemclear(transients + tran_off + addPrevSamples,
    577               noCols * sizeof(FIXP_DBL));
    578 
    579   endCond = noCols; /* Amount of new transient values to be calculated. */
    580   startEnerg = (tran_off - 3) >> YBufferSzShift; /* >>YBufferSzShift because of
    581                                                     amount of energy values. -3
    582                                                     because of neighbors being
    583                                                     watched. */
    584   endEnerg =
    585       ((noCols + (YBufferWriteOffset << YBufferSzShift)) - 1) >>
    586       YBufferSzShift; /* YBufferSzShift shifts because of half energy values. */
    587 
    588   /* Compute differential values with two different weightings in every subband
    589    */
    590   for (i = start_band; i < stop_band; i++) {
    591     FIXP_DBL thres = thresholds[i];
    592 
    593     if ((LONG)thresholds[i] >= 256)
    594       i_thres = (LONG)((LONG)MAXVAL_DBL / ((((LONG)thresholds[i])) + 1))
    595                 << (32 - 24);
    596     else
    597       i_thres = (LONG)MAXVAL_DBL;
    598 
    599     /* Copy one timeslot and de-scale and de-squish */
    600     if (YBufferSzShift == 1) {
    601       for (j = startEnerg; j < YBufferWriteOffset; j++) {
    602         FIXP_DBL tmp = Energies[j][i];
    603         EnergiesTemp[(j << 1) + 1] = EnergiesTemp[j << 1] =
    604             tmp >> tmpScaleEnergies0;
    605       }
    606       for (; j <= endEnerg; j++) {
    607         FIXP_DBL tmp = Energies[j][i];
    608         EnergiesTemp[(j << 1) + 1] = EnergiesTemp[j << 1] =
    609             tmp >> tmpScaleEnergies1;
    610       }
    611     } else {
    612       for (j = startEnerg; j < YBufferWriteOffset; j++) {
    613         FIXP_DBL tmp = Energies[j][i];
    614         EnergiesTemp[j] = tmp >> tmpScaleEnergies0;
    615       }
    616       for (; j <= endEnerg; j++) {
    617         FIXP_DBL tmp = Energies[j][i];
    618         EnergiesTemp[j] = tmp >> tmpScaleEnergies1;
    619       }
    620     }
    621 
    622     /* Detect peaks in energy values. */
    623 
    624     jIndex = tran_off;
    625     jpBM = jIndex + addPrevSamples;
    626 
    627     for (j = endCond; j--; jIndex++, jpBM++) {
    628       FIXP_DBL delta, tran;
    629       int d;
    630 
    631       delta = (FIXP_DBL)0;
    632       tran = (FIXP_DBL)0;
    633 
    634       for (d = 1; d < 4; d++) {
    635         delta += EnergiesTemp[jIndex + d]; /* R */
    636         delta -= EnergiesTemp[jIndex - d]; /* L */
    637         delta -= thres;
    638 
    639         if (delta > (FIXP_DBL)0) {
    640           tran = fMultAddDiv2(tran, i_thres, delta);
    641         }
    642       }
    643       transients[jpBM] += (tran << 1);
    644     }
    645   }
    646   C_ALLOC_SCRATCH_END(EnergiesTemp, FIXP_DBL, 2 * 32)
    647 }
    648 
    649 void FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTran,
    650                                FIXP_DBL **Energies, INT *scaleEnergies,
    651                                UCHAR *transient_info, int YBufferWriteOffset,
    652                                int YBufferSzShift, int timeStep,
    653                                int frameMiddleBorder) {
    654   int no_cols = h_sbrTran->no_cols;
    655   int qmfStartSample;
    656   int addPrevSamples;
    657   int timeStepShift = 0;
    658   int i, cond;
    659 
    660   /* Where to start looking for transients in the transient candidate buffer */
    661   qmfStartSample = timeStep * frameMiddleBorder;
    662   /* We need to look one value backwards in the transients, so we might need one
    663    * more previous value. */
    664   addPrevSamples = (qmfStartSample > 0) ? 0 : 1;
    665 
    666   switch (timeStep) {
    667     case 1:
    668       timeStepShift = 0;
    669       break;
    670     case 2:
    671       timeStepShift = 1;
    672       break;
    673     case 4:
    674       timeStepShift = 2;
    675       break;
    676   }
    677 
    678   calculateThresholds(Energies, scaleEnergies, h_sbrTran->thresholds,
    679                       YBufferWriteOffset, YBufferSzShift, h_sbrTran->no_cols,
    680                       h_sbrTran->no_rows, h_sbrTran->tran_off);
    681 
    682   extractTransientCandidates(
    683       Energies, scaleEnergies, h_sbrTran->thresholds, h_sbrTran->transients,
    684       YBufferWriteOffset, YBufferSzShift, h_sbrTran->no_cols, 0,
    685       h_sbrTran->no_rows, h_sbrTran->tran_off, addPrevSamples);
    686 
    687   transient_info[0] = 0;
    688   transient_info[1] = 0;
    689   transient_info[2] = 0;
    690 
    691   /* Offset by the amount of additional previous transient candidates being
    692    * kept. */
    693   qmfStartSample += addPrevSamples;
    694 
    695   /* Check for transients in second granule (pick the last value of subsequent
    696    * values)  */
    697   for (i = qmfStartSample; i < qmfStartSample + no_cols; i++) {
    698     cond = (h_sbrTran->transients[i] <
    699             fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1])) &&
    700            (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr);
    701 
    702     if (cond) {
    703       transient_info[0] = (i - qmfStartSample) >> timeStepShift;
    704       transient_info[1] = 1;
    705       break;
    706     }
    707   }
    708 
    709   if (h_sbrTran->frameShift != 0) {
    710     /* transient prediction for LDSBR */
    711     /* Check for transients in first <frameShift> qmf-slots of second frame */
    712     for (i = qmfStartSample + no_cols;
    713          i < qmfStartSample + no_cols + h_sbrTran->frameShift; i++) {
    714       cond = (h_sbrTran->transients[i] <
    715               fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1])) &&
    716              (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr);
    717 
    718       if (cond) {
    719         int pos = (int)((i - qmfStartSample - no_cols) >> timeStepShift);
    720         if ((pos < 3) && (transient_info[1] == 0)) {
    721           transient_info[2] = 1;
    722         }
    723         break;
    724       }
    725     }
    726   }
    727 }
    728 
    729 int FDKsbrEnc_InitSbrTransientDetector(
    730     HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
    731     UINT sbrSyntaxFlags, /* SBR syntax flags derived from AOT. */
    732     INT frameSize, INT sampleFreq, sbrConfigurationPtr params, int tran_fc,
    733     int no_cols, int no_rows, int YBufferWriteOffset, int YBufferSzShift,
    734     int frameShift, int tran_off) {
    735   INT totalBitrate =
    736       params->codecSettings.standardBitrate * params->codecSettings.nChannels;
    737   INT codecBitrate = params->codecSettings.bitRate;
    738   FIXP_DBL bitrateFactor_m, framedur_fix;
    739   INT bitrateFactor_e, tmp_e;
    740 
    741   FDKmemclear(h_sbrTransientDetector, sizeof(SBR_TRANSIENT_DETECTOR));
    742 
    743   h_sbrTransientDetector->frameShift = frameShift;
    744   h_sbrTransientDetector->tran_off = tran_off;
    745 
    746   if (codecBitrate) {
    747     bitrateFactor_m = fDivNorm((FIXP_DBL)totalBitrate,
    748                                (FIXP_DBL)(codecBitrate << 2), &bitrateFactor_e);
    749     bitrateFactor_e += 2;
    750   } else {
    751     bitrateFactor_m = FL2FXCONST_DBL(1.0 / 4.0);
    752     bitrateFactor_e = 2;
    753   }
    754 
    755   framedur_fix = fDivNorm(frameSize, sampleFreq);
    756 
    757   /* The longer the frames, the more often should the FIXFIX-
    758   case transmit 2 envelopes instead of 1.
    759   Frame durations below 10 ms produce the highest threshold
    760   so that practically always only 1 env is transmitted. */
    761   FIXP_DBL tmp = framedur_fix - FL2FXCONST_DBL(0.010);
    762 
    763   tmp = fixMax(tmp, FL2FXCONST_DBL(0.0001));
    764   tmp = fDivNorm(FL2FXCONST_DBL(0.000075), fPow2(tmp), &tmp_e);
    765 
    766   bitrateFactor_e = (tmp_e + bitrateFactor_e);
    767 
    768   if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) {
    769     bitrateFactor_e--; /* divide by 2 */
    770   }
    771 
    772   FDK_ASSERT(no_cols <= 32);
    773   FDK_ASSERT(no_rows <= 64);
    774 
    775   h_sbrTransientDetector->no_cols = no_cols;
    776   h_sbrTransientDetector->tran_thr =
    777       (FIXP_DBL)((params->tran_thr << (32 - 24 - 1)) / no_rows);
    778   h_sbrTransientDetector->tran_fc = tran_fc;
    779   h_sbrTransientDetector->split_thr_m = fMult(tmp, bitrateFactor_m);
    780   h_sbrTransientDetector->split_thr_e = bitrateFactor_e;
    781   h_sbrTransientDetector->no_rows = no_rows;
    782   h_sbrTransientDetector->mode = params->tran_det_mode;
    783   h_sbrTransientDetector->prevLowBandEnergy = FL2FXCONST_DBL(0.0f);
    784 
    785   return (0);
    786 }
    787 
    788 #define ENERGY_SCALING_SIZE 32
    789 
    790 INT FDKsbrEnc_InitSbrFastTransientDetector(
    791     HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector,
    792     const INT time_slots_per_frame, const INT bandwidth_qmf_slot,
    793     const INT no_qmf_channels, const INT sbr_qmf_1st_band) {
    794   int i;
    795   int buff_size;
    796   FIXP_DBL myExp;
    797   FIXP_DBL myExpSlot;
    798 
    799   h_sbrFastTransientDetector->lookahead = TRAN_DET_LOOKAHEAD;
    800   h_sbrFastTransientDetector->nTimeSlots = time_slots_per_frame;
    801 
    802   buff_size = h_sbrFastTransientDetector->nTimeSlots +
    803               h_sbrFastTransientDetector->lookahead;
    804 
    805   for (i = 0; i < buff_size; i++) {
    806     h_sbrFastTransientDetector->delta_energy[i] = FL2FXCONST_DBL(0.0f);
    807     h_sbrFastTransientDetector->energy_timeSlots[i] = FL2FXCONST_DBL(0.0f);
    808     h_sbrFastTransientDetector->lowpass_energy[i] = FL2FXCONST_DBL(0.0f);
    809     h_sbrFastTransientDetector->transientCandidates[i] = 0;
    810   }
    811 
    812   FDK_ASSERT(bandwidth_qmf_slot > 0.f);
    813   h_sbrFastTransientDetector->stopBand =
    814       fMin(TRAN_DET_STOP_FREQ / bandwidth_qmf_slot, no_qmf_channels);
    815   h_sbrFastTransientDetector->startBand =
    816       fMin(sbr_qmf_1st_band,
    817            h_sbrFastTransientDetector->stopBand - TRAN_DET_MIN_QMFBANDS);
    818 
    819   FDK_ASSERT(h_sbrFastTransientDetector->startBand < no_qmf_channels);
    820   FDK_ASSERT(h_sbrFastTransientDetector->startBand <
    821              h_sbrFastTransientDetector->stopBand);
    822   FDK_ASSERT(h_sbrFastTransientDetector->startBand > 1);
    823   FDK_ASSERT(h_sbrFastTransientDetector->stopBand > 1);
    824 
    825   /* the energy weighting and adding up has a headroom of 6 Bits,
    826      so up to 64 bands can be added without potential overflow. */
    827   FDK_ASSERT(h_sbrFastTransientDetector->stopBand -
    828                  h_sbrFastTransientDetector->startBand <=
    829              64);
    830 
    831 /* QMF_HP_dB_SLOPE_FIX says that we want a 20 dB per 16 kHz HP filter.
    832    The following lines map this to the QMF bandwidth. */
    833 #define EXP_E 7 /* 64 (=64) multiplications max, max. allowed sum is 0.5 */
    834   myExp = fMultNorm(QMF_HP_dBd_SLOPE_FIX, 0, (FIXP_DBL)bandwidth_qmf_slot,
    835                     DFRACT_BITS - 1, EXP_E);
    836   myExpSlot = myExp;
    837 
    838   for (i = 0; i < 64; i++) {
    839     /* Calculate dBf over all qmf bands:
    840        dBf = (10^(0.002266f/10*bw(slot)))^(band) =
    841            = 2^(log2(10)*0.002266f/10*bw(slot)*band) =
    842            = 2^(0.00075275f*bw(slot)*band)                                   */
    843 
    844     FIXP_DBL dBf_m; /* dBf mantissa        */
    845     INT dBf_e;      /* dBf exponent        */
    846     INT tmp;
    847 
    848     INT dBf_int;        /* dBf integer part    */
    849     FIXP_DBL dBf_fract; /* dBf fractional part */
    850 
    851     /* myExp*(i+1) = myExp_int - myExp_fract
    852        myExp*(i+1) is split up here for better accuracy of CalcInvLdData(),
    853        for its result can be split up into an integer and a fractional part */
    854 
    855     /* Round up to next integer */
    856     FIXP_DBL myExp_int =
    857         (myExpSlot & (FIXP_DBL)0xfe000000) + (FIXP_DBL)0x02000000;
    858 
    859     /* This is the fractional part that needs to be substracted */
    860     FIXP_DBL myExp_fract = myExp_int - myExpSlot;
    861 
    862     /* Calc integer part */
    863     dBf_int = CalcInvLdData(myExp_int);
    864     /* The result needs to be re-scaled. The ld(myExp_int) had been scaled by
    865        EXP_E, the CalcInvLdData expects the operand to be scaled by
    866        LD_DATA_SHIFT. Therefore, the correctly scaled result is
    867        dBf_int^(2^(EXP_E-LD_DATA_SHIFT)), which is dBf_int^2 */
    868 
    869     if (dBf_int <=
    870         46340) { /* compare with maximum allowed value for signed integer
    871                     multiplication, 46340 =
    872                     (INT)floor(sqrt((double)(((UINT)1<<(DFRACT_BITS-1))-1))) */
    873       dBf_int *= dBf_int;
    874 
    875       /* Calc fractional part */
    876       dBf_fract = CalcInvLdData(-myExp_fract);
    877       /* The result needs to be re-scaled. The ld(myExp_fract) had been scaled
    878          by EXP_E, the CalcInvLdData expects the operand to be scaled by
    879          LD_DATA_SHIFT. Therefore, the correctly scaled result is
    880          dBf_fract^(2^(EXP_E-LD_DATA_SHIFT)), which is dBf_fract^2 */
    881       dBf_fract = fMultNorm(dBf_fract, dBf_fract, &tmp);
    882 
    883       /* Get worst case scaling of multiplication result */
    884       dBf_e = (DFRACT_BITS - 1 - tmp) - CountLeadingBits(dBf_int);
    885 
    886       /* Now multiply integer with fractional part of the result, thus resulting
    887          in the overall accurate fractional result */
    888       dBf_m = fMultNorm(dBf_int, DFRACT_BITS - 1, dBf_fract, tmp, dBf_e);
    889 
    890       myExpSlot += myExp;
    891     } else {
    892       dBf_m = (FIXP_DBL)0;
    893       dBf_e = 0;
    894     }
    895 
    896     /* Keep the results */
    897     h_sbrFastTransientDetector->dBf_m[i] = dBf_m;
    898     h_sbrFastTransientDetector->dBf_e[i] = dBf_e;
    899   }
    900 
    901   /* Make sure that dBf is greater than 1.0 (because it should be a highpass) */
    902   /* ... */
    903 
    904   return 0;
    905 }
    906 
    907 void FDKsbrEnc_fastTransientDetect(
    908     const HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector,
    909     const FIXP_DBL *const *Energies, const int *const scaleEnergies,
    910     const INT YBufferWriteOffset, UCHAR *const tran_vector) {
    911   int timeSlot, band;
    912 
    913   FIXP_DBL max_delta_energy; /* helper to store maximum energy ratio          */
    914   int max_delta_energy_scale; /* helper to store scale of maximum energy ratio
    915                                */
    916   int ind_max = 0; /* helper to store index of maximum energy ratio */
    917   int isTransientInFrame = 0;
    918 
    919   const int nTimeSlots = h_sbrFastTransientDetector->nTimeSlots;
    920   const int lookahead = h_sbrFastTransientDetector->lookahead;
    921   const int startBand = h_sbrFastTransientDetector->startBand;
    922   const int stopBand = h_sbrFastTransientDetector->stopBand;
    923 
    924   int *transientCandidates = h_sbrFastTransientDetector->transientCandidates;
    925 
    926   FIXP_DBL *energy_timeSlots = h_sbrFastTransientDetector->energy_timeSlots;
    927   int *energy_timeSlots_scale =
    928       h_sbrFastTransientDetector->energy_timeSlots_scale;
    929 
    930   FIXP_DBL *delta_energy = h_sbrFastTransientDetector->delta_energy;
    931   int *delta_energy_scale = h_sbrFastTransientDetector->delta_energy_scale;
    932 
    933   const FIXP_DBL thr = TRAN_DET_THRSHLD;
    934   const INT thr_scale = TRAN_DET_THRSHLD_SCALE;
    935 
    936   /*reset transient info*/
    937   tran_vector[2] = 0;
    938 
    939   /* reset transient candidates */
    940   FDKmemclear(transientCandidates + lookahead, nTimeSlots * sizeof(int));
    941 
    942   for (timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) {
    943     int i, norm;
    944     FIXP_DBL tmpE = FL2FXCONST_DBL(0.0f);
    945     int headroomEnSlot = DFRACT_BITS - 1;
    946 
    947     FIXP_DBL smallNRG = FL2FXCONST_DBL(1e-2f);
    948     FIXP_DBL denominator;
    949     INT denominator_scale;
    950 
    951     /* determine minimum headroom of energy values for this timeslot */
    952     for (band = startBand; band < stopBand; band++) {
    953       int tmp_headroom = fNormz(Energies[timeSlot][band]) - 1;
    954       if (tmp_headroom < headroomEnSlot) {
    955         headroomEnSlot = tmp_headroom;
    956       }
    957     }
    958 
    959     for (i = 0, band = startBand; band < stopBand; band++, i++) {
    960       /* energy is weighted by weightingfactor stored in dBf_m array */
    961       /* dBf_m index runs from 0 to stopBand-startband               */
    962       /* energy shifted by calculated headroom for maximum precision */
    963       FIXP_DBL weightedEnergy =
    964           fMult(Energies[timeSlot][band] << headroomEnSlot,
    965                 h_sbrFastTransientDetector->dBf_m[i]);
    966 
    967       /* energy is added up                                                */
    968       /* shift by 6 to have a headroom for maximum 64 additions            */
    969       /* shift by dBf_e to handle weighting factor dependent scale factors */
    970       tmpE +=
    971           weightedEnergy >> (6 + (10 - h_sbrFastTransientDetector->dBf_e[i]));
    972     }
    973 
    974     /* store calculated energy for timeslot */
    975     energy_timeSlots[timeSlot] = tmpE;
    976 
    977     /* calculate overall scale factor for energy of this timeslot */
    978     /* =   original scale factor of energies
    979      * (-scaleEnergies[0]+2*QMF_SCALE_OFFSET or
    980      * -scaleEnergies[1]+2*QMF_SCALE_OFFSET    */
    981     /*     depending on YBufferWriteOffset) */
    982     /*   + weighting factor scale            (10) */
    983     /*   + adding up scale factor            ( 6) */
    984     /*   - headroom of energy value          (headroomEnSlot) */
    985     if (timeSlot < YBufferWriteOffset) {
    986       energy_timeSlots_scale[timeSlot] =
    987           (-scaleEnergies[0] + 2 * QMF_SCALE_OFFSET) + (10 + 6) -
    988           headroomEnSlot;
    989     } else {
    990       energy_timeSlots_scale[timeSlot] =
    991           (-scaleEnergies[1] + 2 * QMF_SCALE_OFFSET) + (10 + 6) -
    992           headroomEnSlot;
    993     }
    994 
    995     /* Add a small energy to the denominator, thus making the transient
    996        detection energy-dependent. Loud transients are being detected,
    997        silent ones not. */
    998 
    999     /* make sure that smallNRG does not overflow */
   1000     if (-energy_timeSlots_scale[timeSlot - 1] + 1 > 5) {
   1001       denominator = smallNRG;
   1002       denominator_scale = 0;
   1003     } else {
   1004       /* Leave an additional headroom of 1 bit for this addition. */
   1005       smallNRG =
   1006           scaleValue(smallNRG, -(energy_timeSlots_scale[timeSlot - 1] + 1));
   1007       denominator = (energy_timeSlots[timeSlot - 1] >> 1) + smallNRG;
   1008       denominator_scale = energy_timeSlots_scale[timeSlot - 1] + 1;
   1009     }
   1010 
   1011     delta_energy[timeSlot] =
   1012         fDivNorm(energy_timeSlots[timeSlot], denominator, &norm);
   1013     delta_energy_scale[timeSlot] =
   1014         energy_timeSlots_scale[timeSlot] - denominator_scale + norm;
   1015   }
   1016 
   1017   /*get transient candidates*/
   1018   /* For every timeslot, check if delta(E) exceeds the threshold. If it did,
   1019      it could potentially be marked as a transient candidate. However, the 2
   1020      slots before the current one must not be transients with an energy higher
   1021      than 1.4*E(current). If both aren't transients or if the energy of the
   1022      current timesolot is more than 1.4 times higher than the energy in the
   1023      last or the one before the last slot, it is marked as a transient.*/
   1024 
   1025   FDK_ASSERT(lookahead >= 2);
   1026   for (timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) {
   1027     FIXP_DBL energy_cur_slot_weighted =
   1028         fMult(energy_timeSlots[timeSlot], FL2FXCONST_DBL(1.0f / 1.4f));
   1029     if (!fIsLessThan(delta_energy[timeSlot], delta_energy_scale[timeSlot], thr,
   1030                      thr_scale) &&
   1031         (((transientCandidates[timeSlot - 2] == 0) &&
   1032           (transientCandidates[timeSlot - 1] == 0)) ||
   1033          !fIsLessThan(energy_cur_slot_weighted,
   1034                       energy_timeSlots_scale[timeSlot],
   1035                       energy_timeSlots[timeSlot - 1],
   1036                       energy_timeSlots_scale[timeSlot - 1]) ||
   1037          !fIsLessThan(energy_cur_slot_weighted,
   1038                       energy_timeSlots_scale[timeSlot],
   1039                       energy_timeSlots[timeSlot - 2],
   1040                       energy_timeSlots_scale[timeSlot - 2]))) {
   1041       /* in case of strong transients, subsequent
   1042        * qmf slots might be recognized as transients. */
   1043       transientCandidates[timeSlot] = 1;
   1044     }
   1045   }
   1046 
   1047   /*get transient with max energy*/
   1048   max_delta_energy = FL2FXCONST_DBL(0.0f);
   1049   max_delta_energy_scale = 0;
   1050   ind_max = 0;
   1051   isTransientInFrame = 0;
   1052   for (timeSlot = 0; timeSlot < nTimeSlots; timeSlot++) {
   1053     int scale = fMax(delta_energy_scale[timeSlot], max_delta_energy_scale);
   1054     if (transientCandidates[timeSlot] &&
   1055         ((delta_energy[timeSlot] >> (scale - delta_energy_scale[timeSlot])) >
   1056          (max_delta_energy >> (scale - max_delta_energy_scale)))) {
   1057       max_delta_energy = delta_energy[timeSlot];
   1058       max_delta_energy_scale = scale;
   1059       ind_max = timeSlot;
   1060       isTransientInFrame = 1;
   1061     }
   1062   }
   1063 
   1064   /*from all transient candidates take the one with the biggest energy*/
   1065   if (isTransientInFrame) {
   1066     tran_vector[0] = ind_max;
   1067     tran_vector[1] = 1;
   1068   } else {
   1069     /*reset transient info*/
   1070     tran_vector[0] = tran_vector[1] = 0;
   1071   }
   1072 
   1073   /*check for transients in lookahead*/
   1074   for (timeSlot = nTimeSlots; timeSlot < nTimeSlots + lookahead; timeSlot++) {
   1075     if (transientCandidates[timeSlot]) {
   1076       tran_vector[2] = 1;
   1077     }
   1078   }
   1079 
   1080   /*update buffers*/
   1081   for (timeSlot = 0; timeSlot < lookahead; timeSlot++) {
   1082     transientCandidates[timeSlot] = transientCandidates[nTimeSlots + timeSlot];
   1083 
   1084     /* fixpoint stuff */
   1085     energy_timeSlots[timeSlot] = energy_timeSlots[nTimeSlots + timeSlot];
   1086     energy_timeSlots_scale[timeSlot] =
   1087         energy_timeSlots_scale[nTimeSlots + timeSlot];
   1088 
   1089     delta_energy[timeSlot] = delta_energy[nTimeSlots + timeSlot];
   1090     delta_energy_scale[timeSlot] = delta_energy_scale[nTimeSlots + timeSlot];
   1091   }
   1092 }
   1093