Coverage Report

Created: 2025-11-16 06:35

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