Coverage Report

Created: 2025-07-18 06:08

/src/aac/libSACdec/src/sac_process.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -----------------------------------------------------------------------------
2
Software License for The Fraunhofer FDK AAC Codec Library for Android
3
4
© Copyright  1995 - 2021 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
/*********************** MPEG surround decoder library *************************
96
97
   Author(s):
98
99
   Description: SAC Processing
100
101
*******************************************************************************/
102
103
/* data structures and interfaces for spatial audio reference software */
104
#include "sac_process.h"
105
106
#include "sac_bitdec.h"
107
#include "sac_calcM1andM2.h"
108
#include "sac_smoothing.h"
109
#include "sac_rom.h"
110
111
#include "sac_dec_errorcodes.h"
112
113
#include "FDK_trigFcts.h"
114
#include "FDK_decorrelate.h"
115
116
86.5M
#define SAC_DEC_APPLY_M2_SCALE(spec, s) ((spec) >> (-(s)))
117
118
/**
119
 * \brief  Linear interpolation between two parameter values.
120
 *         a*alpha + b*(1-alpha)
121
 *       = a*alpha + b - b*alpha
122
 *
123
 * \param alpha               Weighting factor.
124
 * \param a                   Parameter a.
125
 * \param b                   Parameter b.
126
 *
127
 * \return Interpolated parameter value.
128
 */
129
FDK_INLINE FIXP_DBL interpolateParameter(const FIXP_SGL alpha, const FIXP_DBL a,
130
269M
                                         const FIXP_DBL b) {
131
269M
  return (b - fMult(alpha, b) + fMult(alpha, a));
132
269M
}
133
134
/**
135
 * \brief Map MPEG Surround channel indices to MPEG 4 PCE like channel indices.
136
 * \param self Spatial decoder handle.
137
 * \param ch MPEG Surround channel index.
138
 * \return MPEG 4 PCE style channel index, corresponding to the given MPEG
139
 * Surround channel index.
140
 */
141
14.0M
static UINT mapChannel(spatialDec *self, UINT ch) {
142
14.0M
  static const UCHAR chanelIdx[][8] = {
143
14.0M
      {0, 1, 2, 3, 4, 5, 6, 7}, /*  binaural, TREE_212, arbitrary tree */
144
14.0M
  };
145
146
14.0M
  int idx = 0;
147
148
14.0M
  return (chanelIdx[idx][ch]);
149
14.0M
}
150
151
134k
FIXP_DBL getChGain(spatialDec *self, UINT ch, INT *scale) {
152
  /* init no gain modifier */
153
134k
  FIXP_DBL gain = 0x80000000;
154
134k
  *scale = 0;
155
156
134k
  if ((!isTwoChMode(self->upmixType)) &&
157
134k
      (self->upmixType != UPMIXTYPE_BYPASS)) {
158
134k
    if ((ch == 0) || (ch == 1) || (ch == 2)) {
159
      /* no modifier */
160
134k
    }
161
134k
  }
162
163
134k
  return gain;
164
134k
}
165
166
SACDEC_ERROR SpatialDecQMFAnalysis(spatialDec *self, const PCM_MPS *inData,
167
                                   const INT ts, const INT bypassMode,
168
                                   FIXP_DBL **qmfReal, FIXP_DBL **qmfImag,
169
1.87M
                                   const int numInputChannels) {
170
1.87M
  SACDEC_ERROR err = MPS_OK;
171
1.87M
  int ch, offset;
172
173
1.87M
  offset = self->pQmfDomain->globalConf.nBandsSynthesis *
174
1.87M
           self->pQmfDomain->globalConf.nQmfTimeSlots;
175
176
1.87M
  {
177
3.75M
    for (ch = 0; ch < numInputChannels; ch++) {
178
1.87M
      const PCM_MPS *inSamples =
179
1.87M
          &inData[ts * self->pQmfDomain->globalConf.nBandsAnalysis];
180
1.87M
      FIXP_DBL *pQmfRealAnalysis = qmfReal[ch]; /* no delay in blind mode */
181
1.87M
      FIXP_DBL *pQmfImagAnalysis = qmfImag[ch];
182
183
1.87M
      CalculateSpaceAnalysisQmf(&self->pQmfDomain->QmfDomainIn[ch].fb,
184
1.87M
                                inSamples + (ch * offset), pQmfRealAnalysis,
185
1.87M
                                pQmfImagAnalysis);
186
187
1.87M
      if (!isTwoChMode(self->upmixType) && !bypassMode) {
188
1.87M
        int i;
189
45.7M
        for (i = 0; i < self->qmfBands; i++) {
190
43.8M
          qmfReal[ch][i] = fMult(
191
43.8M
              scaleValueSaturate(qmfReal[ch][i], self->sacInDataHeadroom - (1)),
192
43.8M
              self->clipProtectGain__FDK);
193
43.8M
          qmfImag[ch][i] = fMult(
194
43.8M
              scaleValueSaturate(qmfImag[ch][i], self->sacInDataHeadroom - (1)),
195
43.8M
              self->clipProtectGain__FDK);
196
43.8M
        }
197
1.87M
      }
198
1.87M
    }
199
1.87M
  }
200
201
1.87M
  self->qmfInputDelayBufPos =
202
1.87M
      (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay;
203
204
1.87M
  return err;
205
1.87M
}
206
207
SACDEC_ERROR SpatialDecFeedQMF(spatialDec *self, FIXP_DBL **qmfInDataReal,
208
                               FIXP_DBL **qmfInDataImag, const INT ts,
209
                               const INT bypassMode, FIXP_DBL **qmfReal__FDK,
210
                               FIXP_DBL **qmfImag__FDK,
211
5.15M
                               const INT numInputChannels) {
212
5.15M
  SACDEC_ERROR err = MPS_OK;
213
5.15M
  int ch;
214
215
5.15M
  {
216
10.3M
    for (ch = 0; ch < numInputChannels; ch++) {
217
5.15M
      FIXP_DBL *pQmfRealAnalysis =
218
5.15M
          qmfReal__FDK[ch]; /* no delay in blind mode */
219
5.15M
      FIXP_DBL *pQmfImagAnalysis = qmfImag__FDK[ch];
220
221
      /* Write Input data to pQmfRealAnalysis. */
222
5.15M
      if (self->bShareDelayWithSBR) {
223
5.13M
        FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch],
224
5.13M
                              ts + HYBRID_FILTER_DELAY, 0,
225
5.13M
                              MAX_QMF_BANDS_TO_HYBRID, pQmfRealAnalysis,
226
5.13M
                              pQmfImagAnalysis, 15 + (1));
227
5.13M
        FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts,
228
5.13M
                              MAX_QMF_BANDS_TO_HYBRID, self->qmfBands,
229
5.13M
                              pQmfRealAnalysis, pQmfImagAnalysis, 15 + (1));
230
5.13M
      } else {
231
17.4k
        FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, 0,
232
17.4k
                              self->qmfBands, pQmfRealAnalysis,
233
17.4k
                              pQmfImagAnalysis, 15 + (1));
234
17.4k
      }
235
5.15M
      if (ts == self->pQmfDomain->globalConf.nQmfTimeSlots - 1) {
236
        /* Is currently also needed in case we dont have any overlap. We need to
237
         * save lb_scale to ov_lb_scale */
238
160k
        FDK_QmfDomain_SaveOverlap(&self->pQmfDomain->QmfDomainIn[ch], 0);
239
160k
      }
240
241
      /* Apply clip protection to output. */
242
5.15M
      if (!isTwoChMode(self->upmixType) && !bypassMode) {
243
5.15M
        int i;
244
334M
        for (i = 0; i < self->qmfBands; i++) {
245
329M
          qmfReal__FDK[ch][i] =
246
329M
              fMult(qmfReal__FDK[ch][i], self->clipProtectGain__FDK);
247
329M
          qmfImag__FDK[ch][i] =
248
329M
              fMult(qmfImag__FDK[ch][i], self->clipProtectGain__FDK);
249
329M
        }
250
5.15M
      }
251
252
5.15M
    } /* End of loop over numInputChannels */
253
5.15M
  }
254
255
5.15M
  self->qmfInputDelayBufPos =
256
5.15M
      (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay;
257
258
5.15M
  return err;
259
5.15M
}
260
261
/*******************************************************************************
262
 Functionname: SpatialDecHybridAnalysis
263
 *******************************************************************************
264
265
 Description:
266
267
 Arguments:
268
269
 Input:
270
  float** pointers[4] leftReal, leftIm, rightReal, rightIm
271
272
 Output:
273
  float self->qmfInputReal[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_QMF_BANDS];
274
  float self->qmfInputImag[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_QMF_BANDS];
275
276
  float
277
self->hybInputReal[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_HYBRID_BANDS]; float
278
self->hybInputImag[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_HYBRID_BANDS];
279
280
281
*******************************************************************************/
282
SACDEC_ERROR SpatialDecHybridAnalysis(spatialDec *self, FIXP_DBL **qmfInputReal,
283
                                      FIXP_DBL **qmfInputImag,
284
                                      FIXP_DBL **hybOutputReal,
285
                                      FIXP_DBL **hybOutputImag, const INT ts,
286
7.03M
                                      const INT numInputChannels) {
287
7.03M
  SACDEC_ERROR err = MPS_OK;
288
7.03M
  int ch;
289
290
14.0M
  for (ch = 0; ch < numInputChannels;
291
7.03M
       ch++) /* hybrid filtering for down-mix signals */
292
7.03M
  {
293
7.03M
    if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
294
735k
      int k;
295
      /* No hybrid filtering. Just copy the QMF data. */
296
25.0M
      for (k = 0; k < self->hybridBands; k += 1) {
297
24.3M
        hybOutputReal[ch][k] = qmfInputReal[ch][k];
298
24.3M
        hybOutputImag[ch][k] = qmfInputImag[ch][k];
299
24.3M
      }
300
6.29M
    } else {
301
6.29M
      self->hybridAnalysis[ch].hfMode = self->bShareDelayWithSBR;
302
303
6.29M
      if (self->stereoConfigIndex == 3)
304
6.29M
        FDK_ASSERT(self->hybridAnalysis[ch].hfMode == 0);
305
6.29M
      FDKhybridAnalysisApply(&self->hybridAnalysis[ch], qmfInputReal[ch],
306
6.29M
                             qmfInputImag[ch], hybOutputReal[ch],
307
6.29M
                             hybOutputImag[ch]);
308
6.29M
    }
309
7.03M
  }
310
311
7.03M
  if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) &&
312
7.03M
      self->residualCoding) {
313
1.25M
    self->hybridAnalysis[numInputChannels].hfMode = 0;
314
1.25M
    FDKhybridAnalysisApply(
315
1.25M
        &self->hybridAnalysis[numInputChannels],
316
1.25M
        self->qmfResidualReal__FDK[0][0], self->qmfResidualImag__FDK[0][0],
317
1.25M
        self->hybResidualReal__FDK[0], self->hybResidualImag__FDK[0]);
318
1.25M
  }
319
320
7.03M
  return err;
321
7.03M
}
322
323
SACDEC_ERROR SpatialDecCreateX(spatialDec *self, FIXP_DBL **hybInputReal,
324
                               FIXP_DBL **hybInputImag, FIXP_DBL **pxReal,
325
7.03M
                               FIXP_DBL **pxImag) {
326
7.03M
  SACDEC_ERROR err = MPS_OK;
327
7.03M
  int row;
328
329
  /* Creating wDry */
330
14.0M
  for (row = 0; row < self->numInputChannels; row++) {
331
    /* pointer to direct signals */
332
7.03M
    pxReal[row] = hybInputReal[row];
333
7.03M
    pxImag[row] = hybInputImag[row];
334
7.03M
  }
335
336
7.03M
  return err;
337
7.03M
}
338
339
static void M2ParamToKernelMult(FIXP_SGL *RESTRICT pKernel,
340
                                FIXP_DBL *RESTRICT Mparam,
341
                                FIXP_DBL *RESTRICT MparamPrev,
342
                                int *RESTRICT pWidth, FIXP_SGL alpha__FDK,
343
24.5M
                                int nBands) {
344
24.5M
  int pb;
345
346
245M
  for (pb = 0; pb < nBands; pb++) {
347
221M
    FIXP_SGL tmp = FX_DBL2FX_SGL(
348
221M
        interpolateParameter(alpha__FDK, Mparam[pb], MparamPrev[pb]));
349
350
221M
    int i = pWidth[pb];
351
221M
    if (i & 1) *pKernel++ = tmp;
352
221M
    if (i & 2) {
353
101M
      *pKernel++ = tmp;
354
101M
      *pKernel++ = tmp;
355
101M
    }
356
534M
    for (i >>= 2; i--;) {
357
313M
      *pKernel++ = tmp;
358
313M
      *pKernel++ = tmp;
359
313M
      *pKernel++ = tmp;
360
313M
      *pKernel++ = tmp;
361
313M
    }
362
221M
  }
363
24.5M
}
364
365
SACDEC_ERROR SpatialDecApplyM1_CreateW_Mode212(
366
    spatialDec *self, const SPATIAL_BS_FRAME *frame, FIXP_DBL **xReal,
367
7.03M
    FIXP_DBL **xImag, FIXP_DBL **vReal, FIXP_DBL **vImag) {
368
7.03M
  SACDEC_ERROR err = MPS_OK;
369
7.03M
  int res;
370
7.03M
  FIXP_DBL *decorrInReal = vReal[0];
371
7.03M
  FIXP_DBL *decorrInImag = vImag[0];
372
373
  /* M1 does not do anything in 212 mode, so use simplified processing */
374
7.03M
  FDK_ASSERT(self->numVChannels == 2);
375
7.03M
  FDK_ASSERT(self->numDirektSignals == 1);
376
7.03M
  FDK_ASSERT(self->numDecorSignals == 1);
377
7.03M
  FDKmemcpy(vReal[0], xReal[0], self->hybridBands * sizeof(FIXP_DBL));
378
7.03M
  FDKmemcpy(vImag[0], xImag[0], self->hybridBands * sizeof(FIXP_DBL));
379
380
7.03M
  if (isTsdActive(frame->TsdData)) {
381
    /* Generate v_{x,nonTr} as input for allpass based decorrelator */
382
29.8k
    TsdGenerateNonTr(self->hybridBands, frame->TsdData, self->TsdTs, vReal[0],
383
29.8k
                     vImag[0], vReal[1], vImag[1], &decorrInReal,
384
29.8k
                     &decorrInImag);
385
29.8k
  }
386
  /* - Decorrelate */
387
7.03M
  res = SpatialDecGetResidualIndex(self, 1);
388
7.03M
  if (FDKdecorrelateApply(&self->apDecor[0], decorrInReal, decorrInImag,
389
7.03M
                          vReal[1], vImag[1],
390
7.03M
                          self->param2hyb[self->residualBands[res]])) {
391
0
    return MPS_NOTOK;
392
0
  }
393
7.03M
  if (isTsdActive(frame->TsdData)) {
394
    /* Generate v_{x,Tr}, apply transient decorrelator and add to allpass based
395
     * decorrelator output */
396
29.8k
    TsdApply(self->hybridBands, frame->TsdData, &self->TsdTs,
397
29.8k
             vReal[0], /* input: v_x */
398
29.8k
             vImag[0],
399
29.8k
             vReal[1], /* input: d_{x,nonTr}; output: d_{x,nonTr} + d_{x,Tr} */
400
29.8k
             vImag[1]);
401
29.8k
  }
402
403
  /* Write residual signal in approriate parameter bands */
404
7.03M
  if (self->residualBands[res] > 0) {
405
1.10M
    int stopBand = self->param2hyb[self->residualBands[res]];
406
1.10M
    FDKmemcpy(vReal[1], self->hybResidualReal__FDK[res],
407
1.10M
              fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL));
408
1.10M
    FDKmemcpy(vImag[1], self->hybResidualImag__FDK[res],
409
1.10M
              fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL));
410
1.10M
  } /* (self->residualBands[res]>0) */
411
412
7.03M
  return err;
413
7.03M
}
414
415
SACDEC_ERROR SpatialDecApplyM2_Mode212(spatialDec *self, INT ps,
416
                                       const FIXP_SGL alpha, FIXP_DBL **wReal,
417
                                       FIXP_DBL **wImag,
418
                                       FIXP_DBL **hybOutputRealDry,
419
911k
                                       FIXP_DBL **hybOutputImagDry) {
420
911k
  SACDEC_ERROR err = MPS_OK;
421
911k
  INT row;
422
423
911k
  INT *pWidth = self->kernels_width;
424
  /* for stereoConfigIndex == 3 case hybridBands is < 71 */
425
911k
  INT pb_max = self->kernels[self->hybridBands - 1] + 1;
426
911k
  INT max_row = self->numOutputChannels;
427
428
911k
  INT M2_exp = 0;
429
911k
  if (self->residualCoding) M2_exp = 3;
430
431
2.73M
  for (row = 0; row < max_row; row++)  // 2 times
432
1.82M
  {
433
1.82M
    FIXP_DBL *Mparam0 = self->M2Real__FDK[row][0];
434
1.82M
    FIXP_DBL *Mparam1 = self->M2Real__FDK[row][1];
435
1.82M
    FIXP_DBL *MparamPrev0 = self->M2RealPrev__FDK[row][0];
436
1.82M
    FIXP_DBL *MparamPrev1 = self->M2RealPrev__FDK[row][1];
437
438
1.82M
    FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row];
439
1.82M
    FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row];
440
441
1.82M
    FIXP_DBL *RESTRICT pWReal0 = wReal[0];
442
1.82M
    FIXP_DBL *RESTRICT pWReal1 = wReal[1];
443
1.82M
    FIXP_DBL *RESTRICT pWImag0 = wImag[0];
444
1.82M
    FIXP_DBL *RESTRICT pWImag1 = wImag[1];
445
18.7M
    for (INT pb = 0; pb < pb_max; pb++) {
446
16.9M
      FIXP_DBL tmp0, tmp1;
447
448
16.9M
      tmp0 = interpolateParameter(alpha, Mparam0[pb], MparamPrev0[pb]);
449
16.9M
      tmp1 = interpolateParameter(alpha, Mparam1[pb], MparamPrev1[pb]);
450
451
16.9M
      INT i = pWidth[pb];
452
453
16.9M
      do  // about 3-4 times
454
55.6M
      {
455
55.6M
        FIXP_DBL var0, var1, real, imag;
456
457
55.6M
        var0 = *pWReal0++;
458
55.6M
        var1 = *pWReal1++;
459
55.6M
        real = fMultDiv2(var0, tmp0);
460
55.6M
        var0 = *pWImag0++;
461
55.6M
        real = fMultAddDiv2(real, var1, tmp1);
462
55.6M
        var1 = *pWImag1++;
463
55.6M
        imag = fMultDiv2(var0, tmp0);
464
55.6M
        *pHybOutRealDry++ = real << (1 + M2_exp);
465
55.6M
        imag = fMultAddDiv2(imag, var1, tmp1);
466
55.6M
        *pHybOutImagDry++ = imag << (1 + M2_exp);
467
55.6M
      } while (--i != 0);
468
16.9M
    }
469
1.82M
  }
470
911k
  return err;
471
911k
}
472
473
SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding(
474
    spatialDec *self, INT ps, const FIXP_SGL alpha, FIXP_DBL **wReal,
475
    FIXP_DBL **wImag, FIXP_DBL **hybOutputRealDry,
476
77.4k
    FIXP_DBL **hybOutputImagDry) {
477
77.4k
  SACDEC_ERROR err = MPS_OK;
478
77.4k
  INT row;
479
77.4k
  INT scale_param_m2;
480
77.4k
  INT *pWidth = self->kernels_width;
481
77.4k
  INT pb_max = self->kernels[self->hybridBands - 1] + 1;
482
483
77.4k
  scale_param_m2 = SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2;
484
485
232k
  for (row = 0; row < self->numM2rows; row++) {
486
154k
    INT qs, pb;
487
488
154k
    FIXP_DBL *RESTRICT pWReal0 = wReal[0];
489
154k
    FIXP_DBL *RESTRICT pWImag0 = wImag[0];
490
154k
    FIXP_DBL *RESTRICT pWReal1 = wReal[1];
491
154k
    FIXP_DBL *RESTRICT pWImag1 = wImag[1];
492
493
154k
    FIXP_DBL *MReal0 = self->M2Real__FDK[row][0];
494
154k
    FIXP_DBL *MImag0 = self->M2Imag__FDK[row][0];
495
154k
    FIXP_DBL *MReal1 = self->M2Real__FDK[row][1];
496
154k
    FIXP_DBL *MRealPrev0 = self->M2RealPrev__FDK[row][0];
497
154k
    FIXP_DBL *MImagPrev0 = self->M2ImagPrev__FDK[row][0];
498
154k
    FIXP_DBL *MRealPrev1 = self->M2RealPrev__FDK[row][1];
499
500
154k
    FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row];
501
154k
    FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row];
502
503
154k
    FDK_ASSERT(!(self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD));
504
154k
    FDK_ASSERT((pWidth[0] + pWidth[1]) >= 3);
505
506
464k
    for (pb = 0, qs = 3; pb < 2; pb++) {
507
309k
      INT s;
508
309k
      FIXP_DBL maxVal;
509
309k
      FIXP_DBL mReal1;
510
309k
      FIXP_DBL mReal0, mImag0;
511
309k
      FIXP_DBL iReal0, iImag0, iReal1;
512
513
309k
      iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]);
514
309k
      iImag0 = -interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]);
515
309k
      iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]);
516
517
309k
      maxVal = fAbs(iReal0) | fAbs(iImag0);
518
309k
      maxVal |= fAbs(iReal1);
519
520
309k
      s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2);
521
522
309k
      mReal0 = scaleValue(iReal0, s);
523
309k
      mImag0 = scaleValue(iImag0, s);
524
309k
      mReal1 = scaleValue(iReal1, s);
525
526
309k
      s = scale_param_m2 - s;
527
528
309k
      INT i = pWidth[pb];
529
530
964k
      do {
531
964k
        FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1;
532
533
964k
        wReal0 = *pWReal0++;
534
964k
        wImag0 = *pWImag0++;
535
964k
        wReal1 = *pWReal1++;
536
964k
        wImag1 = *pWImag1++;
537
538
964k
        cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0);
539
540
964k
        *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s;
541
964k
        *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s;
542
543
964k
        if (qs > 0) {
544
464k
          mImag0 = -mImag0;
545
464k
          qs--;
546
464k
        }
547
964k
      } while (--i != 0);
548
309k
    }
549
550
1.98M
    for (; pb < pb_max; pb++) {
551
1.82M
      INT s;
552
1.82M
      FIXP_DBL maxVal;
553
1.82M
      FIXP_SGL mReal1;
554
1.82M
      FIXP_SGL mReal0, mImag0;
555
1.82M
      FIXP_DBL iReal0, iImag0, iReal1;
556
557
1.82M
      iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]);
558
1.82M
      iImag0 = interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]);
559
1.82M
      iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]);
560
561
1.82M
      maxVal = fAbs(iReal0) | fAbs(iImag0);
562
1.82M
      maxVal |= fAbs(iReal1);
563
564
1.82M
      s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2);
565
566
1.82M
      mReal0 = FX_DBL2FX_SGL(scaleValue(iReal0, s));
567
1.82M
      mImag0 = FX_DBL2FX_SGL(scaleValue(iImag0, s));
568
1.82M
      mReal1 = FX_DBL2FX_SGL(scaleValue(iReal1, s));
569
570
1.82M
      s = scale_param_m2 - s;
571
572
1.82M
      INT i = pWidth[pb];
573
574
5.55M
      do {
575
5.55M
        FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1;
576
577
5.55M
        wReal0 = *pWReal0++;
578
5.55M
        wImag0 = *pWImag0++;
579
5.55M
        wReal1 = *pWReal1++;
580
5.55M
        wImag1 = *pWImag1++;
581
582
5.55M
        cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0);
583
584
5.55M
        *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s;
585
5.55M
        *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s;
586
5.55M
      } while (--i != 0);
587
1.82M
    }
588
154k
  }
589
590
77.4k
  return err;
591
77.4k
}
592
593
SACDEC_ERROR SpatialDecApplyM2(spatialDec *self, INT ps, const FIXP_SGL alpha,
594
                               FIXP_DBL **wReal, FIXP_DBL **wImag,
595
                               FIXP_DBL **hybOutputRealDry,
596
                               FIXP_DBL **hybOutputImagDry,
597
                               FIXP_DBL **hybOutputRealWet,
598
6.04M
                               FIXP_DBL **hybOutputImagWet) {
599
6.04M
  SACDEC_ERROR err = MPS_OK;
600
601
6.04M
  {
602
6.04M
    int qs, row, col;
603
6.04M
    int complexHybBands;
604
6.04M
    int complexParBands;
605
6.04M
    int scale_param_m2 = 0;
606
6.04M
    int toolsDisabled;
607
608
6.04M
    UCHAR activParamBands;
609
6.04M
    FIXP_DBL *RESTRICT pWReal, *RESTRICT pWImag, *RESTRICT pHybOutRealDry,
610
6.04M
        *RESTRICT pHybOutImagDry, *RESTRICT pHybOutRealWet,
611
6.04M
        *RESTRICT pHybOutImagWet;
612
6.04M
    C_ALLOC_SCRATCH_START(pKernel, FIXP_SGL, MAX_HYBRID_BANDS);
613
614
    /* The wet signal is added to the dry signal directly in applyM2 if GES and
615
     * STP are disabled */
616
6.04M
    toolsDisabled =
617
6.04M
        ((self->tempShapeConfig == 1) || (self->tempShapeConfig == 2)) ? 0 : 1;
618
619
6.04M
    {
620
6.04M
      complexHybBands = self->hybridBands;
621
6.04M
      complexParBands = self->numParameterBands;
622
6.04M
    }
623
624
6.04M
    FDKmemclear(hybOutputImagDry[0],
625
6.04M
                self->createParams.maxNumOutputChannels *
626
6.04M
                    self->createParams.maxNumCmplxHybBands * sizeof(FIXP_DBL));
627
6.04M
    FDKmemclear(hybOutputRealDry[0], self->createParams.maxNumOutputChannels *
628
6.04M
                                         self->createParams.maxNumHybridBands *
629
6.04M
                                         sizeof(FIXP_DBL));
630
631
6.04M
    if (!toolsDisabled) {
632
5.85M
      FDKmemclear(hybOutputRealWet[0],
633
5.85M
                  self->createParams.maxNumOutputChannels *
634
5.85M
                      self->createParams.maxNumHybridBands * sizeof(FIXP_DBL));
635
5.85M
      FDKmemclear(hybOutputImagWet[0],
636
5.85M
                  self->createParams.maxNumOutputChannels *
637
5.85M
                      self->createParams.maxNumCmplxHybBands *
638
5.85M
                      sizeof(FIXP_DBL));
639
5.85M
    }
640
641
6.04M
    if (self->phaseCoding == 3) {
642
105k
      scale_param_m2 = -(SCALE_DATA_APPLY_M2_PC - 1);
643
105k
    }
644
645
18.1M
    for (row = 0; row < self->numM2rows; row++) {
646
12.0M
      pHybOutRealDry = hybOutputRealDry[row];
647
12.0M
      pHybOutImagDry = hybOutputImagDry[row];
648
649
12.0M
      if (toolsDisabled) {
650
367k
        pHybOutRealWet = hybOutputRealDry[row];
651
367k
        pHybOutImagWet = hybOutputImagDry[row];
652
11.7M
      } else {
653
11.7M
        pHybOutRealWet = hybOutputRealWet[row];
654
11.7M
        pHybOutImagWet = hybOutputImagWet[row];
655
11.7M
      }
656
657
24.1M
      for (col = 0; col < self->numDirektSignals; col++) {
658
12.0M
        if (self->pActivM2ParamBands ==
659
12.0M
            0) { /* default setting, calculate all rows and columns */
660
12.0M
          activParamBands = 1;
661
12.0M
        } else {
662
0
          if (self->pActivM2ParamBands[MAX_M2_INPUT * row +
663
0
                                       col]) /* table with activ and inactiv
664
                                                bands exists for current
665
                                                configuration */
666
0
            activParamBands = 1;
667
0
          else
668
0
            activParamBands = 0;
669
0
        }
670
12.0M
        if (activParamBands) {
671
12.0M
          pWReal = wReal[col];
672
12.0M
          pWImag = wImag[col];
673
674
12.0M
          M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col],
675
12.0M
                              self->M2RealPrev__FDK[row][col],
676
12.0M
                              self->kernels_width, alpha,
677
12.0M
                              self->numParameterBands);
678
679
12.0M
          if (1 && (self->phaseCoding != 3)) {
680
            /* direct signals */
681
11.8M
            {
682
              /* only one sample will be assigned to each row, hence
683
               * accumulation is not neccessary; that is valid for all
684
               * configurations */
685
773M
              for (qs = 0; qs < complexHybBands; qs++) {
686
761M
                pHybOutRealDry[qs] = fMult(pWReal[qs], pKernel[qs]);
687
761M
                pHybOutImagDry[qs] = fMult(pWImag[qs], pKernel[qs]);
688
761M
              }
689
11.8M
            }
690
11.8M
          } else { /*  isBinauralMode(self->upmixType)  */
691
692
11.0M
            for (qs = 0; qs < complexHybBands; qs++) {
693
10.8M
              pHybOutRealDry[qs] += SAC_DEC_APPLY_M2_SCALE(
694
10.8M
                  fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
695
10.8M
              pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
696
10.8M
                  fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
697
10.8M
            }
698
699
211k
            M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col],
700
211k
                                self->M2ImagPrev__FDK[row][col],
701
211k
                                self->kernels_width, alpha, complexParBands);
702
703
            /* direct signals sign is -1 for qs = 0,2 */
704
211k
            pHybOutRealDry[0] += SAC_DEC_APPLY_M2_SCALE(
705
211k
                fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2);
706
211k
            pHybOutImagDry[0] -= SAC_DEC_APPLY_M2_SCALE(
707
211k
                fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2);
708
709
211k
            pHybOutRealDry[2] += SAC_DEC_APPLY_M2_SCALE(
710
211k
                fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2);
711
211k
            pHybOutImagDry[2] -= SAC_DEC_APPLY_M2_SCALE(
712
211k
                fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2);
713
714
            /* direct signals sign is +1 for qs = 1,3,4,5,...,complexHybBands */
715
211k
            pHybOutRealDry[1] -= SAC_DEC_APPLY_M2_SCALE(
716
211k
                fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2);
717
211k
            pHybOutImagDry[1] += SAC_DEC_APPLY_M2_SCALE(
718
211k
                fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2);
719
720
10.4M
            for (qs = 3; qs < complexHybBands; qs++) {
721
10.1M
              pHybOutRealDry[qs] -= SAC_DEC_APPLY_M2_SCALE(
722
10.1M
                  fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
723
10.1M
              pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
724
10.1M
                  fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
725
10.1M
            }
726
211k
          } /* self->upmixType */
727
12.0M
        }   /* if (activParamBands) */
728
12.0M
      }     /* self->numDirektSignals */
729
730
24.1M
      for (; col < self->numVChannels; col++) {
731
12.0M
        if (self->pActivM2ParamBands ==
732
12.0M
            0) { /* default setting, calculate all rows and columns */
733
12.0M
          activParamBands = 1;
734
12.0M
        } else {
735
0
          if (self->pActivM2ParamBands[MAX_M2_INPUT * row +
736
0
                                       col]) /* table with activ and inactiv
737
                                                bands exists for current
738
                                                configuration */
739
0
            activParamBands = 1;
740
0
          else
741
0
            activParamBands = 0;
742
0
        }
743
744
12.0M
        if (activParamBands) {
745
12.0M
          int resBandIndex;
746
12.0M
          int resHybIndex;
747
748
12.0M
          resBandIndex =
749
12.0M
              self->residualBands[SpatialDecGetResidualIndex(self, col)];
750
12.0M
          resHybIndex = self->param2hyb[resBandIndex];
751
752
12.0M
          pWReal = wReal[col];
753
12.0M
          pWImag = wImag[col];
754
755
12.0M
          M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col],
756
12.0M
                              self->M2RealPrev__FDK[row][col],
757
12.0M
                              self->kernels_width, alpha,
758
12.0M
                              self->numParameterBands);
759
760
12.0M
          if (1 && (self->phaseCoding != 3)) {
761
            /* residual signals */
762
17.2M
            for (qs = 0; qs < resHybIndex; qs++) {
763
5.38M
              pHybOutRealDry[qs] += fMult(pWReal[qs], pKernel[qs]);
764
5.38M
              pHybOutImagDry[qs] += fMult(pWImag[qs], pKernel[qs]);
765
5.38M
            }
766
            /* decor signals */
767
768M
            for (; qs < complexHybBands; qs++) {
768
756M
              pHybOutRealWet[qs] += fMult(pWReal[qs], pKernel[qs]);
769
756M
              pHybOutImagWet[qs] += fMult(pWImag[qs], pKernel[qs]);
770
756M
            }
771
11.8M
          } else { /* self->upmixType */
772
            /* residual signals */
773
211k
            FIXP_DBL *RESTRICT pHybOutReal;
774
211k
            FIXP_DBL *RESTRICT pHybOutImag;
775
776
1.34M
            for (qs = 0; qs < resHybIndex; qs++) {
777
1.13M
              pHybOutRealDry[qs] += SAC_DEC_APPLY_M2_SCALE(
778
1.13M
                  fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
779
1.13M
              pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
780
1.13M
                  fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
781
1.13M
            }
782
            /* decor signals */
783
9.89M
            for (; qs < complexHybBands; qs++) {
784
9.68M
              pHybOutRealWet[qs] += SAC_DEC_APPLY_M2_SCALE(
785
9.68M
                  fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
786
9.68M
              pHybOutImagWet[qs] += SAC_DEC_APPLY_M2_SCALE(
787
9.68M
                  fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
788
9.68M
            }
789
790
211k
            M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col],
791
211k
                                self->M2ImagPrev__FDK[row][col],
792
211k
                                self->kernels_width, alpha, complexParBands);
793
794
            /* direct signals sign is -1 for qs = 0,2 */
795
            /* direct signals sign is +1 for qs = 1,3.. */
796
211k
            if (toolsDisabled) {
797
0
              pHybOutRealDry[0] += SAC_DEC_APPLY_M2_SCALE(
798
0
                  fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2);
799
0
              pHybOutImagDry[0] -= SAC_DEC_APPLY_M2_SCALE(
800
0
                  fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2);
801
802
0
              pHybOutRealDry[1] -= SAC_DEC_APPLY_M2_SCALE(
803
0
                  fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2);
804
0
              pHybOutImagDry[1] += SAC_DEC_APPLY_M2_SCALE(
805
0
                  fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2);
806
807
0
              pHybOutRealDry[2] += SAC_DEC_APPLY_M2_SCALE(
808
0
                  fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2);
809
0
              pHybOutImagDry[2] -= SAC_DEC_APPLY_M2_SCALE(
810
0
                  fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2);
811
211k
            } else {
812
211k
              pHybOutReal = &pHybOutRealDry[0];
813
211k
              pHybOutImag = &pHybOutImagDry[0];
814
211k
              if (0 == resHybIndex) {
815
90.2k
                pHybOutReal = &pHybOutRealWet[0];
816
90.2k
                pHybOutImag = &pHybOutImagWet[0];
817
90.2k
              }
818
211k
              pHybOutReal[0] += SAC_DEC_APPLY_M2_SCALE(
819
211k
                  fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2);
820
211k
              pHybOutImag[0] -= SAC_DEC_APPLY_M2_SCALE(
821
211k
                  fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2);
822
823
211k
              if (1 == resHybIndex) {
824
0
                pHybOutReal = &pHybOutRealWet[0];
825
0
                pHybOutImag = &pHybOutImagWet[0];
826
0
              }
827
211k
              pHybOutReal[1] -= SAC_DEC_APPLY_M2_SCALE(
828
211k
                  fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2);
829
211k
              pHybOutImag[1] += SAC_DEC_APPLY_M2_SCALE(
830
211k
                  fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2);
831
832
211k
              if (2 == resHybIndex) {
833
1.28k
                pHybOutReal = &pHybOutRealWet[0];
834
1.28k
                pHybOutImag = &pHybOutImagWet[0];
835
1.28k
              }
836
211k
              pHybOutReal[2] += SAC_DEC_APPLY_M2_SCALE(
837
211k
                  fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2);
838
211k
              pHybOutImag[2] -= SAC_DEC_APPLY_M2_SCALE(
839
211k
                  fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2);
840
211k
            }
841
842
987k
            for (qs = 3; qs < resHybIndex; qs++) {
843
776k
              pHybOutRealDry[qs] -= SAC_DEC_APPLY_M2_SCALE(
844
776k
                  fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
845
776k
              pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
846
776k
                  fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
847
776k
            }
848
            /* decor signals */
849
9.62M
            for (; qs < complexHybBands; qs++) {
850
9.41M
              pHybOutRealWet[qs] -= SAC_DEC_APPLY_M2_SCALE(
851
9.41M
                  fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
852
9.41M
              pHybOutImagWet[qs] += SAC_DEC_APPLY_M2_SCALE(
853
9.41M
                  fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
854
9.41M
            }
855
211k
          } /* self->upmixType */
856
12.0M
        }   /* if (activParamBands) { */
857
12.0M
      }     /*  self->numVChannels */
858
859
12.0M
      if (self->phaseCoding == 3) {
860
211k
        scaleValuesSaturate(pHybOutRealDry, complexHybBands,
861
211k
                            SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
862
211k
        scaleValuesSaturate(pHybOutImagDry, complexHybBands,
863
211k
                            SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
864
865
211k
        if (!toolsDisabled) {
866
211k
          scaleValuesSaturate(pHybOutRealWet, complexHybBands,
867
211k
                              SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
868
211k
          scaleValuesSaturate(pHybOutImagWet, complexHybBands,
869
211k
                              SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
870
211k
        }
871
211k
      }
872
12.0M
    }
873
874
6.04M
    C_ALLOC_SCRATCH_END(pKernel, FIXP_SGL, MAX_HYBRID_BANDS);
875
6.04M
  }
876
877
6.04M
  return err;
878
6.04M
}
879
880
SACDEC_ERROR SpatialDecSynthesis(spatialDec *self, const INT ts,
881
                                 FIXP_DBL **hybOutputReal,
882
                                 FIXP_DBL **hybOutputImag, PCM_MPS *timeOut,
883
                                 const INT numInputChannels,
884
7.03M
                                 const FDK_channelMapDescr *const mapDescr) {
885
7.03M
  SACDEC_ERROR err = MPS_OK;
886
887
7.03M
  int ch;
888
7.03M
  int stride, offset;
889
890
7.03M
  stride = self->numOutputChannelsAT;
891
7.03M
  offset = 1;
892
893
7.03M
  PCM_MPS *pTimeOut__FDK =
894
7.03M
      &timeOut[stride * self->pQmfDomain->globalConf.nBandsSynthesis * ts];
895
7.03M
  C_ALLOC_SCRATCH_START(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
896
7.03M
  C_ALLOC_SCRATCH_START(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
897
898
21.0M
  for (ch = 0; ch < self->numOutputChannelsAT; ch++) {
899
14.0M
    if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
900
1.47M
      int k;
901
      /* No hybrid filtering. Just copy the QMF data. */
902
50.1M
      for (k = 0; k < self->hybridBands; k += 1) {
903
48.6M
        pQmfReal[k] = hybOutputReal[ch][k];
904
48.6M
        pQmfImag[k] = hybOutputImag[ch][k];
905
48.6M
      }
906
12.5M
    } else {
907
12.5M
      FDKhybridSynthesisApply(&self->hybridSynthesis[ch], hybOutputReal[ch],
908
12.5M
                              hybOutputImag[ch], pQmfReal, pQmfImag);
909
12.5M
    }
910
911
    /* Map channel indices from MPEG Surround -> PCE style -> channelMapping[]
912
     */
913
14.0M
    FDK_ASSERT(self->numOutputChannelsAT <= 6);
914
14.0M
    int outCh = FDK_chMapDescr_getMapValue(mapDescr, mapChannel(self, ch),
915
14.0M
                                           self->numOutputChannelsAT);
916
917
14.0M
    {
918
14.0M
      if (self->stereoConfigIndex == 3) {
919
        /* MPS -> SBR */
920
2.32M
        int i;
921
2.32M
        FIXP_DBL *pWorkBufReal, *pWorkBufImag;
922
2.32M
        FDK_ASSERT((self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_m ==
923
2.32M
                    (FIXP_DBL)0x80000000) &&
924
2.32M
                   (self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_e == 0));
925
2.32M
        FDK_QmfDomain_GetWorkBuffer(&self->pQmfDomain->QmfDomainIn[outCh], ts,
926
2.32M
                                    &pWorkBufReal, &pWorkBufImag);
927
2.32M
        FDK_ASSERT(self->qmfBands <=
928
2.32M
                   self->pQmfDomain->QmfDomainIn[outCh].workBuf_nBands);
929
43.2M
        for (i = 0; i < self->qmfBands; i++) {
930
40.9M
          pWorkBufReal[i] = pQmfReal[i];
931
40.9M
          pWorkBufImag[i] = pQmfImag[i];
932
40.9M
        }
933
2.32M
        self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale =
934
2.32M
            -7; /*-ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK;*/
935
2.32M
        self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -=
936
2.32M
            self->pQmfDomain->QmfDomainIn[outCh].fb.filterScale;
937
2.32M
        self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -=
938
2.32M
            self->clipProtectGainSF__FDK;
939
940
2.32M
        self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= (1);
941
11.7M
      } else {
942
        /* Call the QMF synthesis for dry. */
943
11.7M
        err = CalculateSpaceSynthesisQmf(&self->pQmfDomain->QmfDomainOut[outCh],
944
11.7M
                                         pQmfReal, pQmfImag, stride,
945
11.7M
                                         pTimeOut__FDK + (offset * outCh));
946
11.7M
      }
947
14.0M
      if (err != MPS_OK) goto bail;
948
14.0M
    }
949
14.0M
  } /* ch loop */
950
951
7.03M
bail:
952
7.03M
  C_ALLOC_SCRATCH_END(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
953
7.03M
  C_ALLOC_SCRATCH_END(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
954
955
7.03M
  return err;
956
7.03M
}
957
958
271k
void SpatialDecBufferMatrices(spatialDec *self) {
959
271k
  int row, col;
960
271k
  int complexParBands;
961
271k
  complexParBands = self->numParameterBands;
962
963
  /*
964
    buffer matrices M2
965
  */
966
815k
  for (row = 0; row < self->numM2rows; row++) {
967
1.63M
    for (col = 0; col < self->numVChannels; col++) {
968
1.08M
      FDKmemcpy(self->M2RealPrev__FDK[row][col], self->M2Real__FDK[row][col],
969
1.08M
                self->numParameterBands * sizeof(FIXP_DBL));
970
1.08M
      if (0 || (self->phaseCoding == 3)) {
971
25.3k
        FDKmemcpy(self->M2ImagPrev__FDK[row][col], self->M2Imag__FDK[row][col],
972
25.3k
                  complexParBands * sizeof(FIXP_DBL));
973
25.3k
      }
974
1.08M
    }
975
543k
  }
976
977
  /* buffer phase */
978
271k
  FDKmemcpy(self->PhasePrevLeft__FDK, self->PhaseLeft__FDK,
979
271k
            self->numParameterBands * sizeof(FIXP_DBL));
980
271k
  FDKmemcpy(self->PhasePrevRight__FDK, self->PhaseRight__FDK,
981
271k
            self->numParameterBands * sizeof(FIXP_DBL));
982
271k
}
983
984
113M
#define PHASE_SCALE 2
985
986
#ifndef P_PI
987
#define P_PI 3.1415926535897932
988
#endif
989
990
/* For better precision, PI (pi_x2) is already doubled */
991
static FIXP_DBL interp_angle__FDK(FIXP_DBL angle1, FIXP_DBL angle2,
992
7.86M
                                  FIXP_SGL alpha, FIXP_DBL pi_x2) {
993
7.86M
  if (angle2 - angle1 > (pi_x2 >> 1)) angle2 -= pi_x2;
994
995
7.86M
  if (angle1 - angle2 > (pi_x2 >> 1)) angle1 -= pi_x2;
996
997
7.86M
  return interpolateParameter(alpha, angle2, angle1);
998
7.86M
}
999
1000
/*
1001
 *
1002
 */
1003
void SpatialDecApplyPhase(spatialDec *self, FIXP_SGL alpha__FDK,
1004
400k
                          int lastSlotOfParamSet) {
1005
400k
  int pb, qs;
1006
400k
  FIXP_DBL ppb[MAX_PARAMETER_BANDS *
1007
400k
               4]; /* left real, imag - right real, imag interleaved */
1008
1009
400k
  const FIXP_DBL pi_x2 = PIx2__IPD;
1010
4.33M
  for (pb = 0; pb < self->numParameterBands; pb++) {
1011
3.93M
    FIXP_DBL pl, pr;
1012
1013
3.93M
    pl = interp_angle__FDK(self->PhasePrevLeft__FDK[pb],
1014
3.93M
                           self->PhaseLeft__FDK[pb], alpha__FDK, pi_x2);
1015
3.93M
    pr = interp_angle__FDK(self->PhasePrevRight__FDK[pb],
1016
3.93M
                           self->PhaseRight__FDK[pb], alpha__FDK, pi_x2);
1017
1018
3.93M
    inline_fixp_cos_sin(pl, pr, IPD_SCALE, &ppb[4 * pb]);
1019
3.93M
  }
1020
1021
  /* sign is -1 for qs = 0,2 and +1 for qs = 1 */
1022
1023
400k
  const SCHAR *kernels = &self->kernels[0];
1024
1025
400k
  FIXP_DBL *Dry_real0 = &self->hybOutputRealDry__FDK[0][0];
1026
400k
  FIXP_DBL *Dry_imag0 = &self->hybOutputImagDry__FDK[0][0];
1027
400k
  FIXP_DBL *Dry_real1 = &self->hybOutputRealDry__FDK[1][0];
1028
400k
  FIXP_DBL *Dry_imag1 = &self->hybOutputImagDry__FDK[1][0];
1029
1030
1.60M
  for (qs = 2; qs >= 0; qs--) {
1031
1.20M
    FIXP_DBL out_re, out_im;
1032
1033
1.20M
    pb = *kernels++;
1034
1.20M
    if (qs == 1) /* sign[qs] >= 0 */
1035
400k
    {
1036
400k
      cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1037
400k
                   ppb[4 * pb + 1]);
1038
400k
      out_re <<= PHASE_SCALE - 1;
1039
400k
      out_im <<= PHASE_SCALE - 1;
1040
400k
      *Dry_real0++ = out_re;
1041
400k
      *Dry_imag0++ = out_im;
1042
1043
400k
      cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1044
400k
                   ppb[4 * pb + 3]);
1045
400k
      out_re <<= PHASE_SCALE - 1;
1046
400k
      out_im <<= PHASE_SCALE - 1;
1047
400k
      *Dry_real1++ = out_re;
1048
400k
      *Dry_imag1++ = out_im;
1049
800k
    } else {
1050
800k
      cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1051
800k
                   -ppb[4 * pb + 1]);
1052
800k
      out_re <<= PHASE_SCALE - 1;
1053
800k
      out_im <<= PHASE_SCALE - 1;
1054
800k
      *Dry_real0++ = out_re;
1055
800k
      *Dry_imag0++ = out_im;
1056
1057
800k
      cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1058
800k
                   -ppb[4 * pb + 3]);
1059
800k
      out_re <<= PHASE_SCALE - 1;
1060
800k
      out_im <<= PHASE_SCALE - 1;
1061
800k
      *Dry_real1++ = out_re;
1062
800k
      *Dry_imag1++ = out_im;
1063
800k
    }
1064
1.20M
  }
1065
1066
  /* sign is +1 for qs >=3 */
1067
27.6M
  for (qs = self->hybridBands - 3; qs--;) {
1068
27.2M
    FIXP_DBL out_re, out_im;
1069
1070
27.2M
    pb = *kernels++;
1071
27.2M
    cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1072
27.2M
                 ppb[4 * pb + 1]);
1073
27.2M
    out_re <<= PHASE_SCALE - 1;
1074
27.2M
    out_im <<= PHASE_SCALE - 1;
1075
27.2M
    *Dry_real0++ = out_re;
1076
27.2M
    *Dry_imag0++ = out_im;
1077
1078
27.2M
    cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1079
27.2M
                 ppb[4 * pb + 3]);
1080
27.2M
    out_re <<= PHASE_SCALE - 1;
1081
27.2M
    out_im <<= PHASE_SCALE - 1;
1082
27.2M
    *Dry_real1++ = out_re;
1083
27.2M
    *Dry_imag1++ = out_im;
1084
27.2M
  }
1085
400k
}