2 /* -----------------------------------------------------------------------------------------------------------
3 Software License for The Fraunhofer FDK AAC Codec Library for Android
5 © Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
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.
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.
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.
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.
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:
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.
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.
42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43 prior written permission.
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.
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."
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.
59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60 by appropriate patent licenses.
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.
73 5. CONTACT INFORMATION
75 Fraunhofer Institute for Integrated Circuits IIS
76 Attention: Audio and Multimedia Departments - FDK AAC LL
78 91058 Erlangen, Germany
80 www.iis.fraunhofer.de/amm
81 amm-info@iis.fraunhofer.de
82 ----------------------------------------------------------------------------------------------------------- */
90 #include "genericStds.h"
92 #define NORM_QMF_ENERGY 5.684341886080801486968994140625e-14 /* 2^-44 */
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)
97 /*******************************************************************************
98 Functionname: spectralChange
99 *******************************************************************************
100 \brief Calculates a measure for the spectral change within the frame
102 The function says how good it would be to split the frame at the given border
103 position into 2 envelopes.
105 The return value delta_sum is scaled with the factor 1/64
107 \return calculated value
108 *******************************************************************************/
109 static FIXP_DBL
spectralChange(FIXP_DBL Energies
[NUMBER_TIME_SLOTS_2304
][MAX_FREQ_COEFFS
],
111 FIXP_DBL EnergyTotal
,
119 FIXP_DBL delta
,tmp0
,tmp1
,tmp2
;
120 FIXP_DBL accu1
,accu2
,delta_sum
,result
;
122 FDK_ASSERT(scaleEnergies
[0] >= 0);
124 /* equal for aac (would be not equal for mp3) */
128 /* prefer borders near the middle of the frame */
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);
133 delta_sum
= FL2FXCONST_DBL(0.0f
);
135 /* Sum up energies of all QMF-timeslots for both halfs */
136 for (j
=0; j
<nSfb
; j
++) {
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 */
143 /* Sum up energies in first half */
144 for (i
=start
; i
<border
; i
++) {
145 accu1
+= (Energies
[i
][j
]>>NRG_SCALE
);
148 /* Sum up energies in second half */
149 for (i
=border
; i
<stop
; i
++) {
150 accu2
+= (Energies
[i
][j
]>>NRG_SCALE
);
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
)));
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)) );
166 delta_sum
+= (FIXP_DBL
)(fMult(sqrtFixp(result
), delta
));
169 return fMult(delta_sum
, pos_weight
);
173 /*******************************************************************************
174 Functionname: addLowbandEnergies
175 *******************************************************************************
176 \brief Calculates total lowband energy
178 The return value nrgTotal is scaled by the factor (1/32.0)
180 \return total energy in the lowband
181 *******************************************************************************/
182 static FIXP_DBL
addLowbandEnergies(FIXP_DBL
**Energies
,
184 int YBufferWriteOffset
,
187 UCHAR
*freqBandTable
,
191 FIXP_DBL accu1
= FL2FXCONST_DBL(0.0f
);
192 FIXP_DBL accu2
= FL2FXCONST_DBL(0.0f
);
193 int tran_offdiv2
= tran_off
>>nrgSzShift
;
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;
202 for (; ts
<tran_offdiv2
+(slots
>>nrgSzShift
); ts
++) {
203 for (k
= 0; k
< freqBandTable
[0]; k
++) {
204 accu2
+= Energies
[ts
][k
] >> 6;
208 nrgTotal
= ( (accu1
>> fixMin(scaleEnergies
[0],(DFRACT_BITS
-1)))
209 + (accu2
>> fixMin(scaleEnergies
[1],(DFRACT_BITS
-1))) ) << (2);
215 /*******************************************************************************
216 Functionname: addHighbandEnergies
217 *******************************************************************************
218 \brief Add highband energies
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
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)
228 \return total energy in the highband
229 *******************************************************************************/
231 static FIXP_DBL
addHighbandEnergies(FIXP_DBL
**RESTRICT Energies
, /*!< input */
233 FIXP_DBL EnergiesM
[NUMBER_TIME_SLOTS_2304
][MAX_FREQ_COEFFS
], /*!< Combined output */
234 UCHAR
*RESTRICT freqBandTable
,
239 INT i
,j
,k
,slotIn
,slotOut
,scale
;
242 FIXP_DBL accu
= FL2FXCONST_DBL(0.0f
);
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
++) {
250 for (j
=0; j
<nSfb
; j
++) {
251 accu
= FL2FXCONST_DBL(0.0f
);
253 li
= freqBandTable
[j
];
254 ui
= freqBandTable
[j
+ 1];
256 for (k
=li
; k
<ui
; k
++) {
257 for (i
=0; i
<timeStep
; i
++) {
258 accu
+= (Energies
[(slotIn
+i
)>>1][k
] >> 5);
261 EnergiesM
[slotOut
][j
] = accu
;
265 scale
= fixMin(8,scaleEnergies
[0]); /* scale energies down before add up */
267 if ((scaleEnergies
[0]-1) > (DFRACT_BITS
-1) )
268 nrgTotal
= FL2FXCONST_DBL(0.0f
);
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
);
277 nrgTotal
= accu
>> (scaleEnergies
[0]-scale
);
284 /*******************************************************************************
285 Functionname: FDKsbrEnc_frameSplitter
286 *******************************************************************************
287 \brief Decides if a FIXFIX-frame shall be splitted into 2 envelopes
289 If no transient has been detected before, the frame can still be splitted
291 *******************************************************************************/
293 FDKsbrEnc_frameSplitter(FIXP_DBL
**Energies
,
295 HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector
,
296 UCHAR
*freqBandTable
,
298 int YBufferWriteOffset
,
304 if (tran_vector
[1]==0) /* no transient was detected */
307 FIXP_DBL EnergiesM
[NUMBER_TIME_SLOTS_2304
][MAX_FREQ_COEFFS
];
308 FIXP_DBL EnergyTotal
,newLowbandEnergy
,newHighbandEnergy
;
310 INT sbrSlots
= fMultI(GetInvInt(timeStep
),no_cols
);
312 FDK_ASSERT( sbrSlots
* timeStep
== no_cols
);
315 Get Lowband-energy over a range of 2 frames (Look half a frame back and ahead).
317 newLowbandEnergy
= addLowbandEnergies(Energies
,
321 h_sbrTransientDetector
->tran_off
,
325 newHighbandEnergy
= addHighbandEnergies(Energies
,
333 if ( h_sbrTransientDetector
->frameShift
!= 0 ) {
334 if (tran_vector
[1]==0)
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;
346 delta
= spectralChange(EnergiesM
,
354 if (delta
> (h_sbrTransientDetector
->split_thr
>> LD_DATA_SHIFT
)) /* delta scaled by 1/64 */
355 tran_vector
[0] = 1; /* Set flag for splitting */
360 /* Update prevLowBandEnergy */
361 h_sbrTransientDetector
->prevLowBandEnergy
= newLowbandEnergy
;
362 h_sbrTransientDetector
->prevHighBandEnergy
= newHighbandEnergy
;
367 * Calculate transient energy threshold for each QMF band
370 calculateThresholds(FIXP_DBL
**RESTRICT Energies
,
371 INT
*RESTRICT scaleEnergies
,
372 FIXP_DBL
*RESTRICT thresholds
,
373 int YBufferWriteOffset
,
379 FIXP_DBL mean_val
,std_val
,temp
;
382 FIXP_DBL accu
,accu0
,accu1
;
383 int scaleFactor0
,scaleFactor1
,commonScale
;
386 i_noCols
= GetInvInt(noCols
+ tran_off
) << YBufferSzShift
;
387 i_noCols1
= GetInvInt(noCols
+ tran_off
- 1) << YBufferSzShift
;
389 /* calc minimum scale of energies of previous and current frame */
390 commonScale
= fixMin(scaleEnergies
[0],scaleEnergies
[1]);
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));
396 FDK_ASSERT((scaleFactor0
>= 0) && (scaleFactor1
>= 0));
398 /* calculate standard deviation in every subband */
399 for (i
=0; i
<noRows
; i
++)
401 int startEnergy
= (tran_off
>>YBufferSzShift
);
402 int endEnergy
= ((noCols
>>YBufferSzShift
)+tran_off
);
405 /* calculate mean value over decimated energy values (downsampled by 2). */
406 accu0
= accu1
= FL2FXCONST_DBL(0.0f
);
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
);
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 */
416 /* calculate standard deviation */
417 accu
= FL2FXCONST_DBL(0.0f
);
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
;
423 temp
= fMult(temp
, i_noCols1
);
426 for (; j
<endEnergy
; j
++) {
427 temp
= ((FIXP_DBL
)mean_val
- ((FIXP_DBL
)Energies
[j
][i
] >> scaleFactor1
))<<shift
;
429 temp
= fMult(temp
, i_noCols1
);
433 std_val
= sqrtFixp(accu
)>>shift
; /* standard deviation */
436 Take new threshold as average of calculated standard deviation ratio
437 and old threshold if greater than absolute threshold
439 temp
= ( commonScale
<=(DFRACT_BITS
-1) )
440 ? fMult(FL2FXCONST_DBL(0.66f
), thresholds
[i
]) + (fMult(FL2FXCONST_DBL(0.34f
), std_val
) >> commonScale
)
443 thresholds
[i
] = fixMax(ABS_THRES
,temp
);
445 FDK_ASSERT(commonScale
>= 0);
450 * Calculate transient levels for each QMF time slot.
453 extractTransientCandidates(FIXP_DBL
**RESTRICT Energies
,
454 INT
*RESTRICT scaleEnergies
,
455 FIXP_DBL
*RESTRICT thresholds
,
456 FIXP_DBL
*RESTRICT transients
,
457 int YBufferWriteOffset
,
466 C_ALLOC_SCRATCH_START(EnergiesTemp
, FIXP_DBL
, 2*QMF_MAX_TIME_SLOTS
);
467 FIXP_DBL
*RESTRICT pEnergiesTemp
= EnergiesTemp
;
468 int tmpScaleEnergies0
, tmpScaleEnergies1
;
470 int startEnerg
,endEnerg
;
473 tmpScaleEnergies0
= scaleEnergies
[0];
474 tmpScaleEnergies1
= scaleEnergies
[1];
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
);
481 FDK_ASSERT((tmpScaleEnergies0
>= 0) && (tmpScaleEnergies1
>= 0));
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
));
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. */
491 /* Compute differential values with two different weightings in every subband */
492 for (i
=start_band
; i
<stop_band
; i
++)
494 FIXP_DBL thres
= thresholds
[i
];
496 if((LONG
)thresholds
[i
]>=256)
497 i_thres
= (LONG
)( (LONG
)MAXVAL_DBL
/ ((((LONG
)thresholds
[i
]))+1) )<<(32-24);
499 i_thres
= (LONG
)MAXVAL_DBL
;
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
;
507 for(; j
<=endEnerg
; j
++) {
508 FIXP_DBL tmp
= Energies
[j
][i
];
509 EnergiesTemp
[(j
<<1)+1] = EnergiesTemp
[j
<<1] = tmp
>>tmpScaleEnergies1
;
512 for(j
=startEnerg
; j
<YBufferWriteOffset
; j
++) {
513 FIXP_DBL tmp
= Energies
[j
][i
];
514 EnergiesTemp
[j
] = tmp
>>tmpScaleEnergies0
;
516 for(; j
<=endEnerg
; j
++) {
517 FIXP_DBL tmp
= Energies
[j
][i
];
518 EnergiesTemp
[j
] = tmp
>>tmpScaleEnergies1
;
522 /* Detect peaks in energy values. */
525 jpBM
= jIndex
+addPrevSamples
;
527 for (j
=endCond
; j
--; jIndex
++, jpBM
++)
530 FIXP_DBL delta
, tran
;
536 for (d
=1; d
<4; d
++) {
537 delta
+= pEnergiesTemp
[jIndex
+d
]; /* R */
538 delta
-= pEnergiesTemp
[jIndex
-d
]; /* L */
541 if ( delta
> (FIXP_DBL
)0 ) {
542 tran
+= fMult(i_thres
, delta
);
545 transients
[jpBM
] += tran
;
548 C_ALLOC_SCRATCH_END(EnergiesTemp
, FIXP_DBL
, 2*QMF_MAX_TIME_SLOTS
);
552 FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTran
,
555 UCHAR
*transient_info
,
556 int YBufferWriteOffset
,
559 int frameMiddleBorder
)
561 int no_cols
= h_sbrTran
->no_cols
;
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;
573 case 1: timeStepShift
= 0; break;
574 case 2: timeStepShift
= 1; break;
575 case 4: timeStepShift
= 2; break;
578 calculateThresholds(Energies
,
580 h_sbrTran
->thresholds
,
585 h_sbrTran
->tran_off
);
587 extractTransientCandidates(Energies
,
589 h_sbrTran
->thresholds
,
590 h_sbrTran
->transients
,
599 transient_info
[0] = 0;
600 transient_info
[1] = 0;
601 transient_info
[2] = 0;
603 /* Offset by the amount of additional previous transient candidates being kept. */
604 qmfStartSample
+= addPrevSamples
;
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
);
612 transient_info
[0] = (i
- qmfStartSample
)>>timeStepShift
;
613 transient_info
[1] = 1;
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
++) {
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
);
627 int pos
= (int) ( (i
- qmfStartSample
-no_cols
) >> timeStepShift
);
628 if ((pos
< 3) && (transient_info
[1]==0)) {
629 transient_info
[2] = 1;
638 FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector
,
641 sbrConfigurationPtr params
,
645 int YBufferWriteOffset
,
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
;
655 FDKmemclear(h_sbrTransientDetector
,sizeof(SBR_TRANSIENT_DETECTOR
));
657 h_sbrTransientDetector
->frameShift
= frameShift
;
658 h_sbrTransientDetector
->tran_off
= tran_off
;
661 bitrateFactor_fix
= fDivNorm((FIXP_DBL
)totalBitrate
, (FIXP_DBL
)(codecBitrate
<<2),&scale_0
);
664 bitrateFactor_fix
= FL2FXCONST_DBL(1.0/4.0);
668 framedur_fix
= fDivNorm(frameSize
, sampleFreq
);
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);
676 tmp
= fixMax(tmp
, FL2FXCONST_DBL(0.0001));
677 tmp
= fDivNorm(FL2FXCONST_DBL(0.000075), fPow2(tmp
), &scale_1
);
679 scale_1
= -(scale_1
+ scale_0
+ 2);
681 FDK_ASSERT(no_cols
<= QMF_MAX_TIME_SLOTS
);
682 FDK_ASSERT(no_rows
<= QMF_CHANNELS
);
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
;
689 h_sbrTransientDetector
->split_thr
= fMult(tmp
, bitrateFactor_fix
) >> scale_1
;
692 h_sbrTransientDetector
->split_thr
= fMult(tmp
, bitrateFactor_fix
) << (-scale_1
);
695 h_sbrTransientDetector
->no_rows
= no_rows
;
696 h_sbrTransientDetector
->mode
= params
->tran_det_mode
;
697 h_sbrTransientDetector
->prevLowBandEnergy
= FL2FXCONST_DBL(0.0f
);