Coverage Report

Created: 2025-07-12 07:06

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