Coverage Report

Created: 2024-06-17 06:33

/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
42.3M
#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
186M
                                         const FIXP_DBL b) {
131
186M
  return (b - fMult(alpha, b) + fMult(alpha, a));
132
186M
}
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
10.3M
static UINT mapChannel(spatialDec *self, UINT ch) {
142
10.3M
  static const UCHAR chanelIdx[][8] = {
143
10.3M
      {0, 1, 2, 3, 4, 5, 6, 7}, /*  binaural, TREE_212, arbitrary tree */
144
10.3M
  };
145
146
10.3M
  int idx = 0;
147
148
10.3M
  return (chanelIdx[idx][ch]);
149
10.3M
}
150
151
88.1k
FIXP_DBL getChGain(spatialDec *self, UINT ch, INT *scale) {
152
  /* init no gain modifier */
153
88.1k
  FIXP_DBL gain = 0x80000000;
154
88.1k
  *scale = 0;
155
156
88.1k
  if ((!isTwoChMode(self->upmixType)) &&
157
88.1k
      (self->upmixType != UPMIXTYPE_BYPASS)) {
158
88.1k
    if ((ch == 0) || (ch == 1) || (ch == 2)) {
159
      /* no modifier */
160
88.1k
    }
161
88.1k
  }
162
163
88.1k
  return gain;
164
88.1k
}
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.72M
                                   const int numInputChannels) {
170
1.72M
  SACDEC_ERROR err = MPS_OK;
171
1.72M
  int ch, offset;
172
173
1.72M
  offset = self->pQmfDomain->globalConf.nBandsSynthesis *
174
1.72M
           self->pQmfDomain->globalConf.nQmfTimeSlots;
175
176
1.72M
  {
177
3.44M
    for (ch = 0; ch < numInputChannels; ch++) {
178
1.72M
      const PCM_MPS *inSamples =
179
1.72M
          &inData[ts * self->pQmfDomain->globalConf.nBandsAnalysis];
180
1.72M
      FIXP_DBL *pQmfRealAnalysis = qmfReal[ch]; /* no delay in blind mode */
181
1.72M
      FIXP_DBL *pQmfImagAnalysis = qmfImag[ch];
182
183
1.72M
      CalculateSpaceAnalysisQmf(&self->pQmfDomain->QmfDomainIn[ch].fb,
184
1.72M
                                inSamples + (ch * offset), pQmfRealAnalysis,
185
1.72M
                                pQmfImagAnalysis);
186
187
1.72M
      if (!isTwoChMode(self->upmixType) && !bypassMode) {
188
1.72M
        int i;
189
37.9M
        for (i = 0; i < self->qmfBands; i++) {
190
36.2M
          qmfReal[ch][i] = fMult(
191
36.2M
              scaleValueSaturate(qmfReal[ch][i], self->sacInDataHeadroom - (1)),
192
36.2M
              self->clipProtectGain__FDK);
193
36.2M
          qmfImag[ch][i] = fMult(
194
36.2M
              scaleValueSaturate(qmfImag[ch][i], self->sacInDataHeadroom - (1)),
195
36.2M
              self->clipProtectGain__FDK);
196
36.2M
        }
197
1.72M
      }
198
1.72M
    }
199
1.72M
  }
200
201
1.72M
  self->qmfInputDelayBufPos =
202
1.72M
      (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay;
203
204
1.72M
  return err;
205
1.72M
}
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
3.46M
                               const INT numInputChannels) {
212
3.46M
  SACDEC_ERROR err = MPS_OK;
213
3.46M
  int ch;
214
215
3.46M
  {
216
6.93M
    for (ch = 0; ch < numInputChannels; ch++) {
217
3.46M
      FIXP_DBL *pQmfRealAnalysis =
218
3.46M
          qmfReal__FDK[ch]; /* no delay in blind mode */
219
3.46M
      FIXP_DBL *pQmfImagAnalysis = qmfImag__FDK[ch];
220
221
      /* Write Input data to pQmfRealAnalysis. */
222
3.46M
      if (self->bShareDelayWithSBR) {
223
3.45M
        FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch],
224
3.45M
                              ts + HYBRID_FILTER_DELAY, 0,
225
3.45M
                              MAX_QMF_BANDS_TO_HYBRID, pQmfRealAnalysis,
226
3.45M
                              pQmfImagAnalysis, 15 + (1));
227
3.45M
        FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts,
228
3.45M
                              MAX_QMF_BANDS_TO_HYBRID, self->qmfBands,
229
3.45M
                              pQmfRealAnalysis, pQmfImagAnalysis, 15 + (1));
230
3.45M
      } else {
231
14.3k
        FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, 0,
232
14.3k
                              self->qmfBands, pQmfRealAnalysis,
233
14.3k
                              pQmfImagAnalysis, 15 + (1));
234
14.3k
      }
235
3.46M
      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
107k
        FDK_QmfDomain_SaveOverlap(&self->pQmfDomain->QmfDomainIn[ch], 0);
239
107k
      }
240
241
      /* Apply clip protection to output. */
242
3.46M
      if (!isTwoChMode(self->upmixType) && !bypassMode) {
243
3.46M
        int i;
244
225M
        for (i = 0; i < self->qmfBands; i++) {
245
221M
          qmfReal__FDK[ch][i] =
246
221M
              fMult(qmfReal__FDK[ch][i], self->clipProtectGain__FDK);
247
221M
          qmfImag__FDK[ch][i] =
248
221M
              fMult(qmfImag__FDK[ch][i], self->clipProtectGain__FDK);
249
221M
        }
250
3.46M
      }
251
252
3.46M
    } /* End of loop over numInputChannels */
253
3.46M
  }
254
255
3.46M
  self->qmfInputDelayBufPos =
256
3.46M
      (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay;
257
258
3.46M
  return err;
259
3.46M
}
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
5.19M
                                      const INT numInputChannels) {
287
5.19M
  SACDEC_ERROR err = MPS_OK;
288
5.19M
  int ch;
289
290
10.3M
  for (ch = 0; ch < numInputChannels;
291
5.19M
       ch++) /* hybrid filtering for down-mix signals */
292
5.19M
  {
293
5.19M
    if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
294
487k
      int k;
295
      /* No hybrid filtering. Just copy the QMF data. */
296
16.2M
      for (k = 0; k < self->hybridBands; k += 1) {
297
15.7M
        hybOutputReal[ch][k] = qmfInputReal[ch][k];
298
15.7M
        hybOutputImag[ch][k] = qmfInputImag[ch][k];
299
15.7M
      }
300
4.70M
    } else {
301
4.70M
      self->hybridAnalysis[ch].hfMode = self->bShareDelayWithSBR;
302
303
4.70M
      if (self->stereoConfigIndex == 3)
304
4.70M
        FDK_ASSERT(self->hybridAnalysis[ch].hfMode == 0);
305
4.70M
      FDKhybridAnalysisApply(&self->hybridAnalysis[ch], qmfInputReal[ch],
306
4.70M
                             qmfInputImag[ch], hybOutputReal[ch],
307
4.70M
                             hybOutputImag[ch]);
308
4.70M
    }
309
5.19M
  }
310
311
5.19M
  if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) &&
312
5.19M
      self->residualCoding) {
313
1.33M
    self->hybridAnalysis[numInputChannels].hfMode = 0;
314
1.33M
    FDKhybridAnalysisApply(
315
1.33M
        &self->hybridAnalysis[numInputChannels],
316
1.33M
        self->qmfResidualReal__FDK[0][0], self->qmfResidualImag__FDK[0][0],
317
1.33M
        self->hybResidualReal__FDK[0], self->hybResidualImag__FDK[0]);
318
1.33M
  }
319
320
5.19M
  return err;
321
5.19M
}
322
323
SACDEC_ERROR SpatialDecCreateX(spatialDec *self, FIXP_DBL **hybInputReal,
324
                               FIXP_DBL **hybInputImag, FIXP_DBL **pxReal,
325
5.19M
                               FIXP_DBL **pxImag) {
326
5.19M
  SACDEC_ERROR err = MPS_OK;
327
5.19M
  int row;
328
329
  /* Creating wDry */
330
10.3M
  for (row = 0; row < self->numInputChannels; row++) {
331
    /* pointer to direct signals */
332
5.19M
    pxReal[row] = hybInputReal[row];
333
5.19M
    pxImag[row] = hybInputImag[row];
334
5.19M
  }
335
336
5.19M
  return err;
337
5.19M
}
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
16.1M
                                int nBands) {
344
16.1M
  int pb;
345
346
154M
  for (pb = 0; pb < nBands; pb++) {
347
138M
    FIXP_SGL tmp = FX_DBL2FX_SGL(
348
138M
        interpolateParameter(alpha__FDK, Mparam[pb], MparamPrev[pb]));
349
350
138M
    int i = pWidth[pb];
351
138M
    if (i & 1) *pKernel++ = tmp;
352
138M
    if (i & 2) {
353
68.7M
      *pKernel++ = tmp;
354
68.7M
      *pKernel++ = tmp;
355
68.7M
    }
356
346M
    for (i >>= 2; i--;) {
357
208M
      *pKernel++ = tmp;
358
208M
      *pKernel++ = tmp;
359
208M
      *pKernel++ = tmp;
360
208M
      *pKernel++ = tmp;
361
208M
    }
362
138M
  }
363
16.1M
}
364
365
SACDEC_ERROR SpatialDecApplyM1_CreateW_Mode212(
366
    spatialDec *self, const SPATIAL_BS_FRAME *frame, FIXP_DBL **xReal,
367
5.19M
    FIXP_DBL **xImag, FIXP_DBL **vReal, FIXP_DBL **vImag) {
368
5.19M
  SACDEC_ERROR err = MPS_OK;
369
5.19M
  int res;
370
5.19M
  FIXP_DBL *decorrInReal = vReal[0];
371
5.19M
  FIXP_DBL *decorrInImag = vImag[0];
372
373
  /* M1 does not do anything in 212 mode, so use simplified processing */
374
5.19M
  FDK_ASSERT(self->numVChannels == 2);
375
5.19M
  FDK_ASSERT(self->numDirektSignals == 1);
376
5.19M
  FDK_ASSERT(self->numDecorSignals == 1);
377
5.19M
  FDKmemcpy(vReal[0], xReal[0], self->hybridBands * sizeof(FIXP_DBL));
378
5.19M
  FDKmemcpy(vImag[0], xImag[0], self->hybridBands * sizeof(FIXP_DBL));
379
380
5.19M
  if (isTsdActive(frame->TsdData)) {
381
    /* Generate v_{x,nonTr} as input for allpass based decorrelator */
382
20.8k
    TsdGenerateNonTr(self->hybridBands, frame->TsdData, self->TsdTs, vReal[0],
383
20.8k
                     vImag[0], vReal[1], vImag[1], &decorrInReal,
384
20.8k
                     &decorrInImag);
385
20.8k
  }
386
  /* - Decorrelate */
387
5.19M
  res = SpatialDecGetResidualIndex(self, 1);
388
5.19M
  if (FDKdecorrelateApply(&self->apDecor[0], decorrInReal, decorrInImag,
389
5.19M
                          vReal[1], vImag[1],
390
5.19M
                          self->param2hyb[self->residualBands[res]])) {
391
0
    return MPS_NOTOK;
392
0
  }
393
5.19M
  if (isTsdActive(frame->TsdData)) {
394
    /* Generate v_{x,Tr}, apply transient decorrelator and add to allpass based
395
     * decorrelator output */
396
20.8k
    TsdApply(self->hybridBands, frame->TsdData, &self->TsdTs,
397
20.8k
             vReal[0], /* input: v_x */
398
20.8k
             vImag[0],
399
20.8k
             vReal[1], /* input: d_{x,nonTr}; output: d_{x,nonTr} + d_{x,Tr} */
400
20.8k
             vImag[1]);
401
20.8k
  }
402
403
  /* Write residual signal in approriate parameter bands */
404
5.19M
  if (self->residualBands[res] > 0) {
405
1.21M
    int stopBand = self->param2hyb[self->residualBands[res]];
406
1.21M
    FDKmemcpy(vReal[1], self->hybResidualReal__FDK[res],
407
1.21M
              fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL));
408
1.21M
    FDKmemcpy(vImag[1], self->hybResidualImag__FDK[res],
409
1.21M
              fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL));
410
1.21M
  } /* (self->residualBands[res]>0) */
411
412
5.19M
  return err;
413
5.19M
}
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
1.16M
                                       FIXP_DBL **hybOutputImagDry) {
420
1.16M
  SACDEC_ERROR err = MPS_OK;
421
1.16M
  INT row;
422
423
1.16M
  INT *pWidth = self->kernels_width;
424
  /* for stereoConfigIndex == 3 case hybridBands is < 71 */
425
1.16M
  INT pb_max = self->kernels[self->hybridBands - 1] + 1;
426
1.16M
  INT max_row = self->numOutputChannels;
427
428
1.16M
  INT M2_exp = 0;
429
1.16M
  if (self->residualCoding) M2_exp = 3;
430
431
3.50M
  for (row = 0; row < max_row; row++)  // 2 times
432
2.33M
  {
433
2.33M
    FIXP_DBL *Mparam0 = self->M2Real__FDK[row][0];
434
2.33M
    FIXP_DBL *Mparam1 = self->M2Real__FDK[row][1];
435
2.33M
    FIXP_DBL *MparamPrev0 = self->M2RealPrev__FDK[row][0];
436
2.33M
    FIXP_DBL *MparamPrev1 = self->M2RealPrev__FDK[row][1];
437
438
2.33M
    FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row];
439
2.33M
    FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row];
440
441
2.33M
    FIXP_DBL *RESTRICT pWReal0 = wReal[0];
442
2.33M
    FIXP_DBL *RESTRICT pWReal1 = wReal[1];
443
2.33M
    FIXP_DBL *RESTRICT pWImag0 = wImag[0];
444
2.33M
    FIXP_DBL *RESTRICT pWImag1 = wImag[1];
445
22.3M
    for (INT pb = 0; pb < pb_max; pb++) {
446
20.0M
      FIXP_DBL tmp0, tmp1;
447
448
20.0M
      tmp0 = interpolateParameter(alpha, Mparam0[pb], MparamPrev0[pb]);
449
20.0M
      tmp1 = interpolateParameter(alpha, Mparam1[pb], MparamPrev1[pb]);
450
451
20.0M
      INT i = pWidth[pb];
452
453
20.0M
      do  // about 3-4 times
454
65.2M
      {
455
65.2M
        FIXP_DBL var0, var1, real, imag;
456
457
65.2M
        var0 = *pWReal0++;
458
65.2M
        var1 = *pWReal1++;
459
65.2M
        real = fMultDiv2(var0, tmp0);
460
65.2M
        var0 = *pWImag0++;
461
65.2M
        real = fMultAddDiv2(real, var1, tmp1);
462
65.2M
        var1 = *pWImag1++;
463
65.2M
        imag = fMultDiv2(var0, tmp0);
464
65.2M
        *pHybOutRealDry++ = real << (1 + M2_exp);
465
65.2M
        imag = fMultAddDiv2(imag, var1, tmp1);
466
65.2M
        *pHybOutImagDry++ = imag << (1 + M2_exp);
467
65.2M
      } while (--i != 0);
468
20.0M
    }
469
2.33M
  }
470
1.16M
  return err;
471
1.16M
}
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
32.0k
    FIXP_DBL **hybOutputImagDry) {
477
32.0k
  SACDEC_ERROR err = MPS_OK;
478
32.0k
  INT row;
479
32.0k
  INT scale_param_m2;
480
32.0k
  INT *pWidth = self->kernels_width;
481
32.0k
  INT pb_max = self->kernels[self->hybridBands - 1] + 1;
482
483
32.0k
  scale_param_m2 = SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2;
484
485
96.0k
  for (row = 0; row < self->numM2rows; row++) {
486
64.0k
    INT qs, pb;
487
488
64.0k
    FIXP_DBL *RESTRICT pWReal0 = wReal[0];
489
64.0k
    FIXP_DBL *RESTRICT pWImag0 = wImag[0];
490
64.0k
    FIXP_DBL *RESTRICT pWReal1 = wReal[1];
491
64.0k
    FIXP_DBL *RESTRICT pWImag1 = wImag[1];
492
493
64.0k
    FIXP_DBL *MReal0 = self->M2Real__FDK[row][0];
494
64.0k
    FIXP_DBL *MImag0 = self->M2Imag__FDK[row][0];
495
64.0k
    FIXP_DBL *MReal1 = self->M2Real__FDK[row][1];
496
64.0k
    FIXP_DBL *MRealPrev0 = self->M2RealPrev__FDK[row][0];
497
64.0k
    FIXP_DBL *MImagPrev0 = self->M2ImagPrev__FDK[row][0];
498
64.0k
    FIXP_DBL *MRealPrev1 = self->M2RealPrev__FDK[row][1];
499
500
64.0k
    FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row];
501
64.0k
    FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row];
502
503
64.0k
    FDK_ASSERT(!(self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD));
504
64.0k
    FDK_ASSERT((pWidth[0] + pWidth[1]) >= 3);
505
506
192k
    for (pb = 0, qs = 3; pb < 2; pb++) {
507
128k
      INT s;
508
128k
      FIXP_DBL maxVal;
509
128k
      FIXP_DBL mReal1;
510
128k
      FIXP_DBL mReal0, mImag0;
511
128k
      FIXP_DBL iReal0, iImag0, iReal1;
512
513
128k
      iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]);
514
128k
      iImag0 = -interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]);
515
128k
      iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]);
516
517
128k
      maxVal = fAbs(iReal0) | fAbs(iImag0);
518
128k
      maxVal |= fAbs(iReal1);
519
520
128k
      s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2);
521
522
128k
      mReal0 = scaleValue(iReal0, s);
523
128k
      mImag0 = scaleValue(iImag0, s);
524
128k
      mReal1 = scaleValue(iReal1, s);
525
526
128k
      s = scale_param_m2 - s;
527
528
128k
      INT i = pWidth[pb];
529
530
559k
      do {
531
559k
        FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1;
532
533
559k
        wReal0 = *pWReal0++;
534
559k
        wImag0 = *pWImag0++;
535
559k
        wReal1 = *pWReal1++;
536
559k
        wImag1 = *pWImag1++;
537
538
559k
        cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0);
539
540
559k
        *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s;
541
559k
        *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s;
542
543
559k
        if (qs > 0) {
544
192k
          mImag0 = -mImag0;
545
192k
          qs--;
546
192k
        }
547
559k
      } while (--i != 0);
548
128k
    }
549
550
667k
    for (; pb < pb_max; pb++) {
551
603k
      INT s;
552
603k
      FIXP_DBL maxVal;
553
603k
      FIXP_SGL mReal1;
554
603k
      FIXP_SGL mReal0, mImag0;
555
603k
      FIXP_DBL iReal0, iImag0, iReal1;
556
557
603k
      iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]);
558
603k
      iImag0 = interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]);
559
603k
      iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]);
560
561
603k
      maxVal = fAbs(iReal0) | fAbs(iImag0);
562
603k
      maxVal |= fAbs(iReal1);
563
564
603k
      s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2);
565
566
603k
      mReal0 = FX_DBL2FX_SGL(scaleValue(iReal0, s));
567
603k
      mImag0 = FX_DBL2FX_SGL(scaleValue(iImag0, s));
568
603k
      mReal1 = FX_DBL2FX_SGL(scaleValue(iReal1, s));
569
570
603k
      s = scale_param_m2 - s;
571
572
603k
      INT i = pWidth[pb];
573
574
3.40M
      do {
575
3.40M
        FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1;
576
577
3.40M
        wReal0 = *pWReal0++;
578
3.40M
        wImag0 = *pWImag0++;
579
3.40M
        wReal1 = *pWReal1++;
580
3.40M
        wImag1 = *pWImag1++;
581
582
3.40M
        cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0);
583
584
3.40M
        *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s;
585
3.40M
        *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s;
586
3.40M
      } while (--i != 0);
587
603k
    }
588
64.0k
  }
589
590
32.0k
  return err;
591
32.0k
}
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
3.99M
                               FIXP_DBL **hybOutputImagWet) {
599
3.99M
  SACDEC_ERROR err = MPS_OK;
600
601
3.99M
  {
602
3.99M
    int qs, row, col;
603
3.99M
    int complexHybBands;
604
3.99M
    int complexParBands;
605
3.99M
    int scale_param_m2 = 0;
606
3.99M
    int toolsDisabled;
607
608
3.99M
    UCHAR activParamBands;
609
3.99M
    FIXP_DBL *RESTRICT pWReal, *RESTRICT pWImag, *RESTRICT pHybOutRealDry,
610
3.99M
        *RESTRICT pHybOutImagDry, *RESTRICT pHybOutRealWet,
611
3.99M
        *RESTRICT pHybOutImagWet;
612
3.99M
    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
3.99M
    toolsDisabled =
617
3.99M
        ((self->tempShapeConfig == 1) || (self->tempShapeConfig == 2)) ? 0 : 1;
618
619
3.99M
    {
620
3.99M
      complexHybBands = self->hybridBands;
621
3.99M
      complexParBands = self->numParameterBands;
622
3.99M
    }
623
624
3.99M
    FDKmemclear(hybOutputImagDry[0],
625
3.99M
                self->createParams.maxNumOutputChannels *
626
3.99M
                    self->createParams.maxNumCmplxHybBands * sizeof(FIXP_DBL));
627
3.99M
    FDKmemclear(hybOutputRealDry[0], self->createParams.maxNumOutputChannels *
628
3.99M
                                         self->createParams.maxNumHybridBands *
629
3.99M
                                         sizeof(FIXP_DBL));
630
631
3.99M
    if (!toolsDisabled) {
632
3.85M
      FDKmemclear(hybOutputRealWet[0],
633
3.85M
                  self->createParams.maxNumOutputChannels *
634
3.85M
                      self->createParams.maxNumHybridBands * sizeof(FIXP_DBL));
635
3.85M
      FDKmemclear(hybOutputImagWet[0],
636
3.85M
                  self->createParams.maxNumOutputChannels *
637
3.85M
                      self->createParams.maxNumCmplxHybBands *
638
3.85M
                      sizeof(FIXP_DBL));
639
3.85M
    }
640
641
3.99M
    if (self->phaseCoding == 3) {
642
50.8k
      scale_param_m2 = -(SCALE_DATA_APPLY_M2_PC - 1);
643
50.8k
    }
644
645
11.9M
    for (row = 0; row < self->numM2rows; row++) {
646
7.98M
      pHybOutRealDry = hybOutputRealDry[row];
647
7.98M
      pHybOutImagDry = hybOutputImagDry[row];
648
649
7.98M
      if (toolsDisabled) {
650
277k
        pHybOutRealWet = hybOutputRealDry[row];
651
277k
        pHybOutImagWet = hybOutputImagDry[row];
652
7.70M
      } else {
653
7.70M
        pHybOutRealWet = hybOutputRealWet[row];
654
7.70M
        pHybOutImagWet = hybOutputImagWet[row];
655
7.70M
      }
656
657
15.9M
      for (col = 0; col < self->numDirektSignals; col++) {
658
7.98M
        if (self->pActivM2ParamBands ==
659
7.98M
            0) { /* default setting, calculate all rows and columns */
660
7.98M
          activParamBands = 1;
661
7.98M
        } 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
7.98M
        if (activParamBands) {
671
7.98M
          pWReal = wReal[col];
672
7.98M
          pWImag = wImag[col];
673
674
7.98M
          M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col],
675
7.98M
                              self->M2RealPrev__FDK[row][col],
676
7.98M
                              self->kernels_width, alpha,
677
7.98M
                              self->numParameterBands);
678
679
7.98M
          if (1 && (self->phaseCoding != 3)) {
680
            /* direct signals */
681
7.88M
            {
682
              /* only one sample will be assigned to each row, hence
683
               * accumulation is not neccessary; that is valid for all
684
               * configurations */
685
514M
              for (qs = 0; qs < complexHybBands; qs++) {
686
507M
                pHybOutRealDry[qs] = fMult(pWReal[qs], pKernel[qs]);
687
507M
                pHybOutImagDry[qs] = fMult(pWImag[qs], pKernel[qs]);
688
507M
              }
689
7.88M
            }
690
7.88M
          } else { /*  isBinauralMode(self->upmixType)  */
691
692
5.39M
            for (qs = 0; qs < complexHybBands; qs++) {
693
5.28M
              pHybOutRealDry[qs] += SAC_DEC_APPLY_M2_SCALE(
694
5.28M
                  fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
695
5.28M
              pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
696
5.28M
                  fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
697
5.28M
            }
698
699
101k
            M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col],
700
101k
                                self->M2ImagPrev__FDK[row][col],
701
101k
                                self->kernels_width, alpha, complexParBands);
702
703
            /* direct signals sign is -1 for qs = 0,2 */
704
101k
            pHybOutRealDry[0] += SAC_DEC_APPLY_M2_SCALE(
705
101k
                fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2);
706
101k
            pHybOutImagDry[0] -= SAC_DEC_APPLY_M2_SCALE(
707
101k
                fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2);
708
709
101k
            pHybOutRealDry[2] += SAC_DEC_APPLY_M2_SCALE(
710
101k
                fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2);
711
101k
            pHybOutImagDry[2] -= SAC_DEC_APPLY_M2_SCALE(
712
101k
                fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2);
713
714
            /* direct signals sign is +1 for qs = 1,3,4,5,...,complexHybBands */
715
101k
            pHybOutRealDry[1] -= SAC_DEC_APPLY_M2_SCALE(
716
101k
                fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2);
717
101k
            pHybOutImagDry[1] += SAC_DEC_APPLY_M2_SCALE(
718
101k
                fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2);
719
720
5.08M
            for (qs = 3; qs < complexHybBands; qs++) {
721
4.98M
              pHybOutRealDry[qs] -= SAC_DEC_APPLY_M2_SCALE(
722
4.98M
                  fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
723
4.98M
              pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
724
4.98M
                  fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
725
4.98M
            }
726
101k
          } /* self->upmixType */
727
7.98M
        }   /* if (activParamBands) */
728
7.98M
      }     /* self->numDirektSignals */
729
730
15.9M
      for (; col < self->numVChannels; col++) {
731
7.98M
        if (self->pActivM2ParamBands ==
732
7.98M
            0) { /* default setting, calculate all rows and columns */
733
7.98M
          activParamBands = 1;
734
7.98M
        } 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
7.98M
        if (activParamBands) {
745
7.98M
          int resBandIndex;
746
7.98M
          int resHybIndex;
747
748
7.98M
          resBandIndex =
749
7.98M
              self->residualBands[SpatialDecGetResidualIndex(self, col)];
750
7.98M
          resHybIndex = self->param2hyb[resBandIndex];
751
752
7.98M
          pWReal = wReal[col];
753
7.98M
          pWImag = wImag[col];
754
755
7.98M
          M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col],
756
7.98M
                              self->M2RealPrev__FDK[row][col],
757
7.98M
                              self->kernels_width, alpha,
758
7.98M
                              self->numParameterBands);
759
760
7.98M
          if (1 && (self->phaseCoding != 3)) {
761
            /* residual signals */
762
11.4M
            for (qs = 0; qs < resHybIndex; qs++) {
763
3.58M
              pHybOutRealDry[qs] += fMult(pWReal[qs], pKernel[qs]);
764
3.58M
              pHybOutImagDry[qs] += fMult(pWImag[qs], pKernel[qs]);
765
3.58M
            }
766
            /* decor signals */
767
511M
            for (; qs < complexHybBands; qs++) {
768
503M
              pHybOutRealWet[qs] += fMult(pWReal[qs], pKernel[qs]);
769
503M
              pHybOutImagWet[qs] += fMult(pWImag[qs], pKernel[qs]);
770
503M
            }
771
7.88M
          } else { /* self->upmixType */
772
            /* residual signals */
773
101k
            FIXP_DBL *RESTRICT pHybOutReal;
774
101k
            FIXP_DBL *RESTRICT pHybOutImag;
775
776
981k
            for (qs = 0; qs < resHybIndex; qs++) {
777
879k
              pHybOutRealDry[qs] += SAC_DEC_APPLY_M2_SCALE(
778
879k
                  fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
779
879k
              pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
780
879k
                  fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
781
879k
            }
782
            /* decor signals */
783
4.51M
            for (; qs < complexHybBands; qs++) {
784
4.40M
              pHybOutRealWet[qs] += SAC_DEC_APPLY_M2_SCALE(
785
4.40M
                  fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
786
4.40M
              pHybOutImagWet[qs] += SAC_DEC_APPLY_M2_SCALE(
787
4.40M
                  fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
788
4.40M
            }
789
790
101k
            M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col],
791
101k
                                self->M2ImagPrev__FDK[row][col],
792
101k
                                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
101k
            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
101k
            } else {
812
101k
              pHybOutReal = &pHybOutRealDry[0];
813
101k
              pHybOutImag = &pHybOutImagDry[0];
814
101k
              if (0 == resHybIndex) {
815
44.3k
                pHybOutReal = &pHybOutRealWet[0];
816
44.3k
                pHybOutImag = &pHybOutImagWet[0];
817
44.3k
              }
818
101k
              pHybOutReal[0] += SAC_DEC_APPLY_M2_SCALE(
819
101k
                  fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2);
820
101k
              pHybOutImag[0] -= SAC_DEC_APPLY_M2_SCALE(
821
101k
                  fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2);
822
823
101k
              if (1 == resHybIndex) {
824
0
                pHybOutReal = &pHybOutRealWet[0];
825
0
                pHybOutImag = &pHybOutImagWet[0];
826
0
              }
827
101k
              pHybOutReal[1] -= SAC_DEC_APPLY_M2_SCALE(
828
101k
                  fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2);
829
101k
              pHybOutImag[1] += SAC_DEC_APPLY_M2_SCALE(
830
101k
                  fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2);
831
832
101k
              if (2 == resHybIndex) {
833
192
                pHybOutReal = &pHybOutRealWet[0];
834
192
                pHybOutImag = &pHybOutImagWet[0];
835
192
              }
836
101k
              pHybOutReal[2] += SAC_DEC_APPLY_M2_SCALE(
837
101k
                  fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2);
838
101k
              pHybOutImag[2] -= SAC_DEC_APPLY_M2_SCALE(
839
101k
                  fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2);
840
101k
            }
841
842
809k
            for (qs = 3; qs < resHybIndex; qs++) {
843
707k
              pHybOutRealDry[qs] -= SAC_DEC_APPLY_M2_SCALE(
844
707k
                  fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
845
707k
              pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
846
707k
                  fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
847
707k
            }
848
            /* decor signals */
849
4.37M
            for (; qs < complexHybBands; qs++) {
850
4.27M
              pHybOutRealWet[qs] -= SAC_DEC_APPLY_M2_SCALE(
851
4.27M
                  fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
852
4.27M
              pHybOutImagWet[qs] += SAC_DEC_APPLY_M2_SCALE(
853
4.27M
                  fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
854
4.27M
            }
855
101k
          } /* self->upmixType */
856
7.98M
        }   /* if (activParamBands) { */
857
7.98M
      }     /*  self->numVChannels */
858
859
7.98M
      if (self->phaseCoding == 3) {
860
101k
        scaleValuesSaturate(pHybOutRealDry, complexHybBands,
861
101k
                            SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
862
101k
        scaleValuesSaturate(pHybOutImagDry, complexHybBands,
863
101k
                            SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
864
865
101k
        if (!toolsDisabled) {
866
101k
          scaleValuesSaturate(pHybOutRealWet, complexHybBands,
867
101k
                              SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
868
101k
          scaleValuesSaturate(pHybOutImagWet, complexHybBands,
869
101k
                              SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
870
101k
        }
871
101k
      }
872
7.98M
    }
873
874
3.99M
    C_ALLOC_SCRATCH_END(pKernel, FIXP_SGL, MAX_HYBRID_BANDS);
875
3.99M
  }
876
877
3.99M
  return err;
878
3.99M
}
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
5.19M
                                 const FDK_channelMapDescr *const mapDescr) {
885
5.19M
  SACDEC_ERROR err = MPS_OK;
886
887
5.19M
  int ch;
888
5.19M
  int stride, offset;
889
890
5.19M
  stride = self->numOutputChannelsAT;
891
5.19M
  offset = 1;
892
893
5.19M
  PCM_MPS *pTimeOut__FDK =
894
5.19M
      &timeOut[stride * self->pQmfDomain->globalConf.nBandsSynthesis * ts];
895
5.19M
  C_ALLOC_SCRATCH_START(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
896
5.19M
  C_ALLOC_SCRATCH_START(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
897
898
15.5M
  for (ch = 0; ch < self->numOutputChannelsAT; ch++) {
899
10.3M
    if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
900
974k
      int k;
901
      /* No hybrid filtering. Just copy the QMF data. */
902
32.4M
      for (k = 0; k < self->hybridBands; k += 1) {
903
31.4M
        pQmfReal[k] = hybOutputReal[ch][k];
904
31.4M
        pQmfImag[k] = hybOutputImag[ch][k];
905
31.4M
      }
906
9.41M
    } else {
907
9.41M
      FDKhybridSynthesisApply(&self->hybridSynthesis[ch], hybOutputReal[ch],
908
9.41M
                              hybOutputImag[ch], pQmfReal, pQmfImag);
909
9.41M
    }
910
911
    /* Map channel indices from MPEG Surround -> PCE style -> channelMapping[]
912
     */
913
10.3M
    FDK_ASSERT(self->numOutputChannelsAT <= 6);
914
10.3M
    int outCh = FDK_chMapDescr_getMapValue(mapDescr, mapChannel(self, ch),
915
10.3M
                                           self->numOutputChannelsAT);
916
917
10.3M
    {
918
10.3M
      if (self->stereoConfigIndex == 3) {
919
        /* MPS -> SBR */
920
2.50M
        int i;
921
2.50M
        FIXP_DBL *pWorkBufReal, *pWorkBufImag;
922
2.50M
        FDK_ASSERT((self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_m ==
923
2.50M
                    (FIXP_DBL)0x80000000) &&
924
2.50M
                   (self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_e == 0));
925
2.50M
        FDK_QmfDomain_GetWorkBuffer(&self->pQmfDomain->QmfDomainIn[outCh], ts,
926
2.50M
                                    &pWorkBufReal, &pWorkBufImag);
927
2.50M
        FDK_ASSERT(self->qmfBands <=
928
2.50M
                   self->pQmfDomain->QmfDomainIn[outCh].workBuf_nBands);
929
44.4M
        for (i = 0; i < self->qmfBands; i++) {
930
41.9M
          pWorkBufReal[i] = pQmfReal[i];
931
41.9M
          pWorkBufImag[i] = pQmfImag[i];
932
41.9M
        }
933
2.50M
        self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale =
934
2.50M
            -7; /*-ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK;*/
935
2.50M
        self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -=
936
2.50M
            self->pQmfDomain->QmfDomainIn[outCh].fb.filterScale;
937
2.50M
        self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -=
938
2.50M
            self->clipProtectGainSF__FDK;
939
940
2.50M
        self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= (1);
941
7.88M
      } else {
942
        /* Call the QMF synthesis for dry. */
943
7.88M
        err = CalculateSpaceSynthesisQmf(&self->pQmfDomain->QmfDomainOut[outCh],
944
7.88M
                                         pQmfReal, pQmfImag, stride,
945
7.88M
                                         pTimeOut__FDK + (offset * outCh));
946
7.88M
      }
947
10.3M
      if (err != MPS_OK) goto bail;
948
10.3M
    }
949
10.3M
  } /* ch loop */
950
951
5.19M
bail:
952
5.19M
  C_ALLOC_SCRATCH_END(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
953
5.19M
  C_ALLOC_SCRATCH_END(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
954
955
5.19M
  return err;
956
5.19M
}
957
958
197k
void SpatialDecBufferMatrices(spatialDec *self) {
959
197k
  int row, col;
960
197k
  int complexParBands;
961
197k
  complexParBands = self->numParameterBands;
962
963
  /*
964
    buffer matrices M2
965
  */
966
593k
  for (row = 0; row < self->numM2rows; row++) {
967
1.18M
    for (col = 0; col < self->numVChannels; col++) {
968
791k
      FDKmemcpy(self->M2RealPrev__FDK[row][col], self->M2Real__FDK[row][col],
969
791k
                self->numParameterBands * sizeof(FIXP_DBL));
970
791k
      if (0 || (self->phaseCoding == 3)) {
971
11.4k
        FDKmemcpy(self->M2ImagPrev__FDK[row][col], self->M2Imag__FDK[row][col],
972
11.4k
                  complexParBands * sizeof(FIXP_DBL));
973
11.4k
      }
974
791k
    }
975
395k
  }
976
977
  /* buffer phase */
978
197k
  FDKmemcpy(self->PhasePrevLeft__FDK, self->PhaseLeft__FDK,
979
197k
            self->numParameterBands * sizeof(FIXP_DBL));
980
197k
  FDKmemcpy(self->PhasePrevRight__FDK, self->PhaseRight__FDK,
981
197k
            self->numParameterBands * sizeof(FIXP_DBL));
982
197k
}
983
984
82.9M
#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
5.70M
                                  FIXP_SGL alpha, FIXP_DBL pi_x2) {
993
5.70M
  if (angle2 - angle1 > (pi_x2 >> 1)) angle2 -= pi_x2;
994
995
5.70M
  if (angle1 - angle2 > (pi_x2 >> 1)) angle1 -= pi_x2;
996
997
5.70M
  return interpolateParameter(alpha, angle2, angle1);
998
5.70M
}
999
1000
/*
1001
 *
1002
 */
1003
void SpatialDecApplyPhase(spatialDec *self, FIXP_SGL alpha__FDK,
1004
291k
                          int lastSlotOfParamSet) {
1005
291k
  int pb, qs;
1006
291k
  FIXP_DBL ppb[MAX_PARAMETER_BANDS *
1007
291k
               4]; /* left real, imag - right real, imag interleaved */
1008
1009
291k
  const FIXP_DBL pi_x2 = PIx2__IPD;
1010
3.14M
  for (pb = 0; pb < self->numParameterBands; pb++) {
1011
2.85M
    FIXP_DBL pl, pr;
1012
1013
2.85M
    pl = interp_angle__FDK(self->PhasePrevLeft__FDK[pb],
1014
2.85M
                           self->PhaseLeft__FDK[pb], alpha__FDK, pi_x2);
1015
2.85M
    pr = interp_angle__FDK(self->PhasePrevRight__FDK[pb],
1016
2.85M
                           self->PhaseRight__FDK[pb], alpha__FDK, pi_x2);
1017
1018
2.85M
    inline_fixp_cos_sin(pl, pr, IPD_SCALE, &ppb[4 * pb]);
1019
2.85M
  }
1020
1021
  /* sign is -1 for qs = 0,2 and +1 for qs = 1 */
1022
1023
291k
  const SCHAR *kernels = &self->kernels[0];
1024
1025
291k
  FIXP_DBL *Dry_real0 = &self->hybOutputRealDry__FDK[0][0];
1026
291k
  FIXP_DBL *Dry_imag0 = &self->hybOutputImagDry__FDK[0][0];
1027
291k
  FIXP_DBL *Dry_real1 = &self->hybOutputRealDry__FDK[1][0];
1028
291k
  FIXP_DBL *Dry_imag1 = &self->hybOutputImagDry__FDK[1][0];
1029
1030
1.16M
  for (qs = 2; qs >= 0; qs--) {
1031
875k
    FIXP_DBL out_re, out_im;
1032
1033
875k
    pb = *kernels++;
1034
875k
    if (qs == 1) /* sign[qs] >= 0 */
1035
291k
    {
1036
291k
      cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1037
291k
                   ppb[4 * pb + 1]);
1038
291k
      out_re <<= PHASE_SCALE - 1;
1039
291k
      out_im <<= PHASE_SCALE - 1;
1040
291k
      *Dry_real0++ = out_re;
1041
291k
      *Dry_imag0++ = out_im;
1042
1043
291k
      cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1044
291k
                   ppb[4 * pb + 3]);
1045
291k
      out_re <<= PHASE_SCALE - 1;
1046
291k
      out_im <<= PHASE_SCALE - 1;
1047
291k
      *Dry_real1++ = out_re;
1048
291k
      *Dry_imag1++ = out_im;
1049
583k
    } else {
1050
583k
      cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1051
583k
                   -ppb[4 * pb + 1]);
1052
583k
      out_re <<= PHASE_SCALE - 1;
1053
583k
      out_im <<= PHASE_SCALE - 1;
1054
583k
      *Dry_real0++ = out_re;
1055
583k
      *Dry_imag0++ = out_im;
1056
1057
583k
      cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1058
583k
                   -ppb[4 * pb + 3]);
1059
583k
      out_re <<= PHASE_SCALE - 1;
1060
583k
      out_im <<= PHASE_SCALE - 1;
1061
583k
      *Dry_real1++ = out_re;
1062
583k
      *Dry_imag1++ = out_im;
1063
583k
    }
1064
875k
  }
1065
1066
  /* sign is +1 for qs >=3 */
1067
20.1M
  for (qs = self->hybridBands - 3; qs--;) {
1068
19.8M
    FIXP_DBL out_re, out_im;
1069
1070
19.8M
    pb = *kernels++;
1071
19.8M
    cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1072
19.8M
                 ppb[4 * pb + 1]);
1073
19.8M
    out_re <<= PHASE_SCALE - 1;
1074
19.8M
    out_im <<= PHASE_SCALE - 1;
1075
19.8M
    *Dry_real0++ = out_re;
1076
19.8M
    *Dry_imag0++ = out_im;
1077
1078
19.8M
    cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1079
19.8M
                 ppb[4 * pb + 3]);
1080
19.8M
    out_re <<= PHASE_SCALE - 1;
1081
19.8M
    out_im <<= PHASE_SCALE - 1;
1082
19.8M
    *Dry_real1++ = out_re;
1083
19.8M
    *Dry_imag1++ = out_im;
1084
19.8M
  }
1085
291k
}