1
2 /* -----------------------------------------------------------------------------------------------------------
3 Software License for The Fraunhofer FDK AAC Codec Library for Android
4
5 � Copyright 1995 - 2012 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 5.684341886080801486968994140625e-14 /* 2^-44 */
93
94 /* static FIXP_DBL ABS_THRES = fixMax( FL2FXCONST_DBL(1.28e5 * NORM_QMF_ENERGY), (FIXP_DBL)1) Minimum threshold for detecting changes */
95 #define ABS_THRES ((FIXP_DBL)16)
96
97 /*******************************************************************************
98 Functionname: spectralChange
99 *******************************************************************************
100 \brief Calculates a measure for the spectral change within the frame
101
102 The function says how good it would be to split the frame at the given border
103 position into 2 envelopes.
104
105 The return value delta_sum is scaled with the factor 1/64
106
107 \return calculated value
108 *******************************************************************************/
spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS],INT * scaleEnergies,FIXP_DBL EnergyTotal,INT nSfb,INT start,INT border,INT stop)109 static FIXP_DBL spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS],
110 INT *scaleEnergies,
111 FIXP_DBL EnergyTotal,
112 INT nSfb,
113 INT start,
114 INT border,
115 INT stop)
116 {
117 INT i,j;
118 INT len1,len2;
119 FIXP_DBL delta,tmp0,tmp1,tmp2;
120 FIXP_DBL accu1,accu2,delta_sum,result;
121
122 FDK_ASSERT(scaleEnergies[0] >= 0);
123
124 /* equal for aac (would be not equal for mp3) */
125 len1 = border-start;
126 len2 = stop-border;
127
128 /* prefer borders near the middle of the frame */
129 FIXP_DBL pos_weight;
130 pos_weight = FL2FXCONST_DBL(0.5f) - (len1*GetInvInt(len1+len2));
131 pos_weight = /*FL2FXCONST_DBL(1.0)*/ (FIXP_DBL)MAXVAL_DBL - (fMult(pos_weight, pos_weight)<<2);
132
133 delta_sum = FL2FXCONST_DBL(0.0f);
134
135 /* Sum up energies of all QMF-timeslots for both halfs */
136 for (j=0; j<nSfb; j++) {
137 #define NRG_SCALE 3
138 /* init with some energy to prevent division by zero
139 and to prevent splitting for very low levels */
140 accu1 = ((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY*8.0/32))) << fixMin(scaleEnergies[0],25))>>NRG_SCALE; /* complex init for compare with original version */
141 accu2 = ((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY*8.0/32))) << fixMin(scaleEnergies[0],25))>>NRG_SCALE; /* can be simplified in dsp implementation */
142
143 /* Sum up energies in first half */
144 for (i=start; i<border; i++) {
145 accu1 += (Energies[i][j]>>NRG_SCALE);
146 }
147
148 /* Sum up energies in second half */
149 for (i=border; i<stop; i++) {
150 accu2 += (Energies[i][j]>>NRG_SCALE);
151 }
152
153 /* Energy change in current band */
154 tmp0 = CalcLdData(accu2);
155 tmp1 = CalcLdData(accu1);
156 tmp2 = (tmp0 - tmp1 + CalcLdData(len1)-CalcLdData(len2));
157 delta = fixp_abs(fMult(tmp2, FL2FXCONST_DBL(0.6931471806f)));
158
159 /* Weighting with amplitude ratio of this band */
160 result = (EnergyTotal == FL2FXCONST_DBL(0.0f))
161 ? FL2FXCONST_DBL(0.f)
162 : FDKsbrEnc_LSI_divide_scale_fract( (accu1+accu2),
163 (EnergyTotal>>NRG_SCALE)+(FIXP_DBL)1,
164 (FIXP_DBL)MAXVAL_DBL >> fixMin(scaleEnergies[0],(DFRACT_BITS-1)) );
165
166 delta_sum += (FIXP_DBL)(fMult(sqrtFixp(result), delta));
167 }
168
169 return fMult(delta_sum, pos_weight);
170 }
171
172
173 /*******************************************************************************
174 Functionname: addLowbandEnergies
175 *******************************************************************************
176 \brief Calculates total lowband energy
177
178 The return value nrgTotal is scaled by the factor (1/32.0)
179
180 \return total energy in the lowband
181 *******************************************************************************/
addLowbandEnergies(FIXP_DBL ** Energies,int * scaleEnergies,int YBufferWriteOffset,int nrgSzShift,int tran_off,UCHAR * freqBandTable,int slots)182 static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies,
183 int *scaleEnergies,
184 int YBufferWriteOffset,
185 int nrgSzShift,
186 int tran_off,
187 UCHAR *freqBandTable,
188 int slots)
189 {
190 FIXP_DBL nrgTotal;
191 FIXP_DBL accu1 = FL2FXCONST_DBL(0.0f);
192 FIXP_DBL accu2 = FL2FXCONST_DBL(0.0f);
193 int tran_offdiv2 = tran_off>>nrgSzShift;
194 int ts,k;
195
196 /* Sum up lowband energy from one frame at offset tran_off */
197 for (ts=tran_offdiv2; ts<YBufferWriteOffset; ts++) {
198 for (k = 0; k < freqBandTable[0]; k++) {
199 accu1 += Energies[ts][k] >> 6;
200 }
201 }
202 for (; ts<tran_offdiv2+(slots>>nrgSzShift); ts++) {
203 for (k = 0; k < freqBandTable[0]; k++) {
204 accu2 += Energies[ts][k] >> 6;
205 }
206 }
207
208 nrgTotal = ( (accu1 >> fixMin(scaleEnergies[0],(DFRACT_BITS-1)))
209 + (accu2 >> fixMin(scaleEnergies[1],(DFRACT_BITS-1))) ) << (2);
210
211 return(nrgTotal);
212 }
213
214
215 /*******************************************************************************
216 Functionname: addHighbandEnergies
217 *******************************************************************************
218 \brief Add highband energies
219
220 Highband energies are mapped to an array with smaller dimension:
221 Its time resolution is only 1 SBR-timeslot and its frequency resolution
222 is 1 SBR-band. Therefore the data to be fed into the spectralChange
223 function is reduced.
224
225 The values EnergiesM are scaled by the factor (1/32.0) and scaleEnergies[0]
226 The return value nrgTotal is scaled by the factor (1/32.0)
227
228 \return total energy in the highband
229 *******************************************************************************/
230
addHighbandEnergies(FIXP_DBL ** RESTRICT Energies,INT * scaleEnergies,FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS],UCHAR * RESTRICT freqBandTable,INT nSfb,INT sbrSlots,INT timeStep)231 static FIXP_DBL addHighbandEnergies(FIXP_DBL **RESTRICT Energies, /*!< input */
232 INT *scaleEnergies,
233 FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS], /*!< Combined output */
234 UCHAR *RESTRICT freqBandTable,
235 INT nSfb,
236 INT sbrSlots,
237 INT timeStep)
238 {
239 INT i,j,k,slotIn,slotOut,scale;
240 INT li,ui;
241 FIXP_DBL nrgTotal;
242 FIXP_DBL accu = FL2FXCONST_DBL(0.0f);
243
244 /* Combine QMF-timeslots to SBR-timeslots,
245 combine QMF-bands to SBR-bands,
246 combine Left and Right channel */
247 for (slotOut=0; slotOut<sbrSlots; slotOut++) {
248 slotIn = 2*slotOut;
249
250 for (j=0; j<nSfb; j++) {
251 accu = FL2FXCONST_DBL(0.0f);
252
253 li = freqBandTable[j];
254 ui = freqBandTable[j + 1];
255
256 for (k=li; k<ui; k++) {
257 for (i=0; i<timeStep; i++) {
258 accu += (Energies[(slotIn+i)>>1][k] >> 5);
259 }
260 }
261 EnergiesM[slotOut][j] = accu;
262 }
263 }
264
265 scale = fixMin(8,scaleEnergies[0]); /* scale energies down before add up */
266
267 if ((scaleEnergies[0]-1) > (DFRACT_BITS-1) )
268 nrgTotal = FL2FXCONST_DBL(0.0f);
269 else {
270 /* Now add all energies */
271 accu = FL2FXCONST_DBL(0.0f);
272 for (slotOut=0; slotOut<sbrSlots; slotOut++) {
273 for (j=0; j<nSfb; j++) {
274 accu += (EnergiesM[slotOut][j] >> scale);
275 }
276 }
277 nrgTotal = accu >> (scaleEnergies[0]-scale);
278 }
279
280 return(nrgTotal);
281 }
282
283
284 /*******************************************************************************
285 Functionname: FDKsbrEnc_frameSplitter
286 *******************************************************************************
287 \brief Decides if a FIXFIX-frame shall be splitted into 2 envelopes
288
289 If no transient has been detected before, the frame can still be splitted
290 into 2 envelopes.
291 *******************************************************************************/
292 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)293 FDKsbrEnc_frameSplitter(FIXP_DBL **Energies,
294 INT *scaleEnergies,
295 HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
296 UCHAR *freqBandTable,
297 UCHAR *tran_vector,
298 int YBufferWriteOffset,
299 int YBufferSzShift,
300 int nSfb,
301 int timeStep,
302 int no_cols)
303 {
304 if (tran_vector[1]==0) /* no transient was detected */
305 {
306 FIXP_DBL delta;
307 FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS];
308 FIXP_DBL EnergyTotal,newLowbandEnergy,newHighbandEnergy;
309 INT border;
310 INT sbrSlots = fMultI(GetInvInt(timeStep),no_cols);
311
312 FDK_ASSERT( sbrSlots * timeStep == no_cols );
313
314 /*
315 Get Lowband-energy over a range of 2 frames (Look half a frame back and ahead).
316 */
317 newLowbandEnergy = addLowbandEnergies(Energies,
318 scaleEnergies,
319 YBufferWriteOffset,
320 YBufferSzShift,
321 h_sbrTransientDetector->tran_off,
322 freqBandTable,
323 no_cols);
324
325 newHighbandEnergy = addHighbandEnergies(Energies,
326 scaleEnergies,
327 EnergiesM,
328 freqBandTable,
329 nSfb,
330 sbrSlots,
331 timeStep);
332
333 if ( h_sbrTransientDetector->frameShift != 0 ) {
334 if (tran_vector[1]==0)
335 tran_vector[0] = 0;
336 } else
337 {
338 /* prevLowBandEnergy: Corresponds to 1 frame, starting with half a frame look-behind
339 newLowbandEnergy: Corresponds to 1 frame, starting in the middle of the current frame */
340 EnergyTotal = (newLowbandEnergy + h_sbrTransientDetector->prevLowBandEnergy) >> 1;
341 EnergyTotal += newHighbandEnergy;
342 /* The below border should specify the same position as the middle border
343 of a FIXFIX-frame with 2 envelopes. */
344 border = (sbrSlots+1) >> 1;
345
346 delta = spectralChange(EnergiesM,
347 scaleEnergies,
348 EnergyTotal,
349 nSfb,
350 0,
351 border,
352 sbrSlots);
353
354 if (delta > (h_sbrTransientDetector->split_thr >> LD_DATA_SHIFT)) /* delta scaled by 1/64 */
355 tran_vector[0] = 1; /* Set flag for splitting */
356 else
357 tran_vector[0] = 0;
358 }
359
360 /* Update prevLowBandEnergy */
361 h_sbrTransientDetector->prevLowBandEnergy = newLowbandEnergy;
362 h_sbrTransientDetector->prevHighBandEnergy = newHighbandEnergy;
363 }
364 }
365
366 /*
367 * Calculate transient energy threshold for each QMF band
368 */
369 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)370 calculateThresholds(FIXP_DBL **RESTRICT Energies,
371 INT *RESTRICT scaleEnergies,
372 FIXP_DBL *RESTRICT thresholds,
373 int YBufferWriteOffset,
374 int YBufferSzShift,
375 int noCols,
376 int noRows,
377 int tran_off)
378 {
379 FIXP_DBL mean_val,std_val,temp;
380 FIXP_DBL i_noCols;
381 FIXP_DBL i_noCols1;
382 FIXP_DBL accu,accu0,accu1;
383 int scaleFactor0,scaleFactor1,commonScale;
384 int i,j;
385
386 i_noCols = GetInvInt(noCols + tran_off ) << YBufferSzShift;
387 i_noCols1 = GetInvInt(noCols + tran_off - 1) << YBufferSzShift;
388
389 /* calc minimum scale of energies of previous and current frame */
390 commonScale = fixMin(scaleEnergies[0],scaleEnergies[1]);
391
392 /* calc scalefactors to adapt energies to common scale */
393 scaleFactor0 = fixMin((scaleEnergies[0]-commonScale), (DFRACT_BITS-1));
394 scaleFactor1 = fixMin((scaleEnergies[1]-commonScale), (DFRACT_BITS-1));
395
396 FDK_ASSERT((scaleFactor0 >= 0) && (scaleFactor1 >= 0));
397
398 /* calculate standard deviation in every subband */
399 for (i=0; i<noRows; i++)
400 {
401 int startEnergy = (tran_off>>YBufferSzShift);
402 int endEnergy = ((noCols>>YBufferSzShift)+tran_off);
403 int shift;
404
405 /* calculate mean value over decimated energy values (downsampled by 2). */
406 accu0 = accu1 = FL2FXCONST_DBL(0.0f);
407
408 for (j=startEnergy; j<YBufferWriteOffset; j++)
409 accu0 += fMult(Energies[j][i], i_noCols);
410 for (; j<endEnergy; j++)
411 accu1 += fMult(Energies[j][i], i_noCols);
412
413 mean_val = (accu0 >> scaleFactor0) + (accu1 >> scaleFactor1); /* average */
414 shift = fixMax(0,CountLeadingBits(mean_val)-6); /* -6 to keep room for accumulating upto N = 24 values */
415
416 /* calculate standard deviation */
417 accu = FL2FXCONST_DBL(0.0f);
418
419 /* summe { ((mean_val-nrg)^2) * i_noCols1 } */
420 for (j=startEnergy; j<YBufferWriteOffset; j++) {
421 temp = ((FIXP_DBL)mean_val - ((FIXP_DBL)Energies[j][i] >> scaleFactor0))<<shift;
422 temp = fPow2(temp);
423 temp = fMult(temp, i_noCols1);
424 accu += temp;
425 }
426 for (; j<endEnergy; j++) {
427 temp = ((FIXP_DBL)mean_val - ((FIXP_DBL)Energies[j][i] >> scaleFactor1))<<shift;
428 temp = fPow2(temp);
429 temp = fMult(temp, i_noCols1);
430 accu += temp;
431 }
432
433 std_val = sqrtFixp(accu)>>shift; /* standard deviation */
434
435 /*
436 Take new threshold as average of calculated standard deviation ratio
437 and old threshold if greater than absolute threshold
438 */
439 temp = ( commonScale<=(DFRACT_BITS-1) )
440 ? fMult(FL2FXCONST_DBL(0.66f), thresholds[i]) + (fMult(FL2FXCONST_DBL(0.34f), std_val) >> commonScale)
441 : (FIXP_DBL) 0;
442
443 thresholds[i] = fixMax(ABS_THRES,temp);
444
445 FDK_ASSERT(commonScale >= 0);
446 }
447 }
448
449 /*
450 * Calculate transient levels for each QMF time slot.
451 */
452 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)453 extractTransientCandidates(FIXP_DBL **RESTRICT Energies,
454 INT *RESTRICT scaleEnergies,
455 FIXP_DBL *RESTRICT thresholds,
456 FIXP_DBL *RESTRICT transients,
457 int YBufferWriteOffset,
458 int YBufferSzShift,
459 int noCols,
460 int start_band,
461 int stop_band,
462 int tran_off,
463 int addPrevSamples)
464 {
465 FIXP_DBL i_thres;
466 C_ALLOC_SCRATCH_START(EnergiesTemp, FIXP_DBL, 2*QMF_MAX_TIME_SLOTS);
467 FIXP_DBL *RESTRICT pEnergiesTemp = EnergiesTemp;
468 int tmpScaleEnergies0, tmpScaleEnergies1;
469 int endCond;
470 int startEnerg,endEnerg;
471 int i,j,jIndex,jpBM;
472
473 tmpScaleEnergies0 = scaleEnergies[0];
474 tmpScaleEnergies1 = scaleEnergies[1];
475
476 /* Scale value for first energies, upto YBufferWriteOffset */
477 tmpScaleEnergies0 = fixMin(tmpScaleEnergies0, MAX_SHIFT_DBL);
478 /* Scale value for first energies, from YBufferWriteOffset upwards */
479 tmpScaleEnergies1 = fixMin(tmpScaleEnergies1, MAX_SHIFT_DBL);
480
481 FDK_ASSERT((tmpScaleEnergies0 >= 0) && (tmpScaleEnergies1 >= 0));
482
483 /* Keep addPrevSamples extra previous transient candidates. */
484 FDKmemmove(transients, transients + noCols - addPrevSamples, (tran_off+addPrevSamples) * sizeof (FIXP_DBL));
485 FDKmemclear(transients + tran_off + addPrevSamples, noCols * sizeof (FIXP_DBL));
486
487 endCond = noCols; /* Amount of new transient values to be calculated. */
488 startEnerg = (tran_off-3)>>YBufferSzShift; /* >>YBufferSzShift because of amount of energy values. -3 because of neighbors being watched. */
489 endEnerg = ((noCols+ (YBufferWriteOffset<<YBufferSzShift))-1)>>YBufferSzShift; /* YBufferSzShift shifts because of half energy values. */
490
491 /* Compute differential values with two different weightings in every subband */
492 for (i=start_band; i<stop_band; i++)
493 {
494 FIXP_DBL thres = thresholds[i];
495
496 if((LONG)thresholds[i]>=256)
497 i_thres = (LONG)( (LONG)MAXVAL_DBL / ((((LONG)thresholds[i]))+1) )<<(32-24);
498 else
499 i_thres = (LONG)MAXVAL_DBL;
500
501 /* Copy one timeslot and de-scale and de-squish */
502 if (YBufferSzShift == 1) {
503 for(j=startEnerg; j<YBufferWriteOffset; j++) {
504 FIXP_DBL tmp = Energies[j][i];
505 EnergiesTemp[(j<<1)+1] = EnergiesTemp[j<<1] = tmp>>tmpScaleEnergies0;
506 }
507 for(; j<=endEnerg; j++) {
508 FIXP_DBL tmp = Energies[j][i];
509 EnergiesTemp[(j<<1)+1] = EnergiesTemp[j<<1] = tmp>>tmpScaleEnergies1;
510 }
511 } else {
512 for(j=startEnerg; j<YBufferWriteOffset; j++) {
513 FIXP_DBL tmp = Energies[j][i];
514 EnergiesTemp[j] = tmp>>tmpScaleEnergies0;
515 }
516 for(; j<=endEnerg; j++) {
517 FIXP_DBL tmp = Energies[j][i];
518 EnergiesTemp[j] = tmp>>tmpScaleEnergies1;
519 }
520 }
521
522 /* Detect peaks in energy values. */
523
524 jIndex = tran_off;
525 jpBM = jIndex+addPrevSamples;
526
527 for (j=endCond; j--; jIndex++, jpBM++)
528 {
529
530 FIXP_DBL delta, tran;
531 int d;
532
533 delta = (FIXP_DBL)0;
534 tran = (FIXP_DBL)0;
535
536 for (d=1; d<4; d++) {
537 delta += pEnergiesTemp[jIndex+d]; /* R */
538 delta -= pEnergiesTemp[jIndex-d]; /* L */
539 delta -= thres;
540
541 if ( delta > (FIXP_DBL)0 ) {
542 tran += fMult(i_thres, delta);
543 }
544 }
545 transients[jpBM] += tran;
546 }
547 }
548 C_ALLOC_SCRATCH_END(EnergiesTemp, FIXP_DBL, 2*QMF_MAX_TIME_SLOTS);
549 }
550
551 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)552 FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTran,
553 FIXP_DBL **Energies,
554 INT *scaleEnergies,
555 UCHAR *transient_info,
556 int YBufferWriteOffset,
557 int YBufferSzShift,
558 int timeStep,
559 int frameMiddleBorder)
560 {
561 int no_cols = h_sbrTran->no_cols;
562 int qmfStartSample;
563 int addPrevSamples;
564 int timeStepShift=0;
565 int i, cond;
566
567 /* Where to start looking for transients in the transient candidate buffer */
568 qmfStartSample = timeStep * frameMiddleBorder;
569 /* We need to look one value backwards in the transients, so we might need one more previous value. */
570 addPrevSamples = (qmfStartSample > 0) ? 0: 1;
571
572 switch (timeStep) {
573 case 1: timeStepShift = 0; break;
574 case 2: timeStepShift = 1; break;
575 case 4: timeStepShift = 2; break;
576 }
577
578 calculateThresholds(Energies,
579 scaleEnergies,
580 h_sbrTran->thresholds,
581 YBufferWriteOffset,
582 YBufferSzShift,
583 h_sbrTran->no_cols,
584 h_sbrTran->no_rows,
585 h_sbrTran->tran_off);
586
587 extractTransientCandidates(Energies,
588 scaleEnergies,
589 h_sbrTran->thresholds,
590 h_sbrTran->transients,
591 YBufferWriteOffset,
592 YBufferSzShift,
593 h_sbrTran->no_cols,
594 0,
595 h_sbrTran->no_rows,
596 h_sbrTran->tran_off,
597 addPrevSamples );
598
599 transient_info[0] = 0;
600 transient_info[1] = 0;
601 transient_info[2] = 0;
602
603 /* Offset by the amount of additional previous transient candidates being kept. */
604 qmfStartSample += addPrevSamples;
605
606 /* Check for transients in second granule (pick the last value of subsequent values) */
607 for (i=qmfStartSample; i<qmfStartSample + no_cols; i++) {
608 cond = (h_sbrTran->transients[i] < fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1]) )
609 && (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr);
610
611 if (cond) {
612 transient_info[0] = (i - qmfStartSample)>>timeStepShift;
613 transient_info[1] = 1;
614 break;
615 }
616 }
617
618 if ( h_sbrTran->frameShift != 0) {
619 /* transient prediction for LDSBR */
620 /* Check for transients in first <frameShift> qmf-slots of second frame */
621 for (i=qmfStartSample+no_cols; i<qmfStartSample + no_cols+h_sbrTran->frameShift; i++) {
622
623 cond = (h_sbrTran->transients[i] < fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1]) )
624 && (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr);
625
626 if (cond) {
627 int pos = (int) ( (i - qmfStartSample-no_cols) >> timeStepShift );
628 if ((pos < 3) && (transient_info[1]==0)) {
629 transient_info[2] = 1;
630 }
631 break;
632 }
633 }
634 }
635 }
636
637 int
FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,INT frameSize,INT sampleFreq,sbrConfigurationPtr params,int tran_fc,int no_cols,int no_rows,int YBufferWriteOffset,int YBufferSzShift,int frameShift,int tran_off)638 FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
639 INT frameSize,
640 INT sampleFreq,
641 sbrConfigurationPtr params,
642 int tran_fc,
643 int no_cols,
644 int no_rows,
645 int YBufferWriteOffset,
646 int YBufferSzShift,
647 int frameShift,
648 int tran_off)
649 {
650 INT totalBitrate = params->codecSettings.standardBitrate * params->codecSettings.nChannels;
651 INT codecBitrate = params->codecSettings.bitRate;
652 FIXP_DBL bitrateFactor_fix, framedur_fix;
653 INT scale_0, scale_1;
654
655 FDKmemclear(h_sbrTransientDetector,sizeof(SBR_TRANSIENT_DETECTOR));
656
657 h_sbrTransientDetector->frameShift = frameShift;
658 h_sbrTransientDetector->tran_off = tran_off;
659
660 if(codecBitrate) {
661 bitrateFactor_fix = fDivNorm((FIXP_DBL)totalBitrate, (FIXP_DBL)(codecBitrate<<2),&scale_0);
662 }
663 else {
664 bitrateFactor_fix = FL2FXCONST_DBL(1.0/4.0);
665 scale_0 = 0;
666 }
667
668 framedur_fix = fDivNorm(frameSize, sampleFreq);
669
670 /* The longer the frames, the more often should the FIXFIX-
671 case transmit 2 envelopes instead of 1.
672 Frame durations below 10 ms produce the highest threshold
673 so that practically always only 1 env is transmitted. */
674 FIXP_DBL tmp = framedur_fix - FL2FXCONST_DBL(0.010);
675
676 tmp = fixMax(tmp, FL2FXCONST_DBL(0.0001));
677 tmp = fDivNorm(FL2FXCONST_DBL(0.000075), fPow2(tmp), &scale_1);
678
679 scale_1 = -(scale_1 + scale_0 + 2);
680
681 FDK_ASSERT(no_cols <= QMF_MAX_TIME_SLOTS);
682 FDK_ASSERT(no_rows <= QMF_CHANNELS);
683
684 h_sbrTransientDetector->no_cols = no_cols;
685 h_sbrTransientDetector->tran_thr = (FIXP_DBL)((params->tran_thr << (32-24-1)) / no_rows);
686 h_sbrTransientDetector->tran_fc = tran_fc;
687
688 if (scale_1>=0) {
689 h_sbrTransientDetector->split_thr = fMult(tmp, bitrateFactor_fix) >> scale_1;
690 }
691 else {
692 h_sbrTransientDetector->split_thr = fMult(tmp, bitrateFactor_fix) << (-scale_1);
693 }
694
695 h_sbrTransientDetector->no_rows = no_rows;
696 h_sbrTransientDetector->mode = params->tran_det_mode;
697 h_sbrTransientDetector->prevLowBandEnergy = FL2FXCONST_DBL(0.0f);
698
699 return (0);
700 }
701
702