Coverage Report

Created: 2023-03-26 06:13

/src/aac/libAACenc/src/metadata_compressor.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 - 2018 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. Neusinger
98
99
   Description: Compressor for AAC Metadata Generator
100
101
*******************************************************************************/
102
103
#include "metadata_compressor.h"
104
#include "channel_map.h"
105
106
#define LOG2 0.69314718056f /* natural logarithm of 2 */
107
#define ILOG2 1.442695041f  /* 1/LOG2 */
108
0
#define FIXP_ILOG2_DIV2 (FL2FXCONST_DBL(ILOG2 / 2))
109
110
/*----------------- defines ----------------------*/
111
112
#define MAX_DRC_CHANNELS (8)       /*!< Max number of audio input channels. */
113
0
#define DOWNMIX_SHIFT (3)          /*!< Max 8 channel. */
114
0
#define WEIGHTING_FILTER_SHIFT (2) /*!< Scaling used in weighting filter. */
115
116
0
#define METADATA_INT_BITS 10
117
0
#define METADATA_LINT_BITS 20
118
#define METADATA_INT_SCALE (INT64(1) << (METADATA_INT_BITS))
119
0
#define METADATA_FRACT_BITS (DFRACT_BITS - 1 - METADATA_INT_BITS)
120
0
#define METADATA_FRACT_SCALE (INT64(1) << (METADATA_FRACT_BITS))
121
122
/**
123
 *  Enum for channel assignment.
124
 */
125
enum { L = 0, R = 1, C = 2, LFE = 3, LS = 4, RS = 5, S = 6, LS2 = 7, RS2 = 8 };
126
127
/*--------------- structure definitions --------------------*/
128
129
/**
130
 *  Structure holds weighting filter filter states.
131
 */
132
struct WEIGHTING_STATES {
133
  FIXP_DBL x1;
134
  FIXP_DBL x2;
135
  FIXP_DBL y1;
136
  FIXP_DBL y2;
137
};
138
139
/**
140
 *  Dynamic Range Control compressor structure.
141
 */
142
struct DRC_COMP {
143
  FIXP_DBL maxBoostThr[2]; /*!< Max boost threshold. */
144
  FIXP_DBL boostThr[2];    /*!< Boost threshold. */
145
  FIXP_DBL earlyCutThr[2]; /*!< Early cut threshold. */
146
  FIXP_DBL cutThr[2];      /*!< Cut threshold. */
147
  FIXP_DBL maxCutThr[2];   /*!< Max cut threshold. */
148
149
  FIXP_DBL boostFac[2]; /*!< Precalculated factor for boost compression. */
150
  FIXP_DBL
151
  earlyCutFac[2];     /*!< Precalculated factor for early cut compression. */
152
  FIXP_DBL cutFac[2]; /*!< Precalculated factor for cut compression. */
153
154
  FIXP_DBL maxBoost[2];    /*!< Maximum boost. */
155
  FIXP_DBL maxCut[2];      /*!< Maximum cut. */
156
  FIXP_DBL maxEarlyCut[2]; /*!< Maximum early cut. */
157
158
  FIXP_DBL fastAttack[2]; /*!< Fast attack coefficient. */
159
  FIXP_DBL fastDecay[2];  /*!< Fast release coefficient. */
160
  FIXP_DBL slowAttack[2]; /*!< Slow attack coefficient. */
161
  FIXP_DBL slowDecay[2];  /*!< Slow release coefficient. */
162
  UINT holdOff[2];        /*!< Hold time in blocks. */
163
164
  FIXP_DBL attackThr[2]; /*!< Slow/fast attack threshold. */
165
  FIXP_DBL decayThr[2];  /*!< Slow/fast release threshold. */
166
167
  DRC_PROFILE profile[2];  /*!< DRC profile. */
168
  INT blockLength;         /*!< Block length in samples. */
169
  UINT sampleRate;         /*!< Sample rate. */
170
  CHANNEL_MODE chanConfig; /*!< Channel configuration. */
171
172
  UCHAR useWeighting; /*!< Use weighting filter. */
173
174
  UINT channels;     /*!< Number of channels. */
175
  UINT fullChannels; /*!< Number of full range channels. */
176
  INT channelIdx[9]; /*!< Offsets of interleaved channel samples (L, R, C, LFE,
177
                        Ls, Rs, S, Ls2, Rs2). */
178
179
  FIXP_DBL smoothLevel[2]; /*!< level smoothing states */
180
  FIXP_DBL smoothGain[2];  /*!< gain smoothing states */
181
  UINT holdCnt[2];         /*!< hold counter */
182
183
  FIXP_DBL limGain[2];  /*!< limiter gain */
184
  FIXP_DBL limDecay;    /*!< limiter decay (linear) */
185
  FIXP_DBL prevPeak[2]; /*!< max peak of previous block (stereo/mono)*/
186
187
  WEIGHTING_STATES
188
  filter[MAX_DRC_CHANNELS]; /*!< array holds weighting filter states */
189
};
190
191
/*---------------- constants -----------------------*/
192
193
/**
194
 *  Profile tables.
195
 */
196
static const FIXP_DBL tabMaxBoostThr[] = {
197
    (FIXP_DBL)(-(43 << METADATA_FRACT_BITS)),
198
    (FIXP_DBL)(-(53 << METADATA_FRACT_BITS)),
199
    (FIXP_DBL)(-(55 << METADATA_FRACT_BITS)),
200
    (FIXP_DBL)(-(65 << METADATA_FRACT_BITS)),
201
    (FIXP_DBL)(-(50 << METADATA_FRACT_BITS)),
202
    (FIXP_DBL)(-(40 << METADATA_FRACT_BITS))};
203
static const FIXP_DBL tabBoostThr[] = {
204
    (FIXP_DBL)(-(31 << METADATA_FRACT_BITS)),
205
    (FIXP_DBL)(-(41 << METADATA_FRACT_BITS)),
206
    (FIXP_DBL)(-(31 << METADATA_FRACT_BITS)),
207
    (FIXP_DBL)(-(41 << METADATA_FRACT_BITS)),
208
    (FIXP_DBL)(-(31 << METADATA_FRACT_BITS)),
209
    (FIXP_DBL)(-(31 << METADATA_FRACT_BITS))};
210
static const FIXP_DBL tabEarlyCutThr[] = {
211
    (FIXP_DBL)(-(26 << METADATA_FRACT_BITS)),
212
    (FIXP_DBL)(-(21 << METADATA_FRACT_BITS)),
213
    (FIXP_DBL)(-(26 << METADATA_FRACT_BITS)),
214
    (FIXP_DBL)(-(21 << METADATA_FRACT_BITS)),
215
    (FIXP_DBL)(-(26 << METADATA_FRACT_BITS)),
216
    (FIXP_DBL)(-(20 << METADATA_FRACT_BITS))};
217
static const FIXP_DBL tabCutThr[] = {(FIXP_DBL)(-(16 << METADATA_FRACT_BITS)),
218
                                     (FIXP_DBL)(-(11 << METADATA_FRACT_BITS)),
219
                                     (FIXP_DBL)(-(16 << METADATA_FRACT_BITS)),
220
                                     (FIXP_DBL)(-(21 << METADATA_FRACT_BITS)),
221
                                     (FIXP_DBL)(-(16 << METADATA_FRACT_BITS)),
222
                                     (FIXP_DBL)(-(10 << METADATA_FRACT_BITS))};
223
static const FIXP_DBL tabMaxCutThr[] = {
224
    (FIXP_DBL)(4 << METADATA_FRACT_BITS), (FIXP_DBL)(9 << METADATA_FRACT_BITS),
225
    (FIXP_DBL)(4 << METADATA_FRACT_BITS), (FIXP_DBL)(9 << METADATA_FRACT_BITS),
226
    (FIXP_DBL)(4 << METADATA_FRACT_BITS), (FIXP_DBL)(4 << METADATA_FRACT_BITS)};
227
static const FIXP_DBL tabBoostRatio[] = {
228
    FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f)),
229
    FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f)),
230
    FL2FXCONST_DBL(((1.f / 5.f) - 1.f)), FL2FXCONST_DBL(((1.f / 5.f) - 1.f))};
231
static const FIXP_DBL tabEarlyCutRatio[] = {
232
    FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f)),
233
    FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 1.f) - 1.f)),
234
    FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f))};
235
static const FIXP_DBL tabCutRatio[] = {
236
    FL2FXCONST_DBL(((1.f / 20.f) - 1.f)), FL2FXCONST_DBL(((1.f / 20.f) - 1.f)),
237
    FL2FXCONST_DBL(((1.f / 20.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f)),
238
    FL2FXCONST_DBL(((1.f / 20.f) - 1.f)), FL2FXCONST_DBL(((1.f / 20.f) - 1.f))};
239
static const FIXP_DBL tabMaxBoost[] = {(FIXP_DBL)(6 << METADATA_FRACT_BITS),
240
                                       (FIXP_DBL)(6 << METADATA_FRACT_BITS),
241
                                       (FIXP_DBL)(12 << METADATA_FRACT_BITS),
242
                                       (FIXP_DBL)(12 << METADATA_FRACT_BITS),
243
                                       (FIXP_DBL)(15 << METADATA_FRACT_BITS),
244
                                       (FIXP_DBL)(15 << METADATA_FRACT_BITS)};
245
static const FIXP_DBL tabMaxCut[] = {(FIXP_DBL)(24 << METADATA_FRACT_BITS),
246
                                     (FIXP_DBL)(24 << METADATA_FRACT_BITS),
247
                                     (FIXP_DBL)(24 << METADATA_FRACT_BITS),
248
                                     (FIXP_DBL)(15 << METADATA_FRACT_BITS),
249
                                     (FIXP_DBL)(24 << METADATA_FRACT_BITS),
250
                                     (FIXP_DBL)(24 << METADATA_FRACT_BITS)};
251
static const FIXP_DBL tabFastAttack[] = {
252
    FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE),
253
    FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE),
254
    FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE),
255
    FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE),
256
    FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE),
257
    FL2FXCONST_DBL((0.f / 1000.f) / METADATA_INT_SCALE)};
258
static const FIXP_DBL tabFastDecay[] = {
259
    FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE),
260
    FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE),
261
    FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE),
262
    FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE),
263
    FL2FXCONST_DBL((200.f / 1000.f) / METADATA_INT_SCALE),
264
    FL2FXCONST_DBL((0.f / 1000.f) / METADATA_INT_SCALE)};
265
static const FIXP_DBL tabSlowAttack[] = {
266
    FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE),
267
    FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE),
268
    FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE),
269
    FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE),
270
    FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE),
271
    FL2FXCONST_DBL((0.f / 1000.f) / METADATA_INT_SCALE)};
272
static const FIXP_DBL tabSlowDecay[] = {
273
    FL2FXCONST_DBL((3000.f / 1000.f) / METADATA_INT_SCALE),
274
    FL2FXCONST_DBL((3000.f / 1000.f) / METADATA_INT_SCALE),
275
    FL2FXCONST_DBL((10000.f / 1000.f) / METADATA_INT_SCALE),
276
    FL2FXCONST_DBL((3000.f / 1000.f) / METADATA_INT_SCALE),
277
    FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE),
278
    FL2FXCONST_DBL((0.f / 1000.f) / METADATA_INT_SCALE)};
279
280
static const INT tabHoldOff[] = {10, 10, 10, 10, 10, 0};
281
282
static const FIXP_DBL tabAttackThr[] = {(FIXP_DBL)(15 << METADATA_FRACT_BITS),
283
                                        (FIXP_DBL)(15 << METADATA_FRACT_BITS),
284
                                        (FIXP_DBL)(15 << METADATA_FRACT_BITS),
285
                                        (FIXP_DBL)(15 << METADATA_FRACT_BITS),
286
                                        (FIXP_DBL)(10 << METADATA_FRACT_BITS),
287
                                        (FIXP_DBL)(0 << METADATA_FRACT_BITS)};
288
static const FIXP_DBL tabDecayThr[] = {(FIXP_DBL)(20 << METADATA_FRACT_BITS),
289
                                       (FIXP_DBL)(20 << METADATA_FRACT_BITS),
290
                                       (FIXP_DBL)(20 << METADATA_FRACT_BITS),
291
                                       (FIXP_DBL)(20 << METADATA_FRACT_BITS),
292
                                       (FIXP_DBL)(10 << METADATA_FRACT_BITS),
293
                                       (FIXP_DBL)(0 << METADATA_FRACT_BITS)};
294
295
/**
296
 *  Weighting filter coefficients (biquad bandpass).
297
 */
298
static const FIXP_DBL b0 = FL2FXCONST_DBL(0.53050662f); /* b1 = 0, b2 = -b0 */
299
static const FIXP_DBL a1 = FL2FXCONST_DBL(-0.95237983f),
300
                      a2 = FL2FXCONST_DBL(-0.02248836f); /* a0 = 1 */
301
302
/*------------- function definitions ----------------*/
303
304
/**
305
 * \brief  Calculate scaling factor for denoted processing block.
306
 *
307
 * \param blockLength   Length of processing block.
308
 *
309
 * \return    shiftFactor
310
 */
311
0
static UINT getShiftFactor(const UINT length) {
312
0
  UINT ldN;
313
0
  for (ldN = 1; (((UINT)1) << ldN) < length; ldN++)
314
0
    ;
315
316
0
  return ldN;
317
0
}
318
319
/**
320
 * \brief  Sum up fixpoint values with best possible accuracy.
321
 *
322
 * \param value1        First input value.
323
 * \param q1            Scaling factor of first input value.
324
 * \param pValue2       Pointer to second input value, will be modified on
325
 * return.
326
 * \param pQ2           Pointer to second scaling factor, will be modified on
327
 * return.
328
 *
329
 * \return    void
330
 */
331
static void fixpAdd(const FIXP_DBL value1, const int q1,
332
0
                    FIXP_DBL* const pValue2, int* const pQ2) {
333
0
  const int headroom1 = fNormz(fixp_abs(value1)) - 1;
334
0
  const int headroom2 = fNormz(fixp_abs(*pValue2)) - 1;
335
0
  int resultScale = fixMax(q1 - headroom1, (*pQ2) - headroom2);
336
337
0
  if ((value1 != FL2FXCONST_DBL(0.f)) && (*pValue2 != FL2FXCONST_DBL(0.f))) {
338
0
    resultScale++;
339
0
  }
340
341
0
  *pValue2 = scaleValue(value1, q1 - resultScale) +
342
0
             scaleValue(*pValue2, (*pQ2) - resultScale);
343
0
  *pQ2 = (*pValue2 != (FIXP_DBL)0) ? resultScale : DFRACT_BITS - 1;
344
0
}
345
346
/**
347
 * \brief  Function for converting time constant to filter coefficient.
348
 *
349
 * \param t             Time constant.
350
 * \param sampleRate    Sampling rate in Hz.
351
 * \param blockLength   Length of processing block in samples per channel.
352
 *
353
 * \return    result = 1.0 - exp(-1.0/((t) * (f)))
354
 */
355
static FIXP_DBL tc2Coeff(const FIXP_DBL t, const INT sampleRate,
356
0
                         const INT blockLength) {
357
0
  FIXP_DBL sampleRateFract;
358
0
  FIXP_DBL blockLengthFract;
359
0
  FIXP_DBL f, product;
360
0
  FIXP_DBL exponent, result;
361
0
  INT e_res;
362
363
  /* f = sampleRate/blockLength */
364
0
  sampleRateFract =
365
0
      (FIXP_DBL)(sampleRate << (DFRACT_BITS - 1 - METADATA_LINT_BITS));
366
0
  blockLengthFract =
367
0
      (FIXP_DBL)(blockLength << (DFRACT_BITS - 1 - METADATA_LINT_BITS));
368
0
  f = fDivNorm(sampleRateFract, blockLengthFract, &e_res);
369
0
  f = scaleValue(f, e_res - METADATA_INT_BITS); /* convert to METADATA_FRACT */
370
371
  /* product = t*f */
372
0
  product = fMultNorm(t, f, &e_res);
373
0
  product = scaleValue(
374
0
      product, e_res + METADATA_INT_BITS); /* convert to METADATA_FRACT */
375
376
  /* exponent = (-1.0/((t) * (f))) */
377
0
  exponent = fDivNorm(METADATA_FRACT_SCALE, product, &e_res);
378
0
  exponent = scaleValue(
379
0
      exponent, e_res - METADATA_INT_BITS); /* convert to METADATA_FRACT */
380
381
  /* exponent * ld(e) */
382
0
  exponent = fMult(exponent, FIXP_ILOG2_DIV2) << 1; /* e^(x) = 2^(x*ld(e)) */
383
384
  /* exp(-1.0/((t) * (f))) */
385
0
  result = f2Pow(-exponent, DFRACT_BITS - 1 - METADATA_FRACT_BITS, &e_res);
386
387
  /* result = 1.0 - exp(-1.0/((t) * (f))) */
388
0
  result = (FIXP_DBL)MAXVAL_DBL - scaleValue(result, e_res);
389
390
0
  return result;
391
0
}
392
393
static void findPeakLevels(HDRC_COMP drcComp, const INT_PCM* const inSamples,
394
                           const FIXP_DBL clev, const FIXP_DBL slev,
395
                           const FIXP_DBL ext_leva, const FIXP_DBL ext_levb,
396
                           const FIXP_DBL lfe_lev, const FIXP_DBL dmxGain5,
397
0
                           const FIXP_DBL dmxGain2, FIXP_DBL peak[2]) {
398
0
  int i, c;
399
0
  FIXP_DBL tmp = FL2FXCONST_DBL(0.f);
400
0
  INT_PCM maxSample = 0;
401
402
  /* find peak level */
403
0
  peak[0] = peak[1] = FL2FXCONST_DBL(0.f);
404
0
  for (i = 0; i < drcComp->blockLength; i++) {
405
0
    const INT_PCM* pSamples = &inSamples[i * drcComp->channels];
406
407
    /* single channels */
408
0
    for (c = 0; c < (int)drcComp->channels; c++) {
409
0
      maxSample = fMax(maxSample, (INT_PCM)fAbs(pSamples[c]));
410
0
    }
411
0
  }
412
0
  peak[0] = fixMax(peak[0], FX_PCM2FX_DBL(maxSample) >> DOWNMIX_SHIFT);
413
414
  /* 7.1/6.1 to 5.1 downmixes */
415
0
  if (drcComp->fullChannels > 5) {
416
0
    for (i = 0; i < drcComp->blockLength; i++) {
417
0
      const INT_PCM* pSamples = &inSamples[i * drcComp->channels];
418
419
      /* channel 1 (L, Ls,...) */
420
0
      tmp = FL2FXCONST_DBL(0.f);
421
0
      switch (drcComp->chanConfig) {
422
0
        case MODE_6_1:
423
0
          tmp +=
424
0
              fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >>
425
0
              (DOWNMIX_SHIFT - 1); /* Ls */
426
0
          tmp +=
427
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >>
428
0
              (DOWNMIX_SHIFT - 1); /* Cs */
429
0
          break;
430
0
        case MODE_7_1_BACK:
431
0
        case MODE_7_1_REAR_SURROUND:
432
0
          tmp +=
433
0
              fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >>
434
0
              (DOWNMIX_SHIFT - 1); /* Ls */
435
0
          tmp +=
436
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >>
437
0
              (DOWNMIX_SHIFT - 1); /* Lrs / Lss */
438
0
          break;
439
0
        case MODE_1_2_2_2_1:
440
0
        case MODE_7_1_FRONT_CENTER:
441
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >>
442
0
                  DOWNMIX_SHIFT); /* L */
443
0
          tmp +=
444
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >>
445
0
              (DOWNMIX_SHIFT - 1); /* Lc */
446
0
          break;
447
0
        case MODE_7_1_TOP_FRONT:
448
0
          tmp +=
449
0
              fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >>
450
0
              (DOWNMIX_SHIFT - 1); /* L */
451
0
          tmp +=
452
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >>
453
0
              (DOWNMIX_SHIFT - 1); /* Lvh */
454
0
          break;
455
0
        default:
456
0
          break;
457
0
      }
458
0
      peak[0] = fixMax(peak[0], fixp_abs(tmp));
459
460
      /* channel 2 (R, Rs,...) */
461
0
      tmp = FL2FXCONST_DBL(0.f);
462
0
      switch (drcComp->chanConfig) {
463
0
        case MODE_6_1:
464
0
          tmp +=
465
0
              fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >>
466
0
              (DOWNMIX_SHIFT - 1); /* Rs */
467
0
          tmp +=
468
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >>
469
0
              (DOWNMIX_SHIFT - 1); /* Cs */
470
0
          break;
471
0
        case MODE_7_1_BACK:
472
0
        case MODE_7_1_REAR_SURROUND:
473
0
          tmp +=
474
0
              fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >>
475
0
              (DOWNMIX_SHIFT - 1); /* Rs */
476
0
          tmp +=
477
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >>
478
0
              (DOWNMIX_SHIFT - 1); /* Rrs / Rss */
479
0
          break;
480
0
        case MODE_1_2_2_2_1:
481
0
        case MODE_7_1_FRONT_CENTER:
482
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >>
483
0
                  DOWNMIX_SHIFT); /* R */
484
0
          tmp +=
485
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >>
486
0
              (DOWNMIX_SHIFT - 1); /* Rc */
487
0
          break;
488
0
        case MODE_7_1_TOP_FRONT:
489
0
          tmp +=
490
0
              fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >>
491
0
              (DOWNMIX_SHIFT - 1); /* R */
492
0
          tmp +=
493
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >>
494
0
              (DOWNMIX_SHIFT - 1); /* Rvh */
495
0
          break;
496
0
        default:
497
0
          break;
498
0
      }
499
0
      peak[0] = fixMax(peak[0], fixp_abs(tmp));
500
501
      /* channel 3 (C) */
502
0
      tmp = FL2FXCONST_DBL(0.f);
503
0
      switch (drcComp->chanConfig) {
504
0
        case MODE_1_2_2_2_1:
505
0
        case MODE_7_1_FRONT_CENTER:
506
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >>
507
0
                  DOWNMIX_SHIFT); /* C */
508
0
          tmp +=
509
0
              fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >>
510
0
              (DOWNMIX_SHIFT - 1); /* Lc */
511
0
          tmp +=
512
0
              fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >>
513
0
              (DOWNMIX_SHIFT - 1); /* Rc */
514
0
          break;
515
0
        default:
516
0
          break;
517
0
      }
518
0
      peak[0] = fixMax(peak[0], fixp_abs(tmp));
519
520
0
    } /* for (blocklength) */
521
522
    /* take downmix gain into accout */
523
0
    peak[0] = fMult(dmxGain5, peak[0])
524
0
              << (DFRACT_BITS - 1 - METADATA_FRACT_BITS);
525
0
  }
526
527
  /* 7.1 / 5.1 to stereo downmixes */
528
0
  if (drcComp->fullChannels > 2) {
529
    /* Lt/Rt downmix */
530
0
    for (i = 0; i < drcComp->blockLength; i++) {
531
0
      const INT_PCM* pSamples = &inSamples[i * drcComp->channels];
532
533
      /* Lt */
534
0
      tmp = FL2FXCONST_DBL(0.f);
535
0
      if (drcComp->channelIdx[LS] >= 0)
536
0
        tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f),
537
0
                         (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >>
538
0
               (DOWNMIX_SHIFT - 1); /* Ls */
539
0
      if (drcComp->channelIdx[LS2] >= 0)
540
0
        tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f),
541
0
                         (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >>
542
0
               (DOWNMIX_SHIFT - 1); /* Ls2 */
543
0
      if (drcComp->channelIdx[RS] >= 0)
544
0
        tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f),
545
0
                         (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >>
546
0
               (DOWNMIX_SHIFT - 1); /* Rs */
547
0
      if (drcComp->channelIdx[RS2] >= 0)
548
0
        tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f),
549
0
                         (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >>
550
0
               (DOWNMIX_SHIFT - 1); /* Rs2 */
551
0
      if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0))
552
0
        tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */
553
0
      if (drcComp->channelIdx[S] >= 0)
554
0
        tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f),
555
0
                         (FIXP_PCM)pSamples[drcComp->channelIdx[S]]) >>
556
0
               (DOWNMIX_SHIFT - 1); /* S */
557
0
      if (drcComp->channelIdx[C] >= 0)
558
0
        tmp += fMultDiv2(FL2FXCONST_DBL(0.707f),
559
0
                         (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >>
560
0
               (DOWNMIX_SHIFT - 1); /* C */
561
0
      tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]]) >>
562
0
              DOWNMIX_SHIFT); /* L */
563
564
      /* apply scaling of downmix gains */
565
      /* only for positive values only, as legacy decoders might not know this
566
       * parameter */
567
0
      if (dmxGain2 > FL2FXCONST_DBL(0.f)) {
568
0
        if (drcComp->fullChannels > 5) {
569
0
          tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS);
570
0
        }
571
0
        tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS);
572
0
      }
573
0
      peak[0] = fixMax(peak[0], fixp_abs(tmp));
574
575
      /* Rt */
576
0
      tmp = FL2FXCONST_DBL(0.f);
577
0
      if (drcComp->channelIdx[LS] >= 0)
578
0
        tmp += fMultDiv2(FL2FXCONST_DBL(0.707f),
579
0
                         (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >>
580
0
               (DOWNMIX_SHIFT - 1); /* Ls */
581
0
      if (drcComp->channelIdx[LS2] >= 0)
582
0
        tmp += fMultDiv2(FL2FXCONST_DBL(0.707f),
583
0
                         (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >>
584
0
               (DOWNMIX_SHIFT - 1); /* Ls2 */
585
0
      if (drcComp->channelIdx[RS] >= 0)
586
0
        tmp += fMultDiv2(FL2FXCONST_DBL(0.707f),
587
0
                         (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >>
588
0
               (DOWNMIX_SHIFT - 1); /* Rs */
589
0
      if (drcComp->channelIdx[RS2] >= 0)
590
0
        tmp += fMultDiv2(FL2FXCONST_DBL(0.707f),
591
0
                         (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >>
592
0
               (DOWNMIX_SHIFT - 1); /* Rs2 */
593
0
      if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0))
594
0
        tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */
595
0
      if (drcComp->channelIdx[S] >= 0)
596
0
        tmp += fMultDiv2(FL2FXCONST_DBL(0.707f),
597
0
                         (FIXP_PCM)pSamples[drcComp->channelIdx[S]]) >>
598
0
               (DOWNMIX_SHIFT - 1); /* S */
599
0
      if (drcComp->channelIdx[C] >= 0)
600
0
        tmp += fMultDiv2(FL2FXCONST_DBL(0.707f),
601
0
                         (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >>
602
0
               (DOWNMIX_SHIFT - 1); /* C */
603
0
      tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]]) >>
604
0
              DOWNMIX_SHIFT); /* R */
605
606
      /* apply scaling of downmix gains */
607
      /* only for positive values only, as legacy decoders might not know this
608
       * parameter */
609
0
      if (dmxGain2 > FL2FXCONST_DBL(0.f)) {
610
0
        if (drcComp->fullChannels > 5) {
611
0
          tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS);
612
0
        }
613
0
        tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS);
614
0
      }
615
0
      peak[0] = fixMax(peak[0], fixp_abs(tmp));
616
0
    }
617
618
    /* Lo/Ro downmix */
619
0
    for (i = 0; i < drcComp->blockLength; i++) {
620
0
      const INT_PCM* pSamples = &inSamples[i * drcComp->channels];
621
622
      /* Lo */
623
0
      tmp = FL2FXCONST_DBL(0.f);
624
0
      switch (drcComp->chanConfig) {
625
0
        case MODE_6_1:
626
0
          tmp += fMultDiv2(fMult(slev, ext_leva),
627
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >>
628
0
                 (DOWNMIX_SHIFT - 1); /* Ls */
629
0
          tmp += fMultDiv2(fMult(slev, ext_levb),
630
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >>
631
0
                 (DOWNMIX_SHIFT - 1); /* Cs */
632
0
          tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >>
633
0
                 (DOWNMIX_SHIFT - 1); /* C */
634
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >>
635
0
                  DOWNMIX_SHIFT); /* L */
636
0
          tmp +=
637
0
              fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
638
0
              (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
639
0
          break;
640
0
        case MODE_7_1_BACK:
641
0
        case MODE_7_1_REAR_SURROUND:
642
0
          tmp += fMultDiv2(fMult(slev, ext_leva),
643
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >>
644
0
                 (DOWNMIX_SHIFT - 1); /* Ls */
645
0
          tmp += fMultDiv2(fMult(slev, ext_levb),
646
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >>
647
0
                 (DOWNMIX_SHIFT - 1); /* Lrs / Lss*/
648
0
          tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >>
649
0
                 (DOWNMIX_SHIFT - 1); /* C */
650
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >>
651
0
                  DOWNMIX_SHIFT); /* L */
652
0
          tmp +=
653
0
              fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
654
0
              (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
655
0
          break;
656
0
        case MODE_1_2_2_2_1:
657
0
        case MODE_7_1_FRONT_CENTER:
658
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >>
659
0
                  DOWNMIX_SHIFT); /* L */
660
0
          tmp +=
661
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >>
662
0
              (DOWNMIX_SHIFT - 1); /* Lc */
663
0
          tmp += fMultDiv2(fMult(ext_leva, clev),
664
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >>
665
0
                 (DOWNMIX_SHIFT - 1); /* Lc - second path*/
666
0
          tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >>
667
0
                 (DOWNMIX_SHIFT - 1); /* C */
668
0
          tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >>
669
0
                 (DOWNMIX_SHIFT - 1); /* Ls */
670
0
          tmp +=
671
0
              fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
672
0
              (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
673
0
          break;
674
0
        case MODE_7_1_TOP_FRONT:
675
0
          tmp +=
676
0
              fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >>
677
0
              (DOWNMIX_SHIFT - 1); /* L */
678
0
          tmp +=
679
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >>
680
0
              (DOWNMIX_SHIFT - 1); /* Lvh */
681
0
          tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >>
682
0
                 (DOWNMIX_SHIFT - 1); /* C */
683
0
          tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >>
684
0
                 (DOWNMIX_SHIFT - 1); /* Ls */
685
0
          tmp +=
686
0
              fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
687
0
              (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
688
0
          break;
689
0
        default:
690
0
          if (drcComp->channelIdx[LS] >= 0)
691
0
            tmp +=
692
0
                fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >>
693
0
                (DOWNMIX_SHIFT - 1); /* Ls */
694
0
          if (drcComp->channelIdx[LS2] >= 0)
695
0
            tmp +=
696
0
                fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >>
697
0
                (DOWNMIX_SHIFT - 1); /* Ls2 */
698
0
          if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0))
699
0
            tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */
700
0
          if (drcComp->channelIdx[S] >= 0)
701
0
            tmp +=
702
0
                fMultDiv2(slev,
703
0
                          fMult(FL2FXCONST_DBL(0.7f),
704
0
                                (FIXP_PCM)pSamples[drcComp->channelIdx[S]])) >>
705
0
                (DOWNMIX_SHIFT - 1); /* S */
706
0
          if (drcComp->channelIdx[C] >= 0)
707
0
            tmp +=
708
0
                fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >>
709
0
                (DOWNMIX_SHIFT - 1); /* C */
710
0
          if (drcComp->channelIdx[3] >= 0)
711
0
            tmp += fMultDiv2(lfe_lev,
712
0
                             (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
713
0
                   (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
714
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]]) >>
715
0
                  DOWNMIX_SHIFT); /* L */
716
0
          break;
717
0
      }
718
719
      /* apply scaling of downmix gains */
720
      /* only for positive values only, as legacy decoders might not know this
721
       * parameter */
722
0
      if (dmxGain2 > FL2FXCONST_DBL(0.f)) {
723
0
        if (drcComp->fullChannels > 5) {
724
0
          tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS);
725
0
        }
726
0
        tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS);
727
0
      }
728
0
      peak[0] = fixMax(peak[0], fixp_abs(tmp));
729
730
      /* Ro */
731
0
      tmp = FL2FXCONST_DBL(0.f);
732
0
      switch (drcComp->chanConfig) {
733
0
        case MODE_6_1:
734
0
          tmp += fMultDiv2(fMult(slev, ext_leva),
735
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >>
736
0
                 (DOWNMIX_SHIFT - 1); /* Rs */
737
0
          tmp += fMultDiv2(fMult(slev, ext_levb),
738
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >>
739
0
                 (DOWNMIX_SHIFT - 1); /* Cs */
740
0
          tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >>
741
0
                 (DOWNMIX_SHIFT - 1); /* C */
742
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >>
743
0
                  DOWNMIX_SHIFT); /* R */
744
0
          tmp +=
745
0
              fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
746
0
              (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
747
0
          break;
748
0
        case MODE_7_1_BACK:
749
0
        case MODE_7_1_REAR_SURROUND:
750
0
          tmp += fMultDiv2(fMult(slev, ext_leva),
751
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >>
752
0
                 (DOWNMIX_SHIFT - 1); /* Rs */
753
0
          tmp += fMultDiv2(fMult(slev, ext_levb),
754
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >>
755
0
                 (DOWNMIX_SHIFT - 1); /* Rrs / Rss*/
756
0
          tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >>
757
0
                 (DOWNMIX_SHIFT - 1); /* C */
758
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >>
759
0
                  DOWNMIX_SHIFT); /* R */
760
0
          tmp +=
761
0
              fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
762
0
              (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
763
0
          break;
764
0
        case MODE_1_2_2_2_1:
765
0
        case MODE_7_1_FRONT_CENTER:
766
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >>
767
0
                  DOWNMIX_SHIFT); /* R */
768
0
          tmp +=
769
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >>
770
0
              (DOWNMIX_SHIFT - 1); /* Rc */
771
0
          tmp += fMultDiv2(fMult(ext_leva, clev),
772
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >>
773
0
                 (DOWNMIX_SHIFT - 1); /* Rc - second path*/
774
0
          tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >>
775
0
                 (DOWNMIX_SHIFT - 1); /* C */
776
0
          tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >>
777
0
                 (DOWNMIX_SHIFT - 1); /* Rs */
778
0
          tmp +=
779
0
              fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
780
0
              (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
781
0
          break;
782
0
        case MODE_7_1_TOP_FRONT:
783
0
          tmp +=
784
0
              fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >>
785
0
              (DOWNMIX_SHIFT - 1); /* R */
786
0
          tmp +=
787
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >>
788
0
              (DOWNMIX_SHIFT - 1); /* Rvh */
789
0
          tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >>
790
0
                 (DOWNMIX_SHIFT - 1); /* C */
791
0
          tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >>
792
0
                 (DOWNMIX_SHIFT - 1); /* Rs */
793
0
          tmp +=
794
0
              fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
795
0
              (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
796
0
          break;
797
0
        default:
798
0
          if (drcComp->channelIdx[RS] >= 0)
799
0
            tmp +=
800
0
                fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >>
801
0
                (DOWNMIX_SHIFT - 1); /* Rs */
802
0
          if (drcComp->channelIdx[RS2] >= 0)
803
0
            tmp +=
804
0
                fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >>
805
0
                (DOWNMIX_SHIFT - 1); /* Rs2 */
806
0
          if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0))
807
0
            tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */
808
0
          if (drcComp->channelIdx[S] >= 0)
809
0
            tmp +=
810
0
                fMultDiv2(slev,
811
0
                          fMult(FL2FXCONST_DBL(0.7f),
812
0
                                (FIXP_PCM)pSamples[drcComp->channelIdx[S]])) >>
813
0
                (DOWNMIX_SHIFT - 1); /* S */
814
0
          if (drcComp->channelIdx[C] >= 0)
815
0
            tmp +=
816
0
                fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >>
817
0
                (DOWNMIX_SHIFT - 1); /* C */
818
0
          if (drcComp->channelIdx[3] >= 0)
819
0
            tmp += fMultDiv2(lfe_lev,
820
0
                             (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
821
0
                   (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
822
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]]) >>
823
0
                  DOWNMIX_SHIFT); /* R */
824
0
      }
825
826
      /* apply scaling of downmix gains */
827
      /* only for positive values only, as legacy decoders might not know this
828
       * parameter */
829
0
      if (dmxGain2 > FL2FXCONST_DBL(0.f)) {
830
0
        if (drcComp->fullChannels > 5) {
831
0
          tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS);
832
0
        }
833
0
        tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS);
834
0
      }
835
0
      peak[0] = fixMax(peak[0], fixp_abs(tmp));
836
0
    }
837
0
  }
838
839
0
  peak[1] = fixMax(peak[0], peak[1]);
840
841
  /* Mono Downmix - for comp_val only */
842
0
  if (drcComp->fullChannels > 1) {
843
0
    for (i = 0; i < drcComp->blockLength; i++) {
844
0
      const INT_PCM* pSamples = &inSamples[i * drcComp->channels];
845
846
0
      tmp = FL2FXCONST_DBL(0.f);
847
0
      switch (drcComp->chanConfig) {
848
0
        case MODE_6_1:
849
0
          tmp += fMultDiv2(fMult(slev, ext_leva),
850
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >>
851
0
                 (DOWNMIX_SHIFT - 1); /* Ls */
852
0
          tmp += fMultDiv2(fMult(slev, ext_leva),
853
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >>
854
0
                 (DOWNMIX_SHIFT - 1); /* Rs */
855
0
          tmp += fMult(fMult(slev, ext_levb),
856
0
                       (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >>
857
0
                 (DOWNMIX_SHIFT - 1); /* Cs */
858
0
          tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >>
859
0
                 (DOWNMIX_SHIFT - 1); /* C */
860
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >>
861
0
                  DOWNMIX_SHIFT); /* L */
862
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >>
863
0
                  DOWNMIX_SHIFT); /* R */
864
0
          tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
865
0
                 (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
866
0
          break;
867
0
        case MODE_7_1_BACK:
868
0
        case MODE_7_1_REAR_SURROUND:
869
0
          tmp += fMultDiv2(fMult(slev, ext_leva),
870
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >>
871
0
                 (DOWNMIX_SHIFT - 1); /* Ls */
872
0
          tmp += fMultDiv2(fMult(slev, ext_leva),
873
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >>
874
0
                 (DOWNMIX_SHIFT - 1); /* Rs */
875
0
          tmp += fMultDiv2(fMult(slev, ext_levb),
876
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >>
877
0
                 (DOWNMIX_SHIFT - 1); /* Lrs / Lss*/
878
0
          tmp += fMultDiv2(fMult(slev, ext_levb),
879
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >>
880
0
                 (DOWNMIX_SHIFT - 1); /* Rrs / Rss*/
881
0
          tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >>
882
0
                 (DOWNMIX_SHIFT - 1); /* C */
883
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >>
884
0
                  DOWNMIX_SHIFT); /* L */
885
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >>
886
0
                  DOWNMIX_SHIFT); /* R */
887
0
          tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
888
0
                 (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
889
0
          break;
890
0
        case MODE_1_2_2_2_1:
891
0
        case MODE_7_1_FRONT_CENTER:
892
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >>
893
0
                  DOWNMIX_SHIFT); /* L */
894
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >>
895
0
                  DOWNMIX_SHIFT); /* R */
896
0
          tmp +=
897
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >>
898
0
              (DOWNMIX_SHIFT - 1); /* Lc */
899
0
          tmp +=
900
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >>
901
0
              (DOWNMIX_SHIFT - 1); /* Rc */
902
0
          tmp += fMultDiv2(fMult(ext_leva, clev),
903
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >>
904
0
                 (DOWNMIX_SHIFT - 1); /* Lc - second path*/
905
0
          tmp += fMultDiv2(fMult(ext_leva, clev),
906
0
                           (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >>
907
0
                 (DOWNMIX_SHIFT - 1); /* Rc - second path*/
908
0
          tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >>
909
0
                 (DOWNMIX_SHIFT - 1); /* C */
910
0
          tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >>
911
0
                 (DOWNMIX_SHIFT - 1); /* Ls */
912
0
          tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >>
913
0
                 (DOWNMIX_SHIFT - 1); /* Rs */
914
0
          tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
915
0
                 (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
916
0
          break;
917
0
        case MODE_7_1_TOP_FRONT:
918
0
          tmp +=
919
0
              fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >>
920
0
              (DOWNMIX_SHIFT - 1); /* L */
921
0
          tmp +=
922
0
              fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >>
923
0
              (DOWNMIX_SHIFT - 1); /* R */
924
0
          tmp +=
925
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >>
926
0
              (DOWNMIX_SHIFT - 1); /* Lvh */
927
0
          tmp +=
928
0
              fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >>
929
0
              (DOWNMIX_SHIFT - 1); /* Rvh */
930
0
          tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >>
931
0
                 (DOWNMIX_SHIFT - 1); /* C */
932
0
          tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >>
933
0
                 (DOWNMIX_SHIFT - 1); /* Ls */
934
0
          tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >>
935
0
                 (DOWNMIX_SHIFT - 1); /* Rs */
936
0
          tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
937
0
                 (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
938
0
          break;
939
0
        default:
940
0
          if (drcComp->channelIdx[LS] >= 0)
941
0
            tmp +=
942
0
                fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >>
943
0
                (DOWNMIX_SHIFT - 1); /* Ls */
944
0
          if (drcComp->channelIdx[LS2] >= 0)
945
0
            tmp +=
946
0
                fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >>
947
0
                (DOWNMIX_SHIFT - 1); /* Ls2 */
948
0
          if (drcComp->channelIdx[RS] >= 0)
949
0
            tmp +=
950
0
                fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >>
951
0
                (DOWNMIX_SHIFT - 1); /* Rs */
952
0
          if (drcComp->channelIdx[RS2] >= 0)
953
0
            tmp +=
954
0
                fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >>
955
0
                (DOWNMIX_SHIFT - 1); /* Rs2 */
956
0
          if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0))
957
0
            tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */
958
          /*if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp *=0.707f;*/ /* 7.1ch */
959
0
          if (drcComp->channelIdx[S] >= 0)
960
0
            tmp +=
961
0
                fMultDiv2(slev,
962
0
                          fMult(FL2FXCONST_DBL(0.7f),
963
0
                                (FIXP_PCM)pSamples[drcComp->channelIdx[S]])) >>
964
0
                (DOWNMIX_SHIFT - 1); /* S */
965
0
          if (drcComp->channelIdx[C] >= 0)
966
0
            tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >>
967
0
                   (DOWNMIX_SHIFT - 1); /* C (2*clev) */
968
0
          if (drcComp->channelIdx[3] >= 0)
969
0
            tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >>
970
0
                   (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */
971
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]]) >>
972
0
                  DOWNMIX_SHIFT); /* L */
973
0
          tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]]) >>
974
0
                  DOWNMIX_SHIFT); /* R */
975
0
      }
976
977
      /* apply scaling of downmix gains */
978
      /* only for positive values only, as legacy decoders might not know this
979
       * parameter */
980
0
      if (dmxGain2 > FL2FXCONST_DBL(0.f)) {
981
0
        if (drcComp->fullChannels > 5) {
982
0
          tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS);
983
0
        }
984
0
        tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS);
985
0
      }
986
0
      peak[1] = fixMax(peak[1], fixp_abs(tmp));
987
0
    }
988
0
  }
989
0
}
990
991
0
INT FDK_DRC_Generator_Open(HDRC_COMP* phDrcComp) {
992
0
  INT err = 0;
993
0
  HDRC_COMP hDcComp = NULL;
994
995
0
  if (phDrcComp == NULL) {
996
0
    err = -1;
997
0
    goto bail;
998
0
  }
999
1000
  /* allocate memory */
1001
0
  hDcComp = (HDRC_COMP)FDKcalloc(1, sizeof(DRC_COMP));
1002
1003
0
  if (hDcComp == NULL) {
1004
0
    err = -1;
1005
0
    goto bail;
1006
0
  }
1007
1008
0
  FDKmemclear(hDcComp, sizeof(DRC_COMP));
1009
1010
  /* Return drc compressor instance */
1011
0
  *phDrcComp = hDcComp;
1012
0
  return err;
1013
0
bail:
1014
0
  FDK_DRC_Generator_Close(&hDcComp);
1015
0
  return err;
1016
0
}
1017
1018
0
INT FDK_DRC_Generator_Close(HDRC_COMP* phDrcComp) {
1019
0
  if (phDrcComp == NULL) {
1020
0
    return -1;
1021
0
  }
1022
0
  if (*phDrcComp != NULL) {
1023
0
    FDKfree(*phDrcComp);
1024
0
    *phDrcComp = NULL;
1025
0
  }
1026
0
  return 0;
1027
0
}
1028
1029
INT FDK_DRC_Generator_Initialize(HDRC_COMP drcComp,
1030
                                 const DRC_PROFILE profileLine,
1031
                                 const DRC_PROFILE profileRF,
1032
                                 const INT blockLength, const UINT sampleRate,
1033
                                 const CHANNEL_MODE channelMode,
1034
                                 const CHANNEL_ORDER channelOrder,
1035
0
                                 const UCHAR useWeighting) {
1036
0
  int i;
1037
0
  CHANNEL_MAPPING channelMapping;
1038
1039
0
  drcComp->limDecay =
1040
0
      FL2FXCONST_DBL(((0.006f / 256) * blockLength) / METADATA_INT_SCALE);
1041
1042
  /* Save parameters. */
1043
0
  drcComp->blockLength = blockLength;
1044
0
  drcComp->sampleRate = sampleRate;
1045
0
  drcComp->chanConfig = channelMode;
1046
0
  drcComp->useWeighting = useWeighting;
1047
1048
0
  if (FDK_DRC_Generator_setDrcProfile(drcComp, profileLine, profileRF) !=
1049
0
      0) { /* expects initialized blockLength and sampleRate */
1050
0
    return (-1);
1051
0
  }
1052
1053
  /* Set number of channels and channel offsets. */
1054
0
  if (FDKaacEnc_InitChannelMapping(channelMode, channelOrder,
1055
0
                                   &channelMapping) != AAC_ENC_OK) {
1056
0
    return (-2);
1057
0
  }
1058
1059
0
  for (i = 0; i < 9; i++) drcComp->channelIdx[i] = -1;
1060
1061
0
  switch (channelMode) {
1062
0
    case MODE_1: /* mono */
1063
0
      drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0];
1064
0
      break;
1065
0
    case MODE_2: /* stereo */
1066
0
      drcComp->channelIdx[L] = channelMapping.elInfo[0].ChannelIndex[0];
1067
0
      drcComp->channelIdx[R] = channelMapping.elInfo[0].ChannelIndex[1];
1068
0
      break;
1069
0
    case MODE_1_2: /* 3ch */
1070
0
      drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0];
1071
0
      drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1];
1072
0
      drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0];
1073
0
      break;
1074
0
    case MODE_1_2_1: /* 4ch */
1075
0
      drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0];
1076
0
      drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1];
1077
0
      drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0];
1078
0
      drcComp->channelIdx[S] = channelMapping.elInfo[2].ChannelIndex[0];
1079
0
      break;
1080
0
    case MODE_1_2_2: /* 5ch */
1081
0
      drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0];
1082
0
      drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1];
1083
0
      drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0];
1084
0
      drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0];
1085
0
      drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1];
1086
0
      break;
1087
0
    case MODE_1_2_2_1: /* 5.1 ch */
1088
0
      drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0];
1089
0
      drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1];
1090
0
      drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0];
1091
0
      drcComp->channelIdx[LFE] = channelMapping.elInfo[3].ChannelIndex[0];
1092
0
      drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0];
1093
0
      drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1];
1094
0
      break;
1095
0
    case MODE_1_2_2_2_1: /* 7.1 ch */
1096
0
    case MODE_7_1_FRONT_CENTER:
1097
0
      drcComp->channelIdx[L] = channelMapping.elInfo[2].ChannelIndex[0]; /* l */
1098
0
      drcComp->channelIdx[R] = channelMapping.elInfo[2].ChannelIndex[1]; /* r */
1099
0
      drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */
1100
0
      drcComp->channelIdx[LFE] =
1101
0
          channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */
1102
0
      drcComp->channelIdx[LS] =
1103
0
          channelMapping.elInfo[3].ChannelIndex[0]; /* ls */
1104
0
      drcComp->channelIdx[RS] =
1105
0
          channelMapping.elInfo[3].ChannelIndex[1]; /* rs */
1106
0
      drcComp->channelIdx[LS2] =
1107
0
          channelMapping.elInfo[1].ChannelIndex[0]; /* lc */
1108
0
      drcComp->channelIdx[RS2] =
1109
0
          channelMapping.elInfo[1].ChannelIndex[1]; /* rc */
1110
0
      break;
1111
0
    case MODE_7_1_BACK:
1112
0
    case MODE_7_1_REAR_SURROUND:
1113
0
      drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; /* l */
1114
0
      drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; /* r */
1115
0
      drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */
1116
0
      drcComp->channelIdx[LFE] =
1117
0
          channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */
1118
0
      drcComp->channelIdx[LS] =
1119
0
          channelMapping.elInfo[3].ChannelIndex[0]; /* lrear */
1120
0
      drcComp->channelIdx[RS] =
1121
0
          channelMapping.elInfo[3].ChannelIndex[1]; /* rrear */
1122
0
      drcComp->channelIdx[LS2] =
1123
0
          channelMapping.elInfo[2].ChannelIndex[0]; /* ls */
1124
0
      drcComp->channelIdx[RS2] =
1125
0
          channelMapping.elInfo[2].ChannelIndex[1]; /* rs */
1126
0
      break;
1127
0
    case MODE_6_1:
1128
0
      drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; /* l */
1129
0
      drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; /* r */
1130
0
      drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */
1131
0
      drcComp->channelIdx[LFE] =
1132
0
          channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */
1133
0
      drcComp->channelIdx[LS] =
1134
0
          channelMapping.elInfo[2].ChannelIndex[0]; /* ls */
1135
0
      drcComp->channelIdx[RS] =
1136
0
          channelMapping.elInfo[2].ChannelIndex[1]; /* rs */
1137
0
      drcComp->channelIdx[S] = channelMapping.elInfo[3].ChannelIndex[0]; /* s */
1138
0
      break;
1139
0
    case MODE_7_1_TOP_FRONT:
1140
0
      drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; /* l */
1141
0
      drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; /* r */
1142
0
      drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */
1143
0
      drcComp->channelIdx[LFE] =
1144
0
          channelMapping.elInfo[3].ChannelIndex[0]; /* lfe */
1145
0
      drcComp->channelIdx[LS] =
1146
0
          channelMapping.elInfo[2].ChannelIndex[0]; /* ls */
1147
0
      drcComp->channelIdx[RS] =
1148
0
          channelMapping.elInfo[2].ChannelIndex[1]; /* rs */
1149
0
      drcComp->channelIdx[LS2] =
1150
0
          channelMapping.elInfo[4].ChannelIndex[0]; /* lvh2 */
1151
0
      drcComp->channelIdx[RS2] =
1152
0
          channelMapping.elInfo[4].ChannelIndex[1]; /* rvh2 */
1153
0
      break;
1154
0
    default:
1155
0
      return (-1);
1156
0
  }
1157
1158
0
  drcComp->fullChannels = channelMapping.nChannelsEff;
1159
0
  drcComp->channels = channelMapping.nChannels;
1160
1161
  /* Init states. */
1162
0
  drcComp->smoothLevel[0] = drcComp->smoothLevel[1] =
1163
0
      (FIXP_DBL)(-(135 << METADATA_FRACT_BITS));
1164
1165
0
  FDKmemclear(drcComp->smoothGain, sizeof(drcComp->smoothGain));
1166
0
  FDKmemclear(drcComp->holdCnt, sizeof(drcComp->holdCnt));
1167
0
  FDKmemclear(drcComp->limGain, sizeof(drcComp->limGain));
1168
0
  FDKmemclear(drcComp->prevPeak, sizeof(drcComp->prevPeak));
1169
0
  FDKmemclear(drcComp->filter, sizeof(drcComp->filter));
1170
1171
0
  return (0);
1172
0
}
1173
1174
INT FDK_DRC_Generator_setDrcProfile(HDRC_COMP drcComp,
1175
                                    const DRC_PROFILE profileLine,
1176
0
                                    const DRC_PROFILE profileRF) {
1177
0
  int profileIdx, i;
1178
1179
0
  drcComp->profile[0] = profileLine;
1180
0
  drcComp->profile[1] = profileRF;
1181
1182
0
  for (i = 0; i < 2; i++) {
1183
    /* get profile index */
1184
0
    switch (drcComp->profile[i]) {
1185
0
      case DRC_NONE:
1186
0
      case DRC_NOT_PRESENT:
1187
0
      case DRC_FILMSTANDARD:
1188
0
        profileIdx = 0;
1189
0
        break;
1190
0
      case DRC_FILMLIGHT:
1191
0
        profileIdx = 1;
1192
0
        break;
1193
0
      case DRC_MUSICSTANDARD:
1194
0
        profileIdx = 2;
1195
0
        break;
1196
0
      case DRC_MUSICLIGHT:
1197
0
        profileIdx = 3;
1198
0
        break;
1199
0
      case DRC_SPEECH:
1200
0
        profileIdx = 4;
1201
0
        break;
1202
0
      case DRC_DELAY_TEST:
1203
0
        profileIdx = 5;
1204
0
        break;
1205
0
      default:
1206
0
        return (-1);
1207
0
    }
1208
1209
    /* get parameters for selected profile */
1210
0
    if (profileIdx >= 0) {
1211
0
      drcComp->maxBoostThr[i] = tabMaxBoostThr[profileIdx];
1212
0
      drcComp->boostThr[i] = tabBoostThr[profileIdx];
1213
0
      drcComp->earlyCutThr[i] = tabEarlyCutThr[profileIdx];
1214
0
      drcComp->cutThr[i] = tabCutThr[profileIdx];
1215
0
      drcComp->maxCutThr[i] = tabMaxCutThr[profileIdx];
1216
1217
0
      drcComp->boostFac[i] = tabBoostRatio[profileIdx];
1218
0
      drcComp->earlyCutFac[i] = tabEarlyCutRatio[profileIdx];
1219
0
      drcComp->cutFac[i] = tabCutRatio[profileIdx];
1220
1221
0
      drcComp->maxBoost[i] = tabMaxBoost[profileIdx];
1222
0
      drcComp->maxCut[i] = tabMaxCut[profileIdx];
1223
0
      drcComp->maxEarlyCut[i] =
1224
0
          -fMult((drcComp->cutThr[i] - drcComp->earlyCutThr[i]),
1225
0
                 drcComp->earlyCutFac[i]); /* no scaling after mult needed,
1226
                                              earlyCutFac is in FIXP_DBL */
1227
1228
0
      drcComp->fastAttack[i] = tc2Coeff(
1229
0
          tabFastAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength);
1230
0
      drcComp->fastDecay[i] = tc2Coeff(
1231
0
          tabFastDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength);
1232
0
      drcComp->slowAttack[i] = tc2Coeff(
1233
0
          tabSlowAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength);
1234
0
      drcComp->slowDecay[i] = tc2Coeff(
1235
0
          tabSlowDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength);
1236
0
      drcComp->holdOff[i] = tabHoldOff[profileIdx] * 256 / drcComp->blockLength;
1237
1238
0
      drcComp->attackThr[i] = tabAttackThr[profileIdx];
1239
0
      drcComp->decayThr[i] = tabDecayThr[profileIdx];
1240
0
    }
1241
1242
0
    drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f);
1243
0
  }
1244
0
  return (0);
1245
0
}
1246
1247
INT FDK_DRC_Generator_Calc(HDRC_COMP drcComp, const INT_PCM* const inSamples,
1248
                           const UINT inSamplesBufSize, const INT dialnorm,
1249
                           const INT drc_TargetRefLevel,
1250
                           const INT comp_TargetRefLevel, const FIXP_DBL clev,
1251
                           const FIXP_DBL slev, const FIXP_DBL ext_leva,
1252
                           const FIXP_DBL ext_levb, const FIXP_DBL lfe_lev,
1253
                           const INT dmxGain5, const INT dmxGain2,
1254
0
                           INT* const pDynrng, INT* const pCompr) {
1255
0
  int i, c;
1256
0
  FIXP_DBL peak[2];
1257
1258
  /**************************************************************************
1259
   * compressor
1260
   **************************************************************************/
1261
0
  if ((drcComp->profile[0] != DRC_NONE) || (drcComp->profile[1] != DRC_NONE)) {
1262
    /* Calc loudness level */
1263
0
    FIXP_DBL level_b = FL2FXCONST_DBL(0.f);
1264
0
    int level_e = DFRACT_BITS - 1;
1265
1266
    /* Increase energy time resolution with shorter processing blocks. 16 is an
1267
     * empiric value. */
1268
0
    const int granuleLength = fixMin(16, drcComp->blockLength);
1269
1270
0
    if (drcComp->useWeighting) {
1271
0
      FIXP_DBL x1, x2, y, y1, y2;
1272
      /* sum of filter coefficients about 2.5 -> squared value is 6.25
1273
         WEIGHTING_FILTER_SHIFT is 2 -> scaling about 16, therefore reduce
1274
         granuleShift by 1.
1275
       */
1276
0
      const int granuleShift = getShiftFactor(granuleLength) - 1;
1277
1278
0
      for (c = 0; c < (int)drcComp->channels; c++) {
1279
0
        const INT_PCM* pSamples = inSamples + c * inSamplesBufSize;
1280
1281
0
        if (c == drcComp->channelIdx[LFE]) {
1282
0
          continue; /* skip LFE */
1283
0
        }
1284
1285
        /* get filter states */
1286
0
        x1 = drcComp->filter[c].x1;
1287
0
        x2 = drcComp->filter[c].x2;
1288
0
        y1 = drcComp->filter[c].y1;
1289
0
        y2 = drcComp->filter[c].y2;
1290
1291
0
        i = 0;
1292
1293
0
        do {
1294
0
          int offset = i;
1295
0
          FIXP_DBL accu = FL2FXCONST_DBL(0.f);
1296
1297
0
          for (i = offset;
1298
0
               i < fixMin(offset + granuleLength, drcComp->blockLength); i++) {
1299
            /* apply weighting filter */
1300
0
            FIXP_DBL x =
1301
0
                FX_PCM2FX_DBL((FIXP_PCM)pSamples[i]) >> WEIGHTING_FILTER_SHIFT;
1302
1303
            /* y = b0 * (x - x2) - a1 * y1 - a2 * y2; */
1304
0
            y = fMult(b0, x - x2) - fMult(a1, y1) - fMult(a2, y2);
1305
1306
0
            x2 = x1;
1307
0
            x1 = x;
1308
0
            y2 = y1;
1309
0
            y1 = y;
1310
1311
0
            accu += fPow2Div2(y) >> (granuleShift - 1); /* partial energy */
1312
0
          }                                             /* i */
1313
1314
0
          fixpAdd(accu, granuleShift + 2 * WEIGHTING_FILTER_SHIFT, &level_b,
1315
0
                  &level_e); /* sup up partial energies */
1316
1317
0
        } while (i < drcComp->blockLength);
1318
1319
        /* save filter states */
1320
0
        drcComp->filter[c].x1 = x1;
1321
0
        drcComp->filter[c].x2 = x2;
1322
0
        drcComp->filter[c].y1 = y1;
1323
0
        drcComp->filter[c].y2 = y2;
1324
0
      } /* c */
1325
0
    }   /* weighting */
1326
0
    else {
1327
0
      const int granuleShift = getShiftFactor(granuleLength);
1328
1329
0
      for (c = 0; c < (int)drcComp->channels; c++) {
1330
0
        const INT_PCM* pSamples = inSamples + c * inSamplesBufSize;
1331
1332
0
        if ((int)c == drcComp->channelIdx[LFE]) {
1333
0
          continue; /* skip LFE */
1334
0
        }
1335
1336
0
        i = 0;
1337
1338
0
        do {
1339
0
          int offset = i;
1340
0
          FIXP_DBL accu = FL2FXCONST_DBL(0.f);
1341
1342
0
          for (i = offset;
1343
0
               i < fixMin(offset + granuleLength, drcComp->blockLength); i++) {
1344
            /* partial energy */
1345
0
            accu += fPow2Div2((FIXP_PCM)pSamples[i]) >> (granuleShift - 1);
1346
0
          } /* i */
1347
1348
0
          fixpAdd(accu, granuleShift, &level_b,
1349
0
                  &level_e); /* sup up partial energies */
1350
1351
0
        } while (i < drcComp->blockLength);
1352
0
      }
1353
0
    } /* weighting */
1354
1355
    /*
1356
     * Convert to dBFS, apply dialnorm
1357
     */
1358
    /* level scaling */
1359
1360
    /* descaled level in ld64 representation */
1361
0
    FIXP_DBL ldLevel =
1362
0
        CalcLdData(level_b) +
1363
0
        (FIXP_DBL)((level_e - 12) << (DFRACT_BITS - 1 - LD_DATA_SHIFT)) -
1364
0
        CalcLdData((FIXP_DBL)(drcComp->blockLength << (DFRACT_BITS - 1 - 12)));
1365
1366
    /* if (level < 1e-10) level = 1e-10f; */
1367
0
    ldLevel =
1368
0
        fMax(ldLevel, FL2FXCONST_DBL(-0.51905126482615036685473741085772f));
1369
1370
    /* level = 10 * log(level)/log(10) + 3;
1371
     *       = 10*log(2)/log(10) * ld(level) + 3;
1372
     *       = 10 * 0.30102999566398119521373889472449 * ld(level) + 3
1373
     *       = 10 * (0.30102999566398119521373889472449 * ld(level) + 0.3)
1374
     *       = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64)
1375
     * * 64
1376
     *
1377
     *    additional scaling with METADATA_FRACT_BITS:
1378
     *       = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64)
1379
     * * 64 * 2^(METADATA_FRACT_BITS) = 10 * (0.30102999566398119521373889472449
1380
     * * ld64(level) + 0.3/64) * 2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) =
1381
     * 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * (
1382
     * 0.30102999566398119521373889472449 * ld64(level) + 0.3/64 )
1383
     * */
1384
0
    FIXP_DBL level = fMult(
1385
0
        (FIXP_DBL)(10 << (METADATA_FRACT_BITS + LD_DATA_SHIFT)),
1386
0
        fMult(FL2FXCONST_DBL(0.30102999566398119521373889472449f), ldLevel) +
1387
0
            (FIXP_DBL)(FL2FXCONST_DBL(0.3f) >> LD_DATA_SHIFT));
1388
1389
    /* level -= dialnorm + 31 */ /* this is fixed to Dolby-ReferenceLevel as
1390
                                    compressor profiles are defined relative to
1391
                                    this */
1392
0
    level -= ((FIXP_DBL)(dialnorm << (METADATA_FRACT_BITS - 16)) +
1393
0
              (FIXP_DBL)(31 << METADATA_FRACT_BITS));
1394
1395
0
    for (i = 0; i < 2; i++) {
1396
0
      if (drcComp->profile[i] == DRC_NONE) {
1397
        /* no compression */
1398
0
        drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f);
1399
0
      } else {
1400
0
        FIXP_DBL gain, alpha, lvl2smthlvl;
1401
1402
        /* calc static gain */
1403
0
        if (level <= drcComp->maxBoostThr[i]) {
1404
          /* max boost */
1405
0
          gain = drcComp->maxBoost[i];
1406
0
        } else if (level < drcComp->boostThr[i]) {
1407
          /* boost range */
1408
0
          gain = fMult((level - drcComp->boostThr[i]), drcComp->boostFac[i]);
1409
0
        } else if (level <= drcComp->earlyCutThr[i]) {
1410
          /* null band */
1411
0
          gain = FL2FXCONST_DBL(0.f);
1412
0
        } else if (level <= drcComp->cutThr[i]) {
1413
          /* early cut range */
1414
0
          gain =
1415
0
              fMult((level - drcComp->earlyCutThr[i]), drcComp->earlyCutFac[i]);
1416
0
        } else if (level < drcComp->maxCutThr[i]) {
1417
          /* cut range */
1418
0
          gain = fMult((level - drcComp->cutThr[i]), drcComp->cutFac[i]) -
1419
0
                 drcComp->maxEarlyCut[i];
1420
0
        } else {
1421
          /* max cut */
1422
0
          gain = -drcComp->maxCut[i];
1423
0
        }
1424
1425
        /* choose time constant */
1426
0
        lvl2smthlvl = level - drcComp->smoothLevel[i];
1427
0
        if (gain < drcComp->smoothGain[i]) {
1428
          /* attack */
1429
0
          if (lvl2smthlvl > drcComp->attackThr[i]) {
1430
            /* fast attack */
1431
0
            alpha = drcComp->fastAttack[i];
1432
0
          } else {
1433
            /* slow attack */
1434
0
            alpha = drcComp->slowAttack[i];
1435
0
          }
1436
0
        } else {
1437
          /* release */
1438
0
          if (lvl2smthlvl < -drcComp->decayThr[i]) {
1439
            /* fast release */
1440
0
            alpha = drcComp->fastDecay[i];
1441
0
          } else {
1442
            /* slow release */
1443
0
            alpha = drcComp->slowDecay[i];
1444
0
          }
1445
0
        }
1446
1447
        /* smooth gain & level */
1448
0
        if ((gain < drcComp->smoothGain[i]) ||
1449
0
            (drcComp->holdCnt[i] ==
1450
0
             0)) { /* hold gain unless we have an attack or hold
1451
                      period is over */
1452
0
          FIXP_DBL accu;
1453
1454
          /* drcComp->smoothLevel[i] = (1-alpha) * drcComp->smoothLevel[i] +
1455
           * alpha * level; */
1456
0
          accu = fMult(((FIXP_DBL)MAXVAL_DBL - alpha), drcComp->smoothLevel[i]);
1457
0
          accu += fMult(alpha, level);
1458
0
          drcComp->smoothLevel[i] = accu;
1459
1460
          /* drcComp->smoothGain[i]  = (1-alpha) * drcComp->smoothGain[i] +
1461
           * alpha * gain; */
1462
0
          accu = fMult(((FIXP_DBL)MAXVAL_DBL - alpha), drcComp->smoothGain[i]);
1463
0
          accu += fMult(alpha, gain);
1464
0
          drcComp->smoothGain[i] = accu;
1465
0
        }
1466
1467
        /* hold counter */
1468
0
        if (drcComp->holdCnt[i]) {
1469
0
          drcComp->holdCnt[i]--;
1470
0
        }
1471
0
        if (gain < drcComp->smoothGain[i]) {
1472
0
          drcComp->holdCnt[i] = drcComp->holdOff[i];
1473
0
        }
1474
0
      } /* profile != DRC_NONE */
1475
0
    }   /* for i=1..2 */
1476
0
  } else {
1477
    /* no compression */
1478
0
    drcComp->smoothGain[0] = FL2FXCONST_DBL(0.f);
1479
0
    drcComp->smoothGain[1] = FL2FXCONST_DBL(0.f);
1480
0
  }
1481
1482
  /**************************************************************************
1483
   * limiter
1484
   **************************************************************************/
1485
1486
0
  findPeakLevels(drcComp, inSamples, clev, slev, ext_leva, ext_levb, lfe_lev,
1487
0
                 (FIXP_DBL)((LONG)(dmxGain5) << (METADATA_FRACT_BITS - 16)),
1488
0
                 (FIXP_DBL)((LONG)(dmxGain2) << (METADATA_FRACT_BITS - 16)),
1489
0
                 peak);
1490
1491
0
  for (i = 0; i < 2; i++) {
1492
0
    FIXP_DBL tmp = drcComp->prevPeak[i];
1493
0
    drcComp->prevPeak[i] = peak[i];
1494
0
    peak[i] = fixMax(peak[i], tmp);
1495
1496
    /*
1497
     * Convert to dBFS, apply dialnorm
1498
     */
1499
    /* descaled peak in ld64 representation */
1500
0
    FIXP_DBL ld_peak =
1501
0
        CalcLdData(peak[i]) +
1502
0
        (FIXP_DBL)((LONG)DOWNMIX_SHIFT << (DFRACT_BITS - 1 - LD_DATA_SHIFT));
1503
1504
    /* if (peak < 1e-6) level = 1e-6f; */
1505
0
    ld_peak =
1506
0
        fMax(ld_peak, FL2FXCONST_DBL(-0.31143075889569022011284244651463f));
1507
1508
    /* peak[i] = 20 * log(peak[i])/log(10) + 0.2f +
1509
     * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) peak[i] = 20 *
1510
     * log(2)/log(10) * ld(peak[i]) + 0.2f +
1511
     * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) peak[i] = 10 *
1512
     * 2*0.30102999566398119521373889472449 * ld(peak[i]) + 0.2f +
1513
     * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS)
1514
     *
1515
     *    additional scaling with METADATA_FRACT_BITS:
1516
     * peak[i] = (10 * 2*0.30102999566398119521373889472449 * ld64(peak[i]) * 64
1517
     * + 0.2f +
1518
     * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS))*2^(-METADATA_FRACT_BITS)
1519
     * peak[i] = 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) *
1520
     * 2*0.30102999566398119521373889472449 * ld64(peak[i])
1521
     *         + 0.2f*2^(-METADATA_FRACT_BITS) + drcComp->smoothGain[i]
1522
     */
1523
0
    peak[i] = fMult(
1524
0
        (FIXP_DBL)(10 << (METADATA_FRACT_BITS + LD_DATA_SHIFT)),
1525
0
        fMult(FL2FX_DBL(2 * 0.30102999566398119521373889472449f), ld_peak));
1526
0
    peak[i] +=
1527
0
        (FL2FX_DBL(0.5f) >> METADATA_INT_BITS); /* add a little bit headroom */
1528
0
    peak[i] += drcComp->smoothGain[i];
1529
0
  }
1530
1531
  /* peak -= dialnorm + 31; */ /* this is Dolby style only */
1532
0
  peak[0] -= (FIXP_DBL)((dialnorm - drc_TargetRefLevel)
1533
0
                        << (METADATA_FRACT_BITS -
1534
0
                            16)); /* peak[0] -= dialnorm - drc_TargetRefLevel */
1535
1536
  /* peak += 11; */
1537
  /* this is Dolby style only */ /* RF mode output is 11dB higher */
1538
  /*peak += comp_TargetRefLevel - drc_TargetRefLevel;*/
1539
0
  peak[1] -=
1540
0
      (FIXP_DBL)((dialnorm - comp_TargetRefLevel)
1541
0
                 << (METADATA_FRACT_BITS -
1542
0
                     16)); /* peak[1] -= dialnorm - comp_TargetRefLevel */
1543
1544
  /* limiter gain */
1545
0
  drcComp->limGain[0] += drcComp->limDecay; /* linear limiter release */
1546
0
  drcComp->limGain[0] = fixMin(drcComp->limGain[0], -peak[0]);
1547
1548
0
  drcComp->limGain[1] += 2 * drcComp->limDecay; /* linear limiter release */
1549
0
  drcComp->limGain[1] = fixMin(drcComp->limGain[1], -peak[1]);
1550
1551
  /*************************************************************************/
1552
1553
  /* apply limiting, return DRC gains*/
1554
0
  {
1555
0
    FIXP_DBL tmp;
1556
1557
0
    tmp = drcComp->smoothGain[0];
1558
0
    if (drcComp->limGain[0] < FL2FXCONST_DBL(0.f)) {
1559
0
      tmp += drcComp->limGain[0];
1560
0
    }
1561
0
    *pDynrng = (LONG)scaleValue(tmp, -(METADATA_FRACT_BITS - 16));
1562
1563
0
    tmp = drcComp->smoothGain[1];
1564
0
    if (drcComp->limGain[1] < FL2FXCONST_DBL(0.f)) {
1565
0
      tmp += drcComp->limGain[1];
1566
0
    }
1567
0
    *pCompr = (LONG)scaleValue(tmp, -(METADATA_FRACT_BITS - 16));
1568
0
  }
1569
1570
0
  return 0;
1571
0
}
1572
1573
0
DRC_PROFILE FDK_DRC_Generator_getDrcProfile(const HDRC_COMP drcComp) {
1574
0
  return drcComp->profile[0];
1575
0
}
1576
1577
0
DRC_PROFILE FDK_DRC_Generator_getCompProfile(const HDRC_COMP drcComp) {
1578
0
  return drcComp->profile[1];
1579
0
}