Coverage Report

Created: 2024-09-06 07:53

/src/fdk-aac/libSBRenc/src/tran_det.cpp
Line
Count
Source (jump to first uncovered line)
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
0
#define NRG_SHIFT 3 /* for energy summation */
130
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
0
    INT YBufferWriteOffset, INT stop, INT *result_e) {
135
0
  INT i, j;
136
0
  INT len1, len2;
137
0
  SCHAR energies_e_diff[NUMBER_TIME_SLOTS_2304], energies_e, energyTotal_e = 19,
138
0
                                                             energies_e_add;
139
0
  SCHAR prevEnergies_e_diff, newEnergies_e_diff;
140
0
  FIXP_DBL tmp0, tmp1;
141
0
  FIXP_DBL delta, delta_sum;
142
0
  INT accu_e, tmp_e;
143
144
0
  delta_sum = FL2FXCONST_DBL(0.0f);
145
0
  *result_e = 0;
146
147
0
  len1 = border - start;
148
0
  len2 = stop - border;
149
150
  /* prefer borders near the middle of the frame */
151
0
  FIXP_DBL pos_weight;
152
0
  pos_weight = FL2FXCONST_DBL(0.5f) - (len1 * GetInvInt(len1 + len2));
153
0
  pos_weight = /*FL2FXCONST_DBL(1.0)*/ (FIXP_DBL)MAXVAL_DBL -
154
0
               (fMult(pos_weight, pos_weight) << 2);
155
156
  /*** Calc scaling for energies ***/
157
0
  FDK_ASSERT(scaleEnergies[0] >= 0);
158
0
  FDK_ASSERT(scaleEnergies[1] >= 0);
159
160
0
  energies_e = 19 - fMin(scaleEnergies[0], scaleEnergies[1]);
161
162
  /* limit shift for energy accumulation, energies_e can be -10 min. */
163
0
  if (energies_e < -10) {
164
0
    energies_e_add = -10 - energies_e;
165
0
    energies_e = -10;
166
0
  } else if (energies_e > 17) {
167
0
    energies_e_add = energies_e - 17;
168
0
    energies_e = 17;
169
0
  } else {
170
0
    energies_e_add = 0;
171
0
  }
172
173
  /* compensate scaling differences between scaleEnergies[0] and
174
   * scaleEnergies[1]  */
175
0
  prevEnergies_e_diff = scaleEnergies[0] -
176
0
                        fMin(scaleEnergies[0], scaleEnergies[1]) +
177
0
                        energies_e_add + NRG_SHIFT;
178
0
  newEnergies_e_diff = scaleEnergies[1] -
179
0
                       fMin(scaleEnergies[0], scaleEnergies[1]) +
180
0
                       energies_e_add + NRG_SHIFT;
181
182
0
  prevEnergies_e_diff = fMin(prevEnergies_e_diff, DFRACT_BITS - 1);
183
0
  newEnergies_e_diff = fMin(newEnergies_e_diff, DFRACT_BITS - 1);
184
185
0
  for (i = start; i < YBufferWriteOffset; i++) {
186
0
    energies_e_diff[i] = prevEnergies_e_diff;
187
0
  }
188
0
  for (i = YBufferWriteOffset; i < stop; i++) {
189
0
    energies_e_diff[i] = newEnergies_e_diff;
190
0
  }
191
192
  /* Sum up energies of all QMF-timeslots for both halfs */
193
0
  FDK_ASSERT(len1 <= 8); /* otherwise an overflow is possible */
194
0
  FDK_ASSERT(len2 <= 8); /* otherwise an overflow is possible */
195
196
0
  for (j = 0; j < nSfb; j++) {
197
0
    FIXP_DBL accu1 = FL2FXCONST_DBL(0.f);
198
0
    FIXP_DBL accu2 = FL2FXCONST_DBL(0.f);
199
0
    accu_e = energies_e + 3;
200
201
    /* Sum up energies in first half */
202
0
    for (i = start; i < border; i++) {
203
0
      accu1 += scaleValue(Energies[i][j], -energies_e_diff[i]);
204
0
    }
205
206
    /* Sum up energies in second half */
207
0
    for (i = border; i < stop; i++) {
208
0
      accu2 += scaleValue(Energies[i][j], -energies_e_diff[i]);
209
0
    }
210
211
    /* Ensure certain energy to prevent division by zero and to prevent
212
     * splitting for very low levels */
213
0
    accu1 = fMax(accu1, (FIXP_DBL)len1);
214
0
    accu2 = fMax(accu2, (FIXP_DBL)len2);
215
216
/* Energy change in current band */
217
0
#define LN2 FL2FXCONST_DBL(0.6931471806f) /* ln(2) */
218
0
    tmp0 = fLog2(accu2, accu_e) - fLog2(accu1, accu_e);
219
0
    tmp1 = fLog2((FIXP_DBL)len1, 31) - fLog2((FIXP_DBL)len2, 31);
220
0
    delta = fMult(LN2, (tmp0 + tmp1));
221
0
    delta = (FIXP_DBL)fAbs(delta);
222
223
    /* Weighting with amplitude ratio of this band */
224
0
    accu_e++; /* scale at least one bit due to (accu1+accu2) */
225
0
    accu1 >>= 1;
226
0
    accu2 >>= 1;
227
228
0
    if (accu_e & 1) {
229
0
      accu_e++; /* for a defined square result exponent, the exponent has to be
230
                   even */
231
0
      accu1 >>= 1;
232
0
      accu2 >>= 1;
233
0
    }
234
235
0
    delta_sum += fMult(sqrtFixp(accu1 + accu2), delta);
236
0
    *result_e = ((accu_e >> 1) + LD_DATA_SHIFT);
237
0
  }
238
239
0
  if (energyTotal_e & 1) {
240
0
    energyTotal_e += 1; /* for a defined square result exponent, the exponent
241
                           has to be even */
242
0
    EnergyTotal >>= 1;
243
0
  }
244
245
0
  delta_sum = fMult(delta_sum, invSqrtNorm2(EnergyTotal, &tmp_e));
246
0
  *result_e = *result_e + (tmp_e - (energyTotal_e >> 1));
247
248
0
  return fMult(delta_sum, pos_weight);
249
0
}
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
*******************************************************************************/
263
static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies, int *scaleEnergies,
264
                                   int YBufferWriteOffset, int nrgSzShift,
265
                                   int tran_off, UCHAR *freqBandTable,
266
0
                                   int slots) {
267
0
  INT nrgTotal_e;
268
0
  FIXP_DBL nrgTotal_m;
269
0
  FIXP_DBL accu1 = FL2FXCONST_DBL(0.0f);
270
0
  FIXP_DBL accu2 = FL2FXCONST_DBL(0.0f);
271
0
  int tran_offdiv2 = tran_off >> nrgSzShift;
272
0
  const int sc1 =
273
0
      DFRACT_BITS -
274
0
      fNormz((FIXP_DBL)fMax(
275
0
          1, (freqBandTable[0] * (YBufferWriteOffset - tran_offdiv2) - 1)));
276
0
  const int sc2 =
277
0
      DFRACT_BITS -
278
0
      fNormz((FIXP_DBL)fMax(
279
0
          1, (freqBandTable[0] *
280
0
                  (tran_offdiv2 + (slots >> nrgSzShift) - YBufferWriteOffset) -
281
0
              1)));
282
0
  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
0
  for (ts = tran_offdiv2; ts < YBufferWriteOffset; ts++) {
287
0
    for (k = 0; k < freqBandTable[0]; k++) {
288
0
      accu1 += Energies[ts][k] >> sc1;
289
0
    }
290
0
  }
291
0
  for (; ts < tran_offdiv2 + (slots >> nrgSzShift); ts++) {
292
0
    for (k = 0; k < freqBandTable[0]; k++) {
293
0
      accu2 += Energies[ts][k] >> sc2;
294
0
    }
295
0
  }
296
297
0
  nrgTotal_m = fAddNorm(accu1, (sc1 - 5) - scaleEnergies[0], accu2,
298
0
                        (sc2 - 5) - scaleEnergies[1], &nrgTotal_e);
299
0
  nrgTotal_m = scaleValueSaturate(nrgTotal_m, nrgTotal_e);
300
301
0
  return (nrgTotal_m);
302
0
}
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
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
0
    UCHAR *RESTRICT freqBandTable, INT nSfb, INT sbrSlots, INT timeStep) {
327
0
  INT i, j, k, slotIn, slotOut, scale[2];
328
0
  INT li, ui;
329
0
  FIXP_DBL nrgTotal;
330
0
  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
0
  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
0
    slotIn = slotOut;
340
341
0
    for (j = 0; j < nSfb; j++) {
342
0
      accu = FL2FXCONST_DBL(0.0f);
343
344
0
      li = freqBandTable[j];
345
0
      ui = freqBandTable[j + 1];
346
347
0
      for (k = li; k < ui; k++) {
348
0
        for (i = 0; i < timeStep; i++) {
349
0
          accu += Energies[slotIn][k] >> 5;
350
0
        }
351
0
      }
352
0
      EnergiesM[slotOut][j] = accu;
353
0
    }
354
0
  }
355
356
  /* scale energies down before add up */
357
0
  scale[0] = fixMin(8, scaleEnergies[0]);
358
0
  scale[1] = fixMin(8, scaleEnergies[1]);
359
360
0
  if ((scaleEnergies[0] - scale[0]) > (DFRACT_BITS - 1) ||
361
0
      (scaleEnergies[1] - scale[1]) > (DFRACT_BITS - 1))
362
0
    nrgTotal = FL2FXCONST_DBL(0.0f);
363
0
  else {
364
    /* Now add all energies */
365
0
    accu = FL2FXCONST_DBL(0.0f);
366
367
0
    for (slotOut = 0; slotOut < YBufferWriteOffset; slotOut++) {
368
0
      for (j = 0; j < nSfb; j++) {
369
0
        accu += (EnergiesM[slotOut][j] >> scale[0]);
370
0
      }
371
0
    }
372
0
    nrgTotal = accu >> (scaleEnergies[0] - scale[0]);
373
374
0
    for (slotOut = YBufferWriteOffset; slotOut < sbrSlots; slotOut++) {
375
0
      for (j = 0; j < nSfb; j++) {
376
0
        accu += (EnergiesM[slotOut][j] >> scale[0]);
377
0
      }
378
0
    }
379
0
    nrgTotal = fAddSaturate(nrgTotal, accu >> (scaleEnergies[1] - scale[1]));
380
0
  }
381
382
0
  return (nrgTotal);
383
0
}
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
*******************************************************************************/
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
0
    int timeStep, int no_cols, FIXP_DBL *tonality) {
398
0
  if (tran_vector[1] == 0) /* no transient was detected */
399
0
  {
400
0
    FIXP_DBL delta;
401
0
    INT delta_e;
402
0
    FIXP_DBL(*EnergiesM)[MAX_FREQ_COEFFS];
403
0
    FIXP_DBL EnergyTotal, newLowbandEnergy, newHighbandEnergy;
404
0
    INT border;
405
0
    INT sbrSlots = fMultI(GetInvInt(timeStep), no_cols);
406
0
    C_ALLOC_SCRATCH_START(_EnergiesM, FIXP_DBL,
407
0
                          NUMBER_TIME_SLOTS_2304 * MAX_FREQ_COEFFS)
408
409
0
    FDK_ASSERT(sbrSlots * timeStep == no_cols);
410
411
0
    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
0
    newLowbandEnergy = addLowbandEnergies(
418
0
        Energies, scaleEnergies, YBufferWriteOffset, YBufferSzShift,
419
0
        h_sbrTransientDetector->tran_off, freqBandTable, no_cols);
420
421
0
    newHighbandEnergy =
422
0
        addHighbandEnergies(Energies, scaleEnergies, YBufferWriteOffset,
423
0
                            EnergiesM, freqBandTable, nSfb, sbrSlots, timeStep);
424
425
0
    {
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
0
      EnergyTotal = (newLowbandEnergy >> 1) +
430
0
                    (h_sbrTransientDetector->prevLowBandEnergy >>
431
0
                     1); /* mean of new and prev LB NRG */
432
0
      EnergyTotal =
433
0
          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
0
      border = (sbrSlots + 1) >> 1;
437
438
0
      if ((INT)EnergyTotal & 0xffffffe0 &&
439
0
          (scaleEnergies[0] < 32 || scaleEnergies[1] < 32)) /* i.e. > 31 */ {
440
0
        delta = spectralChange(EnergiesM, scaleEnergies, EnergyTotal, nSfb, 0,
441
0
                               border, YBufferWriteOffset, sbrSlots, &delta_e);
442
0
      } else {
443
0
        delta = FL2FXCONST_DBL(0.0f);
444
0
        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
0
        *tonality = FL2FXCONST_DBL(0.0f);
449
0
      }
450
451
0
      if (fIsLessThan(h_sbrTransientDetector->split_thr_m,
452
0
                      h_sbrTransientDetector->split_thr_e, delta, delta_e)) {
453
0
        tran_vector[0] = 1; /* Set flag for splitting */
454
0
      } else {
455
0
        tran_vector[0] = 0;
456
0
      }
457
0
    }
458
459
    /* Update prevLowBandEnergy */
460
0
    h_sbrTransientDetector->prevLowBandEnergy = newLowbandEnergy;
461
0
    h_sbrTransientDetector->prevHighBandEnergy = newHighbandEnergy;
462
0
    C_ALLOC_SCRATCH_END(_EnergiesM, FIXP_DBL,
463
0
                        NUMBER_TIME_SLOTS_2304 * MAX_FREQ_COEFFS)
464
0
  }
465
0
}
466
467
/*
468
 * Calculate transient energy threshold for each QMF band
469
 */
470
static void calculateThresholds(FIXP_DBL **RESTRICT Energies,
471
                                INT *RESTRICT scaleEnergies,
472
                                FIXP_DBL *RESTRICT thresholds,
473
                                int YBufferWriteOffset, int YBufferSzShift,
474
0
                                int noCols, int noRows, int tran_off) {
475
0
  FIXP_DBL mean_val, std_val, temp;
476
0
  FIXP_DBL i_noCols;
477
0
  FIXP_DBL i_noCols1;
478
0
  FIXP_DBL accu, accu0, accu1;
479
0
  int scaleFactor0, scaleFactor1, commonScale;
480
0
  int i, j;
481
482
0
  i_noCols = GetInvInt(noCols + tran_off) << YBufferSzShift;
483
0
  i_noCols1 = GetInvInt(noCols + tran_off - 1) << YBufferSzShift;
484
485
  /* calc minimum scale of energies of previous and current frame */
486
0
  commonScale = fixMin(scaleEnergies[0], scaleEnergies[1]);
487
488
  /* calc scalefactors to adapt energies to common scale */
489
0
  scaleFactor0 = fixMin((scaleEnergies[0] - commonScale), (DFRACT_BITS - 1));
490
0
  scaleFactor1 = fixMin((scaleEnergies[1] - commonScale), (DFRACT_BITS - 1));
491
492
0
  FDK_ASSERT((scaleFactor0 >= 0) && (scaleFactor1 >= 0));
493
494
  /* calculate standard deviation in every subband */
495
0
  for (i = 0; i < noRows; i++) {
496
0
    int startEnergy = (tran_off >> YBufferSzShift);
497
0
    int endEnergy = ((noCols >> YBufferSzShift) + tran_off);
498
0
    int shift;
499
500
    /* calculate mean value over decimated energy values (downsampled by 2). */
501
0
    accu0 = accu1 = FL2FXCONST_DBL(0.0f);
502
503
0
    for (j = startEnergy; j < YBufferWriteOffset; j++)
504
0
      accu0 = fMultAddDiv2(accu0, Energies[j][i], i_noCols);
505
0
    for (; j < endEnergy; j++)
506
0
      accu1 = fMultAddDiv2(accu1, Energies[j][i], i_noCols);
507
508
0
    mean_val = ((accu0 << 1) >> scaleFactor0) +
509
0
               ((accu1 << 1) >> scaleFactor1); /* average */
510
0
    shift = fixMax(
511
0
        0, CountLeadingBits(mean_val) -
512
0
               6); /* -6 to keep room for accumulating upto N = 24 values */
513
514
    /* calculate standard deviation */
515
0
    accu = FL2FXCONST_DBL(0.0f);
516
517
    /* summe { ((mean_val-nrg)^2) * i_noCols1 } */
518
0
    for (j = startEnergy; j < YBufferWriteOffset; j++) {
519
0
      temp = ((FIXP_DBL)mean_val - ((FIXP_DBL)Energies[j][i] >> scaleFactor0))
520
0
             << shift;
521
0
      temp = fPow2Div2(temp);
522
0
      accu = fMultAddDiv2(accu, temp, i_noCols1);
523
0
    }
524
0
    for (; j < endEnergy; j++) {
525
0
      temp = ((FIXP_DBL)mean_val - ((FIXP_DBL)Energies[j][i] >> scaleFactor1))
526
0
             << shift;
527
0
      temp = fPow2Div2(temp);
528
0
      accu = fMultAddDiv2(accu, temp, i_noCols1);
529
0
    }
530
0
    accu <<= 2;
531
0
    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
0
    temp = (commonScale <= (DFRACT_BITS - 1))
538
0
               ? fMult(FL2FXCONST_DBL(0.66f), thresholds[i]) +
539
0
                     (fMult(FL2FXCONST_DBL(0.34f), std_val) >> commonScale)
540
0
               : (FIXP_DBL)0;
541
542
0
    thresholds[i] = fixMax(ABS_THRES, temp);
543
544
0
    FDK_ASSERT(commonScale >= 0);
545
0
  }
546
0
}
547
548
/*
549
 * Calculate transient levels for each QMF time slot.
550
 */
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
0
    int stop_band, int tran_off, int addPrevSamples) {
556
0
  FIXP_DBL i_thres;
557
0
  C_ALLOC_SCRATCH_START(EnergiesTemp, FIXP_DBL, 2 * 32)
558
0
  int tmpScaleEnergies0, tmpScaleEnergies1;
559
0
  int endCond;
560
0
  int startEnerg, endEnerg;
561
0
  int i, j, jIndex, jpBM;
562
563
0
  tmpScaleEnergies0 = scaleEnergies[0];
564
0
  tmpScaleEnergies1 = scaleEnergies[1];
565
566
  /* Scale value for first energies, upto YBufferWriteOffset */
567
0
  tmpScaleEnergies0 = fixMin(tmpScaleEnergies0, MAX_SHIFT_DBL);
568
  /* Scale value for first energies, from YBufferWriteOffset upwards */
569
0
  tmpScaleEnergies1 = fixMin(tmpScaleEnergies1, MAX_SHIFT_DBL);
570
571
0
  FDK_ASSERT((tmpScaleEnergies0 >= 0) && (tmpScaleEnergies1 >= 0));
572
573
  /* Keep addPrevSamples extra previous transient candidates. */
574
0
  FDKmemmove(transients, transients + noCols - addPrevSamples,
575
0
             (tran_off + addPrevSamples) * sizeof(FIXP_DBL));
576
0
  FDKmemclear(transients + tran_off + addPrevSamples,
577
0
              noCols * sizeof(FIXP_DBL));
578
579
0
  endCond = noCols; /* Amount of new transient values to be calculated. */
580
0
  startEnerg = (tran_off - 3) >> YBufferSzShift; /* >>YBufferSzShift because of
581
                                                    amount of energy values. -3
582
                                                    because of neighbors being
583
                                                    watched. */
584
0
  endEnerg =
585
0
      ((noCols + (YBufferWriteOffset << YBufferSzShift)) - 1) >>
586
0
      YBufferSzShift; /* YBufferSzShift shifts because of half energy values. */
587
588
  /* Compute differential values with two different weightings in every subband
589
   */
590
0
  for (i = start_band; i < stop_band; i++) {
591
0
    FIXP_DBL thres = thresholds[i];
592
593
0
    if ((LONG)thresholds[i] >= 256)
594
0
      i_thres = (LONG)((LONG)MAXVAL_DBL / ((((LONG)thresholds[i])) + 1))
595
0
                << (32 - 24);
596
0
    else
597
0
      i_thres = (LONG)MAXVAL_DBL;
598
599
    /* Copy one timeslot and de-scale and de-squish */
600
0
    if (YBufferSzShift == 1) {
601
0
      for (j = startEnerg; j < YBufferWriteOffset; j++) {
602
0
        FIXP_DBL tmp = Energies[j][i];
603
0
        EnergiesTemp[(j << 1) + 1] = EnergiesTemp[j << 1] =
604
0
            tmp >> tmpScaleEnergies0;
605
0
      }
606
0
      for (; j <= endEnerg; j++) {
607
0
        FIXP_DBL tmp = Energies[j][i];
608
0
        EnergiesTemp[(j << 1) + 1] = EnergiesTemp[j << 1] =
609
0
            tmp >> tmpScaleEnergies1;
610
0
      }
611
0
    } else {
612
0
      for (j = startEnerg; j < YBufferWriteOffset; j++) {
613
0
        FIXP_DBL tmp = Energies[j][i];
614
0
        EnergiesTemp[j] = tmp >> tmpScaleEnergies0;
615
0
      }
616
0
      for (; j <= endEnerg; j++) {
617
0
        FIXP_DBL tmp = Energies[j][i];
618
0
        EnergiesTemp[j] = tmp >> tmpScaleEnergies1;
619
0
      }
620
0
    }
621
622
    /* Detect peaks in energy values. */
623
624
0
    jIndex = tran_off;
625
0
    jpBM = jIndex + addPrevSamples;
626
627
0
    for (j = endCond; j--; jIndex++, jpBM++) {
628
0
      FIXP_DBL delta, tran;
629
0
      int d;
630
631
0
      delta = (FIXP_DBL)0;
632
0
      tran = (FIXP_DBL)0;
633
634
0
      for (d = 1; d < 4; d++) {
635
0
        delta += EnergiesTemp[jIndex + d]; /* R */
636
0
        delta -= EnergiesTemp[jIndex - d]; /* L */
637
0
        delta -= thres;
638
639
0
        if (delta > (FIXP_DBL)0) {
640
0
          tran = fMultAddDiv2(tran, i_thres, delta);
641
0
        }
642
0
      }
643
0
      transients[jpBM] += (tran << 1);
644
0
    }
645
0
  }
646
0
  C_ALLOC_SCRATCH_END(EnergiesTemp, FIXP_DBL, 2 * 32)
647
0
}
648
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
0
                               int frameMiddleBorder) {
654
0
  int no_cols = h_sbrTran->no_cols;
655
0
  int qmfStartSample;
656
0
  int addPrevSamples;
657
0
  int timeStepShift = 0;
658
0
  int i, cond;
659
660
  /* Where to start looking for transients in the transient candidate buffer */
661
0
  qmfStartSample = timeStep * frameMiddleBorder;
662
  /* We need to look one value backwards in the transients, so we might need one
663
   * more previous value. */
664
0
  addPrevSamples = (qmfStartSample > 0) ? 0 : 1;
665
666
0
  switch (timeStep) {
667
0
    case 1:
668
0
      timeStepShift = 0;
669
0
      break;
670
0
    case 2:
671
0
      timeStepShift = 1;
672
0
      break;
673
0
    case 4:
674
0
      timeStepShift = 2;
675
0
      break;
676
0
  }
677
678
0
  calculateThresholds(Energies, scaleEnergies, h_sbrTran->thresholds,
679
0
                      YBufferWriteOffset, YBufferSzShift, h_sbrTran->no_cols,
680
0
                      h_sbrTran->no_rows, h_sbrTran->tran_off);
681
682
0
  extractTransientCandidates(
683
0
      Energies, scaleEnergies, h_sbrTran->thresholds, h_sbrTran->transients,
684
0
      YBufferWriteOffset, YBufferSzShift, h_sbrTran->no_cols, 0,
685
0
      h_sbrTran->no_rows, h_sbrTran->tran_off, addPrevSamples);
686
687
0
  transient_info[0] = 0;
688
0
  transient_info[1] = 0;
689
0
  transient_info[2] = 0;
690
691
  /* Offset by the amount of additional previous transient candidates being
692
   * kept. */
693
0
  qmfStartSample += addPrevSamples;
694
695
  /* Check for transients in second granule (pick the last value of subsequent
696
   * values)  */
697
0
  for (i = qmfStartSample; i < qmfStartSample + no_cols; i++) {
698
0
    cond = (h_sbrTran->transients[i] <
699
0
            fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1])) &&
700
0
           (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr);
701
702
0
    if (cond) {
703
0
      transient_info[0] = (i - qmfStartSample) >> timeStepShift;
704
0
      transient_info[1] = 1;
705
0
      break;
706
0
    }
707
0
  }
708
709
0
  if (h_sbrTran->frameShift != 0) {
710
    /* transient prediction for LDSBR */
711
    /* Check for transients in first <frameShift> qmf-slots of second frame */
712
0
    for (i = qmfStartSample + no_cols;
713
0
         i < qmfStartSample + no_cols + h_sbrTran->frameShift; i++) {
714
0
      cond = (h_sbrTran->transients[i] <
715
0
              fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1])) &&
716
0
             (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr);
717
718
0
      if (cond) {
719
0
        int pos = (int)((i - qmfStartSample - no_cols) >> timeStepShift);
720
0
        if ((pos < 3) && (transient_info[1] == 0)) {
721
0
          transient_info[2] = 1;
722
0
        }
723
0
        break;
724
0
      }
725
0
    }
726
0
  }
727
0
}
728
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
0
    int frameShift, int tran_off) {
735
0
  INT totalBitrate =
736
0
      params->codecSettings.standardBitrate * params->codecSettings.nChannels;
737
0
  INT codecBitrate = params->codecSettings.bitRate;
738
0
  FIXP_DBL bitrateFactor_m, framedur_fix;
739
0
  INT bitrateFactor_e, tmp_e;
740
741
0
  FDKmemclear(h_sbrTransientDetector, sizeof(SBR_TRANSIENT_DETECTOR));
742
743
0
  h_sbrTransientDetector->frameShift = frameShift;
744
0
  h_sbrTransientDetector->tran_off = tran_off;
745
746
0
  if (codecBitrate) {
747
0
    bitrateFactor_m = fDivNorm((FIXP_DBL)totalBitrate,
748
0
                               (FIXP_DBL)(codecBitrate << 2), &bitrateFactor_e);
749
0
    bitrateFactor_e += 2;
750
0
  } else {
751
0
    bitrateFactor_m = FL2FXCONST_DBL(1.0 / 4.0);
752
0
    bitrateFactor_e = 2;
753
0
  }
754
755
0
  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
0
  FIXP_DBL tmp = framedur_fix - FL2FXCONST_DBL(0.010);
762
763
0
  tmp = fixMax(tmp, FL2FXCONST_DBL(0.0001));
764
0
  tmp = fDivNorm(FL2FXCONST_DBL(0.000075), fPow2(tmp), &tmp_e);
765
766
0
  bitrateFactor_e = (tmp_e + bitrateFactor_e);
767
768
0
  if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) {
769
0
    bitrateFactor_e--; /* divide by 2 */
770
0
  }
771
772
0
  FDK_ASSERT(no_cols <= 32);
773
0
  FDK_ASSERT(no_rows <= 64);
774
775
0
  h_sbrTransientDetector->no_cols = no_cols;
776
0
  h_sbrTransientDetector->tran_thr =
777
0
      (FIXP_DBL)((params->tran_thr << (32 - 24 - 1)) / no_rows);
778
0
  h_sbrTransientDetector->tran_fc = tran_fc;
779
0
  h_sbrTransientDetector->split_thr_m = fMult(tmp, bitrateFactor_m);
780
0
  h_sbrTransientDetector->split_thr_e = bitrateFactor_e;
781
0
  h_sbrTransientDetector->no_rows = no_rows;
782
0
  h_sbrTransientDetector->mode = params->tran_det_mode;
783
0
  h_sbrTransientDetector->prevLowBandEnergy = FL2FXCONST_DBL(0.0f);
784
785
0
  return (0);
786
0
}
787
788
#define ENERGY_SCALING_SIZE 32
789
790
INT FDKsbrEnc_InitSbrFastTransientDetector(
791
    HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector,
792
    const INT time_slots_per_frame, const INT bandwidth_qmf_slot,
793
0
    const INT no_qmf_channels, const INT sbr_qmf_1st_band) {
794
0
  int i;
795
0
  int buff_size;
796
0
  FIXP_DBL myExp;
797
0
  FIXP_DBL myExpSlot;
798
799
0
  h_sbrFastTransientDetector->lookahead = TRAN_DET_LOOKAHEAD;
800
0
  h_sbrFastTransientDetector->nTimeSlots = time_slots_per_frame;
801
802
0
  buff_size = h_sbrFastTransientDetector->nTimeSlots +
803
0
              h_sbrFastTransientDetector->lookahead;
804
805
0
  for (i = 0; i < buff_size; i++) {
806
0
    h_sbrFastTransientDetector->delta_energy[i] = FL2FXCONST_DBL(0.0f);
807
0
    h_sbrFastTransientDetector->energy_timeSlots[i] = FL2FXCONST_DBL(0.0f);
808
0
    h_sbrFastTransientDetector->lowpass_energy[i] = FL2FXCONST_DBL(0.0f);
809
0
    h_sbrFastTransientDetector->transientCandidates[i] = 0;
810
0
  }
811
812
0
  FDK_ASSERT(bandwidth_qmf_slot > 0.f);
813
0
  h_sbrFastTransientDetector->stopBand =
814
0
      fMin(TRAN_DET_STOP_FREQ / bandwidth_qmf_slot, no_qmf_channels);
815
0
  h_sbrFastTransientDetector->startBand =
816
0
      fMin(sbr_qmf_1st_band,
817
0
           h_sbrFastTransientDetector->stopBand - TRAN_DET_MIN_QMFBANDS);
818
819
0
  FDK_ASSERT(h_sbrFastTransientDetector->startBand < no_qmf_channels);
820
0
  FDK_ASSERT(h_sbrFastTransientDetector->startBand <
821
0
             h_sbrFastTransientDetector->stopBand);
822
0
  FDK_ASSERT(h_sbrFastTransientDetector->startBand > 1);
823
0
  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
0
  FDK_ASSERT(h_sbrFastTransientDetector->stopBand -
828
0
                 h_sbrFastTransientDetector->startBand <=
829
0
             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
0
#define EXP_E 7 /* 64 (=64) multiplications max, max. allowed sum is 0.5 */
834
0
  myExp = fMultNorm(QMF_HP_dBd_SLOPE_FIX, 0, (FIXP_DBL)bandwidth_qmf_slot,
835
0
                    DFRACT_BITS - 1, EXP_E);
836
0
  myExpSlot = myExp;
837
838
0
  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
0
    FIXP_DBL dBf_m; /* dBf mantissa        */
845
0
    INT dBf_e;      /* dBf exponent        */
846
0
    INT tmp;
847
848
0
    INT dBf_int;        /* dBf integer part    */
849
0
    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
0
    FIXP_DBL myExp_int =
857
0
        (myExpSlot & (FIXP_DBL)0xfe000000) + (FIXP_DBL)0x02000000;
858
859
    /* This is the fractional part that needs to be substracted */
860
0
    FIXP_DBL myExp_fract = myExp_int - myExpSlot;
861
862
    /* Calc integer part */
863
0
    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
0
    if (dBf_int <=
870
0
        46340) { /* compare with maximum allowed value for signed integer
871
                    multiplication, 46340 =
872
                    (INT)floor(sqrt((double)(((UINT)1<<(DFRACT_BITS-1))-1))) */
873
0
      dBf_int *= dBf_int;
874
875
      /* Calc fractional part */
876
0
      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
0
      dBf_fract = fMultNorm(dBf_fract, dBf_fract, &tmp);
882
883
      /* Get worst case scaling of multiplication result */
884
0
      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
0
      dBf_m = fMultNorm(dBf_int, DFRACT_BITS - 1, dBf_fract, tmp, dBf_e);
889
890
0
      myExpSlot += myExp;
891
0
    } else {
892
0
      dBf_m = (FIXP_DBL)0;
893
0
      dBf_e = 0;
894
0
    }
895
896
    /* Keep the results */
897
0
    h_sbrFastTransientDetector->dBf_m[i] = dBf_m;
898
0
    h_sbrFastTransientDetector->dBf_e[i] = dBf_e;
899
0
  }
900
901
  /* Make sure that dBf is greater than 1.0 (because it should be a highpass) */
902
  /* ... */
903
904
0
  return 0;
905
0
}
906
907
void FDKsbrEnc_fastTransientDetect(
908
    const HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector,
909
    const FIXP_DBL *const *Energies, const int *const scaleEnergies,
910
0
    const INT YBufferWriteOffset, UCHAR *const tran_vector) {
911
0
  int timeSlot, band;
912
913
0
  FIXP_DBL max_delta_energy; /* helper to store maximum energy ratio          */
914
0
  int max_delta_energy_scale; /* helper to store scale of maximum energy ratio
915
                               */
916
0
  int ind_max = 0; /* helper to store index of maximum energy ratio */
917
0
  int isTransientInFrame = 0;
918
919
0
  const int nTimeSlots = h_sbrFastTransientDetector->nTimeSlots;
920
0
  const int lookahead = h_sbrFastTransientDetector->lookahead;
921
0
  const int startBand = h_sbrFastTransientDetector->startBand;
922
0
  const int stopBand = h_sbrFastTransientDetector->stopBand;
923
924
0
  int *transientCandidates = h_sbrFastTransientDetector->transientCandidates;
925
926
0
  FIXP_DBL *energy_timeSlots = h_sbrFastTransientDetector->energy_timeSlots;
927
0
  int *energy_timeSlots_scale =
928
0
      h_sbrFastTransientDetector->energy_timeSlots_scale;
929
930
0
  FIXP_DBL *delta_energy = h_sbrFastTransientDetector->delta_energy;
931
0
  int *delta_energy_scale = h_sbrFastTransientDetector->delta_energy_scale;
932
933
0
  const FIXP_DBL thr = TRAN_DET_THRSHLD;
934
0
  const INT thr_scale = TRAN_DET_THRSHLD_SCALE;
935
936
  /*reset transient info*/
937
0
  tran_vector[2] = 0;
938
939
  /* reset transient candidates */
940
0
  FDKmemclear(transientCandidates + lookahead, nTimeSlots * sizeof(int));
941
942
0
  for (timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) {
943
0
    int i, norm;
944
0
    FIXP_DBL tmpE = FL2FXCONST_DBL(0.0f);
945
0
    int headroomEnSlot = DFRACT_BITS - 1;
946
947
0
    FIXP_DBL smallNRG = FL2FXCONST_DBL(1e-2f);
948
0
    FIXP_DBL denominator;
949
0
    INT denominator_scale;
950
951
    /* determine minimum headroom of energy values for this timeslot */
952
0
    for (band = startBand; band < stopBand; band++) {
953
0
      int tmp_headroom = fNormz(Energies[timeSlot][band]) - 1;
954
0
      if (tmp_headroom < headroomEnSlot) {
955
0
        headroomEnSlot = tmp_headroom;
956
0
      }
957
0
    }
958
959
0
    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
0
      FIXP_DBL weightedEnergy =
964
0
          fMult(Energies[timeSlot][band] << headroomEnSlot,
965
0
                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
0
      tmpE +=
971
0
          weightedEnergy >> (6 + (10 - h_sbrFastTransientDetector->dBf_e[i]));
972
0
    }
973
974
    /* store calculated energy for timeslot */
975
0
    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
0
    if (timeSlot < YBufferWriteOffset) {
986
0
      energy_timeSlots_scale[timeSlot] =
987
0
          (-scaleEnergies[0] + 2 * QMF_SCALE_OFFSET) + (10 + 6) -
988
0
          headroomEnSlot;
989
0
    } else {
990
0
      energy_timeSlots_scale[timeSlot] =
991
0
          (-scaleEnergies[1] + 2 * QMF_SCALE_OFFSET) + (10 + 6) -
992
0
          headroomEnSlot;
993
0
    }
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
0
    if (-energy_timeSlots_scale[timeSlot - 1] + 1 > 5) {
1001
0
      denominator = smallNRG;
1002
0
      denominator_scale = 0;
1003
0
    } else {
1004
      /* Leave an additional headroom of 1 bit for this addition. */
1005
0
      smallNRG =
1006
0
          scaleValue(smallNRG, -(energy_timeSlots_scale[timeSlot - 1] + 1));
1007
0
      denominator = (energy_timeSlots[timeSlot - 1] >> 1) + smallNRG;
1008
0
      denominator_scale = energy_timeSlots_scale[timeSlot - 1] + 1;
1009
0
    }
1010
1011
0
    delta_energy[timeSlot] =
1012
0
        fDivNorm(energy_timeSlots[timeSlot], denominator, &norm);
1013
0
    delta_energy_scale[timeSlot] =
1014
0
        energy_timeSlots_scale[timeSlot] - denominator_scale + norm;
1015
0
  }
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
0
  FDK_ASSERT(lookahead >= 2);
1026
0
  for (timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) {
1027
0
    FIXP_DBL energy_cur_slot_weighted =
1028
0
        fMult(energy_timeSlots[timeSlot], FL2FXCONST_DBL(1.0f / 1.4f));
1029
0
    if (!fIsLessThan(delta_energy[timeSlot], delta_energy_scale[timeSlot], thr,
1030
0
                     thr_scale) &&
1031
0
        (((transientCandidates[timeSlot - 2] == 0) &&
1032
0
          (transientCandidates[timeSlot - 1] == 0)) ||
1033
0
         !fIsLessThan(energy_cur_slot_weighted,
1034
0
                      energy_timeSlots_scale[timeSlot],
1035
0
                      energy_timeSlots[timeSlot - 1],
1036
0
                      energy_timeSlots_scale[timeSlot - 1]) ||
1037
0
         !fIsLessThan(energy_cur_slot_weighted,
1038
0
                      energy_timeSlots_scale[timeSlot],
1039
0
                      energy_timeSlots[timeSlot - 2],
1040
0
                      energy_timeSlots_scale[timeSlot - 2]))) {
1041
      /* in case of strong transients, subsequent
1042
       * qmf slots might be recognized as transients. */
1043
0
      transientCandidates[timeSlot] = 1;
1044
0
    }
1045
0
  }
1046
1047
  /*get transient with max energy*/
1048
0
  max_delta_energy = FL2FXCONST_DBL(0.0f);
1049
0
  max_delta_energy_scale = 0;
1050
0
  ind_max = 0;
1051
0
  isTransientInFrame = 0;
1052
0
  for (timeSlot = 0; timeSlot < nTimeSlots; timeSlot++) {
1053
0
    int scale = fMax(delta_energy_scale[timeSlot], max_delta_energy_scale);
1054
0
    if (transientCandidates[timeSlot] &&
1055
0
        ((delta_energy[timeSlot] >> (scale - delta_energy_scale[timeSlot])) >
1056
0
         (max_delta_energy >> (scale - max_delta_energy_scale)))) {
1057
0
      max_delta_energy = delta_energy[timeSlot];
1058
0
      max_delta_energy_scale = scale;
1059
0
      ind_max = timeSlot;
1060
0
      isTransientInFrame = 1;
1061
0
    }
1062
0
  }
1063
1064
  /*from all transient candidates take the one with the biggest energy*/
1065
0
  if (isTransientInFrame) {
1066
0
    tran_vector[0] = ind_max;
1067
0
    tran_vector[1] = 1;
1068
0
  } else {
1069
    /*reset transient info*/
1070
0
    tran_vector[0] = tran_vector[1] = 0;
1071
0
  }
1072
1073
  /*check for transients in lookahead*/
1074
0
  for (timeSlot = nTimeSlots; timeSlot < nTimeSlots + lookahead; timeSlot++) {
1075
0
    if (transientCandidates[timeSlot]) {
1076
0
      tran_vector[2] = 1;
1077
0
    }
1078
0
  }
1079
1080
  /*update buffers*/
1081
0
  for (timeSlot = 0; timeSlot < lookahead; timeSlot++) {
1082
0
    transientCandidates[timeSlot] = transientCandidates[nTimeSlots + timeSlot];
1083
1084
    /* fixpoint stuff */
1085
0
    energy_timeSlots[timeSlot] = energy_timeSlots[nTimeSlots + timeSlot];
1086
0
    energy_timeSlots_scale[timeSlot] =
1087
0
        energy_timeSlots_scale[nTimeSlots + timeSlot];
1088
1089
0
    delta_energy[timeSlot] = delta_energy[nTimeSlots + timeSlot];
1090
0
    delta_energy_scale[timeSlot] = delta_energy_scale[nTimeSlots + timeSlot];
1091
0
  }
1092
0
}