Coverage Report

Created: 2025-11-09 07:00

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