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