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, 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  */
    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)]);
    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 */
    207 static const FIXP_DBL gainFac[4] = {0x40000000, 0x2d413ccd, 0x20000000,
    208                                     0x16a09e66};
    209 
    210 void 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 
    234 static 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 
    274 INT 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 
    380 INT 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