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,UCHAR * pFacScale,int length,int use_gain,int frame)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 */
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)]);
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
CFac_ApplyGains(FIXP_DBL fac_data[LFAC],const INT fac_length,const FIXP_DBL tcx_gain,const FIXP_DBL alfd_gains[],const INT mod)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
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)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
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)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
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)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