Coverage Report

Created: 2026-02-14 06:49

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