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