1
2/* -----------------------------------------------------------------------------------------------------------
3Software 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
9The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
12
13AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16of the MPEG specifications.
17
18Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20individually for the purpose of encoding or decoding bit streams in products that are compliant with
21the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23software may already be covered under those patent licenses when it is used for those licensed purposes only.
24
25Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27applications information and documentation.
28
292.    COPYRIGHT LICENSE
30
31Redistribution and use in source and binary forms, with or without modification, are permitted without
32payment of copyright license fees provided that you satisfy the following conditions:
33
34You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35your modifications thereto in source code form.
36
37You must retain the complete text of this software license in the documentation and/or other materials
38provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40modifications thereto to recipients of copies in binary form.
41
42The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43prior written permission.
44
45You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46software or your modifications thereto.
47
48Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49and 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
533.    NO PATENT LICENSE
54
55NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57respect to this software.
58
59You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60by appropriate patent licenses.
61
624.    DISCLAIMER
63
64This 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
66of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69or business interruption, however caused and on any theory of liability, whether in contract, strict
70liability, or tort (including negligence), arising in any way out of the use of this software, even if
71advised of the possibility of such damage.
72
735.    CONTACT INFORMATION
74
75Fraunhofer Institute for Integrated Circuits IIS
76Attention: Audio and Multimedia Departments - FDK AAC LL
77Am Wolfsmantel 33
7891058 Erlangen, Germany
79
80www.iis.fraunhofer.de/amm
81amm-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*******************************************************************************/
109static 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*******************************************************************************/
182static 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
231static 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*******************************************************************************/
292void
293FDKsbrEnc_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 */
369static void
370calculateThresholds(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 */
452static void
453extractTransientCandidates(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
551void
552FDKsbrEnc_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
637int
638FDKsbrEnc_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