Home | History | Annotate | Download | only in src
      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 /**************************** 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 
    115 FIXP_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 
    145 int CLpd_FAC_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pFac, SCHAR *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  */
    185 static 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)]) >> (LP_FILTER_SCALE - 1);
    195     }
    196 
    197     L_tmp = scaleValue(L_tmp, a_exp + LP_FILTER_SCALE);
    198     x[i] = fAddSaturate(x[i], L_tmp);
    199   }
    200 }
    201 
    202 /* Table is also correct for coreCoderFrameLength = 768. Factor 3/4 is canceled
    203    out: gainFac = 0.5 * sqrt(fac_length/lFrame)
    204 */
    205 static const FIXP_DBL gainFac[4] = {0x40000000, 0x2d413ccd, 0x20000000,
    206                                     0x16a09e66};
    207 
    208 void CFac_ApplyGains(FIXP_DBL fac_data[LFAC], const INT fac_length,
    209                      const FIXP_DBL tcx_gain, const FIXP_DBL alfd_gains[],
    210                      const INT mod) {
    211   FIXP_DBL facFactor;
    212   int i;
    213 
    214   FDK_ASSERT((fac_length == 128) || (fac_length == 96));
    215 
    216   /* 2) Apply gain factor to FAC data */
    217   facFactor = fMult(gainFac[mod], tcx_gain);
    218   for (i = 0; i < fac_length; i++) {
    219     fac_data[i] = fMult(fac_data[i], facFactor);
    220   }
    221 
    222   /* 3) Apply spectrum deshaping using alfd_gains */
    223   for (i = 0; i < fac_length / 4; i++) {
    224     int k;
    225 
    226     k = i >> (3 - mod);
    227     fac_data[i] = fMult(fac_data[i], alfd_gains[k])
    228                   << 1; /* alfd_gains is scaled by one bit. */
    229   }
    230 }
    231 
    232 static void CFac_CalcFacSignal(FIXP_DBL *pOut, FIXP_DBL *pFac,
    233                                const int fac_scale, const int fac_length,
    234                                const FIXP_LPC A[M_LP_FILTER_ORDER],
    235                                const INT A_exp, const int fAddZir,
    236                                const int isFdFac) {
    237   FIXP_LPC wA[M_LP_FILTER_ORDER];
    238   FIXP_DBL tf_gain = (FIXP_DBL)0;
    239   int wlength;
    240   int scale = fac_scale;
    241 
    242   /* obtain tranform gain. */
    243   imdct_gain(&tf_gain, &scale, isFdFac ? 0 : fac_length);
    244 
    245   /* 4) Compute inverse DCT-IV of FAC data. Output scale of DCT IV is 16 bits.
    246    */
    247   dct_IV(pFac, fac_length, &scale);
    248   /* dct_IV scale = log2(fac_length). "- 7" is a factor of 2/128 */
    249   if (tf_gain != (FIXP_DBL)0) { /* non-radix 2 transform gain */
    250     int i;
    251 
    252     for (i = 0; i < fac_length; i++) {
    253       pFac[i] = fMult(tf_gain, pFac[i]);
    254     }
    255   }
    256   scaleValuesSaturate(pOut, pFac, fac_length,
    257                       scale); /* Avoid overflow issues and saturate. */
    258 
    259   E_LPC_a_weight(wA, A, M_LP_FILTER_ORDER);
    260 
    261   /* We need the output of the IIR filter to be longer than "fac_length".
    262   For this reason we run it with zero input appended to the end of the input
    263   sequence, i.e. we generate its ZIR and extend the output signal.*/
    264   FDKmemclear(pOut + fac_length, fac_length * sizeof(FIXP_DBL));
    265   wlength = 2 * fac_length;
    266 
    267   /* 5) Apply weighted synthesis filter to FAC data, including optional Zir (5.
    268    * item 4). */
    269   Syn_filt_zero(wA, A_exp, wlength, pOut);
    270 }
    271 
    272 INT CLpd_FAC_Mdct2Acelp(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *pFac,
    273                         const int fac_scale, FIXP_LPC *A, INT A_exp,
    274                         INT nrOutSamples, const INT fac_length,
    275                         const INT isFdFac, UCHAR prevWindowShape) {
    276   FIXP_DBL *pOvl;
    277   FIXP_DBL *pOut0;
    278   const FIXP_WTP *pWindow;
    279   int i, fl, nrSamples = 0;
    280 
    281   FDK_ASSERT(fac_length <= 1024 / (4 * 2));
    282 
    283   fl = fac_length * 2;
    284 
    285   pWindow = FDKgetWindowSlope(fl, prevWindowShape);
    286 
    287   /* Adapt window slope length in case of frame loss. */
    288   if (hMdct->prev_fr != fl) {
    289     int nl = 0;
    290     imdct_adapt_parameters(hMdct, &fl, &nl, fac_length, pWindow, nrOutSamples);
    291     FDK_ASSERT(nl == 0);
    292   }
    293 
    294   if (nrSamples < nrOutSamples) {
    295     pOut0 = output;
    296     nrSamples += hMdct->ov_offset;
    297     /* Purge buffered output. */
    298     FDKmemcpy(pOut0, hMdct->overlap.time, hMdct->ov_offset * sizeof(pOut0[0]));
    299     hMdct->ov_offset = 0;
    300   }
    301 
    302   pOvl = hMdct->overlap.freq + hMdct->ov_size - 1;
    303 
    304   if (nrSamples >= nrOutSamples) {
    305     pOut0 = hMdct->overlap.time + hMdct->ov_offset;
    306     hMdct->ov_offset += hMdct->prev_nr + fl / 2;
    307   } else {
    308     pOut0 = output + nrSamples;
    309     nrSamples += hMdct->prev_nr + fl / 2;
    310   }
    311   if (hMdct->prevPrevAliasSymmetry == 0) {
    312     for (i = 0; i < hMdct->prev_nr; i++) {
    313       FIXP_DBL x = -(*pOvl--);
    314       *pOut0 = IMDCT_SCALE_DBL(x);
    315       pOut0++;
    316     }
    317   } else {
    318     for (i = 0; i < hMdct->prev_nr; i++) {
    319       FIXP_DBL x = (*pOvl--);
    320       *pOut0 = IMDCT_SCALE_DBL(x);
    321       pOut0++;
    322     }
    323   }
    324   hMdct->prev_nr = 0;
    325 
    326   {
    327     if (pFac != NULL) {
    328       /* Note: The FAC gain might have been applied directly after bit stream
    329        * parse in this case. */
    330       CFac_CalcFacSignal(pOut0, pFac, fac_scale, fac_length, A, A_exp, 0,
    331                          isFdFac);
    332     } else {
    333       /* Clear buffer because of the overlap and ADD! */
    334       FDKmemclear(pOut0, fac_length * sizeof(FIXP_DBL));
    335     }
    336   }
    337 
    338   i = 0;
    339 
    340   if (hMdct->prevPrevAliasSymmetry == 0) {
    341     for (; i < fl / 2; i++) {
    342       FIXP_DBL x0;
    343 
    344       /* Overlap Add */
    345       x0 = -fMult(*pOvl--, pWindow[i].v.re);
    346 
    347       *pOut0 += IMDCT_SCALE_DBL(x0);
    348       pOut0++;
    349     }
    350   } else {
    351     for (; i < fl / 2; i++) {
    352       FIXP_DBL x0;
    353 
    354       /* Overlap Add */
    355       x0 = fMult(*pOvl--, pWindow[i].v.re);
    356 
    357       *pOut0 += IMDCT_SCALE_DBL(x0);
    358       pOut0++;
    359     }
    360   }
    361   if (hMdct->pFacZir !=
    362       0) { /* this should only happen for ACELP -> TCX20 -> ACELP transition */
    363     FIXP_DBL *pOut = pOut0 - fl / 2; /* fl/2 == fac_length */
    364     for (i = 0; i < fl / 2; i++) {
    365       pOut[i] += IMDCT_SCALE_DBL(hMdct->pFacZir[i]);
    366     }
    367     hMdct->pFacZir = NULL;
    368   }
    369 
    370   hMdct->prev_fr = 0;
    371   hMdct->prev_nr = 0;
    372   hMdct->prev_tl = 0;
    373   hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry;
    374 
    375   return nrSamples;
    376 }
    377 
    378 INT CLpd_FAC_Acelp2Mdct(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *_pSpec,
    379                         const SHORT spec_scale[], const int nSpec,
    380                         FIXP_DBL *pFac, const int fac_scale,
    381                         const INT fac_length, INT noOutSamples, const INT tl,
    382                         const FIXP_WTP *wrs, const INT fr, FIXP_LPC A[16],
    383                         INT A_exp, CAcelpStaticMem *acelp_mem,
    384                         const FIXP_DBL gain, const int last_frame_lost,
    385                         const int isFdFac, const UCHAR last_lpd_mode,
    386                         const int k, int currAliasingSymmetry) {
    387   FIXP_DBL *pCurr, *pOvl, *pSpec;
    388   const FIXP_WTP *pWindow;
    389   const FIXP_WTB *FacWindowZir_conceal;
    390   UCHAR doFacZirConceal = 0;
    391   int doDeemph = 1;
    392   const FIXP_WTB *FacWindowZir, *FacWindowSynth;
    393   FIXP_DBL *pOut0 = output, *pOut1;
    394   int w, i, fl, nl, nr, f_len, nrSamples = 0, s = 0, scale, total_gain_e;
    395   FIXP_DBL *pF, *pFAC_and_FAC_ZIR = NULL;
    396   FIXP_DBL total_gain = gain;
    397 
    398   FDK_ASSERT(fac_length <= 1024 / (4 * 2));
    399   switch (fac_length) {
    400     /* coreCoderFrameLength = 1024 */
    401     case 128:
    402       pWindow = SineWindow256;
    403       FacWindowZir = FacWindowZir128;
    404       FacWindowSynth = FacWindowSynth128;
    405       break;
    406     case 64:
    407       pWindow = SineWindow128;
    408       FacWindowZir = FacWindowZir64;
    409       FacWindowSynth = FacWindowSynth64;
    410       break;
    411     case 32:
    412       pWindow = SineWindow64;
    413       FacWindowZir = FacWindowZir32;
    414       FacWindowSynth = FacWindowSynth32;
    415       break;
    416     /* coreCoderFrameLength = 768 */
    417     case 96:
    418       pWindow = SineWindow192;
    419       FacWindowZir = FacWindowZir96;
    420       FacWindowSynth = FacWindowSynth96;
    421       break;
    422     case 48:
    423       pWindow = SineWindow96;
    424       FacWindowZir = FacWindowZir48;
    425       FacWindowSynth = FacWindowSynth48;
    426       break;
    427     default:
    428       FDK_ASSERT(0);
    429       return 0;
    430   }
    431 
    432   FacWindowZir_conceal = FacWindowSynth;
    433   /* Derive NR and NL */
    434   fl = fac_length * 2;
    435   nl = (tl - fl) >> 1;
    436   nr = (tl - fr) >> 1;
    437 
    438   if (noOutSamples > nrSamples) {
    439     /* Purge buffered output. */
    440     FDKmemcpy(pOut0, hMdct->overlap.time, hMdct->ov_offset * sizeof(pOut0[0]));
    441     nrSamples = hMdct->ov_offset;
    442     hMdct->ov_offset = 0;
    443   }
    444 
    445   if (nrSamples >= noOutSamples) {
    446     pOut1 = hMdct->overlap.time + hMdct->ov_offset;
    447     if (hMdct->ov_offset < fac_length) {
    448       pOut0 = output + nrSamples;
    449     } else {
    450       pOut0 = pOut1;
    451     }
    452     hMdct->ov_offset += fac_length + nl;
    453   } else {
    454     pOut1 = output + nrSamples;
    455     pOut0 = output + nrSamples;
    456   }
    457 
    458   {
    459     pFAC_and_FAC_ZIR = CLpd_ACELP_GetFreeExcMem(acelp_mem, 2 * fac_length);
    460     {
    461       const FIXP_DBL *pTmp1, *pTmp2;
    462 
    463       doFacZirConceal |= ((last_frame_lost != 0) && (k == 0));
    464       doDeemph &= (last_lpd_mode != 4);
    465       if (doFacZirConceal) {
    466         /* ACELP contribution in concealment case:
    467            Use ZIR with a modified ZIR window to preserve some more energy.
    468            Dont use FAC, which contains wrong information for concealed frame
    469            Dont use last ACELP samples, but double ZIR, instead (afterwards) */
    470         FDKmemclear(pFAC_and_FAC_ZIR, 2 * fac_length * sizeof(FIXP_DBL));
    471         FacWindowSynth = (FIXP_WTB *)pFAC_and_FAC_ZIR;
    472         FacWindowZir = FacWindowZir_conceal;
    473       } else {
    474         CFac_CalcFacSignal(pFAC_and_FAC_ZIR, pFac, fac_scale + s, fac_length, A,
    475                            A_exp, 1, isFdFac);
    476       }
    477       /* 6) Get windowed past ACELP samples and ACELP ZIR signal */
    478 
    479       /*
    480        * Get ACELP ZIR (pFac[]) and ACELP past samples (pOut0[]) and add them
    481        * to the FAC synth signal contribution on pOut1[].
    482        */
    483       {
    484         {
    485           CLpd_Acelp_Zir(A, A_exp, acelp_mem, fac_length, pFac, doDeemph);
    486 
    487           pTmp1 = pOut0;
    488           pTmp2 = pFac;
    489         }
    490 
    491         for (i = 0, w = 0; i < fac_length; i++) {
    492           FIXP_DBL x;
    493           /* Div2 is compensated by table scaling */
    494           x = fMultDiv2(pTmp2[i], FacWindowZir[w]);
    495           x += fMultDiv2(pTmp1[-i - 1], FacWindowSynth[w]);
    496           x += pFAC_and_FAC_ZIR[i];
    497           pOut1[i] = x;
    498 
    499           w++;
    500         }
    501       }
    502 
    503       if (doFacZirConceal) {
    504         /* ZIR is the only ACELP contribution, so double it */
    505         scaleValues(pOut1, fac_length, 1);
    506       }
    507     }
    508   }
    509 
    510   if (nrSamples < noOutSamples) {
    511     nrSamples += fac_length + nl;
    512   }
    513 
    514   /* Obtain transform gain */
    515   total_gain = gain;
    516   total_gain_e = 0;
    517   imdct_gain(&total_gain, &total_gain_e, tl);
    518 
    519   /* IMDCT overlap add */
    520   scale = total_gain_e;
    521   pSpec = _pSpec;
    522 
    523   /* Note:when comming from an LPD frame (TCX/ACELP) the previous alisaing
    524    * symmetry must always be 0 */
    525   if (currAliasingSymmetry == 0) {
    526     dct_IV(pSpec, tl, &scale);
    527   } else {
    528     FIXP_DBL _tmp[1024 + ALIGNMENT_DEFAULT / sizeof(FIXP_DBL)];
    529     FIXP_DBL *tmp = (FIXP_DBL *)ALIGN_PTR(_tmp);
    530     C_ALLOC_ALIGNED_REGISTER(tmp, sizeof(_tmp));
    531     dst_III(pSpec, tmp, tl, &scale);
    532     C_ALLOC_ALIGNED_UNREGISTER(tmp);
    533   }
    534 
    535   /* Optional scaling of time domain - no yet windowed - of current spectrum */
    536   if (total_gain != (FIXP_DBL)0) {
    537     for (i = 0; i < tl; i++) {
    538       pSpec[i] = fMult(pSpec[i], total_gain);
    539     }
    540   }
    541   int loc_scale = fixmin_I(spec_scale[0] + scale, (INT)DFRACT_BITS - 1);
    542   scaleValuesSaturate(pSpec, tl, loc_scale);
    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       for (i = 0; i < tl; i++) {
    629         pSpec[i] = fMult(pSpec[i], total_gain);
    630       }
    631     }
    632     loc_scale = fixmin_I(spec_scale[w] + scale, (INT)DFRACT_BITS - 1);
    633     scaleValuesSaturate(pSpec, tl, loc_scale);
    634 
    635     if (noOutSamples <= nrSamples) {
    636       /* Divert output first half to overlap buffer if we already got enough
    637        * output samples. */
    638       pOut0 = hMdct->overlap.time + hMdct->ov_offset;
    639       hMdct->ov_offset += hMdct->prev_nr + fl / 2;
    640     } else {
    641       /* Account output samples */
    642       nrSamples += hMdct->prev_nr + fl / 2;
    643     }
    644 
    645     /* NR output samples 0 .. NR. -overlap[TL/2..TL/2-NR] */
    646     for (i = 0; i < hMdct->prev_nr; i++) {
    647       FIXP_DBL x = -(*pOvl--);
    648       *pOut0 = IMDCT_SCALE_DBL(x);
    649       pOut0++;
    650     }
    651 
    652     if (noOutSamples <= nrSamples) {
    653       /* Divert output second half to overlap buffer if we already got enough
    654        * output samples. */
    655       pOut1 = hMdct->overlap.time + hMdct->ov_offset + fl / 2 - 1;
    656       hMdct->ov_offset += fl / 2 + nl;
    657     } else {
    658       pOut1 = pOut0 + (fl - 1);
    659       nrSamples += fl / 2 + nl;
    660     }
    661 
    662     /* output samples before window crossing point NR .. TL/2.
    663      * -overlap[TL/2-NR..TL/2-NR-FL/2] + current[NR..TL/2] */
    664     /* output samples after window crossing point TL/2 .. TL/2+FL/2.
    665      * -overlap[0..FL/2] - current[TL/2..FL/2] */
    666     pCurr = pSpec + tl - fl / 2;
    667     if (currAliasingSymmetry == 0) {
    668       for (i = 0; i < fl / 2; i++) {
    669         FIXP_DBL x0, x1;
    670 
    671         cplxMult(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]);
    672         *pOut0 = IMDCT_SCALE_DBL(x0);
    673         *pOut1 = IMDCT_SCALE_DBL(-x1);
    674         pOut0++;
    675         pOut1--;
    676       }
    677     } else {
    678       if (hMdct->prevPrevAliasSymmetry == 0) {
    679         /* Jump DST II -> DST IV for the second window */
    680         for (i = 0; i < fl / 2; i++) {
    681           FIXP_DBL x0, x1;
    682 
    683           cplxMult(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]);
    684           *pOut0 = IMDCT_SCALE_DBL(x0);
    685           *pOut1 = IMDCT_SCALE_DBL(x1);
    686           pOut0++;
    687           pOut1--;
    688         }
    689       } else {
    690         /* Jump DST IV -> DST IV from the second window on */
    691         for (i = 0; i < fl / 2; i++) {
    692           FIXP_DBL x0, x1;
    693 
    694           cplxMult(&x1, &x0, *pCurr++, *pOvl--, pWindow_prev[i]);
    695           *pOut0 = IMDCT_SCALE_DBL(x0);
    696           *pOut1 = IMDCT_SCALE_DBL(x1);
    697           pOut0++;
    698           pOut1--;
    699         }
    700       }
    701     }
    702 
    703     if (hMdct->pFacZir != 0) {
    704       /* add FAC ZIR of previous ACELP -> mdct transition */
    705       FIXP_DBL *pOut = pOut0 - fl / 2;
    706       FDK_ASSERT(fl / 2 <= 128);
    707       for (i = 0; i < fl / 2; i++) {
    708         pOut[i] += IMDCT_SCALE_DBL(hMdct->pFacZir[i]);
    709       }
    710       hMdct->pFacZir = NULL;
    711     }
    712     pOut0 += (fl / 2);
    713 
    714     /* NL output samples TL/2+FL/2..TL. - current[FL/2..0] */
    715     pOut1 += (fl / 2) + 1;
    716     pCurr = pSpec + tl - fl / 2 - 1;
    717     for (i = 0; i < nl; i++) {
    718       FIXP_DBL x = -(*pCurr--);
    719       *pOut1 = IMDCT_SCALE_DBL(x);
    720       pOut1++;
    721     }
    722 
    723     /* Set overlap source pointer for next window pOvl = pSpec + tl/2 - 1; */
    724     pOvl = pSpec + tl / 2 - 1;
    725 
    726     /* Previous window values. */
    727     hMdct->prev_nr = nr;
    728     hMdct->prev_fr = fr;
    729     hMdct->prev_tl = tl;
    730     hMdct->prev_wrs = pWindow_prev;
    731     hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry;
    732     hMdct->prevAliasSymmetry = currAliasingSymmetry;
    733   }
    734 
    735   /* Save overlap */
    736 
    737   pOvl = hMdct->overlap.freq + hMdct->ov_size - tl / 2;
    738   FDK_ASSERT(pOvl >= hMdct->overlap.time + hMdct->ov_offset);
    739   FDK_ASSERT(tl / 2 <= hMdct->ov_size);
    740   for (i = 0; i < tl / 2; i++) {
    741     pOvl[i] = _pSpec[i + (w - 1) * tl];
    742   }
    743 
    744   return nrSamples;
    745 }
    746