1 /* ----------------------------------------------------------------------------- 2 Software License for The Fraunhofer FDK AAC Codec Library for Android 3 4 Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Frderung 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 (at) 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 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 *******************************************************************************/ 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 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 *******************************************************************************/ 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 */ 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 */ 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 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 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 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 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