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