• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2019 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 /******************* 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 
mdct_init(H_MDCT hMdct,FIXP_DBL * overlap,INT overlapBufferSize)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 */
mdct_block(H_MDCT hMdct,const INT_PCM * RESTRICT timeData,const INT noInSamples,FIXP_DBL * RESTRICT mdctData,const INT nSpec,const INT tl,const FIXP_WTP * pRightWindowPart,const INT fr,SHORT * pMdctData_e)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 
imdct_gain(FIXP_DBL * pGain_m,int * pGain_e,int tl)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 
imdct_drain(H_MDCT hMdct,FIXP_DBL * output,INT nrSamplesRoom)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 
imdct_copy_ov_and_nr(H_MDCT hMdct,FIXP_DBL * pTimeData,INT nrSamples)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 
imdct_adapt_parameters(H_MDCT hMdct,int * pfl,int * pnl,int tl,const FIXP_WTP * wls,int noOutSamples)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.*/
imlt_block(H_MDCT hMdct,FIXP_DBL * output,FIXP_DBL * spectrum,const SHORT scalefactor[],const INT nSpec,const INT noOutSamples,const INT tl,const FIXP_WTP * wls,INT fl,const FIXP_WTP * wrs,const INT fr,FIXP_DBL gain,int flags)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 = fAddSaturate(x, IMDCT_SCALE_DBL(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] = fAddSaturate(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