• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung 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@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 
CLpd_FAC_GetMemory(CAacDecoderChannelInfo * pAacDecoderChannelInfo,UCHAR mod[NB_DIV],int * pState)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 
CLpd_FAC_Read(HANDLE_FDK_BITSTREAM hBs,FIXP_DBL * pFac,SCHAR * pFacScale,int length,int use_gain,int frame)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  */
Syn_filt_zero(const FIXP_LPC a[],const INT a_exp,INT length,FIXP_DBL x[])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 
CFac_ApplyGains(FIXP_DBL fac_data[LFAC],const INT fac_length,const FIXP_DBL tcx_gain,const FIXP_DBL alfd_gains[],const INT mod)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 
CFac_CalcFacSignal(FIXP_DBL * pOut,FIXP_DBL * pFac,const int fac_scale,const int fac_length,const FIXP_LPC A[M_LP_FILTER_ORDER],const INT A_exp,const int fAddZir,const int isFdFac)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 
CLpd_FAC_Mdct2Acelp(H_MDCT hMdct,FIXP_DBL * output,FIXP_DBL * pFac,const int fac_scale,FIXP_LPC * A,INT A_exp,INT nrOutSamples,const INT fac_length,const INT isFdFac,UCHAR prevWindowShape)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 
CLpd_FAC_Acelp2Mdct(H_MDCT hMdct,FIXP_DBL * output,FIXP_DBL * _pSpec,const SHORT spec_scale[],const int nSpec,FIXP_DBL * pFac,const int fac_scale,const INT fac_length,INT noOutSamples,const INT tl,const FIXP_WTP * wrs,const INT fr,FIXP_LPC A[16],INT A_exp,CAcelpStaticMem * acelp_mem,const FIXP_DBL gain,const int last_frame_lost,const int isFdFac,const UCHAR last_lpd_mode,const int k,int currAliasingSymmetry)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