Coverage Report

Created: 2026-08-31 06:46

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