Coverage Report

Created: 2026-10-17 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/aac/libSACdec/src/sac_reshapeBBEnv.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 Dec guided envelope shaping
100
101
*******************************************************************************/
102
103
#include "sac_reshapeBBEnv.h"
104
105
#include "sac_dec.h"
106
#include "sac_bitdec.h"
107
#include "sac_calcM1andM2.h"
108
#include "sac_reshapeBBEnv.h"
109
#include "sac_rom.h"
110
111
36.0M
#define INP_DRY_WET 0
112
3.60M
#define INP_DMX 1
113
114
35.1k
#define SF_SHAPE 1
115
3.66M
#define SF_DIV32 6
116
666M
#define SF_FACTOR_SLOT 5
117
118
32.4M
#define START_BB_ENV 0 /* 10 */
119
324M
#define END_BB_ENV 9   /* 18 */
120
121
7.21M
#define SF_ALPHA1 8
122
7.21M
#define SF_BETA1 4
123
124
53.2k
void initBBEnv(spatialDec *self, int initStatesFlag) {
125
53.2k
  INT ch, k;
126
127
159k
  for (ch = 0; ch < self->numOutputChannels; ch++) {
128
106k
    k = row2channelGES[self->treeConfig][ch];
129
106k
    self->row2channelDmxGES[ch] = k;
130
106k
    if (k == -1) continue;
131
132
106k
    switch (self->treeConfig) {
133
106k
      case TREE_212:
134
106k
        self->row2channelDmxGES[ch] = 0;
135
106k
        break;
136
0
      default:;
137
106k
    }
138
106k
  }
139
140
53.2k
  if (initStatesFlag) {
141
84.5k
    for (k = 0; k < 2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS; k++) {
142
70.4k
      self->reshapeBBEnvState->normNrgPrev__FDK[k] =
143
70.4k
          FL2FXCONST_DBL(0.5f); /* 32768.f*32768.f */
144
70.4k
      self->reshapeBBEnvState->normNrgPrevSF[k] = DFRACT_BITS - 1;
145
70.4k
      self->reshapeBBEnvState->partNrgPrevSF[k] = 0;
146
70.4k
      self->reshapeBBEnvState->partNrgPrev2SF[k] = 0;
147
70.4k
      self->reshapeBBEnvState->frameNrgPrevSF[k] = 0;
148
70.4k
    }
149
14.0k
  }
150
151
53.2k
  self->reshapeBBEnvState->alpha__FDK =
152
53.2k
      FL2FXCONST_DBL(0.99637845575f); /* FDKexp(-64 / (0.4f  * 44100)) */
153
53.2k
  self->reshapeBBEnvState->beta__FDK =
154
53.2k
      FL2FXCONST_DBL(0.96436909488f); /* FDKexp(-64 / (0.04f * 44100)) */
155
53.2k
}
156
157
static inline void getSlotNrgHQ(FIXP_DBL *RESTRICT pReal,
158
                                FIXP_DBL *RESTRICT pImag,
159
                                FIXP_DBL *RESTRICT slotNrg, INT maxValSF,
160
10.8M
                                INT hybBands) {
161
10.8M
  INT qs;
162
10.8M
  FIXP_DBL nrg;
163
164
  /* qs = 12, 13, 14 */
165
10.8M
  slotNrg[0] = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
166
10.8M
                (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
167
10.8M
  slotNrg[1] = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
168
10.8M
                (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
169
10.8M
  slotNrg[2] = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
170
10.8M
                (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
171
  /* qs = 15 */
172
10.8M
  slotNrg[3] = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
173
10.8M
                (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
174
  /* qs = 16, 17 */
175
10.8M
  nrg = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
176
10.8M
         (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
177
10.8M
  slotNrg[4] =
178
10.8M
      nrg + ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
179
10.8M
             (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
180
  /* qs = 18, 19, 20 */
181
10.8M
  nrg = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
182
10.8M
         (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
183
10.8M
  nrg += ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
184
10.8M
          (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
185
10.8M
  slotNrg[5] =
186
10.8M
      nrg + ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
187
10.8M
             (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
188
  /* qs = 21, 22 */
189
10.8M
  nrg = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
190
10.8M
         (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
191
10.8M
  slotNrg[6] =
192
10.8M
      nrg + ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
193
10.8M
             (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
194
  /* qs = 23, 24 */
195
10.8M
  if (hybBands > 23) {
196
10.7M
    slotNrg[6] += ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
197
10.7M
                   (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
198
10.7M
    slotNrg[6] += ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
199
10.7M
                   (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
200
    /* qs = 25, 26, 29, 28, 29 */
201
10.7M
    nrg = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
202
10.7M
           (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
203
10.7M
    nrg += ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
204
10.7M
            (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
205
10.7M
    nrg += ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
206
10.7M
            (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
207
10.7M
    nrg += ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
208
10.7M
            (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
209
10.7M
    slotNrg[7] =
210
10.7M
        nrg + ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
211
10.7M
               (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
212
    /* qs = 30 ... min(41,hybBands-1) */
213
10.7M
    nrg = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
214
10.7M
           (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
215
127M
    for (qs = 31; qs < hybBands; qs++) {
216
117M
      nrg += ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) +
217
117M
              (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1)));
218
117M
    }
219
10.7M
    slotNrg[8] = nrg;
220
10.7M
  } else {
221
23.8k
    slotNrg[7] = (FIXP_DBL)0;
222
23.8k
    slotNrg[8] = (FIXP_DBL)0;
223
23.8k
  }
224
10.8M
}
225
226
static inline void combineDryWet(FIXP_DBL *RESTRICT pReal,
227
                                 FIXP_DBL *RESTRICT pImag,
228
                                 FIXP_DBL *RESTRICT pHybOutputRealDry,
229
                                 FIXP_DBL *RESTRICT pHybOutputImagDry,
230
                                 FIXP_DBL *RESTRICT pHybOutputRealWet,
231
                                 FIXP_DBL *RESTRICT pHybOutputImagWet,
232
7.21M
                                 INT cplxBands, INT hybBands) {
233
7.21M
  INT qs;
234
235
222M
  for (qs = 12; qs < cplxBands; qs++) {
236
215M
    pReal[qs] = (pHybOutputRealDry[qs] >> 1) + (pHybOutputRealWet[qs] >> 1);
237
215M
    pImag[qs] = (pHybOutputImagDry[qs] >> 1) + (pHybOutputImagWet[qs] >> 1);
238
215M
  }
239
7.21M
  for (; qs < hybBands; qs++) {
240
0
    pReal[qs] = (pHybOutputRealDry[qs] >> 1) + (pHybOutputRealWet[qs] >> 1);
241
0
  }
242
7.21M
}
243
244
static inline void slotAmp(
245
    FIXP_DBL *RESTRICT slotAmp_dry, INT *RESTRICT slotAmp_dry_e,
246
    FIXP_DBL *RESTRICT slotAmp_wet, INT *RESTRICT slotAmp_wet_e,
247
    FIXP_DBL *RESTRICT pHybOutputRealDry, FIXP_DBL *RESTRICT pHybOutputImagDry,
248
    FIXP_DBL *RESTRICT pHybOutputRealWet, FIXP_DBL *RESTRICT pHybOutputImagWet,
249
60.5k
    INT cplxBands, INT hybBands) {
250
60.5k
  INT qs, s1, s2, headroom_dry, headroom_wet;
251
60.5k
  FIXP_DBL dry, wet;
252
253
  /* headroom can be reduced by 1 bit due to use of fPow2Div2 */
254
60.5k
  s1 = DFRACT_BITS - 1 - CntLeadingZeros(hybBands + cplxBands);
255
60.5k
  headroom_dry = fMin(getScalefactor(pHybOutputRealDry, hybBands),
256
60.5k
                      getScalefactor(pHybOutputImagDry, cplxBands));
257
60.5k
  headroom_wet = fMin(getScalefactor(pHybOutputRealWet, hybBands),
258
60.5k
                      getScalefactor(pHybOutputImagWet, cplxBands));
259
260
60.5k
  dry = wet = FL2FXCONST_DBL(0.0f);
261
3.95M
  for (qs = 0; qs < cplxBands; qs++) {
262
    /* sum up dry part */
263
3.89M
    dry += (fPow2Div2(pHybOutputRealDry[qs] << headroom_dry) >> s1);
264
3.89M
    dry += (fPow2Div2(pHybOutputImagDry[qs] << headroom_dry) >> s1);
265
    /* sum up wet part */
266
3.89M
    wet += (fPow2Div2(pHybOutputRealWet[qs] << headroom_wet) >> s1);
267
3.89M
    wet += (fPow2Div2(pHybOutputImagWet[qs] << headroom_wet) >> s1);
268
3.89M
  }
269
60.5k
  for (; qs < hybBands; qs++) {
270
0
    dry += (fPow2Div2(pHybOutputRealDry[qs] << headroom_dry) >> s1);
271
0
    wet += (fPow2Div2(pHybOutputRealWet[qs] << headroom_wet) >> s1);
272
0
  }
273
274
  /* consider fPow2Div2() */
275
60.5k
  s1 += 1;
276
277
  /* normalize dry part, ensure that exponent is even */
278
60.5k
  s2 = fixMax(0, CntLeadingZeros(dry) - 1);
279
60.5k
  *slotAmp_dry = dry << s2;
280
60.5k
  *slotAmp_dry_e = s1 - s2 - 2 * headroom_dry;
281
60.5k
  if (*slotAmp_dry_e & 1) {
282
42.4k
    *slotAmp_dry = *slotAmp_dry >> 1;
283
42.4k
    *slotAmp_dry_e += 1;
284
42.4k
  }
285
286
  /* normalize wet part, ensure that exponent is even */
287
60.5k
  s2 = fixMax(0, CntLeadingZeros(wet) - 1);
288
60.5k
  *slotAmp_wet = wet << s2;
289
60.5k
  *slotAmp_wet_e = s1 - s2 - 2 * headroom_wet;
290
60.5k
  if (*slotAmp_wet_e & 1) {
291
49.7k
    *slotAmp_wet = *slotAmp_wet >> 1;
292
49.7k
    *slotAmp_wet_e += 1;
293
49.7k
  }
294
60.5k
}
295
296
#if defined(__aarch64__)
297
__attribute__((noinline))
298
#endif
299
static void
300
shapeBBEnv(FIXP_DBL *pHybOutputRealDry, FIXP_DBL *pHybOutputImagDry,
301
60.5k
           FIXP_DBL dryFac, INT scale, INT cplxBands, INT hybBands) {
302
60.5k
  INT qs;
303
304
60.5k
  if (scale == 0) {
305
1.91M
    for (qs = 0; qs < cplxBands; qs++) {
306
1.88M
      pHybOutputRealDry[qs] = fMultDiv2(pHybOutputRealDry[qs], dryFac);
307
1.88M
      pHybOutputImagDry[qs] = fMultDiv2(pHybOutputImagDry[qs], dryFac);
308
1.88M
    }
309
29.4k
    for (; qs < hybBands; qs++) {
310
0
      pHybOutputRealDry[qs] = fMultDiv2(pHybOutputRealDry[qs], dryFac);
311
0
    }
312
31.1k
  } else {
313
2.03M
    for (qs = 0; qs < cplxBands; qs++) {
314
2.00M
      pHybOutputRealDry[qs] = SATURATE_LEFT_SHIFT(
315
2.00M
          fMultDiv2(pHybOutputRealDry[qs], dryFac), scale, DFRACT_BITS);
316
2.00M
      pHybOutputImagDry[qs] = SATURATE_LEFT_SHIFT(
317
2.00M
          fMultDiv2(pHybOutputImagDry[qs], dryFac), scale, DFRACT_BITS);
318
2.00M
    }
319
31.1k
    for (; qs < hybBands; qs++) {
320
0
      pHybOutputRealDry[qs] = SATURATE_LEFT_SHIFT(
321
0
          fMultDiv2(pHybOutputRealDry[qs], dryFac), scale, DFRACT_BITS);
322
0
    }
323
31.1k
  }
324
60.5k
}
325
326
static void extractBBEnv(spatialDec *self, INT inp, INT start, INT channels,
327
7.21M
                         FIXP_DBL *pEnv, const SPATIAL_BS_FRAME *frame) {
328
7.21M
  INT ch, pb, prevChOffs;
329
7.21M
  INT clz, scale, scale_min, envSF;
330
7.21M
  INT scaleCur, scalePrev, commonScale;
331
7.21M
  INT slotNrgSF, partNrgSF, frameNrgSF;
332
7.21M
  INT *pPartNrgPrevSF, *pFrameNrgPrevSF;
333
7.21M
  INT *pNormNrgPrevSF, *pPartNrgPrev2SF;
334
335
7.21M
  FIXP_DBL maxVal, env, frameNrg, normNrg;
336
7.21M
  FIXP_DBL *pReal, *pImag;
337
7.21M
  FIXP_DBL *partNrg, *partNrgPrev;
338
339
7.21M
  C_ALLOC_SCRATCH_START(pScratchBuffer, FIXP_DBL,
340
7.21M
                        (2 * 42 + MAX_PARAMETER_BANDS));
341
7.21M
  C_ALLOC_SCRATCH_START(resPb, FIXP_DBL, (END_BB_ENV - START_BB_ENV));
342
7.21M
  C_ALLOC_SCRATCH_START(resPbSF, INT, (END_BB_ENV - START_BB_ENV));
343
344
7.21M
  FIXP_DBL *slotNrg = pScratchBuffer + (2 * 42);
345
346
7.21M
  RESHAPE_BBENV_STATE *pBBEnvState = self->reshapeBBEnvState;
347
348
7.21M
  FIXP_DBL alpha = pBBEnvState->alpha__FDK;
349
  /*FIXP_DBL  alpha1 = (FL2FXCONST_DBL(1.0f) - alpha) << SF_ALPHA1;*/
350
7.21M
  FIXP_DBL alpha1 = ((FIXP_DBL)MAXVAL_DBL - alpha) << SF_ALPHA1;
351
7.21M
  FIXP_DBL beta = pBBEnvState->beta__FDK;
352
  /*FIXP_DBL  beta1  = (FL2FXCONST_DBL(1.0f) - beta) << SF_BETA1;*/
353
7.21M
  FIXP_DBL beta1 = ((FIXP_DBL)MAXVAL_DBL - beta) << SF_BETA1;
354
355
7.21M
  INT shapeActiv = 1;
356
7.21M
  INT hybBands = fixMin(42, self->hybridBands);
357
7.21M
  INT staticScale = self->staticDecScale + (1);
358
7.21M
  INT cplxBands;
359
7.21M
  cplxBands = fixMin(42, self->hybridBands);
360
361
18.0M
  for (ch = start; ch < channels; ch++) {
362
10.8M
    if (inp == INP_DRY_WET) {
363
7.21M
      INT ch2 = row2channelGES[self->treeConfig][ch];
364
7.21M
      if (ch2 == -1) {
365
0
        continue;
366
7.21M
      } else {
367
7.21M
        if (frame->tempShapeEnableChannelGES[ch2]) {
368
60.5k
          shapeActiv = 1;
369
7.15M
        } else {
370
7.15M
          shapeActiv = 0;
371
7.15M
        }
372
7.21M
      }
373
7.21M
      prevChOffs = ch;
374
7.21M
      pReal = pScratchBuffer;
375
7.21M
      pImag = pScratchBuffer + 42;
376
7.21M
      combineDryWet(pReal, pImag, self->hybOutputRealDry__FDK[ch],
377
7.21M
                    self->hybOutputImagDry__FDK[ch],
378
7.21M
                    self->hybOutputRealWet__FDK[ch],
379
7.21M
                    self->hybOutputImagWet__FDK[ch], cplxBands, hybBands);
380
7.21M
      clz = fMin(getScalefactor(&pReal[12], fMax(0, hybBands - 12)),
381
7.21M
                 getScalefactor(&pImag[12], fMax(0, cplxBands - 12)));
382
7.21M
    } else {
383
3.60M
      prevChOffs = ch + self->numOutputChannels;
384
3.60M
      pReal = self->hybInputReal__FDK[ch];
385
3.60M
      pImag = self->hybInputImag__FDK[ch];
386
3.60M
      clz = fMin(getScalefactor(&pReal[12], fMax(0, hybBands - 12)),
387
3.60M
                 getScalefactor(&pImag[12], fMax(0, cplxBands - 12)));
388
3.60M
    }
389
390
10.8M
    partNrg = partNrgPrev = pBBEnvState->partNrgPrev__FDK[prevChOffs];
391
10.8M
    pPartNrgPrevSF = &pBBEnvState->partNrgPrevSF[prevChOffs];
392
10.8M
    pFrameNrgPrevSF = &pBBEnvState->frameNrgPrevSF[prevChOffs];
393
10.8M
    pNormNrgPrevSF = &pBBEnvState->normNrgPrevSF[prevChOffs];
394
10.8M
    pPartNrgPrev2SF = &pBBEnvState->partNrgPrev2SF[prevChOffs];
395
396
    /* calculate slot energy */
397
10.8M
    {
398
10.8M
      getSlotNrgHQ(&pReal[12], &pImag[12], slotNrg, clz,
399
10.8M
                   fixMin(42, self->hybridBands)); /* scale slotNrg:
400
                                                      2*(staticScale-clz) +
401
                                                      SF_FACTOR_SLOT */
402
10.8M
    }
403
404
10.8M
    slotNrgSF = 2 * (staticScale - clz + ((inp == INP_DRY_WET) ? 1 : 0)) +
405
10.8M
                SF_FACTOR_SLOT;
406
10.8M
    frameNrgSF = 2 * (staticScale - clz + ((inp == INP_DRY_WET) ? 1 : 0)) +
407
10.8M
                 SF_FACTOR_SLOT;
408
409
10.8M
    partNrgSF = fixMax(slotNrgSF - SF_ALPHA1 + 1,
410
10.8M
                       pPartNrgPrevSF[0] - pPartNrgPrev2SF[0] + 1);
411
10.8M
    scalePrev = fixMax(fixMin(partNrgSF - pPartNrgPrevSF[0], DFRACT_BITS - 1),
412
10.8M
                       -(DFRACT_BITS - 1));
413
10.8M
    scaleCur =
414
10.8M
        fixMax(fixMin(partNrgSF - slotNrgSF + SF_ALPHA1, DFRACT_BITS - 1),
415
10.8M
               -(DFRACT_BITS - 1));
416
417
10.8M
    maxVal = FL2FXCONST_DBL(0.0f);
418
10.8M
    frameNrg = FL2FXCONST_DBL(0.0f);
419
10.8M
    if ((scaleCur < 0) && (scalePrev < 0)) {
420
0
      scaleCur = -scaleCur;
421
0
      scalePrev = -scalePrev;
422
0
      for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) {
423
0
        partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) << scaleCur) +
424
0
                       (fMultDiv2(alpha, partNrgPrev[pb]) << scalePrev))
425
0
                      << 1;
426
0
        maxVal |= partNrg[pb];
427
0
        frameNrg += slotNrg[pb] >> 3;
428
0
      }
429
10.8M
    } else if ((scaleCur >= 0) && (scalePrev >= 0)) {
430
105M
      for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) {
431
94.9M
        partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) >> scaleCur) +
432
94.9M
                       (fMultDiv2(alpha, partNrgPrev[pb]) >> scalePrev))
433
94.9M
                      << 1;
434
94.9M
        maxVal |= partNrg[pb];
435
94.9M
        frameNrg += slotNrg[pb] >> 3;
436
94.9M
      }
437
10.5M
    } else if ((scaleCur < 0) && (scalePrev >= 0)) {
438
0
      scaleCur = -scaleCur;
439
0
      for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) {
440
0
        partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) << scaleCur) +
441
0
                       (fMultDiv2(alpha, partNrgPrev[pb]) >> scalePrev))
442
0
                      << 1;
443
0
        maxVal |= partNrg[pb];
444
0
        frameNrg += slotNrg[pb] >> 3;
445
0
      }
446
267k
    } else { /* if ( (scaleCur >= 0) && (scalePrev < 0) ) */
447
267k
      scalePrev = -scalePrev;
448
2.67M
      for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) {
449
2.40M
        partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) >> scaleCur) +
450
2.40M
                       (fMultDiv2(alpha, partNrgPrev[pb]) << scalePrev))
451
2.40M
                      << 1;
452
2.40M
        maxVal |= partNrg[pb];
453
2.40M
        frameNrg += slotNrg[pb] >> 3;
454
2.40M
      }
455
267k
    }
456
457
    /* frameNrg /= (END_BB_ENV - START_BB_ENV); 0.88888888888f =
458
     * (1/(END_BB_ENV-START_BB_ENV)<<3; shift with 3 is compensated in loop
459
     * above */
460
10.8M
    frameNrg = fMult(frameNrg, FL2FXCONST_DBL(0.88888888888f));
461
462
    /* store scalefactor and headroom for part nrg prev */
463
10.8M
    pPartNrgPrevSF[0] = partNrgSF;
464
10.8M
    pPartNrgPrev2SF[0] = fixMax(0, CntLeadingZeros(maxVal) - 1);
465
466
10.8M
    commonScale = fixMax(frameNrgSF - SF_ALPHA1 + 1, pFrameNrgPrevSF[0] + 1);
467
10.8M
    scalePrev = fixMin(commonScale - pFrameNrgPrevSF[0], DFRACT_BITS - 1);
468
10.8M
    scaleCur = fixMin(commonScale - frameNrgSF + SF_ALPHA1, DFRACT_BITS - 1);
469
10.8M
    frameNrgSF = commonScale;
470
471
10.8M
    frameNrg = ((fMultDiv2(alpha1, frameNrg) >> scaleCur) +
472
10.8M
                (fMultDiv2(alpha, pBBEnvState->frameNrgPrev__FDK[prevChOffs]) >>
473
10.8M
                 scalePrev))
474
10.8M
               << 1;
475
476
10.8M
    clz = fixMax(0, CntLeadingZeros(frameNrg) - 1);
477
10.8M
    pBBEnvState->frameNrgPrev__FDK[prevChOffs] = frameNrg << clz;
478
10.8M
    pFrameNrgPrevSF[0] = frameNrgSF - clz;
479
480
10.8M
    env = FL2FXCONST_DBL(0.0f);
481
10.8M
    scale = clz + partNrgSF - frameNrgSF;
482
10.8M
    scale_min = DFRACT_BITS - 1;
483
108M
    for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) {
484
97.3M
      if ((partNrg[pb] | slotNrg[pb]) != FL2FXCONST_DBL(0.0f)) {
485
88.4M
        INT s;
486
88.4M
        INT sc = 0;
487
88.4M
        INT sn = fixMax(0, CntLeadingZeros(slotNrg[pb]) - 1);
488
88.4M
        FIXP_DBL inv_sqrt = invSqrtNorm2(partNrg[pb], &sc);
489
88.4M
        FIXP_DBL res = fMult(slotNrg[pb] << sn, fPow2(inv_sqrt));
490
491
88.4M
        s = fixMax(0, CntLeadingZeros(res) - 1);
492
88.4M
        res = res << s;
493
494
88.4M
        sc = scale - (2 * sc - sn - s);
495
88.4M
        scale_min = fixMin(scale_min, sc);
496
497
88.4M
        resPb[pb] = res;
498
88.4M
        resPbSF[pb] = sc;
499
88.4M
      } else {
500
8.94M
        resPb[pb] = (FIXP_DBL)0;
501
8.94M
        resPbSF[pb] = 0;
502
8.94M
      }
503
97.3M
    }
504
505
10.8M
    scale_min = 4 - scale_min;
506
507
108M
    for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) {
508
97.3M
      INT sc = fixMax(fixMin(resPbSF[pb] + scale_min, DFRACT_BITS - 1),
509
97.3M
                      -(DFRACT_BITS - 1));
510
511
97.3M
      if (sc < 0) {
512
5.99M
        env += resPb[pb] << (-sc);
513
91.3M
      } else {
514
91.3M
        env += resPb[pb] >> (sc);
515
91.3M
      }
516
97.3M
    }
517
518
10.8M
    env = fMultDiv2(env, pBBEnvState->frameNrgPrev__FDK[prevChOffs]);
519
10.8M
    envSF = slotNrgSF + scale_min + 1;
520
521
10.8M
    commonScale = fixMax(envSF - SF_BETA1 + 1, pNormNrgPrevSF[0] + 1);
522
10.8M
    scalePrev = fixMin(commonScale - pNormNrgPrevSF[0], DFRACT_BITS - 1);
523
10.8M
    scaleCur = fixMin(commonScale - envSF + SF_BETA1, DFRACT_BITS - 1);
524
525
10.8M
    normNrg = ((fMultDiv2(beta1, env) >> scaleCur) +
526
10.8M
               (fMultDiv2(beta, pBBEnvState->normNrgPrev__FDK[prevChOffs]) >>
527
10.8M
                scalePrev))
528
10.8M
              << 1;
529
530
10.8M
    clz = fixMax(0, CntLeadingZeros(normNrg) - 1);
531
10.8M
    pBBEnvState->normNrgPrev__FDK[prevChOffs] = normNrg << clz;
532
10.8M
    pNormNrgPrevSF[0] = commonScale - clz;
533
534
10.8M
    if (shapeActiv) {
535
3.66M
      if ((env | normNrg) != FL2FXCONST_DBL(0.0f)) {
536
3.66M
        INT sc, se, sn;
537
3.66M
        se = fixMax(0, CntLeadingZeros(env) - 1);
538
3.66M
        sc = commonScale + SF_DIV32 - envSF + se;
539
3.66M
        env = fMult(sqrtFixp((env << se) >> (sc & 0x1)),
540
3.66M
                    invSqrtNorm2(normNrg, &sn));
541
542
3.66M
        sc = fixMin((sc >> 1) - sn, DFRACT_BITS - 1);
543
3.66M
        if (sc < 0) {
544
3.66k
          env <<= (-sc);
545
3.65M
        } else {
546
3.65M
          env >>= (sc);
547
3.65M
        }
548
3.66M
      }
549
      /* env is scaled by SF_DIV32/2 bits */
550
3.66M
    }
551
10.8M
    pEnv[ch] = env;
552
10.8M
  }
553
554
7.21M
  C_ALLOC_SCRATCH_END(resPbSF, INT, (END_BB_ENV - START_BB_ENV));
555
7.21M
  C_ALLOC_SCRATCH_END(resPb, FIXP_DBL, (END_BB_ENV - START_BB_ENV));
556
7.21M
  C_ALLOC_SCRATCH_END(pScratchBuffer, FIXP_DBL, (2 * 42 + MAX_PARAMETER_BANDS));
557
7.21M
}
558
559
void SpatialDecReshapeBBEnv(spatialDec *self, const SPATIAL_BS_FRAME *frame,
560
3.60M
                            INT ts) {
561
3.60M
  INT ch, scale;
562
3.60M
  INT dryFacSF, slotAmpSF;
563
3.60M
  INT slotAmp_dry_e, slotAmp_wet_e;
564
3.60M
  FIXP_DBL tmp, dryFac, envShape;
565
3.60M
  FIXP_DBL slotAmp_dry, slotAmp_wet, slotAmp_ratio;
566
3.60M
  FIXP_DBL envDry[MAX_OUTPUT_CHANNELS], envDmx[2];
567
568
3.60M
  INT cplxBands;
569
3.60M
  INT hybBands = self->hybridBands - 6;
570
571
3.60M
  cplxBands = self->hybridBands - 6;
572
573
  /* extract downmix envelope(s) */
574
3.60M
  switch (self->treeConfig) {
575
3.60M
    default:
576
3.60M
      extractBBEnv(self, INP_DMX, 0, fMin(self->numInputChannels, 2), envDmx,
577
3.60M
                   frame);
578
3.60M
  }
579
580
  /* extract dry and wet envelopes */
581
3.60M
  extractBBEnv(self, INP_DRY_WET, 0, self->numOutputChannels, envDry, frame);
582
583
10.8M
  for (ch = 0; ch < self->numOutputChannels; ch++) {
584
7.21M
    INT ch2;
585
586
7.21M
    ch2 = row2channelGES[self->treeConfig][ch];
587
588
7.21M
    if (ch2 == -1) continue;
589
590
7.21M
    if (frame->tempShapeEnableChannelGES[ch2]) {
591
60.5k
      INT sc;
592
593
      /* reshape dry and wet signals according to transmitted envelope */
594
595
      /* De-quantize GES data */
596
60.5k
      FDK_ASSERT((frame->bsEnvShapeData[ch2][ts] >= 0) &&
597
60.5k
                 (frame->bsEnvShapeData[ch2][ts] <= 4));
598
60.5k
      FDK_ASSERT((self->envQuantMode == 0) || (self->envQuantMode == 1));
599
60.5k
      envShape =
600
60.5k
          FX_CFG2FX_DBL(envShapeDataTable__FDK[frame->bsEnvShapeData[ch2][ts]]
601
60.5k
                                              [self->envQuantMode]);
602
603
      /* get downmix channel */
604
60.5k
      ch2 = self->row2channelDmxGES[ch];
605
606
      /* multiply ratio with dmx envelope; tmp is scaled by SF_DIV32/2+SF_SHAPE
607
       * bits */
608
60.5k
      if (ch2 == 2) {
609
0
        tmp = fMultDiv2(envShape, envDmx[0]) + fMultDiv2(envShape, envDmx[1]);
610
60.5k
      } else {
611
60.5k
        tmp = fMult(envShape, envDmx[ch2]);
612
60.5k
      }
613
614
      /* weighting factors */
615
60.5k
      dryFacSF = slotAmpSF = 0;
616
60.5k
      dryFac = slotAmp_ratio = FL2FXCONST_DBL(0.0f);
617
618
      /* dryFac will be scaled by dryFacSF bits */
619
60.5k
      if (envDry[ch] != FL2FXCONST_DBL(0.0f)) {
620
35.1k
        envDry[ch] = invSqrtNorm2(envDry[ch], &dryFacSF);
621
35.1k
        dryFac = fMultDiv2(tmp, fPow2Div2(envDry[ch])) << 2;
622
35.1k
        dryFacSF = SF_SHAPE + 2 * dryFacSF;
623
35.1k
      }
624
625
60.5k
      slotAmp_dry_e = slotAmp_wet_e = 0;
626
627
      /* calculate slotAmp_dry and slotAmp_wet */
628
60.5k
      slotAmp(&slotAmp_dry, &slotAmp_dry_e, &slotAmp_wet, &slotAmp_wet_e,
629
60.5k
              &self->hybOutputRealDry__FDK[ch][6],
630
60.5k
              &self->hybOutputImagDry__FDK[ch][6],
631
60.5k
              &self->hybOutputRealWet__FDK[ch][6],
632
60.5k
              &self->hybOutputImagWet__FDK[ch][6], cplxBands, hybBands);
633
634
      /* exponents must be even due to subsequent square root calculation */
635
60.5k
      FDK_ASSERT(((slotAmp_dry_e & 1) == 0) && ((slotAmp_wet_e & 1) == 0));
636
637
      /* slotAmp_ratio will be scaled by slotAmpSF bits */
638
60.5k
      if (slotAmp_dry != FL2FXCONST_DBL(0.0f)) {
639
34.5k
        slotAmp_wet = sqrtFixp(slotAmp_wet);
640
34.5k
        slotAmp_dry = invSqrtNorm2(slotAmp_dry, &slotAmpSF);
641
642
34.5k
        slotAmp_ratio = fMult(slotAmp_wet, slotAmp_dry);
643
34.5k
        slotAmpSF = slotAmpSF + (slotAmp_wet_e >> 1) - (slotAmp_dry_e >> 1);
644
34.5k
      }
645
646
      /* calculate common scale factor */
647
60.5k
      scale =
648
60.5k
          fixMax(3, fixMax(dryFacSF, slotAmpSF)); /* scale is at least with 3
649
                                                     bits to avoid overflows
650
                                                     when calculating dryFac  */
651
60.5k
      dryFac = dryFac >> fixMin(scale - dryFacSF, DFRACT_BITS - 1);
652
60.5k
      slotAmp_ratio =
653
60.5k
          slotAmp_ratio >> fixMin(scale - slotAmpSF, DFRACT_BITS - 1);
654
655
      /* limit dryFac */
656
60.5k
      dryFac = fixMax(
657
60.5k
          FL2FXCONST_DBL(0.25f) >> (INT)fixMin(2 * scale, DFRACT_BITS - 1),
658
60.5k
          fMult(dryFac, slotAmp_ratio) -
659
60.5k
              (slotAmp_ratio >> fixMin(scale, DFRACT_BITS - 1)) +
660
60.5k
              (dryFac >> fixMin(scale, DFRACT_BITS - 1)));
661
60.5k
      dryFac = fixMin(
662
60.5k
          FL2FXCONST_DBL(0.50f) >> (INT)fixMin(2 * scale - 3, DFRACT_BITS - 1),
663
60.5k
          dryFac); /* reduce shift bits by 3, because upper
664
                      limit 4.0 is scaled with 3 bits */
665
60.5k
      scale = 2 * scale + 1;
666
667
      /* improve precision for dryFac */
668
60.5k
      sc = fixMax(0, CntLeadingZeros(dryFac) - 1);
669
60.5k
      dryFac = dryFac << (INT)fixMin(scale, sc);
670
60.5k
      scale = scale - fixMin(scale, sc);
671
672
      /* shaping */
673
60.5k
      shapeBBEnv(&self->hybOutputRealDry__FDK[ch][6],
674
60.5k
                 &self->hybOutputImagDry__FDK[ch][6], dryFac,
675
60.5k
                 fixMin(scale, DFRACT_BITS - 1), cplxBands, hybBands);
676
60.5k
    }
677
7.21M
  }
678
3.60M
}