Coverage Report

Created: 2025-07-23 06:43

/src/aac/libAACenc/src/adj_thr.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -----------------------------------------------------------------------------
2
Software License for The Fraunhofer FDK AAC Codec Library for Android
3
4
© Copyright  1995 - 2019 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
/**************************** AAC encoder library ******************************
96
97
   Author(s):   M. Werner
98
99
   Description: Threshold compensation
100
101
*******************************************************************************/
102
103
#include "adj_thr.h"
104
#include "sf_estim.h"
105
#include "aacEnc_ram.h"
106
107
0
#define NUM_NRG_LEVS (8)
108
#define INV_INT_TAB_SIZE (8)
109
static const FIXP_DBL invInt[INV_INT_TAB_SIZE] = {
110
    0x7fffffff, 0x7fffffff, 0x40000000, 0x2aaaaaaa,
111
    0x20000000, 0x19999999, 0x15555555, 0x12492492};
112
113
#define INV_SQRT4_TAB_SIZE (8)
114
static const FIXP_DBL invSqrt4[INV_SQRT4_TAB_SIZE] = {
115
    0x7fffffff, 0x7fffffff, 0x6ba27e65, 0x61424bb5,
116
    0x5a827999, 0x55994845, 0x51c8e33c, 0x4eb160d1};
117
118
/*static const INT      invRedExp = 4;*/
119
static const FIXP_DBL SnrLdMin1 =
120
    (FIXP_DBL)0xfcad0ddf; /*FL2FXCONST_DBL(FDKlog(0.316)/FDKlog(2.0)/LD_DATA_SCALING);*/
121
static const FIXP_DBL SnrLdMin2 =
122
    (FIXP_DBL)0x0351e1a2; /*FL2FXCONST_DBL(FDKlog(3.16)
123
                             /FDKlog(2.0)/LD_DATA_SCALING);*/
124
static const FIXP_DBL SnrLdFac =
125
    (FIXP_DBL)0xff5b2c3e; /*FL2FXCONST_DBL(FDKlog(0.8)
126
                             /FDKlog(2.0)/LD_DATA_SCALING);*/
127
128
static const FIXP_DBL SnrLdMin3 =
129
    (FIXP_DBL)0xfe000000; /*FL2FXCONST_DBL(FDKlog(0.5)
130
                             /FDKlog(2.0)/LD_DATA_SCALING);*/
131
static const FIXP_DBL SnrLdMin4 =
132
    (FIXP_DBL)0x02000000; /*FL2FXCONST_DBL(FDKlog(2.0)
133
                             /FDKlog(2.0)/LD_DATA_SCALING);*/
134
static const FIXP_DBL SnrLdMin5 =
135
    (FIXP_DBL)0xfc000000; /*FL2FXCONST_DBL(FDKlog(0.25)
136
                             /FDKlog(2.0)/LD_DATA_SCALING);*/
137
138
/*
139
The bits2Pe factors are choosen for the case that some times
140
the crash recovery strategy will be activated once.
141
*/
142
#define AFTERBURNER_STATI 2
143
#define MAX_ALLOWED_EL_CHANNELS 2
144
145
typedef struct {
146
  INT bitrate;
147
  FIXP_DBL bits2PeFactor[AFTERBURNER_STATI][MAX_ALLOWED_EL_CHANNELS];
148
} BIT_PE_SFAC;
149
150
typedef struct {
151
  INT sampleRate;
152
  const BIT_PE_SFAC *pPeTab;
153
  INT nEntries;
154
155
} BITS2PE_CFG_TAB;
156
157
#define FL2B2PE(value) FL2FXCONST_DBL((value) / (1 << 2))
158
159
static const BIT_PE_SFAC S_Bits2PeTab16000[] = {
160
    /* bitrate|   afterburner off              |   afterburner on | |   nCh=1
161
       |   nCh=2       |   nCh=1       |   nCh=2        */
162
    {10000,
163
     {{FL2B2PE(1.60f), FL2B2PE(0.00f)}, {FL2B2PE(1.40f), FL2B2PE(0.00f)}}},
164
    {24000,
165
     {{FL2B2PE(1.80f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}},
166
    {32000,
167
     {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
168
    {48000,
169
     {{FL2B2PE(1.60f), FL2B2PE(1.80f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
170
    {64000,
171
     {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.20f), FL2B2PE(1.60f)}}},
172
    {96000,
173
     {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}},
174
    {128000,
175
     {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.80f)}}},
176
    {148000,
177
     {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.40f)}}}};
178
179
static const BIT_PE_SFAC S_Bits2PeTab22050[] = {
180
    /* bitrate|   afterburner off              |   afterburner on | |   nCh=1
181
       |   nCh=2       |   nCh=1       |   nCh=2        */
182
    {16000,
183
     {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}},
184
    {24000,
185
     {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.40f), FL2B2PE(1.00f)}}},
186
    {32000,
187
     {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.40f), FL2B2PE(1.20f)}}},
188
    {48000,
189
     {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.20f), FL2B2PE(1.40f)}}},
190
    {64000,
191
     {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
192
    {96000,
193
     {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
194
    {128000,
195
     {{FL2B2PE(1.80f), FL2B2PE(1.80f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
196
    {148000,
197
     {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}}};
198
199
static const BIT_PE_SFAC S_Bits2PeTab24000[] = {
200
    /* bitrate|   afterburner off              |   afterburner on | |   nCh=1
201
       |   nCh=2       |   nCh=1      |   nCh=2         */
202
    {16000,
203
     {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}},
204
    {24000,
205
     {{FL2B2PE(1.60f), FL2B2PE(1.20f)}, {FL2B2PE(1.40f), FL2B2PE(1.00f)}}},
206
    {32000,
207
     {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.40f), FL2B2PE(0.80f)}}},
208
    {48000,
209
     {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.40f)}}},
210
    {64000,
211
     {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
212
    {96000,
213
     {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
214
    {128000,
215
     {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.80f)}}},
216
    {148000,
217
     {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.80f)}}}};
218
219
static const BIT_PE_SFAC S_Bits2PeTab32000[] = {
220
    /* bitrate|   afterburner off              |   afterburner on | |   nCh=1
221
       |   nCh=2       |   nCh=1       |   nCh=2        */
222
    {16000,
223
     {{FL2B2PE(1.20f), FL2B2PE(1.40f)}, {FL2B2PE(0.80f), FL2B2PE(0.80f)}}},
224
    {24000,
225
     {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.60f)}}},
226
    {32000,
227
     {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}},
228
    {48000,
229
     {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(1.20f)}}},
230
    {64000,
231
     {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}},
232
    {96000,
233
     {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
234
    {128000,
235
     {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
236
    {148000,
237
     {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
238
    {160000,
239
     {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
240
    {200000,
241
     {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}},
242
    {320000,
243
     {{FL2B2PE(3.20f), FL2B2PE(1.80f)}, {FL2B2PE(3.20f), FL2B2PE(1.80f)}}}};
244
245
static const BIT_PE_SFAC S_Bits2PeTab44100[] = {
246
    /* bitrate|   afterburner off              |   afterburner on | |   nCh=1
247
       |   nCh=2       |   nCh=1       |   nCh=2        */
248
    {16000,
249
     {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(0.80f), FL2B2PE(1.00f)}}},
250
    {24000,
251
     {{FL2B2PE(1.00f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}},
252
    {32000,
253
     {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(0.80f), FL2B2PE(0.60f)}}},
254
    {48000,
255
     {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}},
256
    {64000,
257
     {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(1.00f)}}},
258
    {96000,
259
     {{FL2B2PE(1.60f), FL2B2PE(1.20f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}},
260
    {128000,
261
     {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
262
    {148000,
263
     {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
264
    {160000,
265
     {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
266
    {200000,
267
     {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
268
    {320000,
269
     {{FL2B2PE(3.20f), FL2B2PE(1.60f)}, {FL2B2PE(3.20f), FL2B2PE(1.60f)}}}};
270
271
static const BIT_PE_SFAC S_Bits2PeTab48000[] = {
272
    /* bitrate|   afterburner off              |   afterburner on | |   nCh=1
273
       |   nCh=2       |   nCh=1       |   nCh=2        */
274
    {16000,
275
     {{FL2B2PE(1.40f), FL2B2PE(0.00f)}, {FL2B2PE(0.80f), FL2B2PE(0.00f)}}},
276
    {24000,
277
     {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}},
278
    {32000,
279
     {{FL2B2PE(1.00f), FL2B2PE(1.20f)}, {FL2B2PE(0.60f), FL2B2PE(0.80f)}}},
280
    {48000,
281
     {{FL2B2PE(1.20f), FL2B2PE(1.00f)}, {FL2B2PE(0.80f), FL2B2PE(0.80f)}}},
282
    {64000,
283
     {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(1.00f)}}},
284
    {96000,
285
     {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}},
286
    {128000,
287
     {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
288
    {148000,
289
     {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
290
    {160000,
291
     {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
292
    {200000,
293
     {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
294
    {320000,
295
     {{FL2B2PE(3.20f), FL2B2PE(1.60f)}, {FL2B2PE(3.20f), FL2B2PE(1.60f)}}}};
296
297
static const BITS2PE_CFG_TAB bits2PeConfigTab[] = {
298
    {16000, S_Bits2PeTab16000, sizeof(S_Bits2PeTab16000) / sizeof(BIT_PE_SFAC)},
299
    {22050, S_Bits2PeTab22050, sizeof(S_Bits2PeTab22050) / sizeof(BIT_PE_SFAC)},
300
    {24000, S_Bits2PeTab24000, sizeof(S_Bits2PeTab24000) / sizeof(BIT_PE_SFAC)},
301
    {32000, S_Bits2PeTab32000, sizeof(S_Bits2PeTab32000) / sizeof(BIT_PE_SFAC)},
302
    {44100, S_Bits2PeTab44100, sizeof(S_Bits2PeTab44100) / sizeof(BIT_PE_SFAC)},
303
    {48000, S_Bits2PeTab48000,
304
     sizeof(S_Bits2PeTab48000) / sizeof(BIT_PE_SFAC)}};
305
306
/* values for avoid hole flag */
307
enum _avoid_hole_state { NO_AH = 0, AH_INACTIVE = 1, AH_ACTIVE = 2 };
308
309
/*  Q format definitions */
310
#define Q_BITFAC \
311
  (24) /* Q scaling used in FDKaacEnc_bitresCalcBitFac() calculation */
312
0
#define Q_AVGBITS (17) /* scale bit values */
313
314
/*****************************************************************************
315
    functionname: FDKaacEnc_InitBits2PeFactor
316
    description:  retrieve bits2PeFactor from table
317
*****************************************************************************/
318
static void FDKaacEnc_InitBits2PeFactor(
319
    FIXP_DBL *bits2PeFactor_m, INT *bits2PeFactor_e, const INT bitRate,
320
    const INT nChannels, const INT sampleRate, const INT advancedBitsToPe,
321
0
    const INT dZoneQuantEnable, const INT invQuant) {
322
  /**** 1) Set default bits2pe factor ****/
323
0
  FIXP_DBL bit2PE_m = FL2FXCONST_DBL(1.18f / (1 << (1)));
324
0
  INT bit2PE_e = 1;
325
326
  /**** 2) For AAC-(E)LD, make use of advanced bits to pe factor table ****/
327
0
  if (advancedBitsToPe && nChannels <= (2)) {
328
0
    int i;
329
0
    const BIT_PE_SFAC *peTab = NULL;
330
0
    INT size = 0;
331
332
    /*** 2.1) Get correct table entry ***/
333
0
    for (i = 0; i < (INT)(sizeof(bits2PeConfigTab) / sizeof(BITS2PE_CFG_TAB));
334
0
         i++) {
335
0
      if (sampleRate >= bits2PeConfigTab[i].sampleRate) {
336
0
        peTab = bits2PeConfigTab[i].pPeTab;
337
0
        size = bits2PeConfigTab[i].nEntries;
338
0
      }
339
0
    }
340
341
0
    if ((peTab != NULL) && (size != 0)) {
342
0
      INT startB = -1; /* bitrate entry in table that is the next-lower to
343
                          actual bitrate  */
344
0
      INT stopB = -1;  /* bitrate entry in table that is the next-higher to
345
                          actual bitrate */
346
0
      FIXP_DBL startPF =
347
0
          FL2FXCONST_DBL(0.0f); /* bits2PE factor entry in table that is the
348
                                   next-lower to actual bits2PE factor  */
349
0
      FIXP_DBL stopPF = FL2FXCONST_DBL(0.0f); /* bits2PE factor entry in table
350
                                                 that is the next-higher to
351
                                                 actual bits2PE factor */
352
0
      FIXP_DBL slope = FL2FXCONST_DBL(
353
0
          0.0f); /* the slope from the start bits2Pe entry to the next one */
354
0
      const int qualityIdx = (invQuant == 0) ? 0 : 1;
355
356
0
      if (bitRate >= peTab[size - 1].bitrate) {
357
        /* Chosen bitrate is higher than the highest bitrate in table.
358
           The slope for extrapolating the bits2PE factor must be zero.
359
           Values are set accordingly.                                       */
360
0
        startB = peTab[size - 1].bitrate;
361
0
        stopB =
362
0
            bitRate +
363
0
            1; /* Can be an arbitrary value greater than startB and bitrate. */
364
0
        startPF = peTab[size - 1].bits2PeFactor[qualityIdx][nChannels - 1];
365
0
        stopPF = peTab[size - 1].bits2PeFactor[qualityIdx][nChannels - 1];
366
0
      } else {
367
0
        for (i = 0; i < size - 1; i++) {
368
0
          if ((peTab[i].bitrate <= bitRate) &&
369
0
              (peTab[i + 1].bitrate > bitRate)) {
370
0
            startB = peTab[i].bitrate;
371
0
            stopB = peTab[i + 1].bitrate;
372
0
            startPF = peTab[i].bits2PeFactor[qualityIdx][nChannels - 1];
373
0
            stopPF = peTab[i + 1].bits2PeFactor[qualityIdx][nChannels - 1];
374
0
            break;
375
0
          }
376
0
        }
377
0
      }
378
379
      /*** 2.2) Configuration available? ***/
380
0
      if (startB != -1) {
381
        /** 2.2.1) linear interpolate to actual PEfactor **/
382
0
        FIXP_DBL bit2PE = 0;
383
384
0
        const FIXP_DBL maxBit2PE = FL2FXCONST_DBL(3.f / 4.f);
385
386
        /* bit2PE = ((stopPF-startPF)/(stopB-startB))*(bitRate-startB)+startPF;
387
         */
388
0
        slope = fDivNorm(bitRate - startB, stopB - startB);
389
0
        bit2PE = fMult(slope, stopPF - startPF) + startPF;
390
391
0
        bit2PE = fMin(maxBit2PE, bit2PE);
392
393
        /** 2.2.2) sanity check if bits2pe value is high enough **/
394
0
        if (bit2PE >= (FL2FXCONST_DBL(0.35f) >> 2)) {
395
0
          bit2PE_m = bit2PE;
396
0
          bit2PE_e = 2; /*  table is fixed scaled */
397
0
        }
398
0
      } /* br */
399
0
    }   /* sr */
400
0
  }     /* advancedBitsToPe */
401
402
0
  if (dZoneQuantEnable) {
403
0
    if (bit2PE_m >= (FL2FXCONST_DBL(0.6f)) >> bit2PE_e) {
404
      /* Additional headroom for addition */
405
0
      bit2PE_m >>= 1;
406
0
      bit2PE_e += 1;
407
0
    }
408
409
    /* the quantTendencyCompensator compensates a lower bit consumption due to
410
     * increasing the tendency to quantize low spectral values to the lower
411
     * quantizer border for bitrates below a certain bitrate threshold --> see
412
     * also function calcSfbDistLD in quantize.c */
413
0
    if ((bitRate / nChannels > 32000) && (bitRate / nChannels <= 40000)) {
414
0
      bit2PE_m += (FL2FXCONST_DBL(0.4f)) >> bit2PE_e;
415
0
    } else if (bitRate / nChannels > 20000) {
416
0
      bit2PE_m += (FL2FXCONST_DBL(0.3f)) >> bit2PE_e;
417
0
    } else if (bitRate / nChannels >= 16000) {
418
0
      bit2PE_m += (FL2FXCONST_DBL(0.3f)) >> bit2PE_e;
419
0
    } else {
420
0
      bit2PE_m += (FL2FXCONST_DBL(0.0f)) >> bit2PE_e;
421
0
    }
422
0
  }
423
424
  /***** 3.) Return bits2pe factor *****/
425
0
  *bits2PeFactor_m = bit2PE_m;
426
0
  *bits2PeFactor_e = bit2PE_e;
427
0
}
428
429
/*****************************************************************************
430
functionname: FDKaacEnc_bits2pe2
431
description:  convert from bits to pe
432
*****************************************************************************/
433
FDK_INLINE INT FDKaacEnc_bits2pe2(const INT bits, const FIXP_DBL factor_m,
434
0
                                  const INT factor_e) {
435
0
  return (INT)(fMult(factor_m, (FIXP_DBL)(bits << Q_AVGBITS)) >>
436
0
               (Q_AVGBITS - factor_e));
437
0
}
438
439
/*****************************************************************************
440
functionname: FDKaacEnc_calcThreshExp
441
description:  loudness calculation (threshold to the power of redExp)
442
*****************************************************************************/
443
static void FDKaacEnc_calcThreshExp(
444
    FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB],
445
    const QC_OUT_CHANNEL *const qcOutChannel[(2)],
446
0
    const PSY_OUT_CHANNEL *const psyOutChannel[(2)], const INT nChannels) {
447
0
  INT ch, sfb, sfbGrp;
448
0
  FIXP_DBL thrExpLdData;
449
450
0
  for (ch = 0; ch < nChannels; ch++) {
451
0
    for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
452
0
         sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
453
0
      for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
454
0
        thrExpLdData = psyOutChannel[ch]->sfbThresholdLdData[sfbGrp + sfb] >> 2;
455
0
        thrExp[ch][sfbGrp + sfb] = CalcInvLdData(thrExpLdData);
456
0
      }
457
0
    }
458
0
  }
459
0
}
460
461
/*****************************************************************************
462
    functionname: FDKaacEnc_adaptMinSnr
463
    description:  reduce minSnr requirements for bands with relative low
464
energies
465
*****************************************************************************/
466
static void FDKaacEnc_adaptMinSnr(
467
    QC_OUT_CHANNEL *const qcOutChannel[(2)],
468
    const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
469
0
    const MINSNR_ADAPT_PARAM *const msaParam, const INT nChannels) {
470
0
  INT ch, sfb, sfbGrp, nSfb;
471
0
  FIXP_DBL avgEnLD64, dbRatio, minSnrRed;
472
0
  FIXP_DBL minSnrLimitLD64 =
473
0
      FL2FXCONST_DBL(-0.00503012648262f); /* ld64(0.8f) */
474
0
  FIXP_DBL nSfbLD64;
475
0
  FIXP_DBL accu;
476
477
0
  FIXP_DBL msaParam_maxRed = msaParam->maxRed;
478
0
  FIXP_DBL msaParam_startRatio = msaParam->startRatio;
479
0
  FIXP_DBL msaParam_redRatioFac =
480
0
      fMult(msaParam->redRatioFac, FL2FXCONST_DBL(0.3010299956f));
481
0
  FIXP_DBL msaParam_redOffs = msaParam->redOffs;
482
483
0
  for (ch = 0; ch < nChannels; ch++) {
484
    /* calc average energy per scalefactor band */
485
0
    nSfb = 0;
486
0
    accu = FL2FXCONST_DBL(0.0f);
487
488
0
    DWORD_ALIGNED(psyOutChannel[ch]->sfbEnergy);
489
490
0
    for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
491
0
         sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
492
0
      int maxSfbPerGroup = psyOutChannel[ch]->maxSfbPerGroup;
493
0
      nSfb += maxSfbPerGroup;
494
0
      for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
495
0
        accu += psyOutChannel[ch]->sfbEnergy[sfbGrp + sfb] >> 6;
496
0
      }
497
0
    }
498
499
0
    if ((accu == FL2FXCONST_DBL(0.0f)) || (nSfb == 0)) {
500
0
      avgEnLD64 = FL2FXCONST_DBL(-1.0f);
501
0
    } else {
502
0
      nSfbLD64 = CalcLdInt(nSfb);
503
0
      avgEnLD64 = CalcLdData(accu);
504
0
      avgEnLD64 = avgEnLD64 + FL2FXCONST_DBL(0.09375f) -
505
0
                  nSfbLD64; /* 0.09375f: compensate shift with 6 */
506
0
    }
507
508
    /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */
509
0
    int maxSfbPerGroup = psyOutChannel[ch]->maxSfbPerGroup;
510
0
    int sfbCnt = psyOutChannel[ch]->sfbCnt;
511
0
    int sfbPerGroup = psyOutChannel[ch]->sfbPerGroup;
512
513
0
    for (sfbGrp = 0; sfbGrp < sfbCnt; sfbGrp += sfbPerGroup) {
514
0
      FIXP_DBL *RESTRICT psfbEnergyLdData =
515
0
          &qcOutChannel[ch]->sfbEnergyLdData[sfbGrp];
516
0
      FIXP_DBL *RESTRICT psfbMinSnrLdData =
517
0
          &qcOutChannel[ch]->sfbMinSnrLdData[sfbGrp];
518
0
      for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
519
0
        FIXP_DBL sfbEnergyLdData = *psfbEnergyLdData++;
520
0
        FIXP_DBL sfbMinSnrLdData = *psfbMinSnrLdData;
521
0
        dbRatio = avgEnLD64 - sfbEnergyLdData;
522
0
        int update = (msaParam_startRatio < dbRatio) ? 1 : 0;
523
0
        minSnrRed = msaParam_redOffs + fMult(msaParam_redRatioFac,
524
0
                                             dbRatio); /* scaled by 1.0f/64.0f*/
525
0
        minSnrRed =
526
0
            fixMax(minSnrRed, msaParam_maxRed); /* scaled by 1.0f/64.0f*/
527
0
        minSnrRed = (fMult(sfbMinSnrLdData, minSnrRed)) << 6;
528
0
        minSnrRed = fixMin(minSnrLimitLD64, minSnrRed);
529
0
        *psfbMinSnrLdData++ = update ? minSnrRed : sfbMinSnrLdData;
530
0
      }
531
0
    }
532
0
  }
533
0
}
534
535
/*****************************************************************************
536
functionname: FDKaacEnc_initAvoidHoleFlag
537
description:  determine bands where avoid hole is not necessary resp. possible
538
*****************************************************************************/
539
static void FDKaacEnc_initAvoidHoleFlag(
540
    QC_OUT_CHANNEL *const qcOutChannel[(2)],
541
    const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
542
    UCHAR ahFlag[(2)][MAX_GROUPED_SFB], const struct TOOLSINFO *const toolsInfo,
543
0
    const INT nChannels, const AH_PARAM *const ahParam) {
544
0
  INT ch, sfb, sfbGrp;
545
0
  FIXP_DBL sfbEn, sfbEnm1;
546
0
  FIXP_DBL sfbEnLdData;
547
0
  FIXP_DBL avgEnLdData;
548
549
  /* decrease spread energy by 3dB for long blocks, resp. 2dB for shorts
550
     (avoid more holes in long blocks) */
551
0
  for (ch = 0; ch < nChannels; ch++) {
552
0
    QC_OUT_CHANNEL *const qcOutChan = qcOutChannel[ch];
553
554
0
    if (psyOutChannel[ch]->lastWindowSequence != SHORT_WINDOW) {
555
0
      for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
556
0
           sfbGrp += psyOutChannel[ch]->sfbPerGroup)
557
0
        for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++)
558
0
          qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] >>= 1;
559
0
    } else {
560
0
      for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
561
0
           sfbGrp += psyOutChannel[ch]->sfbPerGroup)
562
0
        for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++)
563
0
          qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] = fMult(
564
0
              FL2FXCONST_DBL(0.63f), qcOutChan->sfbSpreadEnergy[sfbGrp + sfb]);
565
0
    }
566
0
  }
567
568
  /* increase minSnr for local peaks, decrease it for valleys */
569
0
  if (ahParam->modifyMinSnr) {
570
0
    for (ch = 0; ch < nChannels; ch++) {
571
0
      QC_OUT_CHANNEL *const qcOutChan = qcOutChannel[ch];
572
0
      for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
573
0
           sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
574
0
        for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
575
0
          FIXP_DBL sfbEnp1, avgEn;
576
0
          if (sfb > 0)
577
0
            sfbEnm1 = qcOutChan->sfbEnergy[sfbGrp + sfb - 1];
578
0
          else
579
0
            sfbEnm1 = qcOutChan->sfbEnergy[sfbGrp + sfb];
580
581
0
          if (sfb < psyOutChannel[ch]->maxSfbPerGroup - 1)
582
0
            sfbEnp1 = qcOutChan->sfbEnergy[sfbGrp + sfb + 1];
583
0
          else
584
0
            sfbEnp1 = qcOutChan->sfbEnergy[sfbGrp + sfb];
585
586
0
          avgEn = (sfbEnm1 >> 1) + (sfbEnp1 >> 1);
587
0
          avgEnLdData = CalcLdData(avgEn);
588
0
          sfbEn = qcOutChan->sfbEnergy[sfbGrp + sfb];
589
0
          sfbEnLdData = qcOutChan->sfbEnergyLdData[sfbGrp + sfb];
590
          /* peak ? */
591
0
          if (sfbEn > avgEn) {
592
0
            FIXP_DBL tmpMinSnrLdData;
593
0
            if (psyOutChannel[ch]->lastWindowSequence == LONG_WINDOW)
594
0
              tmpMinSnrLdData = SnrLdFac + fixMax(avgEnLdData - sfbEnLdData,
595
0
                                                  SnrLdMin1 - SnrLdFac);
596
0
            else
597
0
              tmpMinSnrLdData = SnrLdFac + fixMax(avgEnLdData - sfbEnLdData,
598
0
                                                  SnrLdMin3 - SnrLdFac);
599
600
0
            qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] = fixMin(
601
0
                qcOutChan->sfbMinSnrLdData[sfbGrp + sfb], tmpMinSnrLdData);
602
0
          }
603
          /* valley ? */
604
0
          if (((sfbEnLdData + (FIXP_DBL)SnrLdMin4) < (FIXP_DBL)avgEnLdData) &&
605
0
              (sfbEn > FL2FXCONST_DBL(0.0))) {
606
0
            FIXP_DBL tmpMinSnrLdData = avgEnLdData - sfbEnLdData -
607
0
                                       (FIXP_DBL)SnrLdMin4 +
608
0
                                       qcOutChan->sfbMinSnrLdData[sfbGrp + sfb];
609
0
            tmpMinSnrLdData = fixMin((FIXP_DBL)SnrLdFac, tmpMinSnrLdData);
610
0
            qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] =
611
0
                fixMin(tmpMinSnrLdData,
612
0
                       (FIXP_DBL)(qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] +
613
0
                                  SnrLdMin2));
614
0
          }
615
0
        }
616
0
      }
617
0
    }
618
0
  }
619
620
  /* stereo: adapt the minimum requirements sfbMinSnr of mid and
621
     side channels to avoid spending unnoticable bits */
622
0
  if (nChannels == 2) {
623
0
    QC_OUT_CHANNEL *qcOutChanM = qcOutChannel[0];
624
0
    QC_OUT_CHANNEL *qcOutChanS = qcOutChannel[1];
625
0
    const PSY_OUT_CHANNEL *const psyOutChanM = psyOutChannel[0];
626
0
    for (sfbGrp = 0; sfbGrp < psyOutChanM->sfbCnt;
627
0
         sfbGrp += psyOutChanM->sfbPerGroup) {
628
0
      for (sfb = 0; sfb < psyOutChanM->maxSfbPerGroup; sfb++) {
629
0
        if (toolsInfo->msMask[sfbGrp + sfb]) {
630
0
          FIXP_DBL maxSfbEnLd =
631
0
              fixMax(qcOutChanM->sfbEnergyLdData[sfbGrp + sfb],
632
0
                     qcOutChanS->sfbEnergyLdData[sfbGrp + sfb]);
633
0
          FIXP_DBL maxThrLd, sfbMinSnrTmpLd;
634
635
0
          if (((SnrLdMin5 >> 1) + (maxSfbEnLd >> 1) +
636
0
               (qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] >> 1)) <=
637
0
              FL2FXCONST_DBL(-0.5f))
638
0
            maxThrLd = FL2FXCONST_DBL(-1.0f);
639
0
          else
640
0
            maxThrLd = SnrLdMin5 + maxSfbEnLd +
641
0
                       qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb];
642
643
0
          if (qcOutChanM->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f))
644
0
            sfbMinSnrTmpLd =
645
0
                maxThrLd - qcOutChanM->sfbEnergyLdData[sfbGrp + sfb];
646
0
          else
647
0
            sfbMinSnrTmpLd = FL2FXCONST_DBL(0.0f);
648
649
0
          qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] =
650
0
              fixMax(qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb], sfbMinSnrTmpLd);
651
652
0
          if (qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] <= FL2FXCONST_DBL(0.0f))
653
0
            qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] = fixMin(
654
0
                qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb], (FIXP_DBL)SnrLdFac);
655
656
0
          if (qcOutChanS->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f))
657
0
            sfbMinSnrTmpLd =
658
0
                maxThrLd - qcOutChanS->sfbEnergyLdData[sfbGrp + sfb];
659
0
          else
660
0
            sfbMinSnrTmpLd = FL2FXCONST_DBL(0.0f);
661
662
0
          qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] =
663
0
              fixMax(qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb], sfbMinSnrTmpLd);
664
665
0
          if (qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] <= FL2FXCONST_DBL(0.0f))
666
0
            qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] = fixMin(
667
0
                qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb], (FIXP_DBL)SnrLdFac);
668
669
0
          if (qcOutChanM->sfbEnergy[sfbGrp + sfb] >
670
0
              qcOutChanM->sfbSpreadEnergy[sfbGrp + sfb])
671
0
            qcOutChanS->sfbSpreadEnergy[sfbGrp + sfb] = fMult(
672
0
                qcOutChanS->sfbEnergy[sfbGrp + sfb], FL2FXCONST_DBL(0.9f));
673
674
0
          if (qcOutChanS->sfbEnergy[sfbGrp + sfb] >
675
0
              qcOutChanS->sfbSpreadEnergy[sfbGrp + sfb])
676
0
            qcOutChanM->sfbSpreadEnergy[sfbGrp + sfb] = fMult(
677
0
                qcOutChanM->sfbEnergy[sfbGrp + sfb], FL2FXCONST_DBL(0.9f));
678
679
0
        } /* if (toolsInfo->msMask[sfbGrp+sfb]) */
680
0
      }   /* sfb */
681
0
    }     /* sfbGrp */
682
0
  }       /* nChannels==2 */
683
684
  /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
685
0
  for (ch = 0; ch < nChannels; ch++) {
686
0
    QC_OUT_CHANNEL *qcOutChan = qcOutChannel[ch];
687
0
    const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch];
688
0
    for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
689
0
         sfbGrp += psyOutChan->sfbPerGroup) {
690
0
      for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
691
0
        if ((qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] >
692
0
             qcOutChan->sfbEnergy[sfbGrp + sfb]) ||
693
0
            (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f))) {
694
0
          ahFlag[ch][sfbGrp + sfb] = NO_AH;
695
0
        } else {
696
0
          ahFlag[ch][sfbGrp + sfb] = AH_INACTIVE;
697
0
        }
698
0
      }
699
0
    }
700
0
  }
701
0
}
702
703
/**
704
 * \brief  Calculate constants that do not change during successive pe
705
 * calculations.
706
 *
707
 * \param peData                Pointer to structure containing PE data of
708
 * current element.
709
 * \param psyOutChannel         Pointer to PSY_OUT_CHANNEL struct holding
710
 * nChannels elements.
711
 * \param qcOutChannel          Pointer to QC_OUT_CHANNEL struct holding
712
 * nChannels elements.
713
 * \param nChannels             Number of channels in element.
714
 * \param peOffset              Fixed PE offset defined while
715
 * FDKaacEnc_AdjThrInit() depending on bitrate.
716
 *
717
 * \return  void
718
 */
719
static void FDKaacEnc_preparePe(PE_DATA *const peData,
720
                                const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
721
                                const QC_OUT_CHANNEL *const qcOutChannel[(2)],
722
0
                                const INT nChannels, const INT peOffset) {
723
0
  INT ch;
724
725
0
  for (ch = 0; ch < nChannels; ch++) {
726
0
    const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch];
727
0
    FDKaacEnc_prepareSfbPe(
728
0
        &peData->peChannelData[ch], psyOutChan->sfbEnergyLdData,
729
0
        psyOutChan->sfbThresholdLdData, qcOutChannel[ch]->sfbFormFactorLdData,
730
0
        psyOutChan->sfbOffsets, psyOutChan->sfbCnt, psyOutChan->sfbPerGroup,
731
0
        psyOutChan->maxSfbPerGroup);
732
0
  }
733
0
  peData->offset = peOffset;
734
0
}
735
736
/**
737
 * \brief  Calculate weighting factor for threshold adjustment.
738
 *
739
 * Calculate weighting factor to be applied at energies and thresholds in ld64
740
 * format.
741
 *
742
 * \param peData,               Pointer to PE data in current element.
743
 * \param psyOutChannel         Pointer to PSY_OUT_CHANNEL struct holding
744
 * nChannels elements.
745
 * \param qcOutChannel          Pointer to QC_OUT_CHANNEL struct holding
746
 * nChannels elements.
747
 * \param toolsInfo             Pointer to tools info struct of current element.
748
 * \param adjThrStateElement    Pointer to ATS_ELEMENT holding enFacPatch
749
 * states.
750
 * \param nChannels             Number of channels in element.
751
 * \param usePatchTool          Apply the weighting tool 0 (no) else (yes).
752
 *
753
 * \return  void
754
 */
755
static void FDKaacEnc_calcWeighting(
756
    const PE_DATA *const peData,
757
    const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
758
    QC_OUT_CHANNEL *const qcOutChannel[(2)],
759
    const struct TOOLSINFO *const toolsInfo,
760
    ATS_ELEMENT *const adjThrStateElement, const INT nChannels,
761
0
    const INT usePatchTool) {
762
0
  int ch, noShortWindowInFrame = TRUE;
763
0
  INT exePatchM = 0;
764
765
0
  for (ch = 0; ch < nChannels; ch++) {
766
0
    if (psyOutChannel[ch]->lastWindowSequence == SHORT_WINDOW) {
767
0
      noShortWindowInFrame = FALSE;
768
0
    }
769
0
    FDKmemclear(qcOutChannel[ch]->sfbEnFacLd,
770
0
                MAX_GROUPED_SFB * sizeof(FIXP_DBL));
771
0
  }
772
773
0
  if (usePatchTool == 0) {
774
0
    return; /* tool is disabled */
775
0
  }
776
777
0
  for (ch = 0; ch < nChannels; ch++) {
778
0
    const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch];
779
780
0
    if (noShortWindowInFrame) { /* retain energy ratio between blocks of
781
                                   different length */
782
783
0
      FIXP_DBL nrgSum14, nrgSum12, nrgSum34, nrgTotal;
784
0
      FIXP_DBL nrgFacLd_14, nrgFacLd_12, nrgFacLd_34;
785
0
      INT usePatch, exePatch;
786
0
      int sfb, sfbGrp, nLinesSum = 0;
787
788
0
      nrgSum14 = nrgSum12 = nrgSum34 = nrgTotal = FL2FXCONST_DBL(0.f);
789
790
      /* calculate flatness of audible spectrum, i.e. spectrum above masking
791
       * threshold. */
792
0
      for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
793
0
           sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
794
0
        for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
795
0
          FIXP_DBL nrgFac12 = CalcInvLdData(
796
0
              psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1); /* nrg^(1/2) */
797
0
          FIXP_DBL nrgFac14 = CalcInvLdData(
798
0
              psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 2); /* nrg^(1/4) */
799
800
          /* maximal number of bands is 64, results scaling factor 6 */
801
0
          nLinesSum += peData->peChannelData[ch]
802
0
                           .sfbNLines[sfbGrp + sfb]; /* relevant lines */
803
0
          nrgTotal +=
804
0
              (psyOutChan->sfbEnergy[sfbGrp + sfb] >> 6); /* sum up nrg */
805
0
          nrgSum12 += (nrgFac12 >> 6);                    /* sum up nrg^(2/4) */
806
0
          nrgSum14 += (nrgFac14 >> 6);                    /* sum up nrg^(1/4) */
807
0
          nrgSum34 += (fMult(nrgFac14, nrgFac12) >> 6);   /* sum up nrg^(3/4) */
808
0
        }
809
0
      }
810
811
0
      nrgTotal = CalcLdData(nrgTotal); /* get ld64 of total nrg */
812
813
0
      nrgFacLd_14 =
814
0
          CalcLdData(nrgSum14) - nrgTotal; /* ld64(nrgSum14/nrgTotal) */
815
0
      nrgFacLd_12 =
816
0
          CalcLdData(nrgSum12) - nrgTotal; /* ld64(nrgSum12/nrgTotal) */
817
0
      nrgFacLd_34 =
818
0
          CalcLdData(nrgSum34) - nrgTotal; /* ld64(nrgSum34/nrgTotal) */
819
820
      /* Note: nLinesSum cannot be larger than the number of total lines, thats
821
       * taken care of in line_pe.cpp FDKaacEnc_prepareSfbPe() */
822
0
      adjThrStateElement->chaosMeasureEnFac[ch] =
823
0
          fMax(FL2FXCONST_DBL(0.1875f),
824
0
               fDivNorm(nLinesSum, psyOutChan->sfbOffsets[psyOutChan->sfbCnt]));
825
826
0
      usePatch = (adjThrStateElement->chaosMeasureEnFac[ch] >
827
0
                  FL2FXCONST_DBL(0.78125f));
828
0
      exePatch = ((usePatch) && (adjThrStateElement->lastEnFacPatch[ch]));
829
830
0
      for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
831
0
           sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
832
0
        for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
833
0
          INT sfbExePatch;
834
          /* for MS coupled SFBs, also execute patch in side channel if done in
835
           * mid channel */
836
0
          if ((ch == 1) && (toolsInfo->msMask[sfbGrp + sfb])) {
837
0
            sfbExePatch = exePatchM;
838
0
          } else {
839
0
            sfbExePatch = exePatch;
840
0
          }
841
842
0
          if ((sfbExePatch) &&
843
0
              (psyOutChan->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.f))) {
844
            /* execute patch based on spectral flatness calculated above */
845
0
            if (adjThrStateElement->chaosMeasureEnFac[ch] >
846
0
                FL2FXCONST_DBL(0.8125f)) {
847
0
              qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] =
848
0
                  ((nrgFacLd_14 +
849
0
                    (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] +
850
0
                     (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1))) >>
851
0
                   1); /* sfbEnergy^(3/4) */
852
0
            } else if (adjThrStateElement->chaosMeasureEnFac[ch] >
853
0
                       FL2FXCONST_DBL(0.796875f)) {
854
0
              qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] =
855
0
                  ((nrgFacLd_12 + psyOutChan->sfbEnergyLdData[sfbGrp + sfb]) >>
856
0
                   1); /* sfbEnergy^(2/4) */
857
0
            } else {
858
0
              qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] =
859
0
                  ((nrgFacLd_34 +
860
0
                    (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1)) >>
861
0
                   1); /* sfbEnergy^(1/4) */
862
0
            }
863
0
            qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] =
864
0
                fixMin(qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb], (FIXP_DBL)0);
865
0
          }
866
0
        }
867
0
      } /* sfb loop */
868
869
0
      adjThrStateElement->lastEnFacPatch[ch] = usePatch;
870
0
      exePatchM = exePatch;
871
0
    } else {
872
      /* !noShortWindowInFrame */
873
0
      adjThrStateElement->chaosMeasureEnFac[ch] = FL2FXCONST_DBL(0.75f);
874
0
      adjThrStateElement->lastEnFacPatch[ch] =
875
0
          TRUE; /* allow use of sfbEnFac patch in upcoming frame */
876
0
    }
877
878
0
  } /* ch loop */
879
0
}
880
881
/*****************************************************************************
882
functionname: FDKaacEnc_calcPe
883
description:  calculate pe for both channels
884
*****************************************************************************/
885
static void FDKaacEnc_calcPe(const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
886
                             const QC_OUT_CHANNEL *const qcOutChannel[(2)],
887
0
                             PE_DATA *const peData, const INT nChannels) {
888
0
  INT ch;
889
890
0
  peData->pe = peData->offset;
891
0
  peData->constPart = 0;
892
0
  peData->nActiveLines = 0;
893
0
  for (ch = 0; ch < nChannels; ch++) {
894
0
    PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch];
895
896
0
    FDKaacEnc_calcSfbPe(
897
0
        peChanData, qcOutChannel[ch]->sfbWeightedEnergyLdData,
898
0
        qcOutChannel[ch]->sfbThresholdLdData, psyOutChannel[ch]->sfbCnt,
899
0
        psyOutChannel[ch]->sfbPerGroup, psyOutChannel[ch]->maxSfbPerGroup,
900
0
        psyOutChannel[ch]->isBook, psyOutChannel[ch]->isScale);
901
902
0
    peData->pe += peChanData->pe;
903
0
    peData->constPart += peChanData->constPart;
904
0
    peData->nActiveLines += peChanData->nActiveLines;
905
0
  }
906
0
}
907
908
void FDKaacEnc_peCalculation(PE_DATA *const peData,
909
                             const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
910
                             QC_OUT_CHANNEL *const qcOutChannel[(2)],
911
                             const struct TOOLSINFO *const toolsInfo,
912
                             ATS_ELEMENT *const adjThrStateElement,
913
0
                             const INT nChannels) {
914
  /* constants that will not change during successive pe calculations */
915
0
  FDKaacEnc_preparePe(peData, psyOutChannel, qcOutChannel, nChannels,
916
0
                      adjThrStateElement->peOffset);
917
918
  /* calculate weighting factor for threshold adjustment */
919
0
  FDKaacEnc_calcWeighting(peData, psyOutChannel, qcOutChannel, toolsInfo,
920
0
                          adjThrStateElement, nChannels, 1);
921
0
  {
922
    /* no weighting of threholds and energies for mlout */
923
    /* weight energies and thresholds */
924
0
    int ch;
925
0
    for (ch = 0; ch < nChannels; ch++) {
926
0
      int sfb, sfbGrp;
927
0
      QC_OUT_CHANNEL *pQcOutCh = qcOutChannel[ch];
928
929
0
      for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
930
0
           sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
931
0
        for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
932
0
          pQcOutCh->sfbWeightedEnergyLdData[sfb + sfbGrp] =
933
0
              pQcOutCh->sfbEnergyLdData[sfb + sfbGrp] -
934
0
              pQcOutCh->sfbEnFacLd[sfb + sfbGrp];
935
0
          pQcOutCh->sfbThresholdLdData[sfb + sfbGrp] -=
936
0
              pQcOutCh->sfbEnFacLd[sfb + sfbGrp];
937
0
        }
938
0
      }
939
0
    }
940
0
  }
941
942
  /* pe without reduction */
943
0
  FDKaacEnc_calcPe(psyOutChannel, qcOutChannel, peData, nChannels);
944
0
}
945
946
/*****************************************************************************
947
functionname: FDKaacEnc_FDKaacEnc_calcPeNoAH
948
description:  sum the pe data only for bands where avoid hole is inactive
949
*****************************************************************************/
950
0
#define CONSTPART_HEADROOM 4
951
static void FDKaacEnc_FDKaacEnc_calcPeNoAH(
952
    INT *const pe, INT *const constPart, INT *const nActiveLines,
953
    const PE_DATA *const peData, const UCHAR ahFlag[(2)][MAX_GROUPED_SFB],
954
0
    const PSY_OUT_CHANNEL *const psyOutChannel[(2)], const INT nChannels) {
955
0
  INT ch, sfb, sfbGrp;
956
957
0
  INT pe_tmp = peData->offset;
958
0
  INT constPart_tmp = 0;
959
0
  INT nActiveLines_tmp = 0;
960
0
  for (ch = 0; ch < nChannels; ch++) {
961
0
    const PE_CHANNEL_DATA *const peChanData = &peData->peChannelData[ch];
962
0
    for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
963
0
         sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
964
0
      for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
965
0
        if (ahFlag[ch][sfbGrp + sfb] < AH_ACTIVE) {
966
0
          pe_tmp += peChanData->sfbPe[sfbGrp + sfb];
967
0
          constPart_tmp +=
968
0
              peChanData->sfbConstPart[sfbGrp + sfb] >> CONSTPART_HEADROOM;
969
0
          nActiveLines_tmp += peChanData->sfbNActiveLines[sfbGrp + sfb];
970
0
        }
971
0
      }
972
0
    }
973
0
  }
974
  /* correct scaled pe and constPart values */
975
0
  *pe = pe_tmp >> PE_CONSTPART_SHIFT;
976
0
  *constPart = constPart_tmp >> (PE_CONSTPART_SHIFT - CONSTPART_HEADROOM);
977
978
0
  *nActiveLines = nActiveLines_tmp;
979
0
}
980
981
/*****************************************************************************
982
functionname: FDKaacEnc_reduceThresholdsCBR
983
description:  apply reduction formula
984
*****************************************************************************/
985
static const FIXP_DBL limitThrReducedLdData =
986
    (FIXP_DBL)0x00008000; /*FL2FXCONST_DBL(FDKpow(2.0,-LD_DATA_SCALING/4.0));*/
987
988
static void FDKaacEnc_reduceThresholdsCBR(
989
    QC_OUT_CHANNEL *const qcOutChannel[(2)],
990
    const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
991
    UCHAR ahFlag[(2)][MAX_GROUPED_SFB],
992
    const FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], const INT nChannels,
993
0
    const FIXP_DBL redVal_m, const SCHAR redVal_e) {
994
0
  INT ch, sfb, sfbGrp;
995
0
  FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData;
996
0
  FIXP_DBL sfbThrExp;
997
998
0
  for (ch = 0; ch < nChannels; ch++) {
999
0
    QC_OUT_CHANNEL *qcOutChan = qcOutChannel[ch];
1000
0
    for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
1001
0
         sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
1002
0
      for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
1003
0
        sfbEnLdData = qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb];
1004
0
        sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp + sfb];
1005
0
        sfbThrExp = thrExp[ch][sfbGrp + sfb];
1006
0
        if ((sfbEnLdData > sfbThrLdData) &&
1007
0
            (ahFlag[ch][sfbGrp + sfb] != AH_ACTIVE)) {
1008
          /* threshold reduction formula:
1009
           float tmp = thrExp[ch][sfb]+redVal;
1010
           tmp *= tmp;
1011
           sfbThrReduced = tmp*tmp;
1012
          */
1013
0
          int minScale = fixMin(CountLeadingBits(sfbThrExp),
1014
0
                                CountLeadingBits(redVal_m) - redVal_e) -
1015
0
                         1;
1016
1017
          /* 4*log( sfbThrExp + redVal ) */
1018
0
          sfbThrReducedLdData =
1019
0
              CalcLdData(fAbs(scaleValue(sfbThrExp, minScale) +
1020
0
                              scaleValue(redVal_m, redVal_e + minScale))) -
1021
0
              (FIXP_DBL)(minScale << (DFRACT_BITS - 1 - LD_DATA_SHIFT));
1022
0
          sfbThrReducedLdData <<= 2;
1023
1024
          /* avoid holes */
1025
0
          if ((sfbThrReducedLdData >
1026
0
               (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData)) &&
1027
0
              (ahFlag[ch][sfbGrp + sfb] != NO_AH)) {
1028
0
            if (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] >
1029
0
                (FL2FXCONST_DBL(-1.0f) - sfbEnLdData)) {
1030
0
              sfbThrReducedLdData = fixMax(
1031
0
                  (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData),
1032
0
                  sfbThrLdData);
1033
0
            } else
1034
0
              sfbThrReducedLdData = sfbThrLdData;
1035
0
            ahFlag[ch][sfbGrp + sfb] = AH_ACTIVE;
1036
0
          }
1037
1038
          /* minimum of 29 dB Ratio for Thresholds */
1039
0
          if ((sfbEnLdData + (FIXP_DBL)MAXVAL_DBL) >
1040
0
              FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING)) {
1041
0
            sfbThrReducedLdData = fixMax(
1042
0
                sfbThrReducedLdData,
1043
0
                (sfbEnLdData - FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING)));
1044
0
          }
1045
1046
0
          qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData;
1047
0
        }
1048
0
      }
1049
0
    }
1050
0
  }
1051
0
}
1052
1053
/* similar to prepareSfbPe1() */
1054
static FIXP_DBL FDKaacEnc_calcChaosMeasure(
1055
    const PSY_OUT_CHANNEL *const psyOutChannel,
1056
0
    const FIXP_DBL *const sfbFormFactorLdData) {
1057
0
#define SCALE_FORM_FAC \
1058
0
  (4) /* (SCALE_FORM_FAC+FORM_FAC_SHIFT) >= ld(FRAME_LENGTH)*/
1059
0
#define SCALE_NRGS (8)
1060
0
#define SCALE_NLINES (16)
1061
0
#define SCALE_NRGS_SQRT4 (2)  /* 0.25 * SCALE_NRGS */
1062
0
#define SCALE_NLINES_P34 (12) /* 0.75 * SCALE_NLINES */
1063
1064
0
  INT sfbGrp, sfb;
1065
0
  FIXP_DBL chaosMeasure;
1066
0
  INT frameNLines = 0;
1067
0
  FIXP_DBL frameFormFactor = FL2FXCONST_DBL(0.f);
1068
0
  FIXP_DBL frameEnergy = FL2FXCONST_DBL(0.f);
1069
1070
0
  for (sfbGrp = 0; sfbGrp < psyOutChannel->sfbCnt;
1071
0
       sfbGrp += psyOutChannel->sfbPerGroup) {
1072
0
    for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) {
1073
0
      if (psyOutChannel->sfbEnergyLdData[sfbGrp + sfb] >
1074
0
          psyOutChannel->sfbThresholdLdData[sfbGrp + sfb]) {
1075
0
        frameFormFactor += (CalcInvLdData(sfbFormFactorLdData[sfbGrp + sfb]) >>
1076
0
                            SCALE_FORM_FAC);
1077
0
        frameNLines += (psyOutChannel->sfbOffsets[sfbGrp + sfb + 1] -
1078
0
                        psyOutChannel->sfbOffsets[sfbGrp + sfb]);
1079
0
        frameEnergy += (psyOutChannel->sfbEnergy[sfbGrp + sfb] >> SCALE_NRGS);
1080
0
      }
1081
0
    }
1082
0
  }
1083
1084
0
  if (frameNLines > 0) {
1085
    /*  frameNActiveLines = frameFormFactor*2^FORM_FAC_SHIFT * ((frameEnergy
1086
       *2^SCALE_NRGS)/frameNLines)^-0.25 chaosMeasure      = frameNActiveLines /
1087
       frameNLines */
1088
0
    chaosMeasure = CalcInvLdData(
1089
0
        (((CalcLdData(frameFormFactor) >> 1) -
1090
0
          (CalcLdData(frameEnergy) >> (2 + 1))) -
1091
0
         (fMultDiv2(FL2FXCONST_DBL(0.75f),
1092
0
                    CalcLdData((FIXP_DBL)frameNLines
1093
0
                               << (DFRACT_BITS - 1 - SCALE_NLINES))) -
1094
0
          (((FIXP_DBL)(-((-SCALE_FORM_FAC + SCALE_NRGS_SQRT4 - FORM_FAC_SHIFT +
1095
0
                          SCALE_NLINES_P34)
1096
0
                         << (DFRACT_BITS - 1 - LD_DATA_SHIFT)))) >>
1097
0
           1)))
1098
0
        << 1);
1099
0
  } else {
1100
    /* assuming total chaos, if no sfb is above thresholds */
1101
0
    chaosMeasure = FL2FXCONST_DBL(1.f);
1102
0
  }
1103
1104
0
  return chaosMeasure;
1105
0
}
1106
1107
/* apply reduction formula for VBR-mode */
1108
static void FDKaacEnc_reduceThresholdsVBR(
1109
    QC_OUT_CHANNEL *const qcOutChannel[(2)],
1110
    const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
1111
    UCHAR ahFlag[(2)][MAX_GROUPED_SFB],
1112
    const FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], const INT nChannels,
1113
0
    const FIXP_DBL vbrQualFactor, FIXP_DBL *const chaosMeasureOld) {
1114
0
  INT ch, sfbGrp, sfb;
1115
0
  FIXP_DBL chGroupEnergy[TRANS_FAC][2]; /*energy for each group and channel*/
1116
0
  FIXP_DBL chChaosMeasure[2];
1117
0
  FIXP_DBL frameEnergy = FL2FXCONST_DBL(1e-10f);
1118
0
  FIXP_DBL chaosMeasure = FL2FXCONST_DBL(0.f);
1119
0
  FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrExp;
1120
0
  FIXP_DBL sfbThrReducedLdData;
1121
0
  FIXP_DBL chaosMeasureAvg;
1122
0
  INT groupCnt;               /* loop counter */
1123
0
  FIXP_DBL redVal[TRANS_FAC]; /* reduction values; in short-block case one
1124
                                 redVal for each group */
1125
0
  QC_OUT_CHANNEL *qcOutChan = NULL;
1126
0
  const PSY_OUT_CHANNEL *psyOutChan = NULL;
1127
1128
0
#define SCALE_GROUP_ENERGY (8)
1129
1130
0
#define CONST_CHAOS_MEAS_AVG_FAC_0 (FL2FXCONST_DBL(0.25f))
1131
0
#define CONST_CHAOS_MEAS_AVG_FAC_1 (FL2FXCONST_DBL(1.f - 0.25f))
1132
1133
0
#define MIN_LDTHRESH (FL2FXCONST_DBL(-0.515625f))
1134
1135
0
  for (ch = 0; ch < nChannels; ch++) {
1136
0
    psyOutChan = psyOutChannel[ch];
1137
1138
    /* adding up energy for each channel and each group separately */
1139
0
    FIXP_DBL chEnergy = FL2FXCONST_DBL(0.f);
1140
0
    groupCnt = 0;
1141
1142
0
    for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
1143
0
         sfbGrp += psyOutChan->sfbPerGroup, groupCnt++) {
1144
0
      chGroupEnergy[groupCnt][ch] = FL2FXCONST_DBL(0.f);
1145
0
      for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
1146
0
        chGroupEnergy[groupCnt][ch] +=
1147
0
            (psyOutChan->sfbEnergy[sfbGrp + sfb] >> SCALE_GROUP_ENERGY);
1148
0
      }
1149
0
      chEnergy += chGroupEnergy[groupCnt][ch];
1150
0
    }
1151
0
    frameEnergy += chEnergy;
1152
1153
    /* chaosMeasure */
1154
0
    if (psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) {
1155
0
      chChaosMeasure[ch] = FL2FXCONST_DBL(
1156
0
          0.5f); /* assume a constant chaos measure of 0.5f for short blocks */
1157
0
    } else {
1158
0
      chChaosMeasure[ch] = FDKaacEnc_calcChaosMeasure(
1159
0
          psyOutChannel[ch], qcOutChannel[ch]->sfbFormFactorLdData);
1160
0
    }
1161
0
    chaosMeasure += fMult(chChaosMeasure[ch], chEnergy);
1162
0
  }
1163
1164
0
  if (frameEnergy > chaosMeasure) {
1165
0
    INT scale = CntLeadingZeros(frameEnergy) - 1;
1166
0
    FIXP_DBL num = chaosMeasure << scale;
1167
0
    FIXP_DBL denum = frameEnergy << scale;
1168
0
    chaosMeasure = schur_div(num, denum, 16);
1169
0
  } else {
1170
0
    chaosMeasure = FL2FXCONST_DBL(1.f);
1171
0
  }
1172
1173
0
  chaosMeasureAvg = fMult(CONST_CHAOS_MEAS_AVG_FAC_0, chaosMeasure) +
1174
0
                    fMult(CONST_CHAOS_MEAS_AVG_FAC_1,
1175
0
                          *chaosMeasureOld); /* averaging chaos measure */
1176
0
  *chaosMeasureOld = chaosMeasure = (fixMin(
1177
0
      chaosMeasure, chaosMeasureAvg)); /* use min-value, safe for next frame */
1178
1179
  /* characteristic curve
1180
     chaosMeasure = 0.2f + 0.7f/0.3f * (chaosMeasure - 0.2f);
1181
     chaosMeasure = fixMin(1.0f, fixMax(0.1f, chaosMeasure));
1182
     constants scaled by 4.f
1183
  */
1184
0
  chaosMeasure = ((FL2FXCONST_DBL(0.2f) >> 2) +
1185
0
                  fMult(FL2FXCONST_DBL(0.7f / (4.f * 0.3f)),
1186
0
                        (chaosMeasure - FL2FXCONST_DBL(0.2f))));
1187
0
  chaosMeasure =
1188
0
      (fixMin((FIXP_DBL)(FL2FXCONST_DBL(1.0f) >> 2),
1189
0
              fixMax((FIXP_DBL)(FL2FXCONST_DBL(0.1f) >> 2), chaosMeasure)))
1190
0
      << 2;
1191
1192
  /* calculation of reduction value */
1193
0
  if (psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) { /* short-blocks */
1194
0
    FDK_ASSERT(TRANS_FAC == 8);
1195
0
#define WIN_TYPE_SCALE (3)
1196
1197
0
    groupCnt = 0;
1198
0
    for (sfbGrp = 0; sfbGrp < psyOutChannel[0]->sfbCnt;
1199
0
         sfbGrp += psyOutChannel[0]->sfbPerGroup, groupCnt++) {
1200
0
      FIXP_DBL groupEnergy = FL2FXCONST_DBL(0.f);
1201
1202
0
      for (ch = 0; ch < nChannels; ch++) {
1203
0
        groupEnergy +=
1204
0
            chGroupEnergy[groupCnt]
1205
0
                         [ch]; /* adding up the channels groupEnergy */
1206
0
      }
1207
1208
0
      FDK_ASSERT(psyOutChannel[0]->groupLen[groupCnt] <= INV_INT_TAB_SIZE);
1209
0
      groupEnergy = fMult(
1210
0
          groupEnergy,
1211
0
          invInt[psyOutChannel[0]->groupLen[groupCnt]]); /* correction of
1212
                                                            group energy */
1213
0
      groupEnergy = fixMin(groupEnergy,
1214
0
                           frameEnergy >> WIN_TYPE_SCALE); /* do not allow an
1215
                                                              higher redVal as
1216
                                                              calculated
1217
                                                              framewise */
1218
1219
0
      groupEnergy >>=
1220
0
          2; /* 2*WIN_TYPE_SCALE = 6 => 6+2 = 8 ==> 8/4 = int number */
1221
1222
0
      redVal[groupCnt] =
1223
0
          fMult(fMult(vbrQualFactor, chaosMeasure),
1224
0
                CalcInvLdData(CalcLdData(groupEnergy) >> 2))
1225
0
          << (int)((2 + (2 * WIN_TYPE_SCALE) + SCALE_GROUP_ENERGY) >> 2);
1226
0
    }
1227
0
  } else { /* long-block */
1228
1229
0
    redVal[0] = fMult(fMult(vbrQualFactor, chaosMeasure),
1230
0
                      CalcInvLdData(CalcLdData(frameEnergy) >> 2))
1231
0
                << (int)(SCALE_GROUP_ENERGY >> 2);
1232
0
  }
1233
1234
0
  for (ch = 0; ch < nChannels; ch++) {
1235
0
    qcOutChan = qcOutChannel[ch];
1236
0
    psyOutChan = psyOutChannel[ch];
1237
1238
0
    for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
1239
0
         sfbGrp += psyOutChan->sfbPerGroup) {
1240
0
      for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
1241
0
        sfbEnLdData = (qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb]);
1242
0
        sfbThrLdData = (qcOutChan->sfbThresholdLdData[sfbGrp + sfb]);
1243
0
        sfbThrExp = thrExp[ch][sfbGrp + sfb];
1244
1245
0
        if ((sfbThrLdData >= MIN_LDTHRESH) && (sfbEnLdData > sfbThrLdData) &&
1246
0
            (ahFlag[ch][sfbGrp + sfb] != AH_ACTIVE)) {
1247
          /* Short-Window */
1248
0
          if (psyOutChannel[ch]->lastWindowSequence == SHORT_WINDOW) {
1249
0
            const int groupNumber = (int)sfb / psyOutChan->sfbPerGroup;
1250
1251
0
            FDK_ASSERT(INV_SQRT4_TAB_SIZE > psyOutChan->groupLen[groupNumber]);
1252
1253
0
            sfbThrExp =
1254
0
                fMult(sfbThrExp,
1255
0
                      fMult(FL2FXCONST_DBL(2.82f / 4.f),
1256
0
                            invSqrt4[psyOutChan->groupLen[groupNumber]]))
1257
0
                << 2;
1258
1259
0
            if (sfbThrExp <= (limitThrReducedLdData - redVal[groupNumber])) {
1260
0
              sfbThrReducedLdData = FL2FXCONST_DBL(-1.0f);
1261
0
            } else {
1262
0
              if ((FIXP_DBL)redVal[groupNumber] >=
1263
0
                  FL2FXCONST_DBL(1.0f) - sfbThrExp)
1264
0
                sfbThrReducedLdData = FL2FXCONST_DBL(0.0f);
1265
0
              else {
1266
                /* threshold reduction formula */
1267
0
                sfbThrReducedLdData =
1268
0
                    CalcLdData(sfbThrExp + redVal[groupNumber]);
1269
0
                sfbThrReducedLdData <<= 2;
1270
0
              }
1271
0
            }
1272
0
            sfbThrReducedLdData +=
1273
0
                (CalcLdInt(psyOutChan->groupLen[groupNumber]) -
1274
0
                 ((FIXP_DBL)6 << (DFRACT_BITS - 1 - LD_DATA_SHIFT)));
1275
0
          }
1276
1277
          /* Long-Window */
1278
0
          else {
1279
0
            if ((FIXP_DBL)redVal[0] >= FL2FXCONST_DBL(1.0f) - sfbThrExp) {
1280
0
              sfbThrReducedLdData = FL2FXCONST_DBL(0.0f);
1281
0
            } else {
1282
              /* threshold reduction formula */
1283
0
              sfbThrReducedLdData = CalcLdData(sfbThrExp + redVal[0]);
1284
0
              sfbThrReducedLdData <<= 2;
1285
0
            }
1286
0
          }
1287
1288
          /* avoid holes */
1289
0
          if (((sfbThrReducedLdData - sfbEnLdData) >
1290
0
               qcOutChan->sfbMinSnrLdData[sfbGrp + sfb]) &&
1291
0
              (ahFlag[ch][sfbGrp + sfb] != NO_AH)) {
1292
0
            if (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] >
1293
0
                (FL2FXCONST_DBL(-1.0f) - sfbEnLdData)) {
1294
0
              sfbThrReducedLdData = fixMax(
1295
0
                  (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData),
1296
0
                  sfbThrLdData);
1297
0
            } else
1298
0
              sfbThrReducedLdData = sfbThrLdData;
1299
0
            ahFlag[ch][sfbGrp + sfb] = AH_ACTIVE;
1300
0
          }
1301
1302
0
          if (sfbThrReducedLdData < FL2FXCONST_DBL(-0.5f))
1303
0
            sfbThrReducedLdData = FL2FXCONST_DBL(-1.f);
1304
1305
0
          sfbThrReducedLdData = fixMax(MIN_LDTHRESH, sfbThrReducedLdData);
1306
1307
0
          qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData;
1308
0
        }
1309
0
      }
1310
0
    }
1311
0
  }
1312
0
}
1313
1314
/*****************************************************************************
1315
functionname: FDKaacEnc_correctThresh
1316
description:  if pe difference deltaPe between desired pe and real pe is small
1317
enough, the difference can be distributed among the scale factor bands. New
1318
thresholds can be derived from this pe-difference
1319
*****************************************************************************/
1320
static void FDKaacEnc_correctThresh(
1321
    const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
1322
    const PSY_OUT_ELEMENT *const psyOutElement[((8))],
1323
    UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB],
1324
    const FIXP_DBL thrExp[((8))][(2)][MAX_GROUPED_SFB], const FIXP_DBL redVal_m,
1325
    const SCHAR redVal_e, const INT deltaPe, const INT processElements,
1326
0
    const INT elementOffset) {
1327
0
  INT ch, sfb, sfbGrp;
1328
0
  QC_OUT_CHANNEL *qcOutChan;
1329
0
  PSY_OUT_CHANNEL *psyOutChan;
1330
0
  PE_CHANNEL_DATA *peChanData;
1331
0
  FIXP_DBL thrFactorLdData;
1332
0
  FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData;
1333
0
  FIXP_DBL *sfbPeFactorsLdData[((8))][(2)];
1334
0
  FIXP_DBL(*sfbNActiveLinesLdData)[(2)][MAX_GROUPED_SFB];
1335
1336
0
  INT normFactorInt;
1337
0
  FIXP_DBL normFactorLdData;
1338
1339
0
  INT nElements = elementOffset + processElements;
1340
0
  INT elementId;
1341
1342
  /* scratch is empty; use temporal memory from quantSpec in QC_OUT_CHANNEL */
1343
0
  for (elementId = elementOffset; elementId < nElements; elementId++) {
1344
0
    for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1345
      /* The reinterpret_cast is used to suppress a compiler warning. We know
1346
       * that qcElement[elementId]->qcOutChannel[ch]->quantSpec is sufficiently
1347
       * aligned, so the cast is safe */
1348
0
      sfbPeFactorsLdData[elementId][ch] =
1349
0
          reinterpret_cast<FIXP_DBL *>(reinterpret_cast<void *>(
1350
0
              qcElement[elementId]->qcOutChannel[ch]->quantSpec));
1351
0
    }
1352
0
  }
1353
  /* The reinterpret_cast is used to suppress a compiler warning. We know that
1354
   * qcElement[0]->dynMem_SfbNActiveLinesLdData is sufficiently aligned, so the
1355
   * cast is safe */
1356
0
  sfbNActiveLinesLdData = reinterpret_cast<FIXP_DBL(*)[(2)][MAX_GROUPED_SFB]>(
1357
0
      reinterpret_cast<void *>(qcElement[0]->dynMem_SfbNActiveLinesLdData));
1358
1359
  /* for each sfb calc relative factors for pe changes */
1360
0
  normFactorInt = 0;
1361
1362
0
  for (elementId = elementOffset; elementId < nElements; elementId++) {
1363
0
    if (cm->elInfo[elementId].elType != ID_DSE) {
1364
0
      for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1365
0
        psyOutChan = psyOutElement[elementId]->psyOutChannel[ch];
1366
0
        peChanData = &qcElement[elementId]->peData.peChannelData[ch];
1367
1368
0
        for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
1369
0
             sfbGrp += psyOutChan->sfbPerGroup) {
1370
0
          for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
1371
0
            if (peChanData->sfbNActiveLines[sfbGrp + sfb] == 0) {
1372
0
              sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] =
1373
0
                  FL2FXCONST_DBL(-1.0f);
1374
0
            } else {
1375
              /* Both CalcLdInt and CalcLdData can be used!
1376
               * No offset has to be subtracted, because sfbNActiveLinesLdData
1377
               * is shorted while thrFactor calculation */
1378
0
              sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] =
1379
0
                  CalcLdInt(peChanData->sfbNActiveLines[sfbGrp + sfb]);
1380
0
            }
1381
0
            if (((ahFlag[elementId][ch][sfbGrp + sfb] < AH_ACTIVE) ||
1382
0
                 (deltaPe > 0)) &&
1383
0
                peChanData->sfbNActiveLines[sfbGrp + sfb] != 0) {
1384
0
              if (thrExp[elementId][ch][sfbGrp + sfb] > -redVal_m) {
1385
                /* sfbPeFactors[ch][sfbGrp+sfb] =
1386
                   peChanData->sfbNActiveLines[sfbGrp+sfb] /
1387
                                  (thrExp[elementId][ch][sfbGrp+sfb] +
1388
                   redVal[elementId]); */
1389
1390
0
                int minScale =
1391
0
                    fixMin(
1392
0
                        CountLeadingBits(thrExp[elementId][ch][sfbGrp + sfb]),
1393
0
                        CountLeadingBits(redVal_m) - redVal_e) -
1394
0
                    1;
1395
1396
                /* sumld = ld64( sfbThrExp + redVal ) */
1397
0
                FIXP_DBL sumLd =
1398
0
                    CalcLdData(scaleValue(thrExp[elementId][ch][sfbGrp + sfb],
1399
0
                                          minScale) +
1400
0
                               scaleValue(redVal_m, redVal_e + minScale)) -
1401
0
                    (FIXP_DBL)(minScale << (DFRACT_BITS - 1 - LD_DATA_SHIFT));
1402
1403
0
                if (sumLd < FL2FXCONST_DBL(0.f)) {
1404
0
                  sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1405
0
                      sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
1406
0
                      sumLd;
1407
0
                } else {
1408
0
                  if (sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] >
1409
0
                      (FL2FXCONST_DBL(-1.f) + sumLd)) {
1410
0
                    sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1411
0
                        sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
1412
0
                        sumLd;
1413
0
                  } else {
1414
0
                    sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1415
0
                        sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb];
1416
0
                  }
1417
0
                }
1418
1419
0
                normFactorInt += (INT)CalcInvLdData(
1420
0
                    sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb]);
1421
0
              } else
1422
0
                sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1423
0
                    FL2FXCONST_DBL(1.0f);
1424
0
            } else
1425
0
              sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
1426
0
                  FL2FXCONST_DBL(-1.0f);
1427
0
          }
1428
0
        }
1429
0
      }
1430
0
    }
1431
0
  }
1432
1433
  /* normFactorLdData = ld64(deltaPe/normFactorInt) */
1434
0
  normFactorLdData =
1435
0
      CalcLdData((FIXP_DBL)((deltaPe < 0) ? (-deltaPe) : (deltaPe))) -
1436
0
      CalcLdData((FIXP_DBL)normFactorInt);
1437
1438
  /* distribute the pe difference to the scalefactors
1439
     and calculate the according thresholds */
1440
0
  for (elementId = elementOffset; elementId < nElements; elementId++) {
1441
0
    if (cm->elInfo[elementId].elType != ID_DSE) {
1442
0
      for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1443
0
        qcOutChan = qcElement[elementId]->qcOutChannel[ch];
1444
0
        psyOutChan = psyOutElement[elementId]->psyOutChannel[ch];
1445
0
        peChanData = &qcElement[elementId]->peData.peChannelData[ch];
1446
1447
0
        for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
1448
0
             sfbGrp += psyOutChan->sfbPerGroup) {
1449
0
          for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
1450
0
            if (peChanData->sfbNActiveLines[sfbGrp + sfb] > 0) {
1451
              /* pe difference for this sfb */
1452
0
              if ((sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] ==
1453
0
                   FL2FXCONST_DBL(-1.0f)) ||
1454
0
                  (deltaPe == 0)) {
1455
0
                thrFactorLdData = FL2FXCONST_DBL(0.f);
1456
0
              } else {
1457
                /* new threshold */
1458
0
                FIXP_DBL tmp = CalcInvLdData(
1459
0
                    sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] +
1460
0
                    normFactorLdData -
1461
0
                    sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
1462
0
                    FL2FXCONST_DBL((float)LD_DATA_SHIFT / LD_DATA_SCALING));
1463
1464
                /* limit thrFactor to 60dB */
1465
0
                tmp = (deltaPe < 0) ? tmp : (-tmp);
1466
0
                thrFactorLdData =
1467
0
                    fMin(tmp, FL2FXCONST_DBL(20.f / LD_DATA_SCALING));
1468
0
              }
1469
1470
              /* new threshold */
1471
0
              sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp + sfb];
1472
0
              sfbEnLdData = qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb];
1473
1474
0
              if (thrFactorLdData < FL2FXCONST_DBL(0.f)) {
1475
0
                if (sfbThrLdData > (FL2FXCONST_DBL(-1.f) - thrFactorLdData)) {
1476
0
                  sfbThrReducedLdData = sfbThrLdData + thrFactorLdData;
1477
0
                } else {
1478
0
                  sfbThrReducedLdData = FL2FXCONST_DBL(-1.f);
1479
0
                }
1480
0
              } else {
1481
0
                sfbThrReducedLdData = sfbThrLdData + thrFactorLdData;
1482
0
              }
1483
1484
              /* avoid hole */
1485
0
              if ((sfbThrReducedLdData - sfbEnLdData >
1486
0
                   qcOutChan->sfbMinSnrLdData[sfbGrp + sfb]) &&
1487
0
                  (ahFlag[elementId][ch][sfbGrp + sfb] == AH_INACTIVE)) {
1488
                /* sfbThrReduced = max(psyOutChan[ch]->sfbMinSnr[i] * sfbEn,
1489
                 * sfbThr); */
1490
0
                if (sfbEnLdData >
1491
0
                    (sfbThrLdData - qcOutChan->sfbMinSnrLdData[sfbGrp + sfb])) {
1492
0
                  sfbThrReducedLdData =
1493
0
                      qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData;
1494
0
                } else {
1495
0
                  sfbThrReducedLdData = sfbThrLdData;
1496
0
                }
1497
0
                ahFlag[elementId][ch][sfbGrp + sfb] = AH_ACTIVE;
1498
0
              }
1499
1500
0
              qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData;
1501
0
            }
1502
0
          }
1503
0
        }
1504
0
      }
1505
0
    }
1506
0
  }
1507
0
}
1508
1509
/*****************************************************************************
1510
    functionname: FDKaacEnc_reduceMinSnr
1511
    description:  if the desired pe can not be reached, reduce pe by
1512
                  reducing minSnr
1513
*****************************************************************************/
1514
static void FDKaacEnc_reduceMinSnr(
1515
    const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
1516
    const PSY_OUT_ELEMENT *const psyOutElement[((8))],
1517
    const UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], const INT desiredPe,
1518
    INT *const redPeGlobal, const INT processElements, const INT elementOffset)
1519
1520
0
{
1521
0
  INT ch, elementId, globalMaxSfb = 0;
1522
0
  const INT nElements = elementOffset + processElements;
1523
0
  INT newGlobalPe = *redPeGlobal;
1524
1525
0
  if (newGlobalPe <= desiredPe) {
1526
0
    goto bail;
1527
0
  }
1528
1529
  /* global maximum of maxSfbPerGroup */
1530
0
  for (elementId = elementOffset; elementId < nElements; elementId++) {
1531
0
    if (cm->elInfo[elementId].elType != ID_DSE) {
1532
0
      for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1533
0
        globalMaxSfb =
1534
0
            fMax(globalMaxSfb,
1535
0
                 psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup);
1536
0
      }
1537
0
    }
1538
0
  }
1539
1540
  /* as long as globalPE is above desirePE reduce SNR to 1.0 dB, starting at
1541
   * highest SFB */
1542
0
  while ((newGlobalPe > desiredPe) && (--globalMaxSfb >= 0)) {
1543
0
    for (elementId = elementOffset; elementId < nElements; elementId++) {
1544
0
      if (cm->elInfo[elementId].elType != ID_DSE) {
1545
0
        PE_DATA *peData = &qcElement[elementId]->peData;
1546
1547
0
        for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1548
0
          QC_OUT_CHANNEL *qcOutChan = qcElement[elementId]->qcOutChannel[ch];
1549
0
          PSY_OUT_CHANNEL *psyOutChan =
1550
0
              psyOutElement[elementId]->psyOutChannel[ch];
1551
1552
          /* try to reduce SNR of channel's uppermost SFB(s) */
1553
0
          if (globalMaxSfb < psyOutChan->maxSfbPerGroup) {
1554
0
            INT sfb, deltaPe = 0;
1555
1556
0
            for (sfb = globalMaxSfb; sfb < psyOutChan->sfbCnt;
1557
0
                 sfb += psyOutChan->sfbPerGroup) {
1558
0
              if (ahFlag[elementId][ch][sfb] != NO_AH &&
1559
0
                  qcOutChan->sfbMinSnrLdData[sfb] < SnrLdFac &&
1560
0
                  (qcOutChan->sfbWeightedEnergyLdData[sfb] >
1561
0
                   qcOutChan->sfbThresholdLdData[sfb] - SnrLdFac)) {
1562
                /* increase threshold to new minSnr of 1dB */
1563
0
                qcOutChan->sfbMinSnrLdData[sfb] = SnrLdFac;
1564
0
                qcOutChan->sfbThresholdLdData[sfb] =
1565
0
                    qcOutChan->sfbWeightedEnergyLdData[sfb] + SnrLdFac;
1566
1567
                /* calc new pe */
1568
                /* C2 + C3*ld(1/0.8) = 1.5 */
1569
0
                deltaPe -= peData->peChannelData[ch].sfbPe[sfb];
1570
1571
                /* sfbPe = 1.5 * sfbNLines */
1572
0
                peData->peChannelData[ch].sfbPe[sfb] =
1573
0
                    (3 * peData->peChannelData[ch].sfbNLines[sfb])
1574
0
                    << (PE_CONSTPART_SHIFT - 1);
1575
0
                deltaPe += peData->peChannelData[ch].sfbPe[sfb];
1576
0
              }
1577
1578
0
            } /* sfb loop */
1579
1580
0
            deltaPe >>= PE_CONSTPART_SHIFT;
1581
0
            peData->pe += deltaPe;
1582
0
            peData->peChannelData[ch].pe += deltaPe;
1583
0
            newGlobalPe += deltaPe;
1584
1585
0
          } /* if globalMaxSfb < maxSfbPerGroup */
1586
1587
          /* stop if enough has been saved */
1588
0
          if (newGlobalPe <= desiredPe) {
1589
0
            goto bail;
1590
0
          }
1591
1592
0
        } /* ch loop */
1593
0
      }   /* != ID_DSE */
1594
0
    }     /* elementId loop */
1595
0
  }       /* while ( newGlobalPe > desiredPe) && (--globalMaxSfb >= 0) ) */
1596
1597
0
bail:
1598
  /* update global PE */
1599
0
  *redPeGlobal = newGlobalPe;
1600
0
}
1601
1602
/*****************************************************************************
1603
    functionname: FDKaacEnc_allowMoreHoles
1604
    description:  if the desired pe can not be reached, some more scalefactor
1605
                  bands have to be quantized to zero
1606
*****************************************************************************/
1607
static void FDKaacEnc_allowMoreHoles(
1608
    const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
1609
    const PSY_OUT_ELEMENT *const psyOutElement[((8))],
1610
    const ATS_ELEMENT *const AdjThrStateElement[((8))],
1611
    UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], const INT desiredPe,
1612
0
    const INT currentPe, const int processElements, const int elementOffset) {
1613
0
  INT elementId;
1614
0
  INT nElements = elementOffset + processElements;
1615
0
  INT actPe = currentPe;
1616
1617
0
  if (actPe <= desiredPe) {
1618
0
    return; /* nothing to do */
1619
0
  }
1620
1621
0
  for (elementId = elementOffset; elementId < nElements; elementId++) {
1622
0
    if (cm->elInfo[elementId].elType != ID_DSE) {
1623
0
      INT ch, sfb, sfbGrp;
1624
1625
0
      PE_DATA *peData = &qcElement[elementId]->peData;
1626
0
      const INT nChannels = cm->elInfo[elementId].nChannelsInEl;
1627
1628
0
      QC_OUT_CHANNEL *qcOutChannel[(2)] = {NULL};
1629
0
      PSY_OUT_CHANNEL *psyOutChannel[(2)] = {NULL};
1630
1631
0
      for (ch = 0; ch < nChannels; ch++) {
1632
        /* init pointers */
1633
0
        qcOutChannel[ch] = qcElement[elementId]->qcOutChannel[ch];
1634
0
        psyOutChannel[ch] = psyOutElement[elementId]->psyOutChannel[ch];
1635
1636
0
        for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
1637
0
             sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
1638
0
          for (sfb = psyOutChannel[ch]->maxSfbPerGroup;
1639
0
               sfb < psyOutChannel[ch]->sfbPerGroup; sfb++) {
1640
0
            peData->peChannelData[ch].sfbPe[sfbGrp + sfb] = 0;
1641
0
          }
1642
0
        }
1643
0
      }
1644
1645
      /* for MS allow hole in the channel with less energy */
1646
0
      if (nChannels == 2 && psyOutChannel[0]->lastWindowSequence ==
1647
0
                                psyOutChannel[1]->lastWindowSequence) {
1648
0
        for (sfb = psyOutChannel[0]->maxSfbPerGroup - 1; sfb >= 0; sfb--) {
1649
0
          for (sfbGrp = 0; sfbGrp < psyOutChannel[0]->sfbCnt;
1650
0
               sfbGrp += psyOutChannel[0]->sfbPerGroup) {
1651
0
            if (psyOutElement[elementId]->toolsInfo.msMask[sfbGrp + sfb]) {
1652
0
              FIXP_DBL EnergyLd_L =
1653
0
                  qcOutChannel[0]->sfbWeightedEnergyLdData[sfbGrp + sfb];
1654
0
              FIXP_DBL EnergyLd_R =
1655
0
                  qcOutChannel[1]->sfbWeightedEnergyLdData[sfbGrp + sfb];
1656
1657
              /* allow hole in side channel ? */
1658
0
              if ((ahFlag[elementId][1][sfbGrp + sfb] != NO_AH) &&
1659
0
                  (((FL2FXCONST_DBL(-0.02065512648f) >> 1) +
1660
0
                    (qcOutChannel[0]->sfbMinSnrLdData[sfbGrp + sfb] >> 1)) >
1661
0
                   ((EnergyLd_R >> 1) - (EnergyLd_L >> 1)))) {
1662
0
                ahFlag[elementId][1][sfbGrp + sfb] = NO_AH;
1663
0
                qcOutChannel[1]->sfbThresholdLdData[sfbGrp + sfb] =
1664
0
                    FL2FXCONST_DBL(0.015625f) + EnergyLd_R;
1665
0
                actPe -= peData->peChannelData[1].sfbPe[sfbGrp + sfb] >>
1666
0
                         PE_CONSTPART_SHIFT;
1667
0
              }
1668
              /* allow hole in mid channel ? */
1669
0
              else if ((ahFlag[elementId][0][sfbGrp + sfb] != NO_AH) &&
1670
0
                       (((FL2FXCONST_DBL(-0.02065512648f) >> 1) +
1671
0
                         (qcOutChannel[1]->sfbMinSnrLdData[sfbGrp + sfb] >>
1672
0
                          1)) > ((EnergyLd_L >> 1) - (EnergyLd_R >> 1)))) {
1673
0
                ahFlag[elementId][0][sfbGrp + sfb] = NO_AH;
1674
0
                qcOutChannel[0]->sfbThresholdLdData[sfbGrp + sfb] =
1675
0
                    FL2FXCONST_DBL(0.015625f) + EnergyLd_L;
1676
0
                actPe -= peData->peChannelData[0].sfbPe[sfbGrp + sfb] >>
1677
0
                         PE_CONSTPART_SHIFT;
1678
0
              } /* if (ahFlag) */
1679
0
            }   /* if MS */
1680
0
          }     /* sfbGrp */
1681
0
          if (actPe <= desiredPe) {
1682
0
            return; /* stop if enough has been saved */
1683
0
          }
1684
0
        } /* sfb */
1685
0
      }   /* MS possible ? */
1686
1687
0
    } /* EOF DSE-suppression */
1688
0
  }   /* EOF for all elements... */
1689
1690
0
  if (actPe > desiredPe) {
1691
    /* more holes necessary? subsequently erase bands starting with low energies
1692
     */
1693
0
    INT ch, sfb, sfbGrp;
1694
0
    INT minSfb, maxSfb;
1695
0
    INT enIdx, ahCnt, done;
1696
0
    INT startSfb[(8)];
1697
0
    INT sfbCnt[(8)];
1698
0
    INT sfbPerGroup[(8)];
1699
0
    INT maxSfbPerGroup[(8)];
1700
0
    FIXP_DBL avgEn;
1701
0
    FIXP_DBL minEnLD64;
1702
0
    FIXP_DBL avgEnLD64;
1703
0
    FIXP_DBL enLD64[NUM_NRG_LEVS];
1704
0
    INT avgEn_e;
1705
1706
    /* get the scaling factor over all audio elements and channels */
1707
0
    maxSfb = 0;
1708
0
    for (elementId = elementOffset; elementId < nElements; elementId++) {
1709
0
      if (cm->elInfo[elementId].elType != ID_DSE) {
1710
0
        for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1711
0
          for (sfbGrp = 0;
1712
0
               sfbGrp < psyOutElement[elementId]->psyOutChannel[ch]->sfbCnt;
1713
0
               sfbGrp +=
1714
0
               psyOutElement[elementId]->psyOutChannel[ch]->sfbPerGroup) {
1715
0
            maxSfb +=
1716
0
                psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup;
1717
0
          }
1718
0
        }
1719
0
      }
1720
0
    }
1721
0
    avgEn_e =
1722
0
        (DFRACT_BITS - fixnormz_D((LONG)fMax(0, maxSfb - 1))); /* ilog2() */
1723
1724
0
    ahCnt = 0;
1725
0
    maxSfb = 0;
1726
0
    minSfb = MAX_SFB;
1727
0
    avgEn = FL2FXCONST_DBL(0.0f);
1728
0
    minEnLD64 = FL2FXCONST_DBL(0.0f);
1729
1730
0
    for (elementId = elementOffset; elementId < nElements; elementId++) {
1731
0
      if (cm->elInfo[elementId].elType != ID_DSE) {
1732
0
        for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1733
0
          const INT chIdx = cm->elInfo[elementId].ChannelIndex[ch];
1734
0
          QC_OUT_CHANNEL *qcOutChannel = qcElement[elementId]->qcOutChannel[ch];
1735
0
          PSY_OUT_CHANNEL *psyOutChannel =
1736
0
              psyOutElement[elementId]->psyOutChannel[ch];
1737
1738
0
          maxSfbPerGroup[chIdx] = psyOutChannel->maxSfbPerGroup;
1739
0
          sfbCnt[chIdx] = psyOutChannel->sfbCnt;
1740
0
          sfbPerGroup[chIdx] = psyOutChannel->sfbPerGroup;
1741
1742
0
          maxSfb = fMax(maxSfb, psyOutChannel->maxSfbPerGroup);
1743
1744
0
          if (psyOutChannel->lastWindowSequence != SHORT_WINDOW) {
1745
0
            startSfb[chIdx] = AdjThrStateElement[elementId]->ahParam.startSfbL;
1746
0
          } else {
1747
0
            startSfb[chIdx] = AdjThrStateElement[elementId]->ahParam.startSfbS;
1748
0
          }
1749
1750
0
          minSfb = fMin(minSfb, startSfb[chIdx]);
1751
1752
0
          sfbGrp = 0;
1753
0
          sfb = startSfb[chIdx];
1754
1755
0
          do {
1756
0
            for (; sfb < psyOutChannel->maxSfbPerGroup; sfb++) {
1757
0
              if ((ahFlag[elementId][ch][sfbGrp + sfb] != NO_AH) &&
1758
0
                  (qcOutChannel->sfbWeightedEnergyLdData[sfbGrp + sfb] >
1759
0
                   qcOutChannel->sfbThresholdLdData[sfbGrp + sfb])) {
1760
0
                minEnLD64 = fixMin(minEnLD64,
1761
0
                                   qcOutChannel->sfbEnergyLdData[sfbGrp + sfb]);
1762
0
                avgEn += qcOutChannel->sfbEnergy[sfbGrp + sfb] >> avgEn_e;
1763
0
                ahCnt++;
1764
0
              }
1765
0
            }
1766
1767
0
            sfbGrp += psyOutChannel->sfbPerGroup;
1768
0
            sfb = startSfb[chIdx];
1769
1770
0
          } while (sfbGrp < psyOutChannel->sfbCnt);
1771
0
        }
1772
0
      } /* (cm->elInfo[elementId].elType != ID_DSE) */
1773
0
    }   /* (elementId = elementOffset;elementId<nElements;elementId++) */
1774
1775
0
    if ((avgEn == FL2FXCONST_DBL(0.0f)) || (ahCnt == 0)) {
1776
0
      avgEnLD64 = FL2FXCONST_DBL(0.0f);
1777
0
    } else {
1778
0
      avgEnLD64 = CalcLdData(avgEn) +
1779
0
                  (FIXP_DBL)(avgEn_e << (DFRACT_BITS - 1 - LD_DATA_SHIFT)) -
1780
0
                  CalcLdInt(ahCnt);
1781
0
    }
1782
1783
    /* calc some energy borders between minEn and avgEn */
1784
1785
    /* for (enIdx = 0; enIdx < NUM_NRG_LEVS; enIdx++) {
1786
         en[enIdx] = (2.0f*enIdx+1.0f)/(2.0f*NUM_NRG_LEVS-1.0f);
1787
       } */
1788
0
    enLD64[0] =
1789
0
        minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.06666667f));
1790
0
    enLD64[1] =
1791
0
        minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.20000000f));
1792
0
    enLD64[2] =
1793
0
        minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.33333334f));
1794
0
    enLD64[3] =
1795
0
        minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.46666667f));
1796
0
    enLD64[4] =
1797
0
        minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.60000002f));
1798
0
    enLD64[5] =
1799
0
        minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.73333335f));
1800
0
    enLD64[6] =
1801
0
        minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.86666667f));
1802
0
    enLD64[7] = minEnLD64 + (avgEnLD64 - minEnLD64);
1803
1804
0
    done = 0;
1805
0
    enIdx = 0;
1806
0
    sfb = maxSfb - 1;
1807
1808
0
    while (!done) {
1809
0
      for (elementId = elementOffset; elementId < nElements; elementId++) {
1810
0
        if (cm->elInfo[elementId].elType != ID_DSE) {
1811
0
          PE_DATA *peData = &qcElement[elementId]->peData;
1812
0
          for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
1813
0
            const INT chIdx = cm->elInfo[elementId].ChannelIndex[ch];
1814
0
            QC_OUT_CHANNEL *qcOutChannel =
1815
0
                qcElement[elementId]->qcOutChannel[ch];
1816
0
            if (sfb >= startSfb[chIdx] && sfb < maxSfbPerGroup[chIdx]) {
1817
0
              for (sfbGrp = 0; sfbGrp < sfbCnt[chIdx];
1818
0
                   sfbGrp += sfbPerGroup[chIdx]) {
1819
                /* sfb energy below border ? */
1820
0
                if (ahFlag[elementId][ch][sfbGrp + sfb] != NO_AH &&
1821
0
                    qcOutChannel->sfbEnergyLdData[sfbGrp + sfb] <
1822
0
                        enLD64[enIdx]) {
1823
                  /* allow hole */
1824
0
                  ahFlag[elementId][ch][sfbGrp + sfb] = NO_AH;
1825
0
                  qcOutChannel->sfbThresholdLdData[sfbGrp + sfb] =
1826
0
                      FL2FXCONST_DBL(0.015625f) +
1827
0
                      qcOutChannel->sfbWeightedEnergyLdData[sfbGrp + sfb];
1828
0
                  actPe -= peData->peChannelData[ch].sfbPe[sfbGrp + sfb] >>
1829
0
                           PE_CONSTPART_SHIFT;
1830
0
                }
1831
0
                if (actPe <= desiredPe) {
1832
0
                  return; /* stop if enough has been saved */
1833
0
                }
1834
0
              } /* sfbGrp */
1835
0
            }   /* sfb */
1836
0
          }     /* nChannelsInEl */
1837
0
        }       /* ID_DSE */
1838
0
      }         /* elementID */
1839
1840
0
      sfb--;
1841
0
      if (sfb < minSfb) {
1842
        /* restart with next energy border */
1843
0
        sfb = maxSfb;
1844
0
        enIdx++;
1845
0
        if (enIdx >= NUM_NRG_LEVS) {
1846
0
          done = 1;
1847
0
        }
1848
0
      }
1849
0
    } /* done */
1850
0
  }   /* (actPe <= desiredPe) */
1851
0
}
1852
1853
/* reset avoid hole flags from AH_ACTIVE to AH_INACTIVE  */
1854
static void FDKaacEnc_resetAHFlags(
1855
    UCHAR ahFlag[(2)][MAX_GROUPED_SFB], const INT nChannels,
1856
0
    const PSY_OUT_CHANNEL *const psyOutChannel[(2)]) {
1857
0
  int ch, sfb, sfbGrp;
1858
1859
0
  for (ch = 0; ch < nChannels; ch++) {
1860
0
    for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
1861
0
         sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
1862
0
      for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
1863
0
        if (ahFlag[ch][sfbGrp + sfb] == AH_ACTIVE) {
1864
0
          ahFlag[ch][sfbGrp + sfb] = AH_INACTIVE;
1865
0
        }
1866
0
      }
1867
0
    }
1868
0
  }
1869
0
}
1870
1871
0
static FIXP_DBL CalcRedValPower(FIXP_DBL num, FIXP_DBL denum, INT *scaling) {
1872
0
  FIXP_DBL value = FL2FXCONST_DBL(0.f);
1873
1874
0
  if (num >= FL2FXCONST_DBL(0.f)) {
1875
0
    value = fDivNorm(num, denum, scaling);
1876
0
  } else {
1877
0
    value = -fDivNorm(-num, denum, scaling);
1878
0
  }
1879
0
  value = f2Pow(value, *scaling, scaling);
1880
1881
0
  return value;
1882
0
}
1883
1884
/*****************************************************************************
1885
functionname: FDKaacEnc_adaptThresholdsToPe
1886
description:  two guesses for the reduction value and one final correction of
1887
the thresholds
1888
*****************************************************************************/
1889
static void FDKaacEnc_adaptThresholdsToPe(
1890
    const CHANNEL_MAPPING *const cm,
1891
    ATS_ELEMENT *const AdjThrStateElement[((8))],
1892
    QC_OUT_ELEMENT *const qcElement[((8))],
1893
    const PSY_OUT_ELEMENT *const psyOutElement[((8))], const INT desiredPe,
1894
    const INT maxIter2ndGuess, const INT processElements,
1895
0
    const INT elementOffset) {
1896
0
  FIXP_DBL reductionValue_m;
1897
0
  SCHAR reductionValue_e;
1898
0
  UCHAR(*pAhFlag)[(2)][MAX_GROUPED_SFB];
1899
0
  FIXP_DBL(*pThrExp)[(2)][MAX_GROUPED_SFB];
1900
0
  int iter;
1901
1902
0
  INT constPartGlobal, noRedPeGlobal, nActiveLinesGlobal, redPeGlobal;
1903
0
  constPartGlobal = noRedPeGlobal = nActiveLinesGlobal = redPeGlobal = 0;
1904
1905
0
  int elementId;
1906
1907
0
  int nElements = elementOffset + processElements;
1908
0
  if (nElements > cm->nElements) {
1909
0
    nElements = cm->nElements;
1910
0
  }
1911
1912
  /* The reinterpret_cast is used to suppress a compiler warning. We know that
1913
   * qcElement[0]->dynMem_Ah_Flag is sufficiently aligned, so the cast is safe
1914
   */
1915
0
  pAhFlag = reinterpret_cast<UCHAR(*)[(2)][MAX_GROUPED_SFB]>(
1916
0
      reinterpret_cast<void *>(qcElement[0]->dynMem_Ah_Flag));
1917
  /* The reinterpret_cast is used to suppress a compiler warning. We know that
1918
   * qcElement[0]->dynMem_Thr_Exp is sufficiently aligned, so the cast is safe
1919
   */
1920
0
  pThrExp = reinterpret_cast<FIXP_DBL(*)[(2)][MAX_GROUPED_SFB]>(
1921
0
      reinterpret_cast<void *>(qcElement[0]->dynMem_Thr_Exp));
1922
1923
  /* ------------------------------------------------------- */
1924
  /* Part I: Initialize data structures and variables... */
1925
  /* ------------------------------------------------------- */
1926
0
  for (elementId = elementOffset; elementId < nElements; elementId++) {
1927
0
    if (cm->elInfo[elementId].elType != ID_DSE) {
1928
0
      INT nChannels = cm->elInfo[elementId].nChannelsInEl;
1929
0
      PE_DATA *peData = &qcElement[elementId]->peData;
1930
1931
      /* thresholds to the power of redExp */
1932
0
      FDKaacEnc_calcThreshExp(
1933
0
          pThrExp[elementId], qcElement[elementId]->qcOutChannel,
1934
0
          psyOutElement[elementId]->psyOutChannel, nChannels);
1935
1936
      /* lower the minSnr requirements for low energies compared to the average
1937
         energy in this frame */
1938
0
      FDKaacEnc_adaptMinSnr(qcElement[elementId]->qcOutChannel,
1939
0
                            psyOutElement[elementId]->psyOutChannel,
1940
0
                            &AdjThrStateElement[elementId]->minSnrAdaptParam,
1941
0
                            nChannels);
1942
1943
      /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
1944
0
      FDKaacEnc_initAvoidHoleFlag(
1945
0
          qcElement[elementId]->qcOutChannel,
1946
0
          psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
1947
0
          &psyOutElement[elementId]->toolsInfo, nChannels,
1948
0
          &AdjThrStateElement[elementId]->ahParam);
1949
1950
      /* sum up */
1951
0
      constPartGlobal += peData->constPart;
1952
0
      noRedPeGlobal += peData->pe;
1953
0
      nActiveLinesGlobal += fixMax((INT)peData->nActiveLines, 1);
1954
1955
0
    } /* EOF DSE-suppression */
1956
0
  }   /* EOF for all elements... */
1957
1958
  /*
1959
     First guess of reduction value:
1960
     avgThrExp = (float)pow(2.0f, (constPartGlobal - noRedPeGlobal)/(4.0f *
1961
     nActiveLinesGlobal)); redVal    = (float)pow(2.0f, (constPartGlobal -
1962
     desiredPe)/(4.0f * nActiveLinesGlobal)) - avgThrExp; redVal    = max(0.f,
1963
     redVal);
1964
  */
1965
0
  int redVal_e, avgThrExp_e, result_e;
1966
0
  FIXP_DBL redVal_m, avgThrExp_m;
1967
1968
0
  redVal_m = CalcRedValPower(constPartGlobal - desiredPe,
1969
0
                             4 * nActiveLinesGlobal, &redVal_e);
1970
0
  avgThrExp_m = CalcRedValPower(constPartGlobal - noRedPeGlobal,
1971
0
                                4 * nActiveLinesGlobal, &avgThrExp_e);
1972
0
  result_e = fMax(redVal_e, avgThrExp_e) + 1;
1973
1974
0
  reductionValue_m = fMax(FL2FXCONST_DBL(0.f),
1975
0
                          scaleValue(redVal_m, redVal_e - result_e) -
1976
0
                              scaleValue(avgThrExp_m, avgThrExp_e - result_e));
1977
0
  reductionValue_e = result_e;
1978
1979
  /* ----------------------------------------------------------------------- */
1980
  /* Part II: Calculate bit consumption of initial bit constraints setup */
1981
  /* ----------------------------------------------------------------------- */
1982
0
  for (elementId = elementOffset; elementId < nElements; elementId++) {
1983
0
    if (cm->elInfo[elementId].elType != ID_DSE) {
1984
0
      INT nChannels = cm->elInfo[elementId].nChannelsInEl;
1985
0
      PE_DATA *peData = &qcElement[elementId]->peData;
1986
1987
      /* reduce thresholds */
1988
0
      FDKaacEnc_reduceThresholdsCBR(
1989
0
          qcElement[elementId]->qcOutChannel,
1990
0
          psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
1991
0
          pThrExp[elementId], nChannels, reductionValue_m, reductionValue_e);
1992
1993
      /* pe after first guess */
1994
0
      FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
1995
0
                       qcElement[elementId]->qcOutChannel, peData, nChannels);
1996
1997
0
      redPeGlobal += peData->pe;
1998
0
    } /* EOF DSE-suppression */
1999
0
  }   /* EOF for all elements... */
2000
2001
  /* -------------------------------------------------- */
2002
  /* Part III: Iterate until bit constraints are met */
2003
  /* -------------------------------------------------- */
2004
0
  iter = 0;
2005
0
  while ((fixp_abs(redPeGlobal - desiredPe) >
2006
0
          fMultI(FL2FXCONST_DBL(0.05f), desiredPe)) &&
2007
0
         (iter < maxIter2ndGuess)) {
2008
0
    INT desiredPeNoAHGlobal;
2009
0
    INT redPeNoAHGlobal = 0;
2010
0
    INT constPartNoAHGlobal = 0;
2011
0
    INT nActiveLinesNoAHGlobal = 0;
2012
2013
0
    for (elementId = elementOffset; elementId < nElements; elementId++) {
2014
0
      if (cm->elInfo[elementId].elType != ID_DSE) {
2015
0
        INT redPeNoAH, constPartNoAH, nActiveLinesNoAH;
2016
0
        INT nChannels = cm->elInfo[elementId].nChannelsInEl;
2017
0
        PE_DATA *peData = &qcElement[elementId]->peData;
2018
2019
        /* pe for bands where avoid hole is inactive */
2020
0
        FDKaacEnc_FDKaacEnc_calcPeNoAH(
2021
0
            &redPeNoAH, &constPartNoAH, &nActiveLinesNoAH, peData,
2022
0
            pAhFlag[elementId], psyOutElement[elementId]->psyOutChannel,
2023
0
            nChannels);
2024
2025
0
        redPeNoAHGlobal += redPeNoAH;
2026
0
        constPartNoAHGlobal += constPartNoAH;
2027
0
        nActiveLinesNoAHGlobal += nActiveLinesNoAH;
2028
0
      } /* EOF DSE-suppression */
2029
0
    }   /* EOF for all elements... */
2030
2031
    /* Calculate new redVal ... */
2032
0
    if (desiredPe < redPeGlobal) {
2033
      /* new desired pe without bands where avoid hole is active */
2034
0
      desiredPeNoAHGlobal = desiredPe - (redPeGlobal - redPeNoAHGlobal);
2035
2036
      /* limit desiredPeNoAH to positive values, as the PE can not become
2037
       * negative */
2038
0
      desiredPeNoAHGlobal = fMax(0, desiredPeNoAHGlobal);
2039
2040
      /* second guess (only if there are bands left where avoid hole is
2041
       * inactive)*/
2042
0
      if (nActiveLinesNoAHGlobal > 0) {
2043
        /*
2044
          avgThrExp = (float)pow(2.0f, (constPartNoAHGlobal - redPeNoAHGlobal) /
2045
          (4.0f * nActiveLinesNoAHGlobal)); redVal   += (float)pow(2.0f,
2046
          (constPartNoAHGlobal - desiredPeNoAHGlobal) / (4.0f *
2047
          nActiveLinesNoAHGlobal)) - avgThrExp; redVal    = max(0.0f, redVal);
2048
        */
2049
2050
0
        redVal_m = CalcRedValPower(constPartNoAHGlobal - desiredPeNoAHGlobal,
2051
0
                                   4 * nActiveLinesNoAHGlobal, &redVal_e);
2052
0
        avgThrExp_m = CalcRedValPower(constPartNoAHGlobal - redPeNoAHGlobal,
2053
0
                                      4 * nActiveLinesNoAHGlobal, &avgThrExp_e);
2054
0
        result_e = fMax(reductionValue_e, fMax(redVal_e, avgThrExp_e) + 1) + 1;
2055
2056
0
        reductionValue_m =
2057
0
            fMax(FL2FXCONST_DBL(0.f),
2058
0
                 scaleValue(reductionValue_m, reductionValue_e - result_e) +
2059
0
                     scaleValue(redVal_m, redVal_e - result_e) -
2060
0
                     scaleValue(avgThrExp_m, avgThrExp_e - result_e));
2061
0
        reductionValue_e = result_e;
2062
2063
0
      } /* nActiveLinesNoAHGlobal > 0 */
2064
0
    } else {
2065
      /* redVal *= redPeGlobal/desiredPe; */
2066
0
      int sc0, sc1;
2067
0
      reductionValue_m = fMultNorm(
2068
0
          reductionValue_m,
2069
0
          fDivNorm((FIXP_DBL)redPeGlobal, (FIXP_DBL)desiredPe, &sc0), &sc1);
2070
0
      reductionValue_e += sc0 + sc1;
2071
2072
0
      for (elementId = elementOffset; elementId < nElements; elementId++) {
2073
0
        if (cm->elInfo[elementId].elType != ID_DSE) {
2074
0
          FDKaacEnc_resetAHFlags(pAhFlag[elementId],
2075
0
                                 cm->elInfo[elementId].nChannelsInEl,
2076
0
                                 psyOutElement[elementId]->psyOutChannel);
2077
0
        } /* EOF DSE-suppression */
2078
0
      }   /* EOF for all elements... */
2079
0
    }
2080
2081
0
    redPeGlobal = 0;
2082
    /* Calculate new redVal's PE... */
2083
0
    for (elementId = elementOffset; elementId < nElements; elementId++) {
2084
0
      if (cm->elInfo[elementId].elType != ID_DSE) {
2085
0
        INT nChannels = cm->elInfo[elementId].nChannelsInEl;
2086
0
        PE_DATA *peData = &qcElement[elementId]->peData;
2087
2088
        /* reduce thresholds */
2089
0
        FDKaacEnc_reduceThresholdsCBR(
2090
0
            qcElement[elementId]->qcOutChannel,
2091
0
            psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
2092
0
            pThrExp[elementId], nChannels, reductionValue_m, reductionValue_e);
2093
2094
        /* pe after second guess */
2095
0
        FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
2096
0
                         qcElement[elementId]->qcOutChannel, peData, nChannels);
2097
0
        redPeGlobal += peData->pe;
2098
2099
0
      } /* EOF DSE-suppression */
2100
0
    }   /* EOF for all elements... */
2101
2102
0
    iter++;
2103
0
  } /* EOF while */
2104
2105
  /* ------------------------------------------------------- */
2106
  /* Part IV: if still required, further reduce constraints  */
2107
  /* ------------------------------------------------------- */
2108
  /*                  1.0*        1.15*       1.20*
2109
   *               desiredPe   desiredPe   desiredPe
2110
   *                   |           |           |
2111
   * ...XXXXXXXXXXXXXXXXXXXXXXXXXXX|           |
2112
   *                   |           |           |XXXXXXXXXXX...
2113
   *                   |           |XXXXXXXXXXX|
2114
   *            --- A ---          | --- B --- | --- C ---
2115
   *
2116
   * (X): redPeGlobal
2117
   * (A): FDKaacEnc_correctThresh()
2118
   * (B): FDKaacEnc_allowMoreHoles()
2119
   * (C): FDKaacEnc_reduceMinSnr()
2120
   */
2121
2122
  /* correct thresholds to get closer to the desired pe */
2123
0
  if (redPeGlobal > desiredPe) {
2124
0
    FDKaacEnc_correctThresh(cm, qcElement, psyOutElement, pAhFlag, pThrExp,
2125
0
                            reductionValue_m, reductionValue_e,
2126
0
                            desiredPe - redPeGlobal, processElements,
2127
0
                            elementOffset);
2128
2129
    /* update PE */
2130
0
    redPeGlobal = 0;
2131
0
    for (elementId = elementOffset; elementId < nElements; elementId++) {
2132
0
      if (cm->elInfo[elementId].elType != ID_DSE) {
2133
0
        INT nChannels = cm->elInfo[elementId].nChannelsInEl;
2134
0
        PE_DATA *peData = &qcElement[elementId]->peData;
2135
2136
        /* pe after correctThresh */
2137
0
        FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
2138
0
                         qcElement[elementId]->qcOutChannel, peData, nChannels);
2139
0
        redPeGlobal += peData->pe;
2140
2141
0
      } /* EOF DSE-suppression */
2142
0
    }   /* EOF for all elements... */
2143
0
  }
2144
2145
0
  if (redPeGlobal > desiredPe) {
2146
    /* reduce pe by reducing minSnr requirements */
2147
0
    FDKaacEnc_reduceMinSnr(
2148
0
        cm, qcElement, psyOutElement, pAhFlag,
2149
0
        (fMultI(FL2FXCONST_DBL(0.15f), desiredPe) + desiredPe), &redPeGlobal,
2150
0
        processElements, elementOffset);
2151
2152
    /* reduce pe by allowing additional spectral holes */
2153
0
    FDKaacEnc_allowMoreHoles(cm, qcElement, psyOutElement, AdjThrStateElement,
2154
0
                             pAhFlag, desiredPe, redPeGlobal, processElements,
2155
0
                             elementOffset);
2156
0
  }
2157
0
}
2158
2159
/* similar to FDKaacEnc_adaptThresholdsToPe(), for  VBR-mode */
2160
static void FDKaacEnc_AdaptThresholdsVBR(
2161
    QC_OUT_CHANNEL *const qcOutChannel[(2)],
2162
    const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
2163
    ATS_ELEMENT *const AdjThrStateElement,
2164
0
    const struct TOOLSINFO *const toolsInfo, const INT nChannels) {
2165
0
  UCHAR(*pAhFlag)[MAX_GROUPED_SFB];
2166
0
  FIXP_DBL(*pThrExp)[MAX_GROUPED_SFB];
2167
2168
  /* allocate scratch memory */
2169
0
  C_ALLOC_SCRATCH_START(_pAhFlag, UCHAR, (2) * MAX_GROUPED_SFB)
2170
0
  C_ALLOC_SCRATCH_START(_pThrExp, FIXP_DBL, (2) * MAX_GROUPED_SFB)
2171
0
  pAhFlag = (UCHAR(*)[MAX_GROUPED_SFB])_pAhFlag;
2172
0
  pThrExp = (FIXP_DBL(*)[MAX_GROUPED_SFB])_pThrExp;
2173
2174
  /* thresholds to the power of redExp */
2175
0
  FDKaacEnc_calcThreshExp(pThrExp, qcOutChannel, psyOutChannel, nChannels);
2176
2177
  /* lower the minSnr requirements for low energies compared to the average
2178
     energy in this frame */
2179
0
  FDKaacEnc_adaptMinSnr(qcOutChannel, psyOutChannel,
2180
0
                        &AdjThrStateElement->minSnrAdaptParam, nChannels);
2181
2182
  /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
2183
0
  FDKaacEnc_initAvoidHoleFlag(qcOutChannel, psyOutChannel, pAhFlag, toolsInfo,
2184
0
                              nChannels, &AdjThrStateElement->ahParam);
2185
2186
  /* reduce thresholds */
2187
0
  FDKaacEnc_reduceThresholdsVBR(qcOutChannel, psyOutChannel, pAhFlag, pThrExp,
2188
0
                                nChannels, AdjThrStateElement->vbrQualFactor,
2189
0
                                &AdjThrStateElement->chaosMeasureOld);
2190
2191
  /* free scratch memory */
2192
0
  C_ALLOC_SCRATCH_END(_pThrExp, FIXP_DBL, (2) * MAX_GROUPED_SFB)
2193
0
  C_ALLOC_SCRATCH_END(_pAhFlag, UCHAR, (2) * MAX_GROUPED_SFB)
2194
0
}
2195
2196
/*****************************************************************************
2197
2198
  functionname: FDKaacEnc_calcBitSave
2199
  description:  Calculates percentage of bit save, see figure below
2200
  returns:
2201
  input:        parameters and bitres-fullness
2202
  output:       percentage of bit save
2203
2204
*****************************************************************************/
2205
/*
2206
        bitsave
2207
                    maxBitSave(%)|   clipLow
2208
                                 |---\
2209
                                 |    \
2210
                                 |     \
2211
                                 |      \
2212
                                 |       \
2213
                                 |--------\--------------> bitres
2214
                                 |         \
2215
                    minBitSave(%)|          \------------
2216
                                          clipHigh      maxBitres
2217
*/
2218
static FIXP_DBL FDKaacEnc_calcBitSave(FIXP_DBL fillLevel,
2219
                                      const FIXP_DBL clipLow,
2220
                                      const FIXP_DBL clipHigh,
2221
                                      const FIXP_DBL minBitSave,
2222
                                      const FIXP_DBL maxBitSave,
2223
0
                                      const FIXP_DBL bitsave_slope) {
2224
0
  FIXP_DBL bitsave;
2225
2226
0
  fillLevel = fixMax(fillLevel, clipLow);
2227
0
  fillLevel = fixMin(fillLevel, clipHigh);
2228
2229
0
  bitsave = maxBitSave - fMult((fillLevel - clipLow), bitsave_slope);
2230
2231
0
  return (bitsave);
2232
0
}
2233
2234
/*****************************************************************************
2235
2236
  functionname: FDKaacEnc_calcBitSpend
2237
  description:  Calculates percentage of bit spend, see figure below
2238
  returns:
2239
  input:        parameters and bitres-fullness
2240
  output:       percentage of bit spend
2241
2242
*****************************************************************************/
2243
/*
2244
                              bitspend      clipHigh
2245
                   maxBitSpend(%)|          /-----------maxBitres
2246
                                 |         /
2247
                                 |        /
2248
                                 |       /
2249
                                 |      /
2250
                                 |     /
2251
                                 |----/-----------------> bitres
2252
                                 |   /
2253
                   minBitSpend(%)|--/
2254
                                   clipLow
2255
*/
2256
static FIXP_DBL FDKaacEnc_calcBitSpend(FIXP_DBL fillLevel,
2257
                                       const FIXP_DBL clipLow,
2258
                                       const FIXP_DBL clipHigh,
2259
                                       const FIXP_DBL minBitSpend,
2260
                                       const FIXP_DBL maxBitSpend,
2261
0
                                       const FIXP_DBL bitspend_slope) {
2262
0
  FIXP_DBL bitspend;
2263
2264
0
  fillLevel = fixMax(fillLevel, clipLow);
2265
0
  fillLevel = fixMin(fillLevel, clipHigh);
2266
2267
0
  bitspend = minBitSpend + fMult(fillLevel - clipLow, bitspend_slope);
2268
2269
0
  return (bitspend);
2270
0
}
2271
2272
/*****************************************************************************
2273
2274
  functionname: FDKaacEnc_adjustPeMinMax()
2275
  description:  adjusts peMin and peMax parameters over time
2276
  returns:
2277
  input:        current pe, peMin, peMax, bitres size
2278
  output:       adjusted peMin/peMax
2279
2280
*****************************************************************************/
2281
0
static void FDKaacEnc_adjustPeMinMax(const INT currPe, INT *peMin, INT *peMax) {
2282
0
  FIXP_DBL minFacHi = FL2FXCONST_DBL(0.3f), maxFacHi = (FIXP_DBL)MAXVAL_DBL,
2283
0
           minFacLo = FL2FXCONST_DBL(0.14f), maxFacLo = FL2FXCONST_DBL(0.07f);
2284
0
  INT diff;
2285
2286
0
  INT minDiff_fix = fMultI(FL2FXCONST_DBL(0.1666666667f), currPe);
2287
2288
0
  if (currPe > *peMax) {
2289
0
    diff = (currPe - *peMax);
2290
0
    *peMin += fMultI(minFacHi, diff);
2291
0
    *peMax += fMultI(maxFacHi, diff);
2292
0
  } else if (currPe < *peMin) {
2293
0
    diff = (*peMin - currPe);
2294
0
    *peMin -= fMultI(minFacLo, diff);
2295
0
    *peMax -= fMultI(maxFacLo, diff);
2296
0
  } else {
2297
0
    *peMin += fMultI(minFacHi, (currPe - *peMin));
2298
0
    *peMax -= fMultI(maxFacLo, (*peMax - currPe));
2299
0
  }
2300
2301
0
  if ((*peMax - *peMin) < minDiff_fix) {
2302
0
    INT peMax_fix = *peMax, peMin_fix = *peMin;
2303
0
    FIXP_DBL partLo_fix, partHi_fix;
2304
2305
0
    partLo_fix = (FIXP_DBL)fixMax(0, currPe - peMin_fix);
2306
0
    partHi_fix = (FIXP_DBL)fixMax(0, peMax_fix - currPe);
2307
2308
0
    peMax_fix =
2309
0
        (INT)(currPe + fMultI(fDivNorm(partHi_fix, (partLo_fix + partHi_fix)),
2310
0
                              minDiff_fix));
2311
0
    peMin_fix =
2312
0
        (INT)(currPe - fMultI(fDivNorm(partLo_fix, (partLo_fix + partHi_fix)),
2313
0
                              minDiff_fix));
2314
0
    peMin_fix = fixMax(0, peMin_fix);
2315
2316
0
    *peMax = peMax_fix;
2317
0
    *peMin = peMin_fix;
2318
0
  }
2319
0
}
2320
2321
/*****************************************************************************
2322
2323
  functionname: BitresCalcBitFac
2324
  description:  calculates factor of spending bits for one frame
2325
  1.0 : take all frame dynpart bits
2326
  >1.0 : take all frame dynpart bits + bitres
2327
  <1.0 : put bits in bitreservoir
2328
  returns:      BitFac
2329
  input:        bitres-fullness, pe, blockType, parameter-settings
2330
  output:
2331
2332
*****************************************************************************/
2333
/*
2334
                     bitfac(%)            pemax
2335
                   bitspend(%)   |          /-----------maxBitres
2336
                                 |         /
2337
                                 |        /
2338
                                 |       /
2339
                                 |      /
2340
                                 |     /
2341
                                 |----/-----------------> pe
2342
                                 |   /
2343
                   bitsave(%)    |--/
2344
                                    pemin
2345
*/
2346
2347
void FDKaacEnc_bitresCalcBitFac(const INT bitresBits, const INT maxBitresBits,
2348
                                const INT pe, const INT lastWindowSequence,
2349
                                const INT avgBits, const FIXP_DBL maxBitFac,
2350
                                const ADJ_THR_STATE *const AdjThr,
2351
                                ATS_ELEMENT *const adjThrChan,
2352
                                FIXP_DBL *const pBitresFac,
2353
0
                                INT *const pBitresFac_e) {
2354
0
  const BRES_PARAM *bresParam;
2355
0
  INT pex;
2356
0
  FIXP_DBL fillLevel;
2357
0
  INT fillLevel_e = 0;
2358
2359
0
  FIXP_DBL bitresFac;
2360
0
  INT bitresFac_e;
2361
2362
0
  FIXP_DBL bitSave, bitSpend;
2363
0
  FIXP_DBL bitsave_slope, bitspend_slope;
2364
0
  FIXP_DBL fillLevel_fix = MAXVAL_DBL;
2365
2366
0
  FIXP_DBL slope = MAXVAL_DBL;
2367
2368
0
  if (lastWindowSequence != SHORT_WINDOW) {
2369
0
    bresParam = &(AdjThr->bresParamLong);
2370
0
    bitsave_slope = FL2FXCONST_DBL(0.466666666);
2371
0
    bitspend_slope = FL2FXCONST_DBL(0.666666666);
2372
0
  } else {
2373
0
    bresParam = &(AdjThr->bresParamShort);
2374
0
    bitsave_slope = (FIXP_DBL)0x2E8BA2E9;
2375
0
    bitspend_slope = (FIXP_DBL)0x7fffffff;
2376
0
  }
2377
2378
  // fillLevel = (float)(bitresBits+avgBits) / (float)(maxBitresBits + avgBits);
2379
0
  if (bitresBits < maxBitresBits) {
2380
0
    fillLevel_fix = fDivNorm(bitresBits, maxBitresBits);
2381
0
  }
2382
2383
0
  pex = fMax(pe, adjThrChan->peMin);
2384
0
  pex = fMin(pex, adjThrChan->peMax);
2385
2386
0
  bitSave = FDKaacEnc_calcBitSave(
2387
0
      fillLevel_fix, bresParam->clipSaveLow, bresParam->clipSaveHigh,
2388
0
      bresParam->minBitSave, bresParam->maxBitSave, bitsave_slope);
2389
2390
0
  bitSpend = FDKaacEnc_calcBitSpend(
2391
0
      fillLevel_fix, bresParam->clipSpendLow, bresParam->clipSpendHigh,
2392
0
      bresParam->minBitSpend, bresParam->maxBitSpend, bitspend_slope);
2393
2394
0
  slope = schur_div((pex - adjThrChan->peMin),
2395
0
                    (adjThrChan->peMax - adjThrChan->peMin), 31);
2396
2397
  /* scale down by 1 bit because the result of the following addition can be
2398
   * bigger than 1 (though smaller than 2) */
2399
0
  bitresFac = ((FIXP_DBL)(MAXVAL_DBL >> 1) - (bitSave >> 1));
2400
0
  bitresFac_e = 1;                                                /* exp=1 */
2401
0
  bitresFac = fMultAddDiv2(bitresFac, slope, bitSpend + bitSave); /* exp=1 */
2402
2403
  /*** limit bitresFac for small bitreservoir ***/
2404
0
  fillLevel = fDivNorm(bitresBits, avgBits, &fillLevel_e);
2405
0
  if (fillLevel_e < 0) {
2406
0
    fillLevel = scaleValue(fillLevel, fillLevel_e);
2407
0
    fillLevel_e = 0;
2408
0
  }
2409
  /* shift down value by 1 because of summation, ... */
2410
0
  fillLevel >>= 1;
2411
0
  fillLevel_e += 1;
2412
  /* ..., this summation: */
2413
0
  fillLevel += scaleValue(FL2FXCONST_DBL(0.7f), -fillLevel_e);
2414
  /* set bitresfactor to same exponent as fillLevel */
2415
0
  if (scaleValue(bitresFac, -fillLevel_e + 1) > fillLevel) {
2416
0
    bitresFac = fillLevel;
2417
0
    bitresFac_e = fillLevel_e;
2418
0
  }
2419
2420
  /* limit bitresFac for high bitrates */
2421
0
  if (scaleValue(bitresFac, bitresFac_e - (DFRACT_BITS - 1 - 24)) > maxBitFac) {
2422
0
    bitresFac = maxBitFac;
2423
0
    bitresFac_e = (DFRACT_BITS - 1 - 24);
2424
0
  }
2425
2426
0
  FDKaacEnc_adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax);
2427
2428
  /* output values */
2429
0
  *pBitresFac = bitresFac;
2430
0
  *pBitresFac_e = bitresFac_e;
2431
0
}
2432
2433
/*****************************************************************************
2434
functionname: FDKaacEnc_AdjThrNew
2435
description:  allocate ADJ_THR_STATE
2436
*****************************************************************************/
2437
0
INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE **phAdjThr, INT nElements) {
2438
0
  INT err = 0;
2439
0
  INT i;
2440
0
  ADJ_THR_STATE *hAdjThr = GetRam_aacEnc_AdjustThreshold();
2441
0
  if (hAdjThr == NULL) {
2442
0
    err = 1;
2443
0
    goto bail;
2444
0
  }
2445
2446
0
  for (i = 0; i < nElements; i++) {
2447
0
    hAdjThr->adjThrStateElem[i] = GetRam_aacEnc_AdjThrStateElement(i);
2448
0
    if (hAdjThr->adjThrStateElem[i] == NULL) {
2449
0
      err = 1;
2450
0
      goto bail;
2451
0
    }
2452
0
  }
2453
2454
0
bail:
2455
0
  *phAdjThr = hAdjThr;
2456
0
  return err;
2457
0
}
2458
2459
/*****************************************************************************
2460
functionname: FDKaacEnc_AdjThrInit
2461
description:  initialize ADJ_THR_STATE
2462
*****************************************************************************/
2463
void FDKaacEnc_AdjThrInit(
2464
    ADJ_THR_STATE *const hAdjThr, const INT meanPe, const INT invQuant,
2465
    const CHANNEL_MAPPING *const channelMapping, const INT sampleRate,
2466
    const INT totalBitrate, const INT isLowDelay,
2467
    const AACENC_BITRES_MODE bitResMode, const INT dZoneQuantEnable,
2468
0
    const INT bitDistributionMode, const FIXP_DBL vbrQualFactor) {
2469
0
  INT i;
2470
2471
0
  FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f);
2472
0
  FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f);
2473
2474
0
  if (bitDistributionMode == 1) {
2475
0
    hAdjThr->bitDistributionMode = AACENC_BD_MODE_INTRA_ELEMENT;
2476
0
  } else {
2477
0
    hAdjThr->bitDistributionMode = AACENC_BD_MODE_INTER_ELEMENT;
2478
0
  }
2479
2480
  /* Max number of iterations in second guess is 3 for lowdelay aot and for
2481
     configurations with multiple audio elements in general, otherwise iteration
2482
     value is always 1. */
2483
0
  hAdjThr->maxIter2ndGuess =
2484
0
      (isLowDelay != 0 || channelMapping->nElements > 1) ? 3 : 1;
2485
2486
  /* common for all elements: */
2487
  /* parameters for bitres control */
2488
0
  hAdjThr->bresParamLong.clipSaveLow =
2489
0
      (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
2490
0
  hAdjThr->bresParamLong.clipSaveHigh =
2491
0
      (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
2492
0
  hAdjThr->bresParamLong.minBitSave =
2493
0
      (FIXP_DBL)0xf999999a; /* FL2FXCONST_DBL(-0.05f); */
2494
0
  hAdjThr->bresParamLong.maxBitSave =
2495
0
      (FIXP_DBL)0x26666666; /* FL2FXCONST_DBL(0.3f); */
2496
0
  hAdjThr->bresParamLong.clipSpendLow =
2497
0
      (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
2498
0
  hAdjThr->bresParamLong.clipSpendHigh =
2499
0
      (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
2500
0
  hAdjThr->bresParamLong.minBitSpend =
2501
0
      (FIXP_DBL)0xf3333333; /* FL2FXCONST_DBL(-0.10f); */
2502
0
  hAdjThr->bresParamLong.maxBitSpend =
2503
0
      (FIXP_DBL)0x33333333; /* FL2FXCONST_DBL(0.4f); */
2504
2505
0
  hAdjThr->bresParamShort.clipSaveLow =
2506
0
      (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
2507
0
  hAdjThr->bresParamShort.clipSaveHigh =
2508
0
      (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
2509
0
  hAdjThr->bresParamShort.minBitSave =
2510
0
      (FIXP_DBL)0x00000000; /* FL2FXCONST_DBL(0.0f); */
2511
0
  hAdjThr->bresParamShort.maxBitSave =
2512
0
      (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
2513
0
  hAdjThr->bresParamShort.clipSpendLow =
2514
0
      (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
2515
0
  hAdjThr->bresParamShort.clipSpendHigh =
2516
0
      (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
2517
0
  hAdjThr->bresParamShort.minBitSpend =
2518
0
      (FIXP_DBL)0xf9999998; /* FL2FXCONST_DBL(-0.05f); */
2519
0
  hAdjThr->bresParamShort.maxBitSpend =
2520
0
      (FIXP_DBL)0x40000000; /* FL2FXCONST_DBL(0.5f); */
2521
2522
  /* specific for each element: */
2523
0
  for (i = 0; i < channelMapping->nElements; i++) {
2524
0
    const FIXP_DBL relativeBits = channelMapping->elInfo[i].relativeBits;
2525
0
    const INT nChannelsInElement = channelMapping->elInfo[i].nChannelsInEl;
2526
0
    const INT bitrateInElement =
2527
0
        (relativeBits != (FIXP_DBL)MAXVAL_DBL)
2528
0
            ? (INT)fMultNorm(relativeBits, (FIXP_DBL)totalBitrate)
2529
0
            : totalBitrate;
2530
0
    const INT chBitrate = bitrateInElement >> (nChannelsInElement == 1 ? 0 : 1);
2531
2532
0
    ATS_ELEMENT *atsElem = hAdjThr->adjThrStateElem[i];
2533
0
    MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam;
2534
2535
    /* parameters for bitres control */
2536
0
    if (isLowDelay) {
2537
0
      atsElem->peMin = fMultI(POINT8, meanPe);
2538
0
      atsElem->peMax = fMultI(POINT6, meanPe) << 1;
2539
0
    } else {
2540
0
      atsElem->peMin = fMultI(POINT8, meanPe) >> 1;
2541
0
      atsElem->peMax = fMultI(POINT6, meanPe);
2542
0
    }
2543
2544
    /* for use in FDKaacEnc_reduceThresholdsVBR */
2545
0
    atsElem->chaosMeasureOld = FL2FXCONST_DBL(0.3f);
2546
2547
    /* additional pe offset to correct pe2bits for low bitrates */
2548
    /* ---- no longer necessary, set by table ----- */
2549
0
    atsElem->peOffset = 0;
2550
2551
    /* vbr initialisation */
2552
0
    atsElem->vbrQualFactor = vbrQualFactor;
2553
0
    if (chBitrate < 32000) {
2554
0
      atsElem->peOffset =
2555
0
          fixMax(50, 100 - fMultI((FIXP_DBL)0x666667, chBitrate));
2556
0
    }
2557
2558
    /* avoid hole parameters */
2559
0
    if (chBitrate >= 20000) {
2560
0
      atsElem->ahParam.modifyMinSnr = TRUE;
2561
0
      atsElem->ahParam.startSfbL = 15;
2562
0
      atsElem->ahParam.startSfbS = 3;
2563
0
    } else {
2564
0
      atsElem->ahParam.modifyMinSnr = FALSE;
2565
0
      atsElem->ahParam.startSfbL = 0;
2566
0
      atsElem->ahParam.startSfbS = 0;
2567
0
    }
2568
2569
    /* minSnr adaptation */
2570
0
    msaParam->maxRed = FL2FXCONST_DBL(0.00390625f); /* 0.25f/64.0f */
2571
    /* start adaptation of minSnr for avgEn/sfbEn > startRatio */
2572
0
    msaParam->startRatio = FL2FXCONST_DBL(0.05190512648f); /* ld64(10.0f) */
2573
    /* maximum minSnr reduction to minSnr^maxRed is reached for
2574
       avgEn/sfbEn >= maxRatio */
2575
    /* msaParam->maxRatio = 1000.0f; */
2576
    /*msaParam->redRatioFac = ((float)1.0f - msaParam->maxRed) /
2577
     * ((float)10.0f*log10(msaParam->startRatio/msaParam->maxRatio)/log10(2.0f)*(float)0.3010299956f);*/
2578
0
    msaParam->redRatioFac = FL2FXCONST_DBL(-0.375f); /* -0.0375f * 10.0f */
2579
    /*msaParam->redOffs = (float)1.0f - msaParam->redRatioFac * (float)10.0f *
2580
     * log10(msaParam->startRatio)/log10(2.0f) * (float)0.3010299956f;*/
2581
0
    msaParam->redOffs = FL2FXCONST_DBL(0.021484375); /* 1.375f/64.0f */
2582
2583
    /* init pe correction */
2584
0
    atsElem->peCorrectionFactor_m = FL2FXCONST_DBL(0.5f); /* 1.0 */
2585
0
    atsElem->peCorrectionFactor_e = 1;
2586
2587
0
    atsElem->dynBitsLast = -1;
2588
0
    atsElem->peLast = 0;
2589
2590
    /* init bits to pe factor */
2591
2592
    /* init bits2PeFactor */
2593
0
    FDKaacEnc_InitBits2PeFactor(
2594
0
        &atsElem->bits2PeFactor_m, &atsElem->bits2PeFactor_e, bitrateInElement,
2595
0
        nChannelsInElement, sampleRate, isLowDelay, dZoneQuantEnable, invQuant);
2596
2597
0
  } /* for nElements */
2598
0
}
2599
2600
/*****************************************************************************
2601
    functionname: FDKaacEnc_FDKaacEnc_calcPeCorrection
2602
    description:  calc desired pe
2603
*****************************************************************************/
2604
static void FDKaacEnc_FDKaacEnc_calcPeCorrection(
2605
    FIXP_DBL *const correctionFac_m, INT *const correctionFac_e,
2606
    const INT peAct, const INT peLast, const INT bitsLast,
2607
0
    const FIXP_DBL bits2PeFactor_m, const INT bits2PeFactor_e) {
2608
0
  if ((bitsLast > 0) && (peAct < 1.5f * peLast) && (peAct > 0.7f * peLast) &&
2609
0
      (FDKaacEnc_bits2pe2(bitsLast,
2610
0
                          fMult(FL2FXCONST_DBL(1.2f / 2.f), bits2PeFactor_m),
2611
0
                          bits2PeFactor_e + 1) > peLast) &&
2612
0
      (FDKaacEnc_bits2pe2(bitsLast,
2613
0
                          fMult(FL2FXCONST_DBL(0.65f), bits2PeFactor_m),
2614
0
                          bits2PeFactor_e) < peLast)) {
2615
0
    FIXP_DBL corrFac = *correctionFac_m;
2616
2617
0
    int scaling = 0;
2618
0
    FIXP_DBL denum = (FIXP_DBL)FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m,
2619
0
                                                  bits2PeFactor_e);
2620
0
    FIXP_DBL newFac = fDivNorm((FIXP_DBL)peLast, denum, &scaling);
2621
2622
    /* dead zone, newFac and corrFac are scaled by 0.5 */
2623
0
    if ((FIXP_DBL)peLast <= denum) { /* ratio <= 1.f */
2624
0
      newFac = fixMax(
2625
0
          scaleValue(fixMin(fMult(FL2FXCONST_DBL(1.1f / 2.f), newFac),
2626
0
                            scaleValue(FL2FXCONST_DBL(1.f / 2.f), -scaling)),
2627
0
                     scaling),
2628
0
          FL2FXCONST_DBL(0.85f / 2.f));
2629
0
    } else { /* ratio < 1.f */
2630
0
      newFac = fixMax(
2631
0
          fixMin(scaleValue(fMult(FL2FXCONST_DBL(0.9f / 2.f), newFac), scaling),
2632
0
                 FL2FXCONST_DBL(1.15f / 2.f)),
2633
0
          FL2FXCONST_DBL(1.f / 2.f));
2634
0
    }
2635
2636
0
    if (((newFac > FL2FXCONST_DBL(1.f / 2.f)) &&
2637
0
         (corrFac < FL2FXCONST_DBL(1.f / 2.f))) ||
2638
0
        ((newFac < FL2FXCONST_DBL(1.f / 2.f)) &&
2639
0
         (corrFac > FL2FXCONST_DBL(1.f / 2.f)))) {
2640
0
      corrFac = FL2FXCONST_DBL(1.f / 2.f);
2641
0
    }
2642
2643
    /* faster adaptation towards 1.0, slower in the other direction */
2644
0
    if ((corrFac < FL2FXCONST_DBL(1.f / 2.f) && newFac < corrFac) ||
2645
0
        (corrFac > FL2FXCONST_DBL(1.f / 2.f) && newFac > corrFac)) {
2646
0
      corrFac = fMult(FL2FXCONST_DBL(0.85f), corrFac) +
2647
0
                fMult(FL2FXCONST_DBL(0.15f), newFac);
2648
0
    } else {
2649
0
      corrFac = fMult(FL2FXCONST_DBL(0.7f), corrFac) +
2650
0
                fMult(FL2FXCONST_DBL(0.3f), newFac);
2651
0
    }
2652
2653
0
    corrFac = fixMax(fixMin(corrFac, FL2FXCONST_DBL(1.15f / 2.f)),
2654
0
                     FL2FXCONST_DBL(0.85 / 2.f));
2655
2656
0
    *correctionFac_m = corrFac;
2657
0
    *correctionFac_e = 1;
2658
0
  } else {
2659
0
    *correctionFac_m = FL2FXCONST_DBL(1.f / 2.f);
2660
0
    *correctionFac_e = 1;
2661
0
  }
2662
0
}
2663
2664
static void FDKaacEnc_calcPeCorrectionLowBitRes(
2665
    FIXP_DBL *const correctionFac_m, INT *const correctionFac_e,
2666
    const INT peLast, const INT bitsLast, const INT bitresLevel,
2667
    const INT nChannels, const FIXP_DBL bits2PeFactor_m,
2668
0
    const INT bits2PeFactor_e) {
2669
  /* tuning params */
2670
0
  const FIXP_DBL amp = FL2FXCONST_DBL(0.005);
2671
0
  const FIXP_DBL maxDiff = FL2FXCONST_DBL(0.25f);
2672
2673
0
  if (bitsLast > 0) {
2674
    /* Estimate deviation of granted and used dynamic bits in previous frame, in
2675
     * PE units */
2676
0
    const int bitsBalLast =
2677
0
        peLast - FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m, bits2PeFactor_e);
2678
2679
    /* reserve n bits per channel */
2680
0
    int headroom = (bitresLevel >= 50 * nChannels) ? 0 : (100 * nChannels);
2681
2682
    /* in PE units */
2683
0
    headroom = FDKaacEnc_bits2pe2(headroom, bits2PeFactor_m, bits2PeFactor_e);
2684
2685
    /*
2686
     * diff = amp * ((bitsBalLast - headroom) / (bitresLevel + headroom)
2687
     * diff = max ( min ( diff, maxDiff, -maxDiff)) / 2
2688
     */
2689
0
    FIXP_DBL denominator = (FIXP_DBL)FDKaacEnc_bits2pe2(
2690
0
                               bitresLevel, bits2PeFactor_m, bits2PeFactor_e) +
2691
0
                           (FIXP_DBL)headroom;
2692
2693
0
    int scaling = 0;
2694
0
    FIXP_DBL diff =
2695
0
        (bitsBalLast >= headroom)
2696
0
            ? fMult(amp, fDivNorm((FIXP_DBL)(bitsBalLast - headroom),
2697
0
                                  denominator, &scaling))
2698
0
            : -fMult(amp, fDivNorm(-(FIXP_DBL)(bitsBalLast - headroom),
2699
0
                                   denominator, &scaling));
2700
2701
0
    scaling -= 1; /* divide by 2 */
2702
2703
0
    diff = (scaling <= 0)
2704
0
               ? fMax(fMin(diff >> (-scaling), maxDiff >> 1), -maxDiff >> 1)
2705
0
               : fMax(fMin(diff, maxDiff >> (1 + scaling)),
2706
0
                      -maxDiff >> (1 + scaling))
2707
0
                     << scaling;
2708
2709
    /*
2710
     * corrFac += diff
2711
     * corrFac = max ( min ( corrFac/2.f, 1.f/2.f, 0.75f/2.f ) )
2712
     */
2713
0
    *correctionFac_m =
2714
0
        fMax(fMin((*correctionFac_m) + diff, FL2FXCONST_DBL(1.0f / 2.f)),
2715
0
             FL2FXCONST_DBL(0.75f / 2.f));
2716
0
    *correctionFac_e = 1;
2717
0
  } else {
2718
0
    *correctionFac_m = FL2FXCONST_DBL(0.75 / 2.f);
2719
0
    *correctionFac_e = 1;
2720
0
  }
2721
0
}
2722
2723
void FDKaacEnc_DistributeBits(
2724
    ADJ_THR_STATE *adjThrState, ATS_ELEMENT *AdjThrStateElement,
2725
    PSY_OUT_CHANNEL *psyOutChannel[(2)], PE_DATA *peData, INT *grantedPe,
2726
    INT *grantedPeCorr, const INT nChannels, const INT commonWindow,
2727
    const INT grantedDynBits, const INT bitresBits, const INT maxBitresBits,
2728
0
    const FIXP_DBL maxBitFac, const AACENC_BITRES_MODE bitResMode) {
2729
0
  FIXP_DBL bitFactor;
2730
0
  INT bitFactor_e;
2731
0
  INT noRedPe = peData->pe;
2732
2733
  /* prefer short windows for calculation of bitFactor */
2734
0
  INT curWindowSequence = LONG_WINDOW;
2735
0
  if (nChannels == 2) {
2736
0
    if ((psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) ||
2737
0
        (psyOutChannel[1]->lastWindowSequence == SHORT_WINDOW)) {
2738
0
      curWindowSequence = SHORT_WINDOW;
2739
0
    }
2740
0
  } else {
2741
0
    curWindowSequence = psyOutChannel[0]->lastWindowSequence;
2742
0
  }
2743
2744
0
  if (grantedDynBits >= 1) {
2745
0
    if (bitResMode != AACENC_BR_MODE_FULL) {
2746
      /* small or disabled bitreservoir */
2747
0
      *grantedPe = FDKaacEnc_bits2pe2(grantedDynBits,
2748
0
                                      AdjThrStateElement->bits2PeFactor_m,
2749
0
                                      AdjThrStateElement->bits2PeFactor_e);
2750
0
    } else {
2751
      /* factor dependend on current fill level and pe */
2752
0
      FDKaacEnc_bitresCalcBitFac(
2753
0
          bitresBits, maxBitresBits, noRedPe, curWindowSequence, grantedDynBits,
2754
0
          maxBitFac, adjThrState, AdjThrStateElement, &bitFactor, &bitFactor_e);
2755
2756
      /* desired pe for actual frame */
2757
      /* Worst case max of grantedDynBits is = 1024 * 5.27 * 2 */
2758
0
      *grantedPe = FDKaacEnc_bits2pe2(
2759
0
          grantedDynBits, fMult(bitFactor, AdjThrStateElement->bits2PeFactor_m),
2760
0
          AdjThrStateElement->bits2PeFactor_e + bitFactor_e);
2761
0
    }
2762
0
  } else {
2763
0
    *grantedPe = 0; /* prevent divsion by 0 */
2764
0
  }
2765
2766
  /* correction of pe value */
2767
0
  switch (bitResMode) {
2768
0
    case AACENC_BR_MODE_DISABLED:
2769
0
    case AACENC_BR_MODE_REDUCED:
2770
      /* correction of pe value for low bitres */
2771
0
      FDKaacEnc_calcPeCorrectionLowBitRes(
2772
0
          &AdjThrStateElement->peCorrectionFactor_m,
2773
0
          &AdjThrStateElement->peCorrectionFactor_e, AdjThrStateElement->peLast,
2774
0
          AdjThrStateElement->dynBitsLast, bitresBits, nChannels,
2775
0
          AdjThrStateElement->bits2PeFactor_m,
2776
0
          AdjThrStateElement->bits2PeFactor_e);
2777
0
      break;
2778
0
    case AACENC_BR_MODE_FULL:
2779
0
    default:
2780
      /* correction of pe value for high bitres */
2781
0
      FDKaacEnc_FDKaacEnc_calcPeCorrection(
2782
0
          &AdjThrStateElement->peCorrectionFactor_m,
2783
0
          &AdjThrStateElement->peCorrectionFactor_e,
2784
0
          fixMin(*grantedPe, noRedPe), AdjThrStateElement->peLast,
2785
0
          AdjThrStateElement->dynBitsLast, AdjThrStateElement->bits2PeFactor_m,
2786
0
          AdjThrStateElement->bits2PeFactor_e);
2787
0
      break;
2788
0
  }
2789
2790
0
  *grantedPeCorr =
2791
0
      (INT)(fMult((FIXP_DBL)(*grantedPe << Q_AVGBITS),
2792
0
                  AdjThrStateElement->peCorrectionFactor_m) >>
2793
0
            (Q_AVGBITS - AdjThrStateElement->peCorrectionFactor_e));
2794
2795
  /* update last pe */
2796
0
  AdjThrStateElement->peLast = *grantedPe;
2797
0
  AdjThrStateElement->dynBitsLast = -1;
2798
0
}
2799
2800
/*****************************************************************************
2801
functionname: FDKaacEnc_AdjustThresholds
2802
description:  adjust thresholds
2803
*****************************************************************************/
2804
void FDKaacEnc_AdjustThresholds(
2805
    ADJ_THR_STATE *const hAdjThr, QC_OUT_ELEMENT *const qcElement[((8))],
2806
    QC_OUT *const qcOut, const PSY_OUT_ELEMENT *const psyOutElement[((8))],
2807
0
    const INT CBRbitrateMode, const CHANNEL_MAPPING *const cm) {
2808
0
  int i;
2809
2810
0
  if (CBRbitrateMode) {
2811
    /* In case, no bits must be shifted between different elements, */
2812
    /* an element-wise execution of the pe-dependent threshold- */
2813
    /* adaption becomes necessary... */
2814
0
    if (hAdjThr->bitDistributionMode == AACENC_BD_MODE_INTRA_ELEMENT) {
2815
0
      for (i = 0; i < cm->nElements; i++) {
2816
0
        ELEMENT_INFO elInfo = cm->elInfo[i];
2817
2818
0
        if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
2819
0
            (elInfo.elType == ID_LFE)) {
2820
          /* qcElement[i]->grantedPe = 2000; */ /* Use this only for debugging
2821
                                                 */
2822
          // if (totalGrantedPeCorr < totalNoRedPe) {
2823
0
          if (qcElement[i]->grantedPeCorr < qcElement[i]->peData.pe) {
2824
            /* calc threshold necessary for desired pe */
2825
0
            FDKaacEnc_adaptThresholdsToPe(
2826
0
                cm, hAdjThr->adjThrStateElem, qcElement, psyOutElement,
2827
0
                qcElement[i]->grantedPeCorr, hAdjThr->maxIter2ndGuess,
2828
0
                1, /* Process only 1 element */
2829
0
                i  /* Process exactly THIS element */
2830
0
            );
2831
0
          }
2832
0
        } /*  -end- if(ID_SCE || ID_CPE || ID_LFE) */
2833
0
      }   /* -end- element loop */
2834
0
    }     /* AACENC_BD_MODE_INTRA_ELEMENT */
2835
0
    else if (hAdjThr->bitDistributionMode == AACENC_BD_MODE_INTER_ELEMENT) {
2836
      /* Use global Pe to obtain the thresholds? */
2837
0
      if (qcOut->totalGrantedPeCorr < qcOut->totalNoRedPe) {
2838
        /* add equal loadness quantization noise to match the */
2839
        /* desired pe calc threshold necessary for desired pe */
2840
        /* Now carried out globally to cover all(!) channels. */
2841
0
        FDKaacEnc_adaptThresholdsToPe(cm, hAdjThr->adjThrStateElem, qcElement,
2842
0
                                      psyOutElement, qcOut->totalGrantedPeCorr,
2843
0
                                      hAdjThr->maxIter2ndGuess,
2844
0
                                      cm->nElements, /* Process all elements */
2845
0
                                      0); /* Process exactly THIS element */
2846
0
      } else {
2847
        /* In case global pe doesn't need to be reduced check each element to
2848
           hold estimated bitrate below maximum element bitrate. */
2849
0
        for (i = 0; i < cm->nElements; i++) {
2850
0
          if ((cm->elInfo[i].elType == ID_SCE) ||
2851
0
              (cm->elInfo[i].elType == ID_CPE) ||
2852
0
              (cm->elInfo[i].elType == ID_LFE)) {
2853
            /* Element pe applies to dynamic bits of maximum element bitrate. */
2854
0
            const int maxElementPe = FDKaacEnc_bits2pe2(
2855
0
                (cm->elInfo[i].nChannelsInEl * MIN_BUFSIZE_PER_EFF_CHAN) -
2856
0
                    qcElement[i]->staticBitsUsed - qcElement[i]->extBitsUsed,
2857
0
                hAdjThr->adjThrStateElem[i]->bits2PeFactor_m,
2858
0
                hAdjThr->adjThrStateElem[i]->bits2PeFactor_e);
2859
2860
0
            if (maxElementPe < qcElement[i]->peData.pe) {
2861
0
              FDKaacEnc_adaptThresholdsToPe(
2862
0
                  cm, hAdjThr->adjThrStateElem, qcElement, psyOutElement,
2863
0
                  maxElementPe, hAdjThr->maxIter2ndGuess, 1, i);
2864
0
            }
2865
0
          } /*  -end- if(ID_SCE || ID_CPE || ID_LFE) */
2866
0
        }   /* -end- element loop */
2867
0
      }     /* (qcOut->totalGrantedPeCorr < qcOut->totalNoRedPe) */
2868
0
    }       /* AACENC_BD_MODE_INTER_ELEMENT */
2869
0
  } else {
2870
0
    for (i = 0; i < cm->nElements; i++) {
2871
0
      ELEMENT_INFO elInfo = cm->elInfo[i];
2872
2873
0
      if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
2874
0
          (elInfo.elType == ID_LFE)) {
2875
        /* for VBR-mode */
2876
0
        FDKaacEnc_AdaptThresholdsVBR(
2877
0
            qcElement[i]->qcOutChannel, psyOutElement[i]->psyOutChannel,
2878
0
            hAdjThr->adjThrStateElem[i], &psyOutElement[i]->toolsInfo,
2879
0
            cm->elInfo[i].nChannelsInEl);
2880
0
      } /*  -end- if(ID_SCE || ID_CPE || ID_LFE) */
2881
2882
0
    } /* -end- element loop */
2883
0
  }
2884
0
  for (i = 0; i < cm->nElements; i++) {
2885
0
    int ch, sfb, sfbGrp;
2886
    /* no weighting of threholds and energies for mlout */
2887
    /* weight energies and thresholds */
2888
0
    for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) {
2889
0
      QC_OUT_CHANNEL *pQcOutCh = qcElement[i]->qcOutChannel[ch];
2890
0
      for (sfbGrp = 0; sfbGrp < psyOutElement[i]->psyOutChannel[ch]->sfbCnt;
2891
0
           sfbGrp += psyOutElement[i]->psyOutChannel[ch]->sfbPerGroup) {
2892
0
        for (sfb = 0; sfb < psyOutElement[i]->psyOutChannel[ch]->maxSfbPerGroup;
2893
0
             sfb++) {
2894
0
          pQcOutCh->sfbThresholdLdData[sfb + sfbGrp] +=
2895
0
              pQcOutCh->sfbEnFacLd[sfb + sfbGrp];
2896
0
        }
2897
0
      }
2898
0
    }
2899
0
  }
2900
0
}
2901
2902
0
void FDKaacEnc_AdjThrClose(ADJ_THR_STATE **phAdjThr) {
2903
0
  INT i;
2904
0
  ADJ_THR_STATE *hAdjThr = *phAdjThr;
2905
2906
0
  if (hAdjThr != NULL) {
2907
0
    for (i = 0; i < ((8)); i++) {
2908
0
      if (hAdjThr->adjThrStateElem[i] != NULL) {
2909
0
        FreeRam_aacEnc_AdjThrStateElement(&hAdjThr->adjThrStateElem[i]);
2910
0
      }
2911
0
    }
2912
0
    FreeRam_aacEnc_AdjustThreshold(phAdjThr);
2913
0
  }
2914
0
}