• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung 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@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 
spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS],INT * scaleEnergies,FIXP_DBL EnergyTotal,INT nSfb,INT start,INT border,INT YBufferWriteOffset,INT stop,INT * result_e)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 *******************************************************************************/
addLowbandEnergies(FIXP_DBL ** Energies,int * scaleEnergies,int YBufferWriteOffset,int nrgSzShift,int tran_off,UCHAR * freqBandTable,int slots)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 
addHighbandEnergies(FIXP_DBL ** RESTRICT Energies,INT * scaleEnergies,INT YBufferWriteOffset,FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS],UCHAR * RESTRICT freqBandTable,INT nSfb,INT sbrSlots,INT timeStep)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 *******************************************************************************/
FDKsbrEnc_frameSplitter(FIXP_DBL ** Energies,INT * scaleEnergies,HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,UCHAR * freqBandTable,UCHAR * tran_vector,int YBufferWriteOffset,int YBufferSzShift,int nSfb,int timeStep,int no_cols,FIXP_DBL * tonality)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  */
calculateThresholds(FIXP_DBL ** RESTRICT Energies,INT * RESTRICT scaleEnergies,FIXP_DBL * RESTRICT thresholds,int YBufferWriteOffset,int YBufferSzShift,int noCols,int noRows,int tran_off)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  */
extractTransientCandidates(FIXP_DBL ** RESTRICT Energies,INT * RESTRICT scaleEnergies,FIXP_DBL * RESTRICT thresholds,FIXP_DBL * RESTRICT transients,int YBufferWriteOffset,int YBufferSzShift,int noCols,int start_band,int stop_band,int tran_off,int addPrevSamples)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 
FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTran,FIXP_DBL ** Energies,INT * scaleEnergies,UCHAR * transient_info,int YBufferWriteOffset,int YBufferSzShift,int timeStep,int frameMiddleBorder)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 
FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,UINT sbrSyntaxFlags,INT frameSize,INT sampleFreq,sbrConfigurationPtr params,int tran_fc,int no_cols,int no_rows,int YBufferWriteOffset,int YBufferSzShift,int frameShift,int tran_off)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 
FDKsbrEnc_InitSbrFastTransientDetector(HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector,const INT time_slots_per_frame,const INT bandwidth_qmf_slot,const INT no_qmf_channels,const INT sbr_qmf_1st_band)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 
FDKsbrEnc_fastTransientDetect(const HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector,const FIXP_DBL * const * Energies,const int * const scaleEnergies,const INT YBufferWriteOffset,UCHAR * const tran_vector)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