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