1/* -----------------------------------------------------------------------------
2Software License for The Fraunhofer FDK AAC Codec Library for Android
3
4© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5Forschung e.V. All rights reserved.
6
7 1.    INTRODUCTION
8The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10scheme for digital audio. This FDK AAC Codec software is intended to be used on
11a wide variety of Android devices.
12
13AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14general perceptual audio codecs. AAC-ELD is considered the best-performing
15full-bandwidth communications codec by independent studies and is widely
16deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17specifications.
18
19Patent licenses for necessary patent claims for the FDK AAC Codec (including
20those of Fraunhofer) may be obtained through Via Licensing
21(www.vialicensing.com) or through the respective patent owners individually for
22the purpose of encoding or decoding bit streams in products that are compliant
23with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24Android devices already license these patent claims through Via Licensing or
25directly from the patent owners, and therefore FDK AAC Codec software may
26already be covered under those patent licenses when it is used for those
27licensed purposes only.
28
29Commercially-licensed AAC software libraries, including floating-point versions
30with enhanced sound quality, are also available from Fraunhofer. Users are
31encouraged to check the Fraunhofer website for additional applications
32information and documentation.
33
342.    COPYRIGHT LICENSE
35
36Redistribution and use in source and binary forms, with or without modification,
37are permitted without payment of copyright license fees provided that you
38satisfy the following conditions:
39
40You must retain the complete text of this software license in redistributions of
41the FDK AAC Codec or your modifications thereto in source code form.
42
43You must retain the complete text of this software license in the documentation
44and/or other materials provided with redistributions of the FDK AAC Codec or
45your modifications thereto in binary form. You must make available free of
46charge copies of the complete source code of the FDK AAC Codec and your
47modifications thereto to recipients of copies in binary form.
48
49The name of Fraunhofer may not be used to endorse or promote products derived
50from this library without prior written permission.
51
52You may not charge copyright license fees for anyone to use, copy or distribute
53the FDK AAC Codec software or your modifications thereto.
54
55Your modified versions of the FDK AAC Codec must carry prominent notices stating
56that you changed the software and the date of any change. For modified versions
57of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59AAC Codec Library for Android."
60
613.    NO PATENT LICENSE
62
63NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65Fraunhofer provides no warranty of patent non-infringement with respect to this
66software.
67
68You may use this FDK AAC Codec software or modifications thereto only for
69purposes that are authorized by appropriate patent licenses.
70
714.    DISCLAIMER
72
73This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75including but not limited to the implied warranties of merchantability and
76fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78or consequential damages, including but not limited to procurement of substitute
79goods or services; loss of use, data, or profits, or business interruption,
80however caused and on any theory of liability, whether in contract, strict
81liability, or tort (including negligence), arising in any way out of the use of
82this software, even if advised of the possibility of such damage.
83
845.    CONTACT INFORMATION
85
86Fraunhofer Institute for Integrated Circuits IIS
87Attention: Audio and Multimedia Departments - FDK AAC LL
88Am Wolfsmantel 33
8991058 Erlangen, Germany
90
91www.iis.fraunhofer.de/amm
92amm-info@iis.fraunhofer.de
93----------------------------------------------------------------------------- */
94
95/*********************** MPEG surround decoder library *************************
96
97   Author(s):
98
99   Description: SAC Dec subband processing
100
101*******************************************************************************/
102
103#include "sac_stp.h"
104#include "sac_calcM1andM2.h"
105#include "sac_bitdec.h"
106#include "FDK_matrixCalloc.h"
107#include "sac_rom.h"
108
109#define BP_GF_START 6
110#define BP_GF_SIZE 25
111#define HP_SIZE 9
112#define STP_UPDATE_ENERGY_RATE 32
113
114#define SF_WET 5
115#define SF_DRY \
116  3 /* SF_DRY == 2 would produce good conformance test results as well */
117#define SF_PRODUCT_BP_GF 13
118#define SF_PRODUCT_BP_GF_GF 26
119#define SF_SCALE 2
120
121#define SF_SCALE_LD64 FL2FXCONST_DBL(0.03125)      /* LD64((1<<SF_SCALE))*/
122#define STP_LPF_COEFF1__FDK FL2FXCONST_DBL(0.950f) /* 0.95 */
123#define ONE_MINUS_STP_LPF_COEFF1__FDK FL2FXCONST_DBL(0.05f) /* 1.0 - 0.95 */
124#define STP_LPF_COEFF2__FDK FL2FXCONST_DBL(0.450f)          /* 0.45 */
125#define ONE_MINUS_STP_LPF_COEFF2__FDK \
126  FL2FXCONST_DBL(1.0f - 0.450f) /* 1.0 - 0.45 */
127#define STP_SCALE_LIMIT__FDK \
128  FL2FXCONST_DBL(2.82f / (float)(1 << SF_SCALE)) /* scaled by SF_SCALE */
129#define ONE_DIV_STP_SCALE_LIMIT__FDK                                          \
130  FL2FXCONST_DBL(1.0f / 2.82f / (float)(1 << SF_SCALE)) /* scaled by SF_SCALE \
131                                                         */
132#define ABS_THR__FDK       \
133  FL2FXCONST_DBL(ABS_THR / \
134                 ((float)(1 << (22 + 22 - 26)))) /* scaled by 18 bits */
135#define ABS_THR2__FDK                      \
136  FL2FXCONST_DBL(ABS_THR * 32.0f * 32.0f / \
137                 ((float)(1 << (22 + 22 - 26)))) /* scaled by 10 bits */
138#define STP_SCALE_LIMIT_HI \
139  FL2FXCONST_DBL(3.02222222222 / (1 << SF_SCALE)) /* see 4. below */
140#define STP_SCALE_LIMIT_LO \
141  FL2FXCONST_DBL(0.28289992119 / (1 << SF_SCALE)) /* see 4. below */
142#define STP_SCALE_LIMIT_HI_LD64                 \
143  FL2FXCONST_DBL(0.04986280452) /* see 4. below \
144                                 */
145#define STP_SCALE_LIMIT_LO_LD64                 \
146  FL2FXCONST_DBL(0.05692613500) /* see 4. below \
147                                 */
148
149/*  Scale factor calculation for the diffuse signal needs adapted thresholds
150    for STP_SCALE_LIMIT and 1/STP_SCALE_LIMIT:
151
152    1. scale = sqrt(DryNrg/WetNrg)
153
154    2. Damping of scale factor
155       scale2 = 0.1 + 0.9 * scale
156
157    3. Limiting of scale factor
158          STP_SCALE_LIMIT           >=        scale2        >= 1/STP_SCALE_LIMIT
159       => STP_SCALE_LIMIT           >=  (0.1 + 0.9 * scale) >= 1/STP_SCALE_LIMIT
160       => (STP_SCALE_LIMIT-0.1)/0.9 >=        scale         >=
161   (1/STP_SCALE_LIMIT-0.1)/0.9
162
163    3. Limiting of scale factor before sqrt calculation
164       ((STP_SCALE_LIMIT-0.1)/0.9)^2 >= (scale^2) >=
165   ((1/STP_SCALE_LIMIT-0.1)/0.9)^2 (STP_SCALE_LIMIT_HI)^2        >= (scale^2) >=
166   (STP_SCALE_LIMIT_LO)^2
167
168    4. Thresholds for limiting of scale factor
169       STP_SCALE_LIMIT_HI      = ((2.82-0.1)/0.9)
170       STP_SCALE_LIMIT_LO      = (((1.0/2.82)-0.1)/0.9)
171       STP_SCALE_LIMIT_HI_LD64 = LD64(STP_SCALE_LIMIT_HI*STP_SCALE_LIMIT_HI)
172       STP_SCALE_LIMIT_LO_LD64 = LD64(STP_SCALE_LIMIT_LO*STP_SCALE_LIMIT_LO)
173*/
174
175#define DRY_ENER_WEIGHT(DryEner) DryEner = DryEner >> dry_scale_dmx
176
177#define WET_ENER_WEIGHT(WetEner) WetEner = WetEner << wet_scale_dmx
178
179#define DRY_ENER_SUM_REAL(DryEner, dmxReal, n) \
180  DryEner +=                                   \
181      fMultDiv2(fPow2Div2(dmxReal << SF_DRY), pBP[n]) >> ((2 * SF_DRY) - 2)
182
183#define DRY_ENER_SUM_CPLX(DryEner, dmxReal, dmxImag, n) \
184  DryEner += fMultDiv2(                                 \
185      fPow2Div2(dmxReal << SF_DRY) + fPow2Div2(dmxImag << SF_DRY), pBP[n])
186
187#define CALC_WET_SCALE(dryIdx, wetIdx)                                         \
188  if ((DryEnerLD64[dryIdx] - STP_SCALE_LIMIT_HI_LD64) > WetEnerLD64[wetIdx]) { \
189    scale[wetIdx] = STP_SCALE_LIMIT_HI;                                        \
190  } else if (DryEnerLD64[dryIdx] <                                             \
191             (WetEnerLD64[wetIdx] - STP_SCALE_LIMIT_LO_LD64)) {                \
192    scale[wetIdx] = STP_SCALE_LIMIT_LO;                                        \
193  } else {                                                                     \
194    tmp = ((DryEnerLD64[dryIdx] - WetEnerLD64[wetIdx]) >> 1) - SF_SCALE_LD64;  \
195    scale[wetIdx] = CalcInvLdData(tmp);                                        \
196  }
197
198struct STP_DEC {
199  FIXP_DBL runDryEner[MAX_INPUT_CHANNELS];
200  FIXP_DBL runWetEner[MAX_OUTPUT_CHANNELS];
201  FIXP_DBL oldDryEnerLD64[MAX_INPUT_CHANNELS];
202  FIXP_DBL oldWetEnerLD64[MAX_OUTPUT_CHANNELS];
203  FIXP_DBL prev_tp_scale[MAX_OUTPUT_CHANNELS];
204  const FIXP_CFG *BP;
205  const FIXP_CFG *BP_GF;
206  int update_old_ener;
207};
208
209inline void combineSignalReal(FIXP_DBL *hybOutputRealDry,
210                              FIXP_DBL *hybOutputRealWet, int bands) {
211  int n;
212
213  for (n = bands - 1; n >= 0; n--) {
214    *hybOutputRealDry = *hybOutputRealDry + *hybOutputRealWet;
215    hybOutputRealDry++, hybOutputRealWet++;
216  }
217}
218
219inline void combineSignalRealScale1(FIXP_DBL *hybOutputRealDry,
220                                    FIXP_DBL *hybOutputRealWet, FIXP_DBL scaleX,
221                                    int bands) {
222  int n;
223
224  for (n = bands - 1; n >= 0; n--) {
225    *hybOutputRealDry =
226        *hybOutputRealDry +
227        (fMultDiv2(*hybOutputRealWet, scaleX) << (SF_SCALE + 1));
228    hybOutputRealDry++, hybOutputRealWet++;
229  }
230}
231
232inline void combineSignalCplx(FIXP_DBL *hybOutputRealDry,
233                              FIXP_DBL *hybOutputImagDry,
234                              FIXP_DBL *hybOutputRealWet,
235                              FIXP_DBL *hybOutputImagWet, int bands) {
236  int n;
237
238  for (n = bands - 1; n >= 0; n--) {
239    *hybOutputRealDry = *hybOutputRealDry + *hybOutputRealWet;
240    *hybOutputImagDry = *hybOutputImagDry + *hybOutputImagWet;
241    hybOutputRealDry++, hybOutputRealWet++;
242    hybOutputImagDry++, hybOutputImagWet++;
243  }
244}
245
246inline void combineSignalCplxScale1(FIXP_DBL *hybOutputRealDry,
247                                    FIXP_DBL *hybOutputImagDry,
248                                    FIXP_DBL *hybOutputRealWet,
249                                    FIXP_DBL *hybOutputImagWet,
250                                    const FIXP_CFG *pBP, FIXP_DBL scaleX,
251                                    int bands) {
252  int n;
253  FIXP_DBL scaleY;
254  for (n = bands - 1; n >= 0; n--) {
255    scaleY = fMultDiv2(scaleX, *pBP);
256    *hybOutputRealDry =
257        *hybOutputRealDry +
258        (fMultDiv2(*hybOutputRealWet, scaleY) << (SF_SCALE + 2));
259    *hybOutputImagDry =
260        *hybOutputImagDry +
261        (fMultDiv2(*hybOutputImagWet, scaleY) << (SF_SCALE + 2));
262    hybOutputRealDry++, hybOutputRealWet++;
263    hybOutputImagDry++, hybOutputImagWet++;
264    pBP++;
265  }
266}
267
268inline void combineSignalCplxScale2(FIXP_DBL *hybOutputRealDry,
269                                    FIXP_DBL *hybOutputImagDry,
270                                    FIXP_DBL *hybOutputRealWet,
271                                    FIXP_DBL *hybOutputImagWet, FIXP_DBL scaleX,
272                                    int bands) {
273  int n;
274
275  for (n = bands - 1; n >= 0; n--) {
276    *hybOutputRealDry =
277        *hybOutputRealDry +
278        (fMultDiv2(*hybOutputRealWet, scaleX) << (SF_SCALE + 1));
279    *hybOutputImagDry =
280        *hybOutputImagDry +
281        (fMultDiv2(*hybOutputImagWet, scaleX) << (SF_SCALE + 1));
282    hybOutputRealDry++, hybOutputRealWet++;
283    hybOutputImagDry++, hybOutputImagWet++;
284  }
285}
286
287/*******************************************************************************
288 Functionname: subbandTPCreate
289 ******************************************************************************/
290SACDEC_ERROR subbandTPCreate(HANDLE_STP_DEC *hStpDec) {
291  HANDLE_STP_DEC self = NULL;
292  FDK_ALLOCATE_MEMORY_1D(self, 1, struct STP_DEC)
293  if (hStpDec != NULL) {
294    *hStpDec = self;
295  }
296
297  return MPS_OK;
298bail:
299  return MPS_OUTOFMEMORY;
300}
301
302SACDEC_ERROR subbandTPInit(HANDLE_STP_DEC self) {
303  SACDEC_ERROR err = MPS_OK;
304  int ch;
305
306  for (ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++) {
307    self->prev_tp_scale[ch] = FL2FXCONST_DBL(1.0f / (1 << SF_SCALE));
308    self->oldWetEnerLD64[ch] =
309        FL2FXCONST_DBL(0.34375f); /* 32768.0*32768.0/2^(44-26-10) */
310  }
311  for (ch = 0; ch < MAX_INPUT_CHANNELS; ch++) {
312    self->oldDryEnerLD64[ch] =
313        FL2FXCONST_DBL(0.1875f); /* 32768.0*32768.0/2^(44-26) */
314  }
315
316  self->BP = BP__FDK;
317  self->BP_GF = BP_GF__FDK;
318
319  self->update_old_ener = 0;
320
321  return err;
322}
323
324/*******************************************************************************
325 Functionname: subbandTPDestroy
326 ******************************************************************************/
327void subbandTPDestroy(HANDLE_STP_DEC *hStpDec) {
328  if (hStpDec != NULL) {
329    FDK_FREE_MEMORY_1D(*hStpDec);
330  }
331}
332
333/*******************************************************************************
334 Functionname: subbandTPApply
335 ******************************************************************************/
336SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) {
337  FIXP_DBL *qmfOutputRealDry[MAX_OUTPUT_CHANNELS];
338  FIXP_DBL *qmfOutputImagDry[MAX_OUTPUT_CHANNELS];
339  FIXP_DBL *qmfOutputRealWet[MAX_OUTPUT_CHANNELS];
340  FIXP_DBL *qmfOutputImagWet[MAX_OUTPUT_CHANNELS];
341
342  FIXP_DBL DryEner[MAX_INPUT_CHANNELS];
343  FIXP_DBL scale[MAX_OUTPUT_CHANNELS];
344
345  FIXP_DBL DryEnerLD64[MAX_INPUT_CHANNELS];
346  FIXP_DBL WetEnerLD64[MAX_OUTPUT_CHANNELS];
347
348  FIXP_DBL DryEner0 = FL2FXCONST_DBL(0.0f);
349  FIXP_DBL WetEnerX, damp, tmp;
350  FIXP_DBL dmxReal0, dmxImag0;
351  int skipChannels[MAX_OUTPUT_CHANNELS];
352  int n, ch, cplxBands, cplxHybBands;
353  int dry_scale_dmx, wet_scale_dmx;
354  int i_LF, i_RF;
355  HANDLE_STP_DEC hStpDec;
356  const FIXP_CFG *pBP;
357
358  int nrgScale = (2 * self->clipProtectGainSF__FDK);
359
360  hStpDec = self->hStpDec;
361
362  /* set scalefactor and loop counter */
363  FDK_ASSERT(SF_DRY >= 1);
364  {
365    cplxBands = BP_GF_SIZE;
366    cplxHybBands = self->hybridBands;
367    dry_scale_dmx = (2 * SF_DRY) - 2;
368    wet_scale_dmx = 2;
369  }
370
371  /* setup pointer for forming the direct downmix signal */
372  for (ch = 0; ch < self->numOutputChannels; ch++) {
373    qmfOutputRealDry[ch] = &self->hybOutputRealDry__FDK[ch][7];
374    qmfOutputRealWet[ch] = &self->hybOutputRealWet__FDK[ch][7];
375    qmfOutputImagDry[ch] = &self->hybOutputImagDry__FDK[ch][7];
376    qmfOutputImagWet[ch] = &self->hybOutputImagWet__FDK[ch][7];
377  }
378
379  /* clear skipping flag for all output channels */
380  FDKmemset(skipChannels, 0, self->numOutputChannels * sizeof(int));
381
382  /* set scale values to zero */
383  FDKmemset(scale, 0, self->numOutputChannels * sizeof(FIXP_DBL));
384
385  /* update normalisation energy with latest smoothed energy */
386  if (hStpDec->update_old_ener == STP_UPDATE_ENERGY_RATE) {
387    hStpDec->update_old_ener = 1;
388    for (ch = 0; ch < self->numInputChannels; ch++) {
389      hStpDec->oldDryEnerLD64[ch] =
390          CalcLdData(hStpDec->runDryEner[ch] + ABS_THR__FDK);
391    }
392    for (ch = 0; ch < self->numOutputChannels; ch++) {
393      hStpDec->oldWetEnerLD64[ch] =
394          CalcLdData(hStpDec->runWetEner[ch] + ABS_THR2__FDK);
395    }
396  } else {
397    hStpDec->update_old_ener++;
398  }
399
400  /* get channel configuration */
401  switch (self->treeConfig) {
402    case TREE_212:
403      i_LF = 0;
404      i_RF = 1;
405      break;
406    default:
407      return MPS_WRONG_TREECONFIG;
408  }
409
410  /* form the 'direct' downmix signal */
411  pBP = hStpDec->BP_GF - BP_GF_START;
412  switch (self->treeConfig) {
413    case TREE_212:
414      for (n = BP_GF_START; n < cplxBands; n++) {
415        dmxReal0 = qmfOutputRealDry[i_LF][n] + qmfOutputRealDry[i_RF][n];
416        dmxImag0 = qmfOutputImagDry[i_LF][n] + qmfOutputImagDry[i_RF][n];
417        DRY_ENER_SUM_CPLX(DryEner0, dmxReal0, dmxImag0, n);
418      }
419      DRY_ENER_WEIGHT(DryEner0);
420      break;
421    default:;
422  }
423  DryEner[0] = DryEner0;
424
425  /* normalise the 'direct' signals */
426  for (ch = 0; ch < self->numInputChannels; ch++) {
427    DryEner[ch] = DryEner[ch] << (nrgScale);
428    hStpDec->runDryEner[ch] =
429        fMult(STP_LPF_COEFF1__FDK, hStpDec->runDryEner[ch]) +
430        fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, DryEner[ch]);
431    if (DryEner[ch] != FL2FXCONST_DBL(0.0f)) {
432      DryEnerLD64[ch] =
433          fixMax((CalcLdData(DryEner[ch]) - hStpDec->oldDryEnerLD64[ch]),
434                 FL2FXCONST_DBL(-0.484375f));
435    } else {
436      DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
437    }
438  }
439  if (self->treeConfig == TREE_212) {
440    for (; ch < MAX_INPUT_CHANNELS; ch++) {
441      DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
442    }
443  }
444
445  /* normalise the 'diffuse' signals */
446  pBP = hStpDec->BP_GF - BP_GF_START;
447  for (ch = 0; ch < self->numOutputChannels; ch++) {
448    if (skipChannels[ch]) {
449      continue;
450    }
451
452    WetEnerX = FL2FXCONST_DBL(0.0f);
453    for (n = BP_GF_START; n < cplxBands; n++) {
454      tmp = fPow2Div2(qmfOutputRealWet[ch][n] << SF_WET);
455      tmp += fPow2Div2(qmfOutputImagWet[ch][n] << SF_WET);
456      WetEnerX += fMultDiv2(tmp, pBP[n]);
457    }
458    WET_ENER_WEIGHT(WetEnerX);
459
460    WetEnerX = WetEnerX << (nrgScale);
461    hStpDec->runWetEner[ch] =
462        fMult(STP_LPF_COEFF1__FDK, hStpDec->runWetEner[ch]) +
463        fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, WetEnerX);
464
465    if (WetEnerX == FL2FXCONST_DBL(0.0f)) {
466      WetEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
467    } else {
468      WetEnerLD64[ch] =
469          fixMax((CalcLdData(WetEnerX) - hStpDec->oldWetEnerLD64[ch]),
470                 FL2FXCONST_DBL(-0.484375f));
471    }
472  }
473
474  /* compute scale factor for the 'diffuse' signals */
475  switch (self->treeConfig) {
476    case TREE_212:
477      if (DryEner[0] != FL2FXCONST_DBL(0.0f)) {
478        CALC_WET_SCALE(0, i_LF);
479        CALC_WET_SCALE(0, i_RF);
480      }
481      break;
482    default:;
483  }
484
485  damp = FL2FXCONST_DBL(0.1f / (1 << SF_SCALE));
486  for (ch = 0; ch < self->numOutputChannels; ch++) {
487    /* damp the scaling factor */
488    scale[ch] = damp + fMult(FL2FXCONST_DBL(0.9f), scale[ch]);
489
490    /* limiting the scale factor */
491    if (scale[ch] > STP_SCALE_LIMIT__FDK) {
492      scale[ch] = STP_SCALE_LIMIT__FDK;
493    }
494    if (scale[ch] < ONE_DIV_STP_SCALE_LIMIT__FDK) {
495      scale[ch] = ONE_DIV_STP_SCALE_LIMIT__FDK;
496    }
497
498    /* low pass filter the scaling factor */
499    scale[ch] =
500        fMult(STP_LPF_COEFF2__FDK, scale[ch]) +
501        fMult(ONE_MINUS_STP_LPF_COEFF2__FDK, hStpDec->prev_tp_scale[ch]);
502    hStpDec->prev_tp_scale[ch] = scale[ch];
503  }
504
505  /* combine 'direct' and scaled 'diffuse' signal */
506  FDK_ASSERT((HP_SIZE - 3 + 10 - 1) == PC_NUM_HYB_BANDS);
507  const SCHAR *channlIndex = row2channelSTP[self->treeConfig];
508
509  for (ch = 0; ch < self->numOutputChannels; ch++) {
510    int no_scaling;
511
512    no_scaling = !frame->tempShapeEnableChannelSTP[channlIndex[ch]];
513    if (no_scaling) {
514      combineSignalCplx(
515          &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder],
516          &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder],
517          &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder],
518          &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder],
519          cplxHybBands - self->tp_hybBandBorder);
520
521    } else {
522      FIXP_DBL scaleX;
523      scaleX = scale[ch];
524      pBP = hStpDec->BP - self->tp_hybBandBorder;
525      /* Band[HP_SIZE-3+10-1] needs not to be processed in
526         combineSignalCplxScale1(), because pB[HP_SIZE-3+10-1] would be 1.0 */
527      combineSignalCplxScale1(
528          &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder],
529          &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder],
530          &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder],
531          &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder],
532          &pBP[self->tp_hybBandBorder], scaleX,
533          (HP_SIZE - 3 + 10 - 1) - self->tp_hybBandBorder);
534
535      {
536        combineSignalCplxScale2(
537            &self->hybOutputRealDry__FDK[ch][HP_SIZE - 3 + 10 - 1],
538            &self->hybOutputImagDry__FDK[ch][HP_SIZE - 3 + 10 - 1],
539            &self->hybOutputRealWet__FDK[ch][HP_SIZE - 3 + 10 - 1],
540            &self->hybOutputImagWet__FDK[ch][HP_SIZE - 3 + 10 - 1], scaleX,
541            cplxHybBands - (HP_SIZE - 3 + 10 - 1));
542      }
543    }
544  }
545
546  return (SACDEC_ERROR)MPS_OK;
547  ;
548}
549