Coverage Report

Created: 2025-11-16 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/aac/libAACdec/src/usacdec_fac.cpp
Line
Count
Source
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
/**************************** 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
44.5k
#define SPEC_FAC(ptr, i, gl) ((ptr) + ((i) * (gl)))
114
115
FIXP_DBL *CLpd_FAC_GetMemory(CAacDecoderChannelInfo *pAacDecoderChannelInfo,
116
46.0k
                             UCHAR mod[NB_DIV], int *pState) {
117
46.0k
  FIXP_DBL *ptr;
118
46.0k
  int i;
119
46.0k
  int k = 0;
120
46.0k
  int max_windows = 8;
121
122
46.0k
  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
129k
  for (i = *pState; i < max_windows; i++) {
127
127k
    if (mod[i >> 1] == 0) {
128
44.5k
      break;
129
44.5k
    }
130
127k
  }
131
132
46.0k
  *pState = i + 1;
133
134
46.0k
  if (i == max_windows) {
135
1.42k
    ptr = pAacDecoderChannelInfo->data.usac.fac_data0;
136
44.5k
  } else {
137
44.5k
    FDK_ASSERT(mod[(i >> 1)] == 0);
138
44.5k
    ptr = SPEC_FAC(pAacDecoderChannelInfo->pSpectralCoefficient, i,
139
44.5k
                   pAacDecoderChannelInfo->granuleLength << k);
140
44.5k
  }
141
142
46.0k
  return ptr;
143
46.0k
}
144
145
int CLpd_FAC_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pFac, SCHAR *pFacScale,
146
86.6k
                  int length, int use_gain, int frame) {
147
86.6k
  FIXP_DBL fac_gain;
148
86.6k
  int fac_gain_e = 0;
149
150
86.6k
  if (use_gain) {
151
43.4k
    CLpd_DecodeGain(&fac_gain, &fac_gain_e, FDKreadBits(hBs, 7));
152
43.4k
  }
153
154
86.6k
  if (CLpc_DecodeAVQ(hBs, pFac, 1, 1, length) != 0) {
155
333
    return -1;
156
333
  }
157
158
86.3k
  {
159
86.3k
    int scale;
160
161
86.3k
    scale = getScalefactor(pFac, length);
162
86.3k
    scaleValues(pFac, length, scale);
163
86.3k
    pFacScale[frame] = DFRACT_BITS - 1 - scale;
164
86.3k
  }
165
166
86.3k
  if (use_gain) {
167
43.1k
    int i;
168
169
43.1k
    pFacScale[frame] += fac_gain_e;
170
171
3.01M
    for (i = 0; i < length; i++) {
172
2.96M
      pFac[i] = fMult(pFac[i], fac_gain);
173
2.96M
    }
174
43.1k
  }
175
86.3k
  return 0;
176
86.6k
}
177
178
/**
179
 * \brief Apply synthesis filter with zero input to x. The overall filter gain
180
 * is 1.0.
181
 * \param a LPC filter coefficients.
182
 * \param length length of the input/output data vector x.
183
 * \param x input/output vector, where the synthesis filter is applied in place.
184
 */
185
static void Syn_filt_zero(const FIXP_LPC a[], const INT a_exp, INT length,
186
67.6k
                          FIXP_DBL x[]) {
187
67.6k
  int i, j;
188
67.6k
  FIXP_DBL L_tmp;
189
190
12.8M
  for (i = 0; i < length; i++) {
191
12.8M
    L_tmp = (FIXP_DBL)0;
192
193
208M
    for (j = 0; j < fMin(i, M_LP_FILTER_ORDER); j++) {
194
196M
      L_tmp -= fMultDiv2(a[j], x[i - (j + 1)]) >> (LP_FILTER_SCALE - 1);
195
196M
    }
196
197
12.8M
    L_tmp = scaleValue(L_tmp, a_exp + LP_FILTER_SCALE);
198
12.8M
    x[i] = fAddSaturate(x[i], L_tmp);
199
12.8M
  }
200
67.6k
}
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
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
37.7k
                     const INT mod) {
211
37.7k
  FIXP_DBL facFactor;
212
37.7k
  int i;
213
214
37.7k
  FDK_ASSERT((fac_length == 128) || (fac_length == 96));
215
216
  /* 2) Apply gain factor to FAC data */
217
37.7k
  facFactor = fMult(gainFac[mod], tcx_gain);
218
4.24M
  for (i = 0; i < fac_length; i++) {
219
4.20M
    fac_data[i] = fMult(fac_data[i], facFactor);
220
4.20M
  }
221
222
  /* 3) Apply spectrum deshaping using alfd_gains */
223
1.08M
  for (i = 0; i < fac_length / 4; i++) {
224
1.05M
    int k;
225
226
1.05M
    k = i >> (3 - mod);
227
1.05M
    fac_data[i] = fMult(fac_data[i], alfd_gains[k])
228
1.05M
                  << 1; /* alfd_gains is scaled by one bit. */
229
1.05M
  }
230
37.7k
}
231
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
67.6k
                               const int isFdFac) {
237
67.6k
  FIXP_LPC wA[M_LP_FILTER_ORDER];
238
67.6k
  FIXP_DBL tf_gain = (FIXP_DBL)0;
239
67.6k
  int wlength;
240
67.6k
  int scale = fac_scale;
241
242
  /* obtain tranform gain. */
243
67.6k
  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
67.6k
  dct_IV(pFac, fac_length, &scale);
248
  /* dct_IV scale = log2(fac_length). "- 7" is a factor of 2/128 */
249
67.6k
  if (tf_gain != (FIXP_DBL)0) { /* non-radix 2 transform gain */
250
23.7k
    int i;
251
252
2.30M
    for (i = 0; i < fac_length; i++) {
253
2.28M
      pFac[i] = fMult(tf_gain, pFac[i]);
254
2.28M
    }
255
23.7k
  }
256
67.6k
  scaleValuesSaturate(pOut, pFac, fac_length,
257
67.6k
                      scale); /* Avoid overflow issues and saturate. */
258
259
67.6k
  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
67.6k
  FDKmemclear(pOut + fac_length, fac_length * sizeof(FIXP_DBL));
265
67.6k
  wlength = 2 * fac_length;
266
267
  /* 5) Apply weighted synthesis filter to FAC data, including optional Zir (5.
268
   * item 4). */
269
67.6k
  Syn_filt_zero(wA, A_exp, wlength, pOut);
270
67.6k
}
271
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
43.0k
                        const INT isFdFac, UCHAR prevWindowShape) {
276
43.0k
  FIXP_DBL *pOvl;
277
43.0k
  FIXP_DBL *pOut0;
278
43.0k
  const FIXP_WTP *pWindow;
279
43.0k
  int i, fl, nrSamples = 0;
280
281
43.0k
  FDK_ASSERT(fac_length <= 1024 / (4 * 2));
282
283
43.0k
  fl = fac_length * 2;
284
285
43.0k
  pWindow = FDKgetWindowSlope(fl, prevWindowShape);
286
287
  /* Adapt window slope length in case of frame loss. */
288
43.0k
  if (hMdct->prev_fr != fl) {
289
9.21k
    int nl = 0;
290
9.21k
    imdct_adapt_parameters(hMdct, &fl, &nl, fac_length, pWindow, nrOutSamples);
291
9.21k
    FDK_ASSERT(nl == 0);
292
9.21k
  }
293
294
43.0k
  if (nrSamples < nrOutSamples) {
295
33.8k
    pOut0 = output;
296
33.8k
    nrSamples += hMdct->ov_offset;
297
    /* Purge buffered output. */
298
33.8k
    FDKmemcpy(pOut0, hMdct->overlap.time, hMdct->ov_offset * sizeof(pOut0[0]));
299
33.8k
    hMdct->ov_offset = 0;
300
33.8k
  }
301
302
43.0k
  pOvl = hMdct->overlap.freq + hMdct->ov_size - 1;
303
304
43.0k
  if (nrSamples >= nrOutSamples) {
305
9.20k
    pOut0 = hMdct->overlap.time + hMdct->ov_offset;
306
9.20k
    hMdct->ov_offset += hMdct->prev_nr + fl / 2;
307
33.8k
  } else {
308
33.8k
    pOut0 = output + nrSamples;
309
33.8k
    nrSamples += hMdct->prev_nr + fl / 2;
310
33.8k
  }
311
43.0k
  if (hMdct->prevPrevAliasSymmetry == 0) {
312
3.84M
    for (i = 0; i < hMdct->prev_nr; i++) {
313
3.80M
      FIXP_DBL x = -(*pOvl--);
314
3.80M
      *pOut0 = IMDCT_SCALE_DBL(x);
315
3.80M
      pOut0++;
316
3.80M
    }
317
43.0k
  } else {
318
0
    for (i = 0; i < hMdct->prev_nr; i++) {
319
0
      FIXP_DBL x = (*pOvl--);
320
0
      *pOut0 = IMDCT_SCALE_DBL(x);
321
0
      pOut0++;
322
0
    }
323
0
  }
324
43.0k
  hMdct->prev_nr = 0;
325
326
43.0k
  {
327
43.0k
    if (pFac != NULL) {
328
      /* Note: The FAC gain might have been applied directly after bit stream
329
       * parse in this case. */
330
28.1k
      CFac_CalcFacSignal(pOut0, pFac, fac_scale, fac_length, A, A_exp, 0,
331
28.1k
                         isFdFac);
332
28.1k
    } else {
333
      /* Clear buffer because of the overlap and ADD! */
334
14.8k
      FDKmemclear(pOut0, fac_length * sizeof(FIXP_DBL));
335
14.8k
    }
336
43.0k
  }
337
338
43.0k
  i = 0;
339
340
43.0k
  if (hMdct->prevPrevAliasSymmetry == 0) {
341
4.28M
    for (; i < fl / 2; i++) {
342
4.24M
      FIXP_DBL x0;
343
344
      /* Overlap Add */
345
4.24M
      x0 = -fMult(*pOvl--, pWindow[i].v.re);
346
347
4.24M
      *pOut0 = fAddSaturate(*pOut0, IMDCT_SCALE_DBL(x0));
348
4.24M
      pOut0++;
349
4.24M
    }
350
43.0k
  } else {
351
0
    for (; i < fl / 2; i++) {
352
0
      FIXP_DBL x0;
353
354
      /* Overlap Add */
355
0
      x0 = fMult(*pOvl--, pWindow[i].v.re);
356
357
0
      *pOut0 = fAddSaturate(*pOut0, IMDCT_SCALE_DBL(x0));
358
0
      pOut0++;
359
0
    }
360
0
  }
361
43.0k
  if (hMdct->pFacZir !=
362
43.0k
      0) { /* this should only happen for ACELP -> TCX20 -> ACELP transition */
363
7.37k
    FIXP_DBL *pOut = pOut0 - fl / 2; /* fl/2 == fac_length */
364
780k
    for (i = 0; i < fl / 2; i++) {
365
772k
      pOut[i] = fAddSaturate(pOut[i], IMDCT_SCALE_DBL(hMdct->pFacZir[i]));
366
772k
    }
367
7.37k
    hMdct->pFacZir = NULL;
368
7.37k
  }
369
370
43.0k
  hMdct->prev_fr = 0;
371
43.0k
  hMdct->prev_nr = 0;
372
43.0k
  hMdct->prev_tl = 0;
373
43.0k
  hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry;
374
375
43.0k
  return nrSamples;
376
43.0k
}
377
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
39.4k
                        const int k, int currAliasingSymmetry) {
387
39.4k
  FIXP_DBL *pCurr, *pOvl, *pSpec;
388
39.4k
  const FIXP_WTP *pWindow;
389
39.4k
  const FIXP_WTB *FacWindowZir_conceal;
390
39.4k
  UCHAR doFacZirConceal = 0;
391
39.4k
  int doDeemph = 1;
392
39.4k
  const FIXP_WTB *FacWindowZir, *FacWindowSynth;
393
39.4k
  FIXP_DBL *pOut0 = output, *pOut1;
394
39.4k
  int w, i, fl, nl, nr, f_len, nrSamples = 0, s = 0, scale, total_gain_e;
395
39.4k
  FIXP_DBL *pF, *pFAC_and_FAC_ZIR = NULL;
396
39.4k
  FIXP_DBL total_gain = gain;
397
398
39.4k
  FDK_ASSERT(fac_length <= 1024 / (4 * 2));
399
39.4k
  switch (fac_length) {
400
    /* coreCoderFrameLength = 1024 */
401
9.57k
    case 128:
402
9.57k
      pWindow = SineWindow256;
403
9.57k
      FacWindowZir = FacWindowZir128;
404
9.57k
      FacWindowSynth = FacWindowSynth128;
405
9.57k
      break;
406
8.16k
    case 64:
407
8.16k
      pWindow = SineWindow128;
408
8.16k
      FacWindowZir = FacWindowZir64;
409
8.16k
      FacWindowSynth = FacWindowSynth64;
410
8.16k
      break;
411
0
    case 32:
412
0
      pWindow = SineWindow64;
413
0
      FacWindowZir = FacWindowZir32;
414
0
      FacWindowSynth = FacWindowSynth32;
415
0
      break;
416
    /* coreCoderFrameLength = 768 */
417
12.4k
    case 96:
418
12.4k
      pWindow = SineWindow192;
419
12.4k
      FacWindowZir = FacWindowZir96;
420
12.4k
      FacWindowSynth = FacWindowSynth96;
421
12.4k
      break;
422
9.32k
    case 48:
423
9.32k
      pWindow = SineWindow96;
424
9.32k
      FacWindowZir = FacWindowZir48;
425
9.32k
      FacWindowSynth = FacWindowSynth48;
426
9.32k
      break;
427
0
    default:
428
0
      FDK_ASSERT(0);
429
0
      return 0;
430
39.4k
  }
431
432
39.4k
  FacWindowZir_conceal = FacWindowSynth;
433
  /* Derive NR and NL */
434
39.4k
  fl = fac_length * 2;
435
39.4k
  nl = (tl - fl) >> 1;
436
39.4k
  nr = (tl - fr) >> 1;
437
438
39.4k
  if (noOutSamples > nrSamples) {
439
    /* Purge buffered output. */
440
30.3k
    FDKmemcpy(pOut0, hMdct->overlap.time, hMdct->ov_offset * sizeof(pOut0[0]));
441
30.3k
    nrSamples = hMdct->ov_offset;
442
30.3k
    hMdct->ov_offset = 0;
443
30.3k
  }
444
445
39.4k
  if (nrSamples >= noOutSamples) {
446
9.10k
    pOut1 = hMdct->overlap.time + hMdct->ov_offset;
447
9.10k
    if (hMdct->ov_offset < fac_length) {
448
6.07k
      pOut0 = output + nrSamples;
449
6.07k
    } else {
450
3.03k
      pOut0 = pOut1;
451
3.03k
    }
452
9.10k
    hMdct->ov_offset += fac_length + nl;
453
30.3k
  } else {
454
30.3k
    pOut1 = output + nrSamples;
455
30.3k
    pOut0 = output + nrSamples;
456
30.3k
  }
457
458
39.4k
  {
459
39.4k
    pFAC_and_FAC_ZIR = CLpd_ACELP_GetFreeExcMem(acelp_mem, 2 * fac_length);
460
39.4k
    {
461
39.4k
      const FIXP_DBL *pTmp1, *pTmp2;
462
463
39.4k
      doFacZirConceal |= ((last_frame_lost != 0) && (k == 0));
464
39.4k
      doDeemph &= (last_lpd_mode != 4);
465
39.4k
      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
10
        FDKmemclear(pFAC_and_FAC_ZIR, 2 * fac_length * sizeof(FIXP_DBL));
471
10
        FacWindowSynth = (FIXP_WTB *)pFAC_and_FAC_ZIR;
472
10
        FacWindowZir = FacWindowZir_conceal;
473
39.4k
      } else {
474
39.4k
        CFac_CalcFacSignal(pFAC_and_FAC_ZIR, pFac, fac_scale + s, fac_length, A,
475
39.4k
                           A_exp, 1, isFdFac);
476
39.4k
      }
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
39.4k
      {
484
39.4k
        {
485
39.4k
          CLpd_Acelp_Zir(A, A_exp, acelp_mem, fac_length, pFac, doDeemph);
486
487
39.4k
          pTmp1 = pOut0;
488
39.4k
          pTmp2 = pFac;
489
39.4k
        }
490
491
3.42M
        for (i = 0, w = 0; i < fac_length; i++) {
492
3.38M
          FIXP_DBL x;
493
          /* Div2 is compensated by table scaling */
494
3.38M
          x = fMultDiv2(pTmp2[i], FacWindowZir[w]);
495
3.38M
          x += fMultDiv2(pTmp1[-i - 1], FacWindowSynth[w]);
496
3.38M
          pOut1[i] = fAddSaturate(x, pFAC_and_FAC_ZIR[i]);
497
3.38M
          w++;
498
3.38M
        }
499
39.4k
      }
500
501
39.4k
      if (doFacZirConceal) {
502
        /* ZIR is the only ACELP contribution, so double it */
503
10
        scaleValues(pOut1, fac_length, 1);
504
10
      }
505
39.4k
    }
506
39.4k
  }
507
508
39.4k
  if (nrSamples < noOutSamples) {
509
30.3k
    nrSamples += fac_length + nl;
510
30.3k
  }
511
512
  /* Obtain transform gain */
513
39.4k
  total_gain = gain;
514
39.4k
  total_gain_e = 0;
515
39.4k
  imdct_gain(&total_gain, &total_gain_e, tl);
516
517
  /* IMDCT overlap add */
518
39.4k
  scale = total_gain_e;
519
39.4k
  pSpec = _pSpec;
520
521
  /* Note:when comming from an LPD frame (TCX/ACELP) the previous alisaing
522
   * symmetry must always be 0 */
523
39.4k
  if (currAliasingSymmetry == 0) {
524
39.4k
    dct_IV(pSpec, tl, &scale);
525
39.4k
  } else {
526
0
    FIXP_DBL _tmp[1024 + ALIGNMENT_DEFAULT / sizeof(FIXP_DBL)];
527
0
    FIXP_DBL *tmp = (FIXP_DBL *)ALIGN_PTR(_tmp);
528
0
    C_ALLOC_ALIGNED_REGISTER(tmp, sizeof(_tmp));
529
0
    dst_III(pSpec, tmp, tl, &scale);
530
0
    C_ALLOC_ALIGNED_UNREGISTER(tmp);
531
0
  }
532
533
  /* Optional scaling of time domain - no yet windowed - of current spectrum */
534
39.4k
  if (total_gain != (FIXP_DBL)0) {
535
7.26M
    for (i = 0; i < tl; i++) {
536
7.23M
      pSpec[i] = fMult(pSpec[i], total_gain);
537
7.23M
    }
538
28.8k
  }
539
39.4k
  int loc_scale = fixmin_I(spec_scale[0] + scale, (INT)DFRACT_BITS - 1);
540
39.4k
  scaleValuesSaturate(pSpec, tl, loc_scale);
541
542
39.4k
  pOut1 += fl / 2 - 1;
543
39.4k
  pCurr = pSpec + tl - fl / 2;
544
545
3.42M
  for (i = 0; i < fl / 2; i++) {
546
3.38M
    FIXP_DBL x1;
547
548
    /* FAC signal is already on pOut1, because of that the += operator. */
549
3.38M
    x1 = fMult(*pCurr++, pWindow[i].v.re);
550
3.38M
    FDK_ASSERT((pOut1 >= hMdct->overlap.time &&
551
3.38M
                pOut1 < hMdct->overlap.time + hMdct->ov_size) ||
552
3.38M
               (pOut1 >= output && pOut1 < output + 1024));
553
3.38M
    *pOut1 = fAddSaturate(*pOut1, IMDCT_SCALE_DBL(-x1));
554
3.38M
    pOut1--;
555
3.38M
  }
556
557
  /* NL output samples TL/2+FL/2..TL. - current[FL/2..0] */
558
39.4k
  pOut1 += (fl / 2) + 1;
559
560
39.4k
  pFAC_and_FAC_ZIR += fac_length; /* set pointer to beginning of FAC ZIR */
561
562
39.4k
  if (nl == 0) {
563
    /* save pointer to write FAC ZIR data later */
564
28.4k
    hMdct->pFacZir = pFAC_and_FAC_ZIR;
565
28.4k
  } else {
566
10.9k
    FDK_ASSERT(nl >= fac_length);
567
    /* FAC ZIR will be added now ... */
568
10.9k
    hMdct->pFacZir = NULL;
569
10.9k
  }
570
571
39.4k
  pF = pFAC_and_FAC_ZIR;
572
39.4k
  f_len = fac_length;
573
574
39.4k
  pCurr = pSpec + tl - fl / 2 - 1;
575
2.05M
  for (i = 0; i < nl; i++) {
576
2.01M
    FIXP_DBL x = -(*pCurr--);
577
    /* 5) (item 4) Synthesis filter Zir component, FAC ZIR (another one). */
578
2.01M
    if (i < f_len) {
579
1.22M
      x = fAddSaturate(x, *pF++);
580
1.22M
    }
581
582
2.01M
    FDK_ASSERT((pOut1 >= hMdct->overlap.time &&
583
2.01M
                pOut1 < hMdct->overlap.time + hMdct->ov_size) ||
584
2.01M
               (pOut1 >= output && pOut1 < output + 1024));
585
2.01M
    *pOut1 = IMDCT_SCALE_DBL(x);
586
2.01M
    pOut1++;
587
2.01M
  }
588
589
39.4k
  hMdct->prev_nr = nr;
590
39.4k
  hMdct->prev_fr = fr;
591
39.4k
  hMdct->prev_wrs = wrs;
592
39.4k
  hMdct->prev_tl = tl;
593
39.4k
  hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry;
594
39.4k
  hMdct->prevAliasSymmetry = currAliasingSymmetry;
595
39.4k
  fl = fr;
596
39.4k
  nl = nr;
597
598
39.4k
  pOvl = pSpec + tl / 2 - 1;
599
39.4k
  pOut0 = pOut1;
600
601
161k
  for (w = 1; w < nSpec; w++) /* for ACELP -> FD short */
602
122k
  {
603
122k
    const FIXP_WTP *pWindow_prev;
604
605
    /* Setup window pointers */
606
122k
    pWindow_prev = hMdct->prev_wrs;
607
608
    /* Current spectrum */
609
122k
    pSpec = _pSpec + w * tl;
610
611
122k
    scale = total_gain_e;
612
613
    /* For the second, third, etc. short frames the alisaing symmetry is equal,
614
     * either (0,0) or (1,1) */
615
122k
    if (currAliasingSymmetry == 0) {
616
      /* DCT IV of current spectrum */
617
122k
      dct_IV(pSpec, tl, &scale);
618
122k
    } else {
619
0
      dst_IV(pSpec, tl, &scale);
620
0
    }
621
622
    /* Optional scaling of time domain - no yet windowed - of current spectrum
623
     */
624
    /* and de-scale current spectrum signal (time domain, no yet windowed) */
625
122k
    if (total_gain != (FIXP_DBL)0) {
626
6.33M
      for (i = 0; i < tl; i++) {
627
6.26M
        pSpec[i] = fMult(pSpec[i], total_gain);
628
6.26M
      }
629
65.2k
    }
630
122k
    loc_scale = fixmin_I(spec_scale[w] + scale, (INT)DFRACT_BITS - 1);
631
122k
    scaleValuesSaturate(pSpec, tl, loc_scale);
632
633
122k
    if (noOutSamples <= nrSamples) {
634
      /* Divert output first half to overlap buffer if we already got enough
635
       * output samples. */
636
52.4k
      pOut0 = hMdct->overlap.time + hMdct->ov_offset;
637
52.4k
      hMdct->ov_offset += hMdct->prev_nr + fl / 2;
638
69.9k
    } else {
639
      /* Account output samples */
640
69.9k
      nrSamples += hMdct->prev_nr + fl / 2;
641
69.9k
    }
642
643
    /* NR output samples 0 .. NR. -overlap[TL/2..TL/2-NR] */
644
122k
    for (i = 0; i < hMdct->prev_nr; i++) {
645
0
      FIXP_DBL x = -(*pOvl--);
646
0
      *pOut0 = IMDCT_SCALE_DBL(x);
647
0
      pOut0++;
648
0
    }
649
650
122k
    if (noOutSamples <= nrSamples) {
651
      /* Divert output second half to overlap buffer if we already got enough
652
       * output samples. */
653
69.9k
      pOut1 = hMdct->overlap.time + hMdct->ov_offset + fl / 2 - 1;
654
69.9k
      hMdct->ov_offset += fl / 2 + nl;
655
69.9k
    } else {
656
52.4k
      pOut1 = pOut0 + (fl - 1);
657
52.4k
      nrSamples += fl / 2 + nl;
658
52.4k
    }
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
122k
    pCurr = pSpec + tl - fl / 2;
665
122k
    if (currAliasingSymmetry == 0) {
666
6.91M
      for (i = 0; i < fl / 2; i++) {
667
6.78M
        FIXP_DBL x0, x1;
668
669
6.78M
        cplxMultDiv2(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]);
670
6.78M
        *pOut0 = IMDCT_SCALE_DBL_LSH1(x0);
671
6.78M
        *pOut1 = IMDCT_SCALE_DBL_LSH1(-x1);
672
6.78M
        pOut0++;
673
6.78M
        pOut1--;
674
6.78M
      }
675
122k
    } else {
676
0
      if (hMdct->prevPrevAliasSymmetry == 0) {
677
        /* Jump DST II -> DST IV for the second window */
678
0
        for (i = 0; i < fl / 2; i++) {
679
0
          FIXP_DBL x0, x1;
680
681
0
          cplxMultDiv2(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]);
682
0
          *pOut0 = IMDCT_SCALE_DBL_LSH1(x0);
683
0
          *pOut1 = IMDCT_SCALE_DBL_LSH1(x1);
684
0
          pOut0++;
685
0
          pOut1--;
686
0
        }
687
0
      } else {
688
        /* Jump DST IV -> DST IV from the second window on */
689
0
        for (i = 0; i < fl / 2; i++) {
690
0
          FIXP_DBL x0, x1;
691
692
0
          cplxMultDiv2(&x1, &x0, *pCurr++, *pOvl--, pWindow_prev[i]);
693
0
          *pOut0 = IMDCT_SCALE_DBL_LSH1(x0);
694
0
          *pOut1 = IMDCT_SCALE_DBL_LSH1(x1);
695
0
          pOut0++;
696
0
          pOut1--;
697
0
        }
698
0
      }
699
0
    }
700
701
122k
    if (hMdct->pFacZir != 0) {
702
      /* add FAC ZIR of previous ACELP -> mdct transition */
703
17.4k
      FIXP_DBL *pOut = pOut0 - fl / 2;
704
17.4k
      FDK_ASSERT(fl / 2 <= 128);
705
987k
      for (i = 0; i < fl / 2; i++) {
706
969k
        pOut[i] = fAddSaturate(pOut[i], IMDCT_SCALE_DBL(hMdct->pFacZir[i]));
707
969k
      }
708
17.4k
      hMdct->pFacZir = NULL;
709
17.4k
    }
710
122k
    pOut0 += (fl / 2);
711
712
    /* NL output samples TL/2+FL/2..TL. - current[FL/2..0] */
713
122k
    pOut1 += (fl / 2) + 1;
714
122k
    pCurr = pSpec + tl - fl / 2 - 1;
715
122k
    for (i = 0; i < nl; i++) {
716
0
      FIXP_DBL x = -(*pCurr--);
717
0
      *pOut1 = IMDCT_SCALE_DBL(x);
718
0
      pOut1++;
719
0
    }
720
721
    /* Set overlap source pointer for next window pOvl = pSpec + tl/2 - 1; */
722
122k
    pOvl = pSpec + tl / 2 - 1;
723
724
    /* Previous window values. */
725
122k
    hMdct->prev_nr = nr;
726
122k
    hMdct->prev_fr = fr;
727
122k
    hMdct->prev_tl = tl;
728
122k
    hMdct->prev_wrs = pWindow_prev;
729
122k
    hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry;
730
122k
    hMdct->prevAliasSymmetry = currAliasingSymmetry;
731
122k
  }
732
733
  /* Save overlap */
734
735
39.4k
  pOvl = hMdct->overlap.freq + hMdct->ov_size - tl / 2;
736
39.4k
  FDK_ASSERT(pOvl >= hMdct->overlap.time + hMdct->ov_offset);
737
39.4k
  FDK_ASSERT(tl / 2 <= hMdct->ov_size);
738
5.43M
  for (i = 0; i < tl / 2; i++) {
739
5.39M
    pOvl[i] = _pSpec[i + (w - 1) * tl];
740
5.39M
  }
741
742
39.4k
  return nrSamples;
743
39.4k
}