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 /******************* Library for basic calculation routines ********************
     96 
     97    Author(s):   Josef Hoepfl, Manuel Jander, Youliy Ninov, Daniel Hagel
     98 
     99    Description: MDCT/MDST routines
    100 
    101 *******************************************************************************/
    102 
    103 #include "mdct.h"
    104 
    105 #include "FDK_tools_rom.h"
    106 #include "dct.h"
    107 #include "fixpoint_math.h"
    108 
    109 void mdct_init(H_MDCT hMdct, FIXP_DBL *overlap, INT overlapBufferSize) {
    110   hMdct->overlap.freq = overlap;
    111   // FDKmemclear(overlap, overlapBufferSize*sizeof(FIXP_DBL));
    112   hMdct->prev_fr = 0;
    113   hMdct->prev_nr = 0;
    114   hMdct->prev_tl = 0;
    115   hMdct->ov_size = overlapBufferSize;
    116   hMdct->prevAliasSymmetry = 0;
    117   hMdct->prevPrevAliasSymmetry = 0;
    118   hMdct->pFacZir = NULL;
    119   hMdct->pAsymOvlp = NULL;
    120 }
    121 
    122 /*
    123 This program implements the forward MDCT transform on an input block of data.
    124 The input block is in a form (A,B,C,D) where A,B,C and D are the respective
    125 1/4th segments of the block. The program takes the input block and folds it in
    126 the form:
    127 (-D-Cr,A-Br). This block is twice shorter and here the 'r' suffix denotes
    128 flipping of the sequence (reversing the order of the samples). While folding the
    129 input block in the above mentioned shorter block the program windows the data.
    130 Because the two operations (windowing and folding) are not implemented
    131 sequentially, but together the program's structure is not easy to understand.
    132 Once the output (already windowed) block (-D-Cr,A-Br) is ready it is passed to
    133 the DCT IV for processing.
    134 */
    135 INT mdct_block(H_MDCT hMdct, const INT_PCM *RESTRICT timeData,
    136                const INT noInSamples, FIXP_DBL *RESTRICT mdctData,
    137                const INT nSpec, const INT tl, const FIXP_WTP *pRightWindowPart,
    138                const INT fr, SHORT *pMdctData_e) {
    139   int i, n;
    140   /* tl: transform length
    141      fl: left window slope length
    142      nl: left window slope offset
    143      fr: right window slope length
    144      nr: right window slope offset
    145      See FDK_tools/doc/intern/mdct.tex for more detail. */
    146   int fl, nl, nr;
    147   const FIXP_WTP *wls, *wrs;
    148 
    149   wrs = pRightWindowPart;
    150 
    151   /* Detect FRprevious / FL mismatches and override parameters accordingly */
    152   if (hMdct->prev_fr ==
    153       0) { /* At start just initialize and pass parameters as they are */
    154     hMdct->prev_fr = fr;
    155     hMdct->prev_wrs = wrs;
    156     hMdct->prev_tl = tl;
    157   }
    158 
    159   /* Derive NR */
    160   nr = (tl - fr) >> 1;
    161 
    162   /* Skip input samples if tl is smaller than block size */
    163   timeData += (noInSamples - tl) >> 1;
    164 
    165   /* windowing */
    166   for (n = 0; n < nSpec; n++) {
    167     /*
    168      * MDCT scale:
    169      * + 1: fMultDiv2() in windowing.
    170      * + 1: Because of factor 1/2 in Princen-Bradley compliant windowed TDAC.
    171      */
    172     INT mdctData_e = 1 + 1;
    173 
    174     /* Derive left parameters */
    175     wls = hMdct->prev_wrs;
    176     fl = hMdct->prev_fr;
    177     nl = (tl - fl) >> 1;
    178 
    179     /* Here we implement a simplified version of what happens after the this
    180     piece of code (see the comments below). We implement the folding of A and B
    181     segments to (A-Br) but A is zero, because in this part of the MDCT sequence
    182     the window coefficients with which A must be multiplied are zero.    */
    183     for (i = 0; i < nl; i++) {
    184 #if SAMPLE_BITS == DFRACT_BITS /* SPC_BITS and DFRACT_BITS should be equal. */
    185       mdctData[(tl / 2) + i] = -((FIXP_DBL)timeData[tl - i - 1] >> (1));
    186 #else
    187       mdctData[(tl / 2) + i] = -(FIXP_DBL)timeData[tl - i - 1]
    188                                << (DFRACT_BITS - SAMPLE_BITS - 1); /* 0(A)-Br */
    189 #endif
    190     }
    191 
    192     /* Implements the folding and windowing of the left part of the sequence,
    193     that is segments A and B. The A segment is multiplied by the respective left
    194     window coefficient and placed in a temporary variable.
    195 
    196     tmp0 = fMultDiv2((FIXP_PCM)timeData[i+nl], pLeftWindowPart[i].v.im);
    197 
    198     After this the B segment taken in reverse order is multiplied by the left
    199     window and subtracted from the previously derived temporary variable, so
    200     that finally we implement the A-Br operation. This output is written to the
    201     right part of the MDCT output : (-D-Cr,A-Br).
    202 
    203     mdctData[(tl/2)+i+nl] = fMultSubDiv2(tmp0, (FIXP_PCM)timeData[tl-nl-i-1],
    204     pLeftWindowPart[i].v.re);//A*window-Br*window
    205 
    206     The (A-Br) data is written to the output buffer (mdctData) without being
    207     flipped.     */
    208     for (i = 0; i < fl / 2; i++) {
    209       FIXP_DBL tmp0;
    210       tmp0 = fMultDiv2((FIXP_PCM)timeData[i + nl], wls[i].v.im); /* a*window */
    211       mdctData[(tl / 2) + i + nl] =
    212           fMultSubDiv2(tmp0, (FIXP_PCM)timeData[tl - nl - i - 1],
    213                        wls[i].v.re); /* A*window-Br*window */
    214     }
    215 
    216     /* Right window slope offset */
    217     /* Here we implement a simplified version of what happens after the this
    218     piece of code (see the comments below). We implement the folding of C and D
    219     segments to (-D-Cr) but D is zero, because in this part of the MDCT sequence
    220     the window coefficients with which D must be multiplied are zero.    */
    221     for (i = 0; i < nr; i++) {
    222 #if SAMPLE_BITS == \
    223     DFRACT_BITS /* This should be SPC_BITS instead of DFRACT_BITS. */
    224       mdctData[(tl / 2) - 1 - i] = -((FIXP_DBL)timeData[tl + i] >> (1));
    225 #else
    226       mdctData[(tl / 2) - 1 - i] =
    227           -(FIXP_DBL)timeData[tl + i]
    228           << (DFRACT_BITS - SAMPLE_BITS - 1); /* -C flipped at placing */
    229 #endif
    230     }
    231 
    232     /* Implements the folding and windowing of the right part of the sequence,
    233     that is, segments C and D. The C segment is multiplied by the respective
    234     right window coefficient and placed in a temporary variable.
    235 
    236     tmp1 = fMultDiv2((FIXP_PCM)timeData[tl+nr+i], pRightWindowPart[i].v.re);
    237 
    238     After this the D segment taken in reverse order is multiplied by the right
    239     window and added from the previously derived temporary variable, so that we
    240     get (C+Dr) operation. This output is negated to get (-C-Dr) and written to
    241     the left part of the MDCT output while being reversed (flipped) at the same
    242     time, so that from (-C-Dr) we get (-D-Cr)=> (-D-Cr,A-Br).
    243 
    244     mdctData[(tl/2)-nr-i-1] = -fMultAddDiv2(tmp1,
    245     (FIXP_PCM)timeData[(tl*2)-nr-i-1], pRightWindowPart[i].v.im);*/
    246     for (i = 0; i < fr / 2; i++) {
    247       FIXP_DBL tmp1;
    248       tmp1 = fMultDiv2((FIXP_PCM)timeData[tl + nr + i],
    249                        wrs[i].v.re); /* C*window */
    250       mdctData[(tl / 2) - nr - i - 1] =
    251           -fMultAddDiv2(tmp1, (FIXP_PCM)timeData[(tl * 2) - nr - i - 1],
    252                         wrs[i].v.im); /* -(C*window+Dr*window) and flip before
    253                                          placing -> -Cr - D */
    254     }
    255 
    256     /* We pass the shortened folded data (-D-Cr,A-Br) to the MDCT function */
    257     dct_IV(mdctData, tl, &mdctData_e);
    258 
    259     pMdctData_e[n] = (SHORT)mdctData_e;
    260 
    261     timeData += tl;
    262     mdctData += tl;
    263 
    264     hMdct->prev_wrs = wrs;
    265     hMdct->prev_fr = fr;
    266     hMdct->prev_tl = tl;
    267   }
    268 
    269   return nSpec * tl;
    270 }
    271 
    272 void imdct_gain(FIXP_DBL *pGain_m, int *pGain_e, int tl) {
    273   FIXP_DBL gain_m = *pGain_m;
    274   int gain_e = *pGain_e;
    275   int log2_tl;
    276 
    277   gain_e += -MDCT_OUTPUT_GAIN - MDCT_OUT_HEADROOM + 1;
    278   if (tl == 0) {
    279     /* Dont regard the 2/N factor from the IDCT. It is compensated for somewhere
    280      * else. */
    281     *pGain_e = gain_e;
    282     return;
    283   }
    284 
    285   log2_tl = DFRACT_BITS - 1 - fNormz((FIXP_DBL)tl);
    286   gain_e += -log2_tl;
    287 
    288   /* Detect non-radix 2 transform length and add amplitude compensation factor
    289      which cannot be included into the exponent above */
    290   switch ((tl) >> (log2_tl - 2)) {
    291     case 0x7: /* 10 ms, 1/tl = 1.0/(FDKpow(2.0, -log2_tl) *
    292                  0.53333333333333333333) */
    293       if (gain_m == (FIXP_DBL)0) {
    294         gain_m = FL2FXCONST_DBL(0.53333333333333333333f);
    295       } else {
    296         gain_m = fMult(gain_m, FL2FXCONST_DBL(0.53333333333333333333f));
    297       }
    298       break;
    299     case 0x6: /* 3/4 of radix 2, 1/tl = 1.0/(FDKpow(2.0, -log2_tl) * 2.0/3.0) */
    300       if (gain_m == (FIXP_DBL)0) {
    301         gain_m = FL2FXCONST_DBL(2.0 / 3.0f);
    302       } else {
    303         gain_m = fMult(gain_m, FL2FXCONST_DBL(2.0 / 3.0f));
    304       }
    305       break;
    306     case 0x5: /* 0.8 of radix 2 (e.g. tl 160), 1/tl = 1.0/(FDKpow(2.0, -log2_tl)
    307                * 0.8/1.5) */
    308       if (gain_m == (FIXP_DBL)0) {
    309         gain_m = FL2FXCONST_DBL(0.53333333333333333333f);
    310       } else {
    311         gain_m = fMult(gain_m, FL2FXCONST_DBL(0.53333333333333333333f));
    312       }
    313       break;
    314     case 0x4:
    315       /* radix 2, nothing to do. */
    316       break;
    317     default:
    318       /* unsupported */
    319       FDK_ASSERT(0);
    320       break;
    321   }
    322 
    323   *pGain_m = gain_m;
    324   *pGain_e = gain_e;
    325 }
    326 
    327 INT imdct_drain(H_MDCT hMdct, FIXP_DBL *output, INT nrSamplesRoom) {
    328   int buffered_samples = 0;
    329 
    330   if (nrSamplesRoom > 0) {
    331     buffered_samples = hMdct->ov_offset;
    332 
    333     FDK_ASSERT(buffered_samples <= nrSamplesRoom);
    334 
    335     if (buffered_samples > 0) {
    336       FDKmemcpy(output, hMdct->overlap.time,
    337                 buffered_samples * sizeof(FIXP_DBL));
    338       hMdct->ov_offset = 0;
    339     }
    340   }
    341   return buffered_samples;
    342 }
    343 
    344 INT imdct_copy_ov_and_nr(H_MDCT hMdct, FIXP_DBL *pTimeData, INT nrSamples) {
    345   FIXP_DBL *pOvl;
    346   int nt, nf, i;
    347 
    348   nt = fMin(hMdct->ov_offset, nrSamples);
    349   nrSamples -= nt;
    350   nf = fMin(hMdct->prev_nr, nrSamples);
    351   FDKmemcpy(pTimeData, hMdct->overlap.time, nt * sizeof(FIXP_DBL));
    352   pTimeData += nt;
    353 
    354   pOvl = hMdct->overlap.freq + hMdct->ov_size - 1;
    355   if (hMdct->prevPrevAliasSymmetry == 0) {
    356     for (i = 0; i < nf; i++) {
    357       FIXP_DBL x = -(*pOvl--);
    358       *pTimeData = IMDCT_SCALE_DBL(x);
    359       pTimeData++;
    360     }
    361   } else {
    362     for (i = 0; i < nf; i++) {
    363       FIXP_DBL x = (*pOvl--);
    364       *pTimeData = IMDCT_SCALE_DBL(x);
    365       pTimeData++;
    366     }
    367   }
    368 
    369   return (nt + nf);
    370 }
    371 
    372 void imdct_adapt_parameters(H_MDCT hMdct, int *pfl, int *pnl, int tl,
    373                             const FIXP_WTP *wls, int noOutSamples) {
    374   int fl = *pfl, nl = *pnl;
    375   int window_diff, use_current = 0, use_previous = 0;
    376   if (hMdct->prev_tl == 0) {
    377     hMdct->prev_wrs = wls;
    378     hMdct->prev_fr = fl;
    379     hMdct->prev_nr = (noOutSamples - fl) >> 1;
    380     hMdct->prev_tl = noOutSamples;
    381     hMdct->ov_offset = 0;
    382     use_current = 1;
    383   }
    384 
    385   window_diff = (hMdct->prev_fr - fl) >> 1;
    386 
    387   /* check if the previous window slope can be adjusted to match the current
    388    * window slope */
    389   if (hMdct->prev_nr + window_diff > 0) {
    390     use_current = 1;
    391   }
    392   /* check if the current window slope can be adjusted to match the previous
    393    * window slope */
    394   if (nl - window_diff > 0) {
    395     use_previous = 1;
    396   }
    397 
    398   /* if both is possible choose the larger of both window slope lengths */
    399   if (use_current && use_previous) {
    400     if (fl < hMdct->prev_fr) {
    401       use_current = 0;
    402     }
    403   }
    404   /*
    405    * If the previous transform block is big enough, enlarge previous window
    406    * overlap, if not, then shrink current window overlap.
    407    */
    408   if (use_current) {
    409     hMdct->prev_nr += window_diff;
    410     hMdct->prev_fr = fl;
    411     hMdct->prev_wrs = wls;
    412   } else {
    413     nl -= window_diff;
    414     fl = hMdct->prev_fr;
    415   }
    416 
    417   *pfl = fl;
    418   *pnl = nl;
    419 }
    420 
    421 /*
    422 This program implements the inverse modulated lapped transform, a generalized
    423 version of the inverse MDCT transform. Setting none of the MLT_*_ALIAS_FLAG
    424 flags computes the IMDCT, setting all of them computes the IMDST. Other
    425 combinations of these flags compute type III transforms used by the RSVD60
    426 multichannel tool for transitions between MDCT/MDST. The following description
    427 relates to the IMDCT only.
    428 
    429 If we pass the data block (A,B,C,D,E,F) to the FORWARD MDCT it will produce two
    430 outputs. The first one will be over the (A,B,C,D) part =>(-D-Cr,A-Br) and the
    431 second one will be over the (C,D,E,F) part => (-F-Er,C-Dr), since there is a
    432 overlap between consequtive passes of the algorithm. This overlap is over the
    433 (C,D) segments. The two outputs will be given sequentially to the DCT IV
    434 algorithm. At the INVERSE MDCT side we get two consecutive outputs from the IDCT
    435 IV algorithm, namely the same blocks: (-D-Cr,A-Br) and (-F-Er,C-Dr). The first
    436 of them lands in the Overlap buffer and the second is in the working one, which,
    437 one algorithm pass later will substitute the one residing in the overlap
    438 register. The IMDCT algorithm has to produce the C and D segments from the two
    439 buffers. In order to do this we take the left part of the overlap
    440 buffer(-D-Cr,A-Br), namely (-D-Cr) and add it appropriately to the right part of
    441 the working buffer (-F-Er,C-Dr), namely (C-Dr), so that we get first the C
    442 segment and later the D segment. We do this in the following way: From the right
    443 part of the working buffer(C-Dr) we subtract the flipped left part of the
    444 overlap buffer(-D-Cr):
    445 
    446 Result = (C-Dr) - flipped(-D-Cr) = C -Dr + Dr + C = 2C
    447 We divide by two and get the C segment. What we did is adding the right part of
    448 the first frame to the left part of the second one.   While applying these
    449 operation we multiply the respective segments with the appropriate window
    450 functions.
    451 
    452 In order to get the D segment we do the following:
    453 From the negated second part of the working buffer(C-Dr) we subtract the flipped
    454 first part of the overlap buffer (-D-Cr):
    455 
    456 Result= - (C -Dr) - flipped(-D-Cr)= -C +Dr +Dr +C = 2Dr.
    457 After dividing by two and flipping we get the D segment.What we did is adding
    458 the right part of the first frame to the left part of the second one.   While
    459 applying these operation we multiply the respective segments with the
    460 appropriate window functions.
    461 
    462 Once we have obtained the C and D segments the overlap buffer is emptied and the
    463 current buffer is sent in it, so that the E and F segments are available for
    464 decoding in the next algorithm pass.*/
    465 INT imlt_block(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *spectrum,
    466                const SHORT scalefactor[], const INT nSpec,
    467                const INT noOutSamples, const INT tl, const FIXP_WTP *wls,
    468                INT fl, const FIXP_WTP *wrs, const INT fr, FIXP_DBL gain,
    469                int flags) {
    470   FIXP_DBL *pOvl;
    471   FIXP_DBL *pOut0 = output, *pOut1;
    472   INT nl, nr;
    473   int w, i, nrSamples = 0, specShiftScale, transform_gain_e = 0;
    474   int currAliasSymmetry = (flags & MLT_FLAG_CURR_ALIAS_SYMMETRY);
    475 
    476   /* Derive NR and NL */
    477   nr = (tl - fr) >> 1;
    478   nl = (tl - fl) >> 1;
    479 
    480   /* Include 2/N IMDCT gain into gain factor and exponent. */
    481   imdct_gain(&gain, &transform_gain_e, tl);
    482 
    483   /* Detect FRprevious / FL mismatches and override parameters accordingly */
    484   if (hMdct->prev_fr != fl) {
    485     imdct_adapt_parameters(hMdct, &fl, &nl, tl, wls, noOutSamples);
    486   }
    487 
    488   pOvl = hMdct->overlap.freq + hMdct->ov_size - 1;
    489 
    490   if (noOutSamples > nrSamples) {
    491     /* Purge buffered output. */
    492     for (i = 0; i < hMdct->ov_offset; i++) {
    493       *pOut0 = hMdct->overlap.time[i];
    494       pOut0++;
    495     }
    496     nrSamples = hMdct->ov_offset;
    497     hMdct->ov_offset = 0;
    498   }
    499 
    500   for (w = 0; w < nSpec; w++) {
    501     FIXP_DBL *pSpec, *pCurr;
    502     const FIXP_WTP *pWindow;
    503 
    504     /* Detect FRprevious / FL mismatches and override parameters accordingly */
    505     if (hMdct->prev_fr != fl) {
    506       imdct_adapt_parameters(hMdct, &fl, &nl, tl, wls, noOutSamples);
    507     }
    508 
    509     specShiftScale = transform_gain_e;
    510 
    511     /* Setup window pointers */
    512     pWindow = hMdct->prev_wrs;
    513 
    514     /* Current spectrum */
    515     pSpec = spectrum + w * tl;
    516 
    517     /* DCT IV of current spectrum. */
    518     if (currAliasSymmetry == 0) {
    519       if (hMdct->prevAliasSymmetry == 0) {
    520         dct_IV(pSpec, tl, &specShiftScale);
    521       } else {
    522         FIXP_DBL _tmp[1024 + ALIGNMENT_DEFAULT / sizeof(FIXP_DBL)];
    523         FIXP_DBL *tmp = (FIXP_DBL *)ALIGN_PTR(_tmp);
    524         C_ALLOC_ALIGNED_REGISTER(tmp, sizeof(_tmp));
    525         dct_III(pSpec, tmp, tl, &specShiftScale);
    526         C_ALLOC_ALIGNED_UNREGISTER(tmp);
    527       }
    528     } else {
    529       if (hMdct->prevAliasSymmetry == 0) {
    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, &specShiftScale);
    534         C_ALLOC_ALIGNED_UNREGISTER(tmp);
    535       } else {
    536         dst_IV(pSpec, tl, &specShiftScale);
    537       }
    538     }
    539 
    540     /* Optional scaling of time domain - no yet windowed - of current spectrum
    541      */
    542     /* and de-scale current spectrum signal (time domain, no yet windowed) */
    543     if (gain != (FIXP_DBL)0) {
    544       for (i = 0; i < tl; i++) {
    545         pSpec[i] = fMult(pSpec[i], gain);
    546       }
    547     }
    548 
    549     {
    550       int loc_scale =
    551           fixmin_I(scalefactor[w] + specShiftScale, (INT)DFRACT_BITS - 1);
    552       DWORD_ALIGNED(pSpec);
    553       scaleValuesSaturate(pSpec, tl, loc_scale);
    554     }
    555 
    556     if (noOutSamples <= nrSamples) {
    557       /* Divert output first half to overlap buffer if we already got enough
    558        * output samples. */
    559       pOut0 = hMdct->overlap.time + hMdct->ov_offset;
    560       hMdct->ov_offset += hMdct->prev_nr + fl / 2;
    561     } else {
    562       /* Account output samples */
    563       nrSamples += hMdct->prev_nr + fl / 2;
    564     }
    565 
    566     /* NR output samples 0 .. NR. -overlap[TL/2..TL/2-NR] */
    567     if ((hMdct->pFacZir != 0) && (hMdct->prev_nr == fl / 2)) {
    568       /* In the case of ACELP -> TCX20 -> FD short add FAC ZIR on nr signal part
    569        */
    570       for (i = 0; i < hMdct->prev_nr; i++) {
    571         FIXP_DBL x = -(*pOvl--);
    572         *pOut0 = IMDCT_SCALE_DBL(x + hMdct->pFacZir[i]);
    573         pOut0++;
    574       }
    575       hMdct->pFacZir = NULL;
    576     } else {
    577       /* Here we implement a simplified version of what happens after the this
    578       piece of code (see the comments below). We implement the folding of C and
    579       D segments from (-D-Cr) but D is zero, because in this part of the MDCT
    580       sequence the window coefficients with which D must be multiplied are zero.
    581       "pOut0" writes sequentially the C block from left to right.   */
    582       if (hMdct->prevPrevAliasSymmetry == 0) {
    583         for (i = 0; i < hMdct->prev_nr; i++) {
    584           FIXP_DBL x = -(*pOvl--);
    585           *pOut0 = IMDCT_SCALE_DBL(x);
    586           pOut0++;
    587         }
    588       } else {
    589         for (i = 0; i < hMdct->prev_nr; i++) {
    590           FIXP_DBL x = *pOvl--;
    591           *pOut0 = IMDCT_SCALE_DBL(x);
    592           pOut0++;
    593         }
    594       }
    595     }
    596 
    597     if (noOutSamples <= nrSamples) {
    598       /* Divert output second half to overlap buffer if we already got enough
    599        * output samples. */
    600       pOut1 = hMdct->overlap.time + hMdct->ov_offset + fl / 2 - 1;
    601       hMdct->ov_offset += fl / 2 + nl;
    602     } else {
    603       pOut1 = pOut0 + (fl - 1);
    604       nrSamples += fl / 2 + nl;
    605     }
    606 
    607     /* output samples before window crossing point NR .. TL/2.
    608      * -overlap[TL/2-NR..TL/2-NR-FL/2] + current[NR..TL/2] */
    609     /* output samples after window crossing point TL/2 .. TL/2+FL/2.
    610      * -overlap[0..FL/2] - current[TL/2..FL/2] */
    611     pCurr = pSpec + tl - fl / 2;
    612     DWORD_ALIGNED(pCurr);
    613     C_ALLOC_ALIGNED_REGISTER(pWindow, fl);
    614     DWORD_ALIGNED(pWindow);
    615     C_ALLOC_ALIGNED_UNREGISTER(pWindow);
    616 
    617     if (hMdct->prevPrevAliasSymmetry == 0) {
    618       if (hMdct->prevAliasSymmetry == 0) {
    619         if (!hMdct->pAsymOvlp) {
    620           for (i = 0; i < fl / 2; i++) {
    621             FIXP_DBL x0, x1;
    622             cplxMultDiv2(&x1, &x0, *pCurr++, -*pOvl--, pWindow[i]);
    623             *pOut0 = IMDCT_SCALE_DBL_LSH1(x0);
    624             *pOut1 = IMDCT_SCALE_DBL_LSH1(-x1);
    625             pOut0++;
    626             pOut1--;
    627           }
    628         } else {
    629           FIXP_DBL *pAsymOvl = hMdct->pAsymOvlp + fl / 2 - 1;
    630           for (i = 0; i < fl / 2; i++) {
    631             FIXP_DBL x0, x1;
    632             x1 = -fMultDiv2(*pCurr, pWindow[i].v.re) +
    633                  fMultDiv2(*pAsymOvl, pWindow[i].v.im);
    634             x0 = fMultDiv2(*pCurr, pWindow[i].v.im) -
    635                  fMultDiv2(*pOvl, pWindow[i].v.re);
    636             pCurr++;
    637             pOvl--;
    638             pAsymOvl--;
    639             *pOut0++ = IMDCT_SCALE_DBL_LSH1(x0);
    640             *pOut1-- = IMDCT_SCALE_DBL_LSH1(x1);
    641           }
    642           hMdct->pAsymOvlp = NULL;
    643         }
    644       } else { /* prevAliasingSymmetry == 1 */
    645         for (i = 0; i < fl / 2; i++) {
    646           FIXP_DBL x0, x1;
    647           cplxMultDiv2(&x1, &x0, *pCurr++, -*pOvl--, pWindow[i]);
    648           *pOut0 = IMDCT_SCALE_DBL_LSH1(x0);
    649           *pOut1 = IMDCT_SCALE_DBL_LSH1(x1);
    650           pOut0++;
    651           pOut1--;
    652         }
    653       }
    654     } else { /* prevPrevAliasingSymmetry == 1 */
    655       if (hMdct->prevAliasSymmetry == 0) {
    656         for (i = 0; i < fl / 2; i++) {
    657           FIXP_DBL x0, x1;
    658           cplxMultDiv2(&x1, &x0, *pCurr++, *pOvl--, pWindow[i]);
    659           *pOut0 = IMDCT_SCALE_DBL_LSH1(x0);
    660           *pOut1 = IMDCT_SCALE_DBL_LSH1(-x1);
    661           pOut0++;
    662           pOut1--;
    663         }
    664       } else { /* prevAliasingSymmetry == 1 */
    665         for (i = 0; i < fl / 2; i++) {
    666           FIXP_DBL x0, x1;
    667           cplxMultDiv2(&x1, &x0, *pCurr++, *pOvl--, pWindow[i]);
    668           *pOut0 = IMDCT_SCALE_DBL_LSH1(x0);
    669           *pOut1 = IMDCT_SCALE_DBL_LSH1(x1);
    670           pOut0++;
    671           pOut1--;
    672         }
    673       }
    674     }
    675 
    676     if (hMdct->pFacZir != 0) {
    677       /* add FAC ZIR of previous ACELP -> mdct transition */
    678       FIXP_DBL *pOut = pOut0 - fl / 2;
    679       FDK_ASSERT(fl / 2 <= 128);
    680       for (i = 0; i < fl / 2; i++) {
    681         pOut[i] += IMDCT_SCALE_DBL(hMdct->pFacZir[i]);
    682       }
    683       hMdct->pFacZir = NULL;
    684     }
    685     pOut0 += (fl / 2) + nl;
    686 
    687     /* NL output samples TL/2+FL/2..TL. - current[FL/2..0] */
    688     pOut1 += (fl / 2) + 1;
    689     pCurr = pSpec + tl - fl / 2 - 1;
    690     /* Here we implement a simplified version of what happens above the this
    691     piece of code (see the comments above). We implement the folding of C and D
    692     segments from (C-Dr) but C is zero, because in this part of the MDCT
    693     sequence the window coefficients with which C must be multiplied are zero.
    694     "pOut1" writes sequentially the D block from left to right.   */
    695     if (hMdct->prevAliasSymmetry == 0) {
    696       for (i = 0; i < nl; i++) {
    697         FIXP_DBL x = -(*pCurr--);
    698         *pOut1++ = IMDCT_SCALE_DBL(x);
    699       }
    700     } else {
    701       for (i = 0; i < nl; i++) {
    702         FIXP_DBL x = *pCurr--;
    703         *pOut1++ = IMDCT_SCALE_DBL(x);
    704       }
    705     }
    706 
    707     /* Set overlap source pointer for next window pOvl = pSpec + tl/2 - 1; */
    708     pOvl = pSpec + tl / 2 - 1;
    709 
    710     /* Previous window values. */
    711     hMdct->prev_nr = nr;
    712     hMdct->prev_fr = fr;
    713     hMdct->prev_tl = tl;
    714     hMdct->prev_wrs = wrs;
    715 
    716     /* Previous aliasing symmetry */
    717     hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry;
    718     hMdct->prevAliasSymmetry = currAliasSymmetry;
    719   }
    720 
    721   /* Save overlap */
    722 
    723   pOvl = hMdct->overlap.freq + hMdct->ov_size - tl / 2;
    724   FDKmemcpy(pOvl, &spectrum[(nSpec - 1) * tl], (tl / 2) * sizeof(FIXP_DBL));
    725 
    726   return nrSamples;
    727 }
    728