1/* ----------------------------------------------------------------------------- 2Software License for The Fraunhofer FDK AAC Codec Library for Android 3 4© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten 5Forschung e.V. All rights reserved. 6 7 1. INTRODUCTION 8The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software 9that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding 10scheme for digital audio. This FDK AAC Codec software is intended to be used on 11a wide variety of Android devices. 12 13AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient 14general perceptual audio codecs. AAC-ELD is considered the best-performing 15full-bandwidth communications codec by independent studies and is widely 16deployed. AAC has been standardized by ISO and IEC as part of the MPEG 17specifications. 18 19Patent licenses for necessary patent claims for the FDK AAC Codec (including 20those of Fraunhofer) may be obtained through Via Licensing 21(www.vialicensing.com) or through the respective patent owners individually for 22the purpose of encoding or decoding bit streams in products that are compliant 23with the ISO/IEC MPEG audio standards. Please note that most manufacturers of 24Android devices already license these patent claims through Via Licensing or 25directly from the patent owners, and therefore FDK AAC Codec software may 26already be covered under those patent licenses when it is used for those 27licensed purposes only. 28 29Commercially-licensed AAC software libraries, including floating-point versions 30with enhanced sound quality, are also available from Fraunhofer. Users are 31encouraged to check the Fraunhofer website for additional applications 32information and documentation. 33 342. COPYRIGHT LICENSE 35 36Redistribution and use in source and binary forms, with or without modification, 37are permitted without payment of copyright license fees provided that you 38satisfy the following conditions: 39 40You must retain the complete text of this software license in redistributions of 41the FDK AAC Codec or your modifications thereto in source code form. 42 43You must retain the complete text of this software license in the documentation 44and/or other materials provided with redistributions of the FDK AAC Codec or 45your modifications thereto in binary form. You must make available free of 46charge copies of the complete source code of the FDK AAC Codec and your 47modifications thereto to recipients of copies in binary form. 48 49The name of Fraunhofer may not be used to endorse or promote products derived 50from this library without prior written permission. 51 52You may not charge copyright license fees for anyone to use, copy or distribute 53the FDK AAC Codec software or your modifications thereto. 54 55Your modified versions of the FDK AAC Codec must carry prominent notices stating 56that you changed the software and the date of any change. For modified versions 57of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" 58must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK 59AAC Codec Library for Android." 60 613. NO PATENT LICENSE 62 63NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without 64limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. 65Fraunhofer provides no warranty of patent non-infringement with respect to this 66software. 67 68You may use this FDK AAC Codec software or modifications thereto only for 69purposes that are authorized by appropriate patent licenses. 70 714. DISCLAIMER 72 73This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright 74holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, 75including but not limited to the implied warranties of merchantability and 76fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 77CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, 78or consequential damages, including but not limited to procurement of substitute 79goods or services; loss of use, data, or profits, or business interruption, 80however caused and on any theory of liability, whether in contract, strict 81liability, or tort (including negligence), arising in any way out of the use of 82this software, even if advised of the possibility of such damage. 83 845. CONTACT INFORMATION 85 86Fraunhofer Institute for Integrated Circuits IIS 87Attention: Audio and Multimedia Departments - FDK AAC LL 88Am Wolfsmantel 33 8991058 Erlangen, Germany 90 91www.iis.fraunhofer.de/amm 92amm-info@iis.fraunhofer.de 93----------------------------------------------------------------------------- */ 94 95/**************************** AAC decoder library ****************************** 96 97 Author(s): Manuel Jander 98 99 Description: USAC FAC 100 101*******************************************************************************/ 102 103#include "usacdec_fac.h" 104 105#include "usacdec_const.h" 106#include "usacdec_lpc.h" 107#include "usacdec_acelp.h" 108#include "usacdec_rom.h" 109#include "dct.h" 110#include "FDK_tools_rom.h" 111#include "mdct.h" 112 113#define SPEC_FAC(ptr, i, gl) ((ptr) + ((i) * (gl))) 114 115FIXP_DBL *CLpd_FAC_GetMemory(CAacDecoderChannelInfo *pAacDecoderChannelInfo, 116 UCHAR mod[NB_DIV], int *pState) { 117 FIXP_DBL *ptr; 118 int i; 119 int k = 0; 120 int max_windows = 8; 121 122 FDK_ASSERT(*pState >= 0 && *pState < max_windows); 123 124 /* Look for free space to store FAC data. 2 FAC data blocks fit into each TCX 125 * spectral data block. */ 126 for (i = *pState; i < max_windows; i++) { 127 if (mod[i >> 1] == 0) { 128 break; 129 } 130 } 131 132 *pState = i + 1; 133 134 if (i == max_windows) { 135 ptr = pAacDecoderChannelInfo->data.usac.fac_data0; 136 } else { 137 FDK_ASSERT(mod[(i >> 1)] == 0); 138 ptr = SPEC_FAC(pAacDecoderChannelInfo->pSpectralCoefficient, i, 139 pAacDecoderChannelInfo->granuleLength << k); 140 } 141 142 return ptr; 143} 144 145int CLpd_FAC_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pFac, UCHAR *pFacScale, 146 int length, int use_gain, int frame) { 147 FIXP_DBL fac_gain; 148 int fac_gain_e = 0; 149 150 if (use_gain) { 151 CLpd_DecodeGain(&fac_gain, &fac_gain_e, FDKreadBits(hBs, 7)); 152 } 153 154 if (CLpc_DecodeAVQ(hBs, pFac, 1, 1, length) != 0) { 155 return -1; 156 } 157 158 { 159 int scale; 160 161 scale = getScalefactor(pFac, length); 162 scaleValues(pFac, length, scale); 163 pFacScale[frame] = DFRACT_BITS - 1 - scale; 164 } 165 166 if (use_gain) { 167 int i; 168 169 pFacScale[frame] += fac_gain_e; 170 171 for (i = 0; i < length; i++) { 172 pFac[i] = fMult(pFac[i], fac_gain); 173 } 174 } 175 return 0; 176} 177 178/** 179 * \brief Apply synthesis filter with zero input to x. The overall filter gain 180 * is 1.0. 181 * \param a LPC filter coefficients. 182 * \param length length of the input/output data vector x. 183 * \param x input/output vector, where the synthesis filter is applied in place. 184 */ 185static void Syn_filt_zero(const FIXP_LPC a[], const INT a_exp, INT length, 186 FIXP_DBL x[]) { 187 int i, j; 188 FIXP_DBL L_tmp; 189 190 for (i = 0; i < length; i++) { 191 L_tmp = (FIXP_DBL)0; 192 193 for (j = 0; j < fMin(i, M_LP_FILTER_ORDER); j++) { 194 L_tmp -= fMultDiv2(a[j], x[i - (j + 1)]); 195 } 196 197 L_tmp = scaleValue(L_tmp, a_exp + 1); 198 199 x[i] = scaleValueSaturate((x[i] >> 1) + (L_tmp >> 1), 200 1); /* Avoid overflow issues and saturate. */ 201 } 202} 203 204/* Table is also correct for coreCoderFrameLength = 768. Factor 3/4 is canceled 205 out: gainFac = 0.5 * sqrt(fac_length/lFrame) 206*/ 207static const FIXP_DBL gainFac[4] = {0x40000000, 0x2d413ccd, 0x20000000, 208 0x16a09e66}; 209 210void CFac_ApplyGains(FIXP_DBL fac_data[LFAC], const INT fac_length, 211 const FIXP_DBL tcx_gain, const FIXP_DBL alfd_gains[], 212 const INT mod) { 213 FIXP_DBL facFactor; 214 int i; 215 216 FDK_ASSERT((fac_length == 128) || (fac_length == 96)); 217 218 /* 2) Apply gain factor to FAC data */ 219 facFactor = fMult(gainFac[mod], tcx_gain); 220 for (i = 0; i < fac_length; i++) { 221 fac_data[i] = fMult(fac_data[i], facFactor); 222 } 223 224 /* 3) Apply spectrum deshaping using alfd_gains */ 225 for (i = 0; i < fac_length / 4; i++) { 226 int k; 227 228 k = i >> (3 - mod); 229 fac_data[i] = fMult(fac_data[i], alfd_gains[k]) 230 << 1; /* alfd_gains is scaled by one bit. */ 231 } 232} 233 234static void CFac_CalcFacSignal(FIXP_DBL *pOut, FIXP_DBL *pFac, 235 const int fac_scale, const int fac_length, 236 const FIXP_LPC A[M_LP_FILTER_ORDER], 237 const INT A_exp, const int fAddZir, 238 const int isFdFac) { 239 FIXP_LPC wA[M_LP_FILTER_ORDER]; 240 FIXP_DBL tf_gain = (FIXP_DBL)0; 241 int wlength; 242 int scale = fac_scale; 243 244 /* obtain tranform gain. */ 245 imdct_gain(&tf_gain, &scale, isFdFac ? 0 : fac_length); 246 247 /* 4) Compute inverse DCT-IV of FAC data. Output scale of DCT IV is 16 bits. 248 */ 249 dct_IV(pFac, fac_length, &scale); 250 /* dct_IV scale = log2(fac_length). "- 7" is a factor of 2/128 */ 251 if (tf_gain != (FIXP_DBL)0) { /* non-radix 2 transform gain */ 252 int i; 253 254 for (i = 0; i < fac_length; i++) { 255 pFac[i] = fMult(tf_gain, pFac[i]); 256 } 257 } 258 scaleValuesSaturate(pOut, pFac, fac_length, 259 scale); /* Avoid overflow issues and saturate. */ 260 261 E_LPC_a_weight(wA, A, M_LP_FILTER_ORDER); 262 263 /* We need the output of the IIR filter to be longer than "fac_length". 264 For this reason we run it with zero input appended to the end of the input 265 sequence, i.e. we generate its ZIR and extend the output signal.*/ 266 FDKmemclear(pOut + fac_length, fac_length * sizeof(FIXP_DBL)); 267 wlength = 2 * fac_length; 268 269 /* 5) Apply weighted synthesis filter to FAC data, including optional Zir (5. 270 * item 4). */ 271 Syn_filt_zero(wA, A_exp, wlength, pOut); 272} 273 274INT CLpd_FAC_Mdct2Acelp(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *pFac, 275 const int fac_scale, FIXP_LPC *A, INT A_exp, 276 INT nrOutSamples, const INT fac_length, 277 const INT isFdFac, UCHAR prevWindowShape) { 278 FIXP_DBL *pOvl; 279 FIXP_DBL *pOut0; 280 const FIXP_WTP *pWindow; 281 int i, fl, nrSamples = 0; 282 283 FDK_ASSERT(fac_length <= 1024 / (4 * 2)); 284 285 fl = fac_length * 2; 286 287 pWindow = FDKgetWindowSlope(fl, prevWindowShape); 288 289 /* Adapt window slope length in case of frame loss. */ 290 if (hMdct->prev_fr != fl) { 291 int nl = 0; 292 imdct_adapt_parameters(hMdct, &fl, &nl, fac_length, pWindow, nrOutSamples); 293 FDK_ASSERT(nl == 0); 294 } 295 296 if (nrSamples < nrOutSamples) { 297 pOut0 = output; 298 nrSamples += hMdct->ov_offset; 299 /* Purge buffered output. */ 300 FDKmemcpy(pOut0, hMdct->overlap.time, hMdct->ov_offset * sizeof(pOut0[0])); 301 hMdct->ov_offset = 0; 302 } 303 304 pOvl = hMdct->overlap.freq + hMdct->ov_size - 1; 305 306 if (nrSamples >= nrOutSamples) { 307 pOut0 = hMdct->overlap.time + hMdct->ov_offset; 308 hMdct->ov_offset += hMdct->prev_nr + fl / 2; 309 } else { 310 pOut0 = output + nrSamples; 311 nrSamples += hMdct->prev_nr + fl / 2; 312 } 313 if (hMdct->prevPrevAliasSymmetry == 0) { 314 for (i = 0; i < hMdct->prev_nr; i++) { 315 FIXP_DBL x = -(*pOvl--); 316 *pOut0 = IMDCT_SCALE_DBL(x); 317 pOut0++; 318 } 319 } else { 320 for (i = 0; i < hMdct->prev_nr; i++) { 321 FIXP_DBL x = (*pOvl--); 322 *pOut0 = IMDCT_SCALE_DBL(x); 323 pOut0++; 324 } 325 } 326 hMdct->prev_nr = 0; 327 328 { 329 if (pFac != NULL) { 330 /* Note: The FAC gain might have been applied directly after bit stream 331 * parse in this case. */ 332 CFac_CalcFacSignal(pOut0, pFac, fac_scale, fac_length, A, A_exp, 0, 333 isFdFac); 334 } else { 335 /* Clear buffer because of the overlap and ADD! */ 336 FDKmemclear(pOut0, fac_length * sizeof(FIXP_DBL)); 337 } 338 } 339 340 i = 0; 341 342 if (hMdct->prevPrevAliasSymmetry == 0) { 343 for (; i < fl / 2; i++) { 344 FIXP_DBL x0; 345 346 /* Overlap Add */ 347 x0 = -fMult(*pOvl--, pWindow[i].v.re); 348 349 *pOut0 += IMDCT_SCALE_DBL(x0); 350 pOut0++; 351 } 352 } else { 353 for (; i < fl / 2; i++) { 354 FIXP_DBL x0; 355 356 /* Overlap Add */ 357 x0 = fMult(*pOvl--, pWindow[i].v.re); 358 359 *pOut0 += IMDCT_SCALE_DBL(x0); 360 pOut0++; 361 } 362 } 363 if (hMdct->pFacZir != 364 0) { /* this should only happen for ACELP -> TCX20 -> ACELP transition */ 365 FIXP_DBL *pOut = pOut0 - fl / 2; /* fl/2 == fac_length */ 366 for (i = 0; i < fl / 2; i++) { 367 pOut[i] += IMDCT_SCALE_DBL(hMdct->pFacZir[i]); 368 } 369 hMdct->pFacZir = NULL; 370 } 371 372 hMdct->prev_fr = 0; 373 hMdct->prev_nr = 0; 374 hMdct->prev_tl = 0; 375 hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry; 376 377 return nrSamples; 378} 379 380INT CLpd_FAC_Acelp2Mdct(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *_pSpec, 381 const SHORT spec_scale[], const int nSpec, 382 FIXP_DBL *pFac, const int fac_scale, 383 const INT fac_length, INT noOutSamples, const INT tl, 384 const FIXP_WTP *wrs, const INT fr, FIXP_LPC A[16], 385 INT A_exp, CAcelpStaticMem *acelp_mem, 386 const FIXP_DBL gain, const int last_frame_lost, 387 const int isFdFac, const UCHAR last_lpd_mode, 388 const int k, int currAliasingSymmetry) { 389 FIXP_DBL *pCurr, *pOvl, *pSpec; 390 const FIXP_WTP *pWindow; 391 const FIXP_WTB *FacWindowZir_conceal; 392 UCHAR doFacZirConceal = 0; 393 int doDeemph = 1; 394 const FIXP_WTB *FacWindowZir, *FacWindowSynth; 395 FIXP_DBL *pOut0 = output, *pOut1; 396 int w, i, fl, nl, nr, f_len, nrSamples = 0, s = 0, scale, total_gain_e; 397 FIXP_DBL *pF, *pFAC_and_FAC_ZIR = NULL; 398 FIXP_DBL total_gain = gain; 399 400 FDK_ASSERT(fac_length <= 1024 / (4 * 2)); 401 switch (fac_length) { 402 /* coreCoderFrameLength = 1024 */ 403 case 128: 404 pWindow = SineWindow256; 405 FacWindowZir = FacWindowZir128; 406 FacWindowSynth = FacWindowSynth128; 407 break; 408 case 64: 409 pWindow = SineWindow128; 410 FacWindowZir = FacWindowZir64; 411 FacWindowSynth = FacWindowSynth64; 412 break; 413 case 32: 414 pWindow = SineWindow64; 415 FacWindowZir = FacWindowZir32; 416 FacWindowSynth = FacWindowSynth32; 417 break; 418 /* coreCoderFrameLength = 768 */ 419 case 96: 420 pWindow = SineWindow192; 421 FacWindowZir = FacWindowZir96; 422 FacWindowSynth = FacWindowSynth96; 423 break; 424 case 48: 425 pWindow = SineWindow96; 426 FacWindowZir = FacWindowZir48; 427 FacWindowSynth = FacWindowSynth48; 428 break; 429 default: 430 FDK_ASSERT(0); 431 return 0; 432 } 433 434 FacWindowZir_conceal = FacWindowSynth; 435 /* Derive NR and NL */ 436 fl = fac_length * 2; 437 nl = (tl - fl) >> 1; 438 nr = (tl - fr) >> 1; 439 440 if (noOutSamples > nrSamples) { 441 /* Purge buffered output. */ 442 FDKmemcpy(pOut0, hMdct->overlap.time, hMdct->ov_offset * sizeof(pOut0[0])); 443 nrSamples = hMdct->ov_offset; 444 hMdct->ov_offset = 0; 445 } 446 447 if (nrSamples >= noOutSamples) { 448 pOut1 = hMdct->overlap.time + hMdct->ov_offset; 449 if (hMdct->ov_offset < fac_length) { 450 pOut0 = output + nrSamples; 451 } else { 452 pOut0 = pOut1; 453 } 454 hMdct->ov_offset += fac_length + nl; 455 } else { 456 pOut1 = output + nrSamples; 457 pOut0 = output + nrSamples; 458 } 459 460 { 461 pFAC_and_FAC_ZIR = CLpd_ACELP_GetFreeExcMem(acelp_mem, 2 * fac_length); 462 { 463 const FIXP_DBL *pTmp1, *pTmp2; 464 465 doFacZirConceal |= ((last_frame_lost != 0) && (k == 0)); 466 doDeemph &= (last_lpd_mode != 4); 467 if (doFacZirConceal) { 468 /* ACELP contribution in concealment case: 469 Use ZIR with a modified ZIR window to preserve some more energy. 470 Dont use FAC, which contains wrong information for concealed frame 471 Dont use last ACELP samples, but double ZIR, instead (afterwards) */ 472 FDKmemclear(pFAC_and_FAC_ZIR, 2 * fac_length * sizeof(FIXP_DBL)); 473 FacWindowSynth = (FIXP_WTB *)pFAC_and_FAC_ZIR; 474 FacWindowZir = FacWindowZir_conceal; 475 } else { 476 CFac_CalcFacSignal(pFAC_and_FAC_ZIR, pFac, fac_scale + s, fac_length, A, 477 A_exp, 1, isFdFac); 478 } 479 /* 6) Get windowed past ACELP samples and ACELP ZIR signal */ 480 481 /* 482 * Get ACELP ZIR (pFac[]) and ACELP past samples (pOut0[]) and add them 483 * to the FAC synth signal contribution on pOut1[]. 484 */ 485 { 486 { 487 CLpd_Acelp_Zir(A, A_exp, acelp_mem, fac_length, pFac, doDeemph); 488 489 pTmp1 = pOut0; 490 pTmp2 = pFac; 491 } 492 493 for (i = 0, w = 0; i < fac_length; i++) { 494 FIXP_DBL x; 495 /* Div2 is compensated by table scaling */ 496 x = fMultDiv2(pTmp2[i], FacWindowZir[w]); 497 x += fMultDiv2(pTmp1[-i - 1], FacWindowSynth[w]); 498 x += pFAC_and_FAC_ZIR[i]; 499 pOut1[i] = x; 500 501 w++; 502 } 503 } 504 505 if (doFacZirConceal) { 506 /* ZIR is the only ACELP contribution, so double it */ 507 scaleValues(pOut1, fac_length, 1); 508 } 509 } 510 } 511 512 if (nrSamples < noOutSamples) { 513 nrSamples += fac_length + nl; 514 } 515 516 /* Obtain transform gain */ 517 total_gain = gain; 518 total_gain_e = 0; 519 imdct_gain(&total_gain, &total_gain_e, tl); 520 521 /* IMDCT overlap add */ 522 scale = total_gain_e; 523 pSpec = _pSpec; 524 525 /* Note:when comming from an LPD frame (TCX/ACELP) the previous alisaing 526 * symmetry must always be 0 */ 527 if (currAliasingSymmetry == 0) { 528 dct_IV(pSpec, tl, &scale); 529 } else { 530 FIXP_DBL _tmp[1024 + ALIGNMENT_DEFAULT / sizeof(FIXP_DBL)]; 531 FIXP_DBL *tmp = (FIXP_DBL *)ALIGN_PTR(_tmp); 532 C_ALLOC_ALIGNED_REGISTER(tmp, sizeof(_tmp)); 533 dst_III(pSpec, tmp, tl, &scale); 534 C_ALLOC_ALIGNED_UNREGISTER(tmp); 535 } 536 537 /* Optional scaling of time domain - no yet windowed - of current spectrum */ 538 if (total_gain != (FIXP_DBL)0) { 539 scaleValuesWithFactor(pSpec, total_gain, tl, spec_scale[0] + scale); 540 } else { 541 scaleValues(pSpec, tl, spec_scale[0] + scale); 542 } 543 544 pOut1 += fl / 2 - 1; 545 pCurr = pSpec + tl - fl / 2; 546 547 for (i = 0; i < fl / 2; i++) { 548 FIXP_DBL x1; 549 550 /* FAC signal is already on pOut1, because of that the += operator. */ 551 x1 = fMult(*pCurr++, pWindow[i].v.re); 552 FDK_ASSERT((pOut1 >= hMdct->overlap.time && 553 pOut1 < hMdct->overlap.time + hMdct->ov_size) || 554 (pOut1 >= output && pOut1 < output + 1024)); 555 *pOut1 += IMDCT_SCALE_DBL(-x1); 556 pOut1--; 557 } 558 559 /* NL output samples TL/2+FL/2..TL. - current[FL/2..0] */ 560 pOut1 += (fl / 2) + 1; 561 562 pFAC_and_FAC_ZIR += fac_length; /* set pointer to beginning of FAC ZIR */ 563 564 if (nl == 0) { 565 /* save pointer to write FAC ZIR data later */ 566 hMdct->pFacZir = pFAC_and_FAC_ZIR; 567 } else { 568 FDK_ASSERT(nl >= fac_length); 569 /* FAC ZIR will be added now ... */ 570 hMdct->pFacZir = NULL; 571 } 572 573 pF = pFAC_and_FAC_ZIR; 574 f_len = fac_length; 575 576 pCurr = pSpec + tl - fl / 2 - 1; 577 for (i = 0; i < nl; i++) { 578 FIXP_DBL x = -(*pCurr--); 579 /* 5) (item 4) Synthesis filter Zir component, FAC ZIR (another one). */ 580 if (i < f_len) { 581 x += *pF++; 582 } 583 584 FDK_ASSERT((pOut1 >= hMdct->overlap.time && 585 pOut1 < hMdct->overlap.time + hMdct->ov_size) || 586 (pOut1 >= output && pOut1 < output + 1024)); 587 *pOut1 = IMDCT_SCALE_DBL(x); 588 pOut1++; 589 } 590 591 hMdct->prev_nr = nr; 592 hMdct->prev_fr = fr; 593 hMdct->prev_wrs = wrs; 594 hMdct->prev_tl = tl; 595 hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry; 596 hMdct->prevAliasSymmetry = currAliasingSymmetry; 597 fl = fr; 598 nl = nr; 599 600 pOvl = pSpec + tl / 2 - 1; 601 pOut0 = pOut1; 602 603 for (w = 1; w < nSpec; w++) /* for ACELP -> FD short */ 604 { 605 const FIXP_WTP *pWindow_prev; 606 607 /* Setup window pointers */ 608 pWindow_prev = hMdct->prev_wrs; 609 610 /* Current spectrum */ 611 pSpec = _pSpec + w * tl; 612 613 scale = total_gain_e; 614 615 /* For the second, third, etc. short frames the alisaing symmetry is equal, 616 * either (0,0) or (1,1) */ 617 if (currAliasingSymmetry == 0) { 618 /* DCT IV of current spectrum */ 619 dct_IV(pSpec, tl, &scale); 620 } else { 621 dst_IV(pSpec, tl, &scale); 622 } 623 624 /* Optional scaling of time domain - no yet windowed - of current spectrum 625 */ 626 /* and de-scale current spectrum signal (time domain, no yet windowed) */ 627 if (total_gain != (FIXP_DBL)0) { 628 scaleValuesWithFactor(pSpec, total_gain, tl, spec_scale[w] + scale); 629 } else { 630 scaleValues(pSpec, tl, spec_scale[w] + scale); 631 } 632 633 if (noOutSamples <= nrSamples) { 634 /* Divert output first half to overlap buffer if we already got enough 635 * output samples. */ 636 pOut0 = hMdct->overlap.time + hMdct->ov_offset; 637 hMdct->ov_offset += hMdct->prev_nr + fl / 2; 638 } else { 639 /* Account output samples */ 640 nrSamples += hMdct->prev_nr + fl / 2; 641 } 642 643 /* NR output samples 0 .. NR. -overlap[TL/2..TL/2-NR] */ 644 for (i = 0; i < hMdct->prev_nr; i++) { 645 FIXP_DBL x = -(*pOvl--); 646 *pOut0 = IMDCT_SCALE_DBL(x); 647 pOut0++; 648 } 649 650 if (noOutSamples <= nrSamples) { 651 /* Divert output second half to overlap buffer if we already got enough 652 * output samples. */ 653 pOut1 = hMdct->overlap.time + hMdct->ov_offset + fl / 2 - 1; 654 hMdct->ov_offset += fl / 2 + nl; 655 } else { 656 pOut1 = pOut0 + (fl - 1); 657 nrSamples += fl / 2 + nl; 658 } 659 660 /* output samples before window crossing point NR .. TL/2. 661 * -overlap[TL/2-NR..TL/2-NR-FL/2] + current[NR..TL/2] */ 662 /* output samples after window crossing point TL/2 .. TL/2+FL/2. 663 * -overlap[0..FL/2] - current[TL/2..FL/2] */ 664 pCurr = pSpec + tl - fl / 2; 665 if (currAliasingSymmetry == 0) { 666 for (i = 0; i < fl / 2; i++) { 667 FIXP_DBL x0, x1; 668 669 cplxMult(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]); 670 *pOut0 = IMDCT_SCALE_DBL(x0); 671 *pOut1 = IMDCT_SCALE_DBL(-x1); 672 pOut0++; 673 pOut1--; 674 } 675 } else { 676 if (hMdct->prevPrevAliasSymmetry == 0) { 677 /* Jump DST II -> DST IV for the second window */ 678 for (i = 0; i < fl / 2; i++) { 679 FIXP_DBL x0, x1; 680 681 cplxMult(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]); 682 *pOut0 = IMDCT_SCALE_DBL(x0); 683 *pOut1 = IMDCT_SCALE_DBL(x1); 684 pOut0++; 685 pOut1--; 686 } 687 } else { 688 /* Jump DST IV -> DST IV from the second window on */ 689 for (i = 0; i < fl / 2; i++) { 690 FIXP_DBL x0, x1; 691 692 cplxMult(&x1, &x0, *pCurr++, *pOvl--, pWindow_prev[i]); 693 *pOut0 = IMDCT_SCALE_DBL(x0); 694 *pOut1 = IMDCT_SCALE_DBL(x1); 695 pOut0++; 696 pOut1--; 697 } 698 } 699 } 700 701 if (hMdct->pFacZir != 0) { 702 /* add FAC ZIR of previous ACELP -> mdct transition */ 703 FIXP_DBL *pOut = pOut0 - fl / 2; 704 FDK_ASSERT(fl / 2 <= 128); 705 for (i = 0; i < fl / 2; i++) { 706 pOut[i] += IMDCT_SCALE_DBL(hMdct->pFacZir[i]); 707 } 708 hMdct->pFacZir = NULL; 709 } 710 pOut0 += (fl / 2); 711 712 /* NL output samples TL/2+FL/2..TL. - current[FL/2..0] */ 713 pOut1 += (fl / 2) + 1; 714 pCurr = pSpec + tl - fl / 2 - 1; 715 for (i = 0; i < nl; i++) { 716 FIXP_DBL x = -(*pCurr--); 717 *pOut1 = IMDCT_SCALE_DBL(x); 718 pOut1++; 719 } 720 721 /* Set overlap source pointer for next window pOvl = pSpec + tl/2 - 1; */ 722 pOvl = pSpec + tl / 2 - 1; 723 724 /* Previous window values. */ 725 hMdct->prev_nr = nr; 726 hMdct->prev_fr = fr; 727 hMdct->prev_tl = tl; 728 hMdct->prev_wrs = pWindow_prev; 729 hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry; 730 hMdct->prevAliasSymmetry = currAliasingSymmetry; 731 } 732 733 /* Save overlap */ 734 735 pOvl = hMdct->overlap.freq + hMdct->ov_size - tl / 2; 736 FDK_ASSERT(pOvl >= hMdct->overlap.time + hMdct->ov_offset); 737 FDK_ASSERT(tl / 2 <= hMdct->ov_size); 738 for (i = 0; i < tl / 2; i++) { 739 pOvl[i] = _pSpec[i + (w - 1) * tl]; 740 } 741 742 return nrSamples; 743} 744