1
2/* -----------------------------------------------------------------------------------------------------------
3Software License for The Fraunhofer FDK AAC Codec Library for Android
4
5� Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V.
6  All rights reserved.
7
8 1.    INTRODUCTION
9The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
12
13AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16of the MPEG specifications.
17
18Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20individually for the purpose of encoding or decoding bit streams in products that are compliant with
21the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23software may already be covered under those patent licenses when it is used for those licensed purposes only.
24
25Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27applications information and documentation.
28
292.    COPYRIGHT LICENSE
30
31Redistribution and use in source and binary forms, with or without modification, are permitted without
32payment of copyright license fees provided that you satisfy the following conditions:
33
34You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35your modifications thereto in source code form.
36
37You must retain the complete text of this software license in the documentation and/or other materials
38provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40modifications thereto to recipients of copies in binary form.
41
42The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43prior written permission.
44
45You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46software or your modifications thereto.
47
48Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49and the date of any change. For modified versions of the FDK AAC Codec, the term
50"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
51"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
52
533.    NO PATENT LICENSE
54
55NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57respect to this software.
58
59You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60by appropriate patent licenses.
61
624.    DISCLAIMER
63
64This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
65"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
66of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69or business interruption, however caused and on any theory of liability, whether in contract, strict
70liability, or tort (including negligence), arising in any way out of the use of this software, even if
71advised of the possibility of such damage.
72
735.    CONTACT INFORMATION
74
75Fraunhofer Institute for Integrated Circuits IIS
76Attention: Audio and Multimedia Departments - FDK AAC LL
77Am Wolfsmantel 33
7891058 Erlangen, Germany
79
80www.iis.fraunhofer.de/amm
81amm-info@iis.fraunhofer.de
82----------------------------------------------------------------------------------------------------------- */
83
84/**********************  Fraunhofer IIS FDK AAC Encoder lib  ******************
85
86   Author(s): M. Neusinger
87   Description: Compressor for AAC Metadata Generator
88
89******************************************************************************/
90
91
92#include "metadata_compressor.h"
93#include "channel_map.h"
94
95
96#define LOG2                                    0.69314718056f  /* natural logarithm of 2 */
97#define ILOG2                                   1.442695041f    /* 1/LOG2 */
98#define FIXP_ILOG2_DIV2                         (FL2FXCONST_DBL(ILOG2/2))
99
100/*----------------- defines ----------------------*/
101
102#define MAX_DRC_CHANNELS        (8)          /*!< Max number of audio input channels. */
103#define DOWNMIX_SHIFT           (3)          /*!< Max 8 channel. */
104#define WEIGHTING_FILTER_SHIFT  (2)          /*!< Scaling used in weighting filter. */
105
106#define METADATA_INT_BITS      10
107#define METADATA_LINT_BITS     20
108#define METADATA_INT_SCALE     (INT64(1)<<(METADATA_INT_BITS))
109#define METADATA_FRACT_BITS    (DFRACT_BITS-1-METADATA_INT_BITS)
110#define METADATA_FRACT_SCALE   (INT64(1)<<(METADATA_FRACT_BITS))
111
112/**
113 *  Enum for channel assignment.
114 */
115enum {
116    L   = 0,
117    R   = 1,
118    C   = 2,
119    LFE = 3,
120    LS  = 4,
121    RS  = 5,
122    S   = 6,
123    LS2 = 7,
124    RS2 = 8
125};
126
127/*--------------- structure definitions --------------------*/
128
129/**
130 *  Structure holds weighting filter filter states.
131 */
132struct 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 */
142struct DRC_COMP {
143
144    FIXP_DBL     maxBoostThr[2];             /*!< Max boost threshold. */
145    FIXP_DBL     boostThr[2];                /*!< Boost threshold. */
146    FIXP_DBL     earlyCutThr[2];             /*!< Early cut threshold. */
147    FIXP_DBL     cutThr[2];                  /*!< Cut threshold. */
148    FIXP_DBL     maxCutThr[2];               /*!< Max cut threshold. */
149
150    FIXP_DBL     boostFac[2];                /*!< Precalculated factor for boost compression. */
151    FIXP_DBL     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, Ls, Rs, S, Ls2, Rs2). */
177
178    FIXP_DBL     smoothLevel[2];             /*!< level smoothing states */
179    FIXP_DBL     smoothGain[2];              /*!< gain smoothing states */
180    UINT         holdCnt[2];                 /*!< hold counter */
181
182    FIXP_DBL     limGain[2];                 /*!< limiter gain */
183    FIXP_DBL     limDecay;                   /*!< limiter decay (linear) */
184    FIXP_DBL     prevPeak[2];                /*!< max peak of previous block (stereo/mono)*/
185
186    WEIGHTING_STATES filter[MAX_DRC_CHANNELS]; /*!< array holds weighting filter states */
187
188};
189
190/*---------------- constants -----------------------*/
191
192/**
193 *  Profile tables.
194 */
195static const FIXP_DBL tabMaxBoostThr[] = {
196    (FIXP_DBL)(-43<<METADATA_FRACT_BITS),
197    (FIXP_DBL)(-53<<METADATA_FRACT_BITS),
198    (FIXP_DBL)(-55<<METADATA_FRACT_BITS),
199    (FIXP_DBL)(-65<<METADATA_FRACT_BITS),
200    (FIXP_DBL)(-50<<METADATA_FRACT_BITS),
201    (FIXP_DBL)(-40<<METADATA_FRACT_BITS)
202};
203static 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};
211static const FIXP_DBL tabEarlyCutThr[] = {
212    (FIXP_DBL)(-26<<METADATA_FRACT_BITS),
213    (FIXP_DBL)(-21<<METADATA_FRACT_BITS),
214    (FIXP_DBL)(-26<<METADATA_FRACT_BITS),
215    (FIXP_DBL)(-21<<METADATA_FRACT_BITS),
216    (FIXP_DBL)(-26<<METADATA_FRACT_BITS),
217    (FIXP_DBL)(-20<<METADATA_FRACT_BITS)
218};
219static const FIXP_DBL tabCutThr[]      = {
220    (FIXP_DBL)(-16<<METADATA_FRACT_BITS),
221    (FIXP_DBL)(-11<<METADATA_FRACT_BITS),
222    (FIXP_DBL)(-16<<METADATA_FRACT_BITS),
223    (FIXP_DBL)(-21<<METADATA_FRACT_BITS),
224    (FIXP_DBL)(-16<<METADATA_FRACT_BITS),
225    (FIXP_DBL)(-10<<METADATA_FRACT_BITS)
226};
227static const FIXP_DBL tabMaxCutThr[]   = {
228    (FIXP_DBL)(4<<METADATA_FRACT_BITS),
229    (FIXP_DBL)(9<<METADATA_FRACT_BITS),
230    (FIXP_DBL)(4<<METADATA_FRACT_BITS),
231    (FIXP_DBL)(9<<METADATA_FRACT_BITS),
232    (FIXP_DBL)(4<<METADATA_FRACT_BITS),
233    (FIXP_DBL)(4<<METADATA_FRACT_BITS)
234};
235static const FIXP_DBL tabBoostRatio[] = {
236    FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
237    FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
238    FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
239    FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
240    FL2FXCONST_DBL( ((1.f/5.f) - 1.f) ),
241    FL2FXCONST_DBL( ((1.f/5.f) - 1.f) )
242};
243static const FIXP_DBL tabEarlyCutRatio[] = {
244    FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
245    FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
246    FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
247    FL2FXCONST_DBL( ((1.f/1.f) - 1.f) ),
248    FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
249    FL2FXCONST_DBL( ((1.f/2.f) - 1.f) )
250};
251static const FIXP_DBL tabCutRatio[]      = {
252    FL2FXCONST_DBL( ((1.f/20.f) - 1.f) ),
253    FL2FXCONST_DBL( ((1.f/20.f) - 1.f) ),
254    FL2FXCONST_DBL( ((1.f/20.f) - 1.f) ),
255    FL2FXCONST_DBL( ((1.f/ 2.f) - 1.f) ),
256    FL2FXCONST_DBL( ((1.f/20.f) - 1.f) ),
257    FL2FXCONST_DBL( ((1.f/20.f) - 1.f) )
258};
259static const FIXP_DBL tabMaxBoost[] = {
260    (FIXP_DBL)( 6<<METADATA_FRACT_BITS),
261    (FIXP_DBL)( 6<<METADATA_FRACT_BITS),
262    (FIXP_DBL)(12<<METADATA_FRACT_BITS),
263    (FIXP_DBL)(12<<METADATA_FRACT_BITS),
264    (FIXP_DBL)(15<<METADATA_FRACT_BITS),
265    (FIXP_DBL)(15<<METADATA_FRACT_BITS)
266};
267static const FIXP_DBL tabMaxCut[]   = {
268    (FIXP_DBL)(24<<METADATA_FRACT_BITS),
269    (FIXP_DBL)(24<<METADATA_FRACT_BITS),
270    (FIXP_DBL)(24<<METADATA_FRACT_BITS),
271    (FIXP_DBL)(15<<METADATA_FRACT_BITS),
272    (FIXP_DBL)(24<<METADATA_FRACT_BITS),
273    (FIXP_DBL)(24<<METADATA_FRACT_BITS)
274};
275static const FIXP_DBL tabFastAttack[] = {
276    FL2FXCONST_DBL((10.f/1000.f)/METADATA_INT_SCALE),
277    FL2FXCONST_DBL((10.f/1000.f)/METADATA_INT_SCALE),
278    FL2FXCONST_DBL((10.f/1000.f)/METADATA_INT_SCALE),
279    FL2FXCONST_DBL((10.f/1000.f)/METADATA_INT_SCALE),
280    FL2FXCONST_DBL((10.f/1000.f)/METADATA_INT_SCALE),
281    FL2FXCONST_DBL( (0.f/1000.f)/METADATA_INT_SCALE)
282};
283static const FIXP_DBL tabFastDecay[]  = {
284    FL2FXCONST_DBL((1000.f/1000.f)/METADATA_INT_SCALE),
285    FL2FXCONST_DBL((1000.f/1000.f)/METADATA_INT_SCALE),
286    FL2FXCONST_DBL((1000.f/1000.f)/METADATA_INT_SCALE),
287    FL2FXCONST_DBL((1000.f/1000.f)/METADATA_INT_SCALE),
288    FL2FXCONST_DBL( (200.f/1000.f)/METADATA_INT_SCALE),
289    FL2FXCONST_DBL(   (0.f/1000.f)/METADATA_INT_SCALE)
290};
291static const FIXP_DBL tabSlowAttack[] = {
292    FL2FXCONST_DBL((100.f/1000.f)/METADATA_INT_SCALE),
293    FL2FXCONST_DBL((100.f/1000.f)/METADATA_INT_SCALE),
294    FL2FXCONST_DBL((100.f/1000.f)/METADATA_INT_SCALE),
295    FL2FXCONST_DBL((100.f/1000.f)/METADATA_INT_SCALE),
296    FL2FXCONST_DBL((100.f/1000.f)/METADATA_INT_SCALE),
297    FL2FXCONST_DBL(  (0.f/1000.f)/METADATA_INT_SCALE)
298};
299static const FIXP_DBL tabSlowDecay[]  = {
300    FL2FXCONST_DBL( (3000.f/1000.f)/METADATA_INT_SCALE),
301    FL2FXCONST_DBL( (3000.f/1000.f)/METADATA_INT_SCALE),
302    FL2FXCONST_DBL((10000.f/1000.f)/METADATA_INT_SCALE),
303    FL2FXCONST_DBL( (3000.f/1000.f)/METADATA_INT_SCALE),
304    FL2FXCONST_DBL( (1000.f/1000.f)/METADATA_INT_SCALE),
305    FL2FXCONST_DBL(    (0.f/1000.f)/METADATA_INT_SCALE)
306};
307
308static const INT tabHoldOff[]    = { 10, 10, 10, 10, 10, 0 };
309
310static const FIXP_DBL tabAttackThr[] = {
311    (FIXP_DBL)(15<<METADATA_FRACT_BITS),
312    (FIXP_DBL)(15<<METADATA_FRACT_BITS),
313    (FIXP_DBL)(15<<METADATA_FRACT_BITS),
314    (FIXP_DBL)(15<<METADATA_FRACT_BITS),
315    (FIXP_DBL)(10<<METADATA_FRACT_BITS),
316    (FIXP_DBL)(0<<METADATA_FRACT_BITS)
317};
318static const FIXP_DBL tabDecayThr[]  = {
319    (FIXP_DBL)(20<<METADATA_FRACT_BITS),
320    (FIXP_DBL)(20<<METADATA_FRACT_BITS),
321    (FIXP_DBL)(20<<METADATA_FRACT_BITS),
322    (FIXP_DBL)(20<<METADATA_FRACT_BITS),
323    (FIXP_DBL)(10<<METADATA_FRACT_BITS),
324    (FIXP_DBL)( 0<<METADATA_FRACT_BITS)
325};
326
327/**
328 *  Weighting filter coefficients (biquad bandpass).
329 */
330static const FIXP_DBL b0 = FL2FXCONST_DBL(0.53050662f);                                      /* b1 = 0, b2 = -b0 */
331static const FIXP_DBL a1 = FL2FXCONST_DBL(-0.95237983f), a2 = FL2FXCONST_DBL(-0.02248836f);  /* a0 = 1 */
332
333
334/*------------- function definitions ----------------*/
335
336/**
337 * \brief  Calculate scaling factor for denoted processing block.
338 *
339 * \param blockLength   Length of processing block.
340 *
341 * \return    shiftFactor
342 */
343static UINT getShiftFactor(
344        const UINT                length
345        )
346{
347    UINT ldN;
348    for(ldN=1;(((UINT)1)<<ldN) < length;ldN++);
349
350    return ldN;
351}
352
353/**
354 * \brief  Sum up fixpoint values with best possible accuracy.
355 *
356 * \param value1        First input value.
357 * \param q1            Scaling factor of first input value.
358 * \param pValue2       Pointer to second input value, will be modified on return.
359 * \param pQ2           Pointer to second scaling factor, will be modified on return.
360 *
361 * \return    void
362 */
363static void fixpAdd(
364        const FIXP_DBL                  value1,
365        const int                       q1,
366        FIXP_DBL *const                 pValue2,
367        int *const                      pQ2
368        )
369{
370  const int headroom1 = fNormz(fixp_abs(value1))-1;
371  const int headroom2 = fNormz(fixp_abs(*pValue2))-1;
372  int resultScale = fixMax(q1-headroom1, (*pQ2)-headroom2);
373
374  if ( (value1!=FL2FXCONST_DBL(0.f)) && (*pValue2!=FL2FXCONST_DBL(0.f)) ) {
375    resultScale++;
376  }
377
378  *pValue2 = scaleValue(value1, q1-resultScale) + scaleValue(*pValue2, (*pQ2)-resultScale);
379  *pQ2 = (*pValue2!=(FIXP_DBL)0) ? resultScale : DFRACT_BITS-1;
380}
381
382/**
383 * \brief  Function for converting time constant to filter coefficient.
384 *
385 * \param t             Time constant.
386 * \param sampleRate    Sampling rate in Hz.
387 * \param blockLength   Length of processing block in samples per channel.
388 *
389 * \return    result = 1.0 - exp(-1.0/((t) * (f)))
390 */
391static FIXP_DBL tc2Coeff(
392        const FIXP_DBL            t,
393        const INT                 sampleRate,
394        const INT                 blockLength
395        )
396{
397   FIXP_DBL sampleRateFract;
398   FIXP_DBL blockLengthFract;
399   FIXP_DBL f, product;
400   FIXP_DBL exponent, result;
401   INT e_res;
402
403   /* f = sampleRate/blockLength */
404   sampleRateFract = (FIXP_DBL)(sampleRate<<(DFRACT_BITS-1-METADATA_LINT_BITS));
405   blockLengthFract = (FIXP_DBL)(blockLength<<(DFRACT_BITS-1-METADATA_LINT_BITS));
406   f = fDivNorm(sampleRateFract, blockLengthFract, &e_res);
407   f = scaleValue(f, e_res-METADATA_INT_BITS); /* convert to METADATA_FRACT */
408
409   /* product = t*f */
410   product = fMultNorm(t, f, &e_res);
411   product = scaleValue(product, e_res+METADATA_INT_BITS); /* convert to METADATA_FRACT */
412
413   /* exponent = (-1.0/((t) * (f))) */
414   exponent = fDivNorm(METADATA_FRACT_SCALE, product, &e_res);
415   exponent = scaleValue(exponent, e_res-METADATA_INT_BITS); /* convert to METADATA_FRACT */
416
417   /* exponent * ld(e) */
418   exponent = fMult(exponent,FIXP_ILOG2_DIV2)<<1; /* e^(x) = 2^(x*ld(e)) */
419
420   /* exp(-1.0/((t) * (f))) */
421   result = f2Pow(-exponent, DFRACT_BITS-1-METADATA_FRACT_BITS, &e_res);
422
423   /* result = 1.0 - exp(-1.0/((t) * (f))) */
424   result = (FIXP_DBL)MAXVAL_DBL - scaleValue(result, e_res);
425
426   return result;
427}
428
429INT FDK_DRC_Generator_Open(
430        HDRC_COMP                      *phDrcComp
431        )
432{
433    INT err = 0;
434    HDRC_COMP hDcComp = NULL;
435
436    if (phDrcComp == NULL) {
437      err = -1;
438      goto bail;
439    }
440
441    /* allocate memory */
442    hDcComp = (HDRC_COMP)FDKcalloc(1, sizeof(DRC_COMP));
443
444    if (hDcComp == NULL) {
445      err = -1;
446      goto bail;
447    }
448
449    FDKmemclear(hDcComp, sizeof(DRC_COMP));
450
451    /* Return drc compressor instance */
452    *phDrcComp = hDcComp;
453    return err;
454bail:
455    FDK_DRC_Generator_Close(&hDcComp);
456    return err;
457}
458
459INT FDK_DRC_Generator_Close(
460        HDRC_COMP                      *phDrcComp
461        )
462{
463    if (phDrcComp == NULL) {
464      return -1;
465    }
466    if (*phDrcComp != NULL) {
467      FDKfree(*phDrcComp);
468      *phDrcComp = NULL;
469    }
470    return 0;
471}
472
473
474INT FDK_DRC_Generator_Initialize(
475        HDRC_COMP                       drcComp,
476        const DRC_PROFILE               profileLine,
477        const DRC_PROFILE               profileRF,
478        const INT                       blockLength,
479        const UINT                      sampleRate,
480        const CHANNEL_MODE              channelMode,
481        const CHANNEL_ORDER             channelOrder,
482        const UCHAR                     useWeighting
483        )
484{
485    int i;
486    CHANNEL_MAPPING channelMapping;
487
488    drcComp->limDecay = FL2FXCONST_DBL( ((0.006f / 256) * blockLength) / METADATA_INT_SCALE );
489
490    /* Save parameters. */
491    drcComp->blockLength = blockLength;
492    drcComp->sampleRate  = sampleRate;
493    drcComp->chanConfig = channelMode;
494    drcComp->useWeighting = useWeighting;
495
496    if (FDK_DRC_Generator_setDrcProfile(drcComp, profileLine, profileRF)!=0) { /* expects initialized blockLength and sampleRate */
497      return (-1);
498    }
499
500    /* Set number of channels and channel offsets. */
501    if (FDKaacEnc_InitChannelMapping(channelMode, channelOrder, &channelMapping)!=AAC_ENC_OK) {
502      return (-2);
503    }
504
505    for (i = 0; i < 9; i++) drcComp->channelIdx[i] = -1;
506
507    switch (channelMode) {
508    case MODE_1: /* mono */
509        drcComp->channelIdx[C]   = channelMapping.elInfo[0].ChannelIndex[0];
510        break;
511    case MODE_2: /* stereo */
512        drcComp->channelIdx[L]   = channelMapping.elInfo[0].ChannelIndex[0];
513        drcComp->channelIdx[R]   = channelMapping.elInfo[0].ChannelIndex[1];
514        break;
515    case MODE_1_2: /* 3ch */
516        drcComp->channelIdx[L]   = channelMapping.elInfo[1].ChannelIndex[0];
517        drcComp->channelIdx[R]   = channelMapping.elInfo[1].ChannelIndex[1];
518        drcComp->channelIdx[C]   = channelMapping.elInfo[0].ChannelIndex[0];
519        break;
520    case MODE_1_2_1: /* 4ch */
521        drcComp->channelIdx[L]   = channelMapping.elInfo[1].ChannelIndex[0];
522        drcComp->channelIdx[R]   = channelMapping.elInfo[1].ChannelIndex[1];
523        drcComp->channelIdx[C]   = channelMapping.elInfo[0].ChannelIndex[0];
524        drcComp->channelIdx[S]   = channelMapping.elInfo[2].ChannelIndex[0];
525        break;
526    case MODE_1_2_2: /* 5ch */
527        drcComp->channelIdx[L]   = channelMapping.elInfo[1].ChannelIndex[0];
528        drcComp->channelIdx[R]   = channelMapping.elInfo[1].ChannelIndex[1];
529        drcComp->channelIdx[C]   = channelMapping.elInfo[0].ChannelIndex[0];
530        drcComp->channelIdx[LS]  = channelMapping.elInfo[2].ChannelIndex[0];
531        drcComp->channelIdx[RS]  = channelMapping.elInfo[2].ChannelIndex[1];
532        break;
533    case MODE_1_2_2_1:  /* 5.1 ch */
534        drcComp->channelIdx[L]   = channelMapping.elInfo[1].ChannelIndex[0];
535        drcComp->channelIdx[R]   = channelMapping.elInfo[1].ChannelIndex[1];
536        drcComp->channelIdx[C]   = channelMapping.elInfo[0].ChannelIndex[0];
537        drcComp->channelIdx[LFE] = channelMapping.elInfo[3].ChannelIndex[0];
538        drcComp->channelIdx[LS]  = channelMapping.elInfo[2].ChannelIndex[0];
539        drcComp->channelIdx[RS]  = channelMapping.elInfo[2].ChannelIndex[1];
540        break;
541    case MODE_1_2_2_2_1: /* 7.1 ch */
542    case MODE_7_1_FRONT_CENTER:
543        drcComp->channelIdx[L]   = channelMapping.elInfo[2].ChannelIndex[0]; /* l */
544        drcComp->channelIdx[R]   = channelMapping.elInfo[2].ChannelIndex[1]; /* r */
545        drcComp->channelIdx[C]   = channelMapping.elInfo[0].ChannelIndex[0]; /* c */
546        drcComp->channelIdx[LFE] = channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */
547        drcComp->channelIdx[LS]  = channelMapping.elInfo[3].ChannelIndex[0]; /* ls */
548        drcComp->channelIdx[RS]  = channelMapping.elInfo[3].ChannelIndex[1]; /* rs */
549        drcComp->channelIdx[LS2] = channelMapping.elInfo[1].ChannelIndex[0]; /* lc */
550        drcComp->channelIdx[RS2] = channelMapping.elInfo[1].ChannelIndex[1]; /* rc */
551        break;
552    case MODE_7_1_REAR_SURROUND:
553        drcComp->channelIdx[L]   = channelMapping.elInfo[1].ChannelIndex[0]; /* l */
554        drcComp->channelIdx[R]   = channelMapping.elInfo[1].ChannelIndex[1]; /* r */
555        drcComp->channelIdx[C]   = channelMapping.elInfo[0].ChannelIndex[0]; /* c */
556        drcComp->channelIdx[LFE] = channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */
557        drcComp->channelIdx[LS]  = channelMapping.elInfo[3].ChannelIndex[0]; /* lrear */
558        drcComp->channelIdx[RS]  = channelMapping.elInfo[3].ChannelIndex[1]; /* rrear */
559        drcComp->channelIdx[LS2] = channelMapping.elInfo[2].ChannelIndex[0]; /* ls */
560        drcComp->channelIdx[RS2] = channelMapping.elInfo[2].ChannelIndex[1]; /* rs */
561        break;
562    case MODE_1_1:
563    case MODE_1_1_1_1:
564    case MODE_1_1_1_1_1_1:
565    case MODE_1_1_1_1_1_1_1_1:
566    case MODE_1_1_1_1_1_1_1_1_1_1_1_1:
567    case MODE_2_2:
568    case MODE_2_2_2:
569    case MODE_2_2_2_2:
570    case MODE_2_2_2_2_2_2:
571    default:
572        return (-1);
573    }
574
575    drcComp->fullChannels = channelMapping.nChannelsEff;
576    drcComp->channels     = channelMapping.nChannels;
577
578    /* Init states. */
579    drcComp->smoothLevel[0] = drcComp->smoothLevel[1] = (FIXP_DBL)(-135<<METADATA_FRACT_BITS);
580
581    FDKmemclear(drcComp->smoothGain, sizeof(drcComp->smoothGain));
582    FDKmemclear(drcComp->holdCnt, sizeof(drcComp->holdCnt));
583    FDKmemclear(drcComp->limGain, sizeof(drcComp->limGain));
584    FDKmemclear(drcComp->prevPeak, sizeof(drcComp->prevPeak));
585    FDKmemclear(drcComp->filter, sizeof(drcComp->filter));
586
587    return (0);
588}
589
590
591INT FDK_DRC_Generator_setDrcProfile(
592        HDRC_COMP                       drcComp,
593        const DRC_PROFILE               profileLine,
594        const DRC_PROFILE               profileRF
595        )
596{
597    int profileIdx, i;
598
599    drcComp->profile[0] = profileLine;
600    drcComp->profile[1] = profileRF;
601
602    for (i = 0; i < 2; i++) {
603        /* get profile index */
604        switch (drcComp->profile[i]) {
605            case DRC_NONE:
606            case DRC_FILMSTANDARD:  profileIdx = 0; break;
607            case DRC_FILMLIGHT:     profileIdx = 1; break;
608            case DRC_MUSICSTANDARD: profileIdx = 2; break;
609            case DRC_MUSICLIGHT:    profileIdx = 3; break;
610            case DRC_SPEECH:        profileIdx = 4; break;
611            case DRC_DELAY_TEST:    profileIdx = 5; break;
612            default: return (-1);
613        }
614
615        /* get parameters for selected profile */
616        if (profileIdx >= 0) {
617            drcComp->maxBoostThr[i] = tabMaxBoostThr[profileIdx];
618            drcComp->boostThr[i]    = tabBoostThr[profileIdx];
619            drcComp->earlyCutThr[i] = tabEarlyCutThr[profileIdx];
620            drcComp->cutThr[i]      = tabCutThr[profileIdx];
621            drcComp->maxCutThr[i]   = tabMaxCutThr[profileIdx];
622
623            drcComp->boostFac[i]    = tabBoostRatio[profileIdx];
624            drcComp->earlyCutFac[i] = tabEarlyCutRatio[profileIdx];
625            drcComp->cutFac[i]      = tabCutRatio[profileIdx];
626
627            drcComp->maxBoost[i]    = tabMaxBoost[profileIdx];
628            drcComp->maxCut[i]      = tabMaxCut[profileIdx];
629            drcComp->maxEarlyCut[i] = - fMult((drcComp->cutThr[i] - drcComp->earlyCutThr[i]), drcComp->earlyCutFac[i]); /* no scaling after mult needed, earlyCutFac is in FIXP_DBL */
630
631            drcComp->fastAttack[i]  = tc2Coeff(tabFastAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength);
632            drcComp->fastDecay[i]   = tc2Coeff(tabFastDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength);
633            drcComp->slowAttack[i]  = tc2Coeff(tabSlowAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength);
634            drcComp->slowDecay[i]   = tc2Coeff(tabSlowDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength);
635            drcComp->holdOff[i]     = tabHoldOff[profileIdx] * 256 / drcComp->blockLength;
636
637            drcComp->attackThr[i]   = tabAttackThr[profileIdx];
638            drcComp->decayThr[i]    = tabDecayThr[profileIdx];
639        }
640
641        drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f);
642    }
643    return (0);
644}
645
646
647INT FDK_DRC_Generator_Calc(
648        HDRC_COMP                       drcComp,
649        const INT_PCM * const           inSamples,
650        const INT                       dialnorm,
651        const INT                       drc_TargetRefLevel,
652        const INT                       comp_TargetRefLevel,
653        FIXP_DBL                        clev,
654        FIXP_DBL                        slev,
655        INT * const                     pDynrng,
656        INT * const                     pCompr
657        )
658{
659    int i, c;
660    FIXP_DBL peak[2];
661
662
663    /**************************************************************************
664    * compressor
665    **************************************************************************/
666      if ((drcComp->profile[0] != DRC_NONE) || (drcComp->profile[1] != DRC_NONE)) {
667        /* Calc loudness level */
668        FIXP_DBL level_b = FL2FXCONST_DBL(0.f);
669        int      level_e = DFRACT_BITS-1;
670
671        /* Increase energy time resolution with shorter processing blocks. 32 is an empiric value. */
672        const int granuleLength = fixMin(32, drcComp->blockLength);
673
674        if (drcComp->useWeighting) {
675            FIXP_DBL x1, x2, y, y1, y2;
676            /* sum of filter coefficients about 2.5 -> squared value is 6.25
677               WEIGHTING_FILTER_SHIFT is 2 -> scaling about 16, therefore reduce granuleShift by 1.
678             */
679            const int granuleShift = getShiftFactor(granuleLength)-1;
680
681            for (c = 0; c < (int)drcComp->channels; c++) {
682                const INT_PCM* pSamples = &inSamples[c];
683
684                if (c == drcComp->channelIdx[LFE]) {
685                  continue;  /* skip LFE */
686                }
687
688                /* get filter states */
689                x1 = drcComp->filter[c].x1;
690                x2 = drcComp->filter[c].x2;
691                y1 = drcComp->filter[c].y1;
692                y2 = drcComp->filter[c].y2;
693
694                i = 0;
695
696                do {
697
698                  int offset = i;
699                  FIXP_DBL accu = FL2FXCONST_DBL(0.f);
700
701                  for (i=offset; i < fixMin(offset+granuleLength,drcComp->blockLength); i++) {
702                    /* apply weighting filter */
703                    FIXP_DBL x = FX_PCM2FX_DBL((FIXP_PCM)pSamples[i*drcComp->channels]) >> WEIGHTING_FILTER_SHIFT;
704
705                    /* y = b0 * (x - x2) - a1 * y1 - a2 * y2; */
706                    y = fMult(b0,x-x2) - fMult(a1,y1) - fMult(a2,y2);
707
708                    x2 = x1;
709                    x1 = x;
710                    y2 = y1;
711                    y1 = y;
712
713                    accu += fPow2Div2(y)>>(granuleShift-1);     /* partial energy */
714                  } /* i */
715
716                  fixpAdd(accu, granuleShift+2*WEIGHTING_FILTER_SHIFT, &level_b, &level_e); /* sup up partial energies */
717
718                } while ( i < drcComp->blockLength );
719
720
721                /* save filter states */
722                drcComp->filter[c].x1 = x1;
723                drcComp->filter[c].x2 = x2;
724                drcComp->filter[c].y1 = y1;
725                drcComp->filter[c].y2 = y2;
726            } /* c */
727        } /* weighting */
728        else {
729            const int granuleShift = getShiftFactor(granuleLength);
730
731            for (c = 0; c < (int)drcComp->channels; c++) {
732                const INT_PCM* pSamples = &inSamples[c];
733
734                if ((int)c == drcComp->channelIdx[LFE]) {
735                  continue;  /* skip LFE */
736                }
737
738                i = 0;
739
740                do {
741                  int offset = i;
742                  FIXP_DBL accu = FL2FXCONST_DBL(0.f);
743
744                  for (i=offset; i < fixMin(offset+granuleLength,drcComp->blockLength); i++) {
745                    /* partial energy */
746                    accu += fPow2Div2((FIXP_PCM)pSamples[i*drcComp->channels])>>(granuleShift-1);
747                  } /* i */
748
749                  fixpAdd(accu, granuleShift, &level_b, &level_e); /* sup up partial energies */
750
751                } while ( i < drcComp->blockLength );
752            }
753        } /* weighting */
754
755        /*
756         * Convert to dBFS, apply dialnorm
757         */
758        /* level scaling */
759
760        /* descaled level in ld64 representation */
761        FIXP_DBL ldLevel = CalcLdData(level_b) + (FIXP_DBL)((level_e-12)<<(DFRACT_BITS-1-LD_DATA_SHIFT)) - CalcLdData((FIXP_DBL)(drcComp->blockLength<<(DFRACT_BITS-1-12)));
762
763        /* if (level < 1e-10) level = 1e-10f; */
764        ldLevel = FDKmax(ldLevel, FL2FXCONST_DBL(-0.51905126482615036685473741085772f));
765
766        /* level = 10 * log(level)/log(10) + 3;
767         *       = 10*log(2)/log(10) * ld(level) + 3;
768         *       = 10 * 0.30102999566398119521373889472449 * ld(level) + 3
769         *       = 10 * (0.30102999566398119521373889472449 * ld(level) + 0.3)
770         *       = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) * 64
771         *
772         *    additional scaling with METADATA_FRACT_BITS:
773         *       = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) * 64 * 2^(METADATA_FRACT_BITS)
774         *       = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) * 2^(METADATA_FRACT_BITS+LD_DATA_SHIFT)
775         *       = 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * ( 0.30102999566398119521373889472449 * ld64(level) + 0.3/64 )
776         * */
777        FIXP_DBL level = fMult((FIXP_DBL)(10<<(METADATA_FRACT_BITS+LD_DATA_SHIFT)), fMult( FL2FXCONST_DBL(0.30102999566398119521373889472449f), ldLevel) + (FIXP_DBL)(FL2FXCONST_DBL(0.3f)>>LD_DATA_SHIFT) );
778
779        /* level -= dialnorm + 31 */   /* this is fixed to Dolby-ReferenceLevel as compressor profiles are defined relative to this */
780        level -= ((FIXP_DBL)(dialnorm<<(METADATA_FRACT_BITS-16))  + (FIXP_DBL)(31<<METADATA_FRACT_BITS));
781
782        for (i = 0; i < 2; i++) {
783            if (drcComp->profile[i] == DRC_NONE) {
784                /* no compression */
785                drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f);
786            }
787            else {
788                FIXP_DBL gain, alpha, lvl2smthlvl;
789
790                /* calc static gain */
791                if (level <= drcComp->maxBoostThr[i]) {
792                    /* max boost */
793                    gain = drcComp->maxBoost[i];
794                }
795                else if (level < drcComp->boostThr[i]) {
796                    /* boost range */
797                    gain = fMult((level - drcComp->boostThr[i]),drcComp->boostFac[i]);
798                }
799                else if (level <= drcComp->earlyCutThr[i]) {
800                    /* null band */
801                    gain = FL2FXCONST_DBL(0.f);
802                }
803                else if (level <= drcComp->cutThr[i]) {
804                    /* early cut range */
805                    gain = fMult((level - drcComp->earlyCutThr[i]), drcComp->earlyCutFac[i]);
806                }
807                else if (level < drcComp->maxCutThr[i]) {
808                    /* cut range */
809                    gain = fMult((level - drcComp->cutThr[i]), drcComp->cutFac[i]) - drcComp->maxEarlyCut[i];
810                }
811                else {
812                    /* max cut */
813                    gain = -drcComp->maxCut[i];
814                }
815
816                /* choose time constant */
817                lvl2smthlvl = level - drcComp->smoothLevel[i];
818                if (gain < drcComp->smoothGain[i]) {
819                    /* attack */
820                    if (lvl2smthlvl > drcComp->attackThr[i]) {
821                        /* fast attack */
822                        alpha = drcComp->fastAttack[i];
823                    }
824                    else {
825                        /* slow attack */
826                        alpha = drcComp->slowAttack[i];
827                    }
828                }
829                else {
830                    /* release */
831                    if (lvl2smthlvl < -drcComp->decayThr[i]) {
832                        /* fast release */
833                        alpha = drcComp->fastDecay[i];
834                    }
835                    else {
836                        /* slow release */
837                        alpha = drcComp->slowDecay[i];
838                    }
839                }
840
841                /* smooth gain & level */
842                if ((gain < drcComp->smoothGain[i]) || (drcComp->holdCnt[i] == 0)) { /* hold gain unless we have an attack or hold period is over */
843                    FIXP_DBL accu;
844
845                    /* drcComp->smoothLevel[i] = (1-alpha) * drcComp->smoothLevel[i] + alpha * level; */
846                    accu =  fMult(((FIXP_DBL)MAXVAL_DBL-alpha), drcComp->smoothLevel[i]);
847                    accu += fMult(alpha,level);
848                    drcComp->smoothLevel[i] = accu;
849
850                    /* drcComp->smoothGain[i]  = (1-alpha) * drcComp->smoothGain[i] + alpha * gain; */
851                    accu =  fMult(((FIXP_DBL)MAXVAL_DBL-alpha), drcComp->smoothGain[i]);
852                    accu += fMult(alpha,gain);
853                    drcComp->smoothGain[i] = accu;
854                }
855
856                /* hold counter */
857                if (drcComp->holdCnt[i]) {
858                  drcComp->holdCnt[i]--;
859                }
860                if (gain < drcComp->smoothGain[i]) {
861                  drcComp->holdCnt[i] = drcComp->holdOff[i];
862                }
863            } /* profile != DRC_NONE */
864        } /* for i=1..2 */
865      } else {
866        /* no compression */
867        drcComp->smoothGain[0] = FL2FXCONST_DBL(0.f);
868        drcComp->smoothGain[1] = FL2FXCONST_DBL(0.f);
869      }
870
871    /**************************************************************************
872    * limiter
873    **************************************************************************/
874
875    /* find peak level */
876    peak[0] = peak[1] = FL2FXCONST_DBL(0.f);
877    for (i = 0; i < drcComp->blockLength; i++) {
878        FIXP_DBL tmp;
879        const INT_PCM* pSamples = &inSamples[i*drcComp->channels];
880        INT_PCM maxSample = 0;
881
882        /* single channels */
883        for (c = 0; c < (int)drcComp->channels; c++) {
884            maxSample = FDKmax(maxSample, fAbs(pSamples[c]));
885        }
886        peak[0] = fixMax(peak[0], FX_PCM2FX_DBL(maxSample)>>DOWNMIX_SHIFT);
887
888        /* Lt/Rt downmix */
889        if (drcComp->fullChannels > 2) {
890            /* Lt */
891            tmp = FL2FXCONST_DBL(0.f);
892
893            if (drcComp->channelIdx[LS] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1);          /* Ls */
894            if (drcComp->channelIdx[LS2] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1);        /* Ls2 */
895            if (drcComp->channelIdx[RS] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1);          /* Rs */
896            if (drcComp->channelIdx[RS2] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1);        /* Rs2 */
897            if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp);                                     /* 7.1ch */
898            if (drcComp->channelIdx[S] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]])>>(DOWNMIX_SHIFT-1);            /* S */
899            if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1);            /* C */
900            tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]])>>DOWNMIX_SHIFT);                                                                   /* L */
901
902            peak[0] = fixMax(peak[0], fixp_abs(tmp));
903
904            /* Rt */
905            tmp = FL2FXCONST_DBL(0.f);
906            if (drcComp->channelIdx[LS] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1);          /* Ls */
907            if (drcComp->channelIdx[LS2] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1);        /* Ls2 */
908            if (drcComp->channelIdx[RS] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1);          /* Rs */
909            if (drcComp->channelIdx[RS2] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1);        /* Rs2 */
910            if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp);                                     /* 7.1ch */
911            if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]])>>(DOWNMIX_SHIFT-1);            /* S */
912            if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1);            /* C */
913            tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]])>>DOWNMIX_SHIFT);                                                                   /* R */
914
915            peak[0] = fixMax(peak[0], fixp_abs(tmp));
916        }
917
918        /* Lo/Ro downmix */
919        if (drcComp->fullChannels > 2) {
920            /* Lo */
921            tmp = FL2FXCONST_DBL(0.f);
922            if (drcComp->channelIdx[LS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1);                            /* Ls */
923            if (drcComp->channelIdx[LS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1);                          /* Ls2 */
924            if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp);                                     /* 7.1ch */
925            if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(slev, fMult(FL2FXCONST_DBL(0.7f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]]))>>(DOWNMIX_SHIFT-1); /* S */
926            if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1);                              /* C */
927            tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]])>>DOWNMIX_SHIFT);                                                                   /* L */
928
929            peak[0] = fixMax(peak[0], fixp_abs(tmp));
930
931            /* Ro */
932            tmp = FL2FXCONST_DBL(0.f);
933            if (drcComp->channelIdx[RS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1);                            /* Rs */
934            if (drcComp->channelIdx[RS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1);                          /* Rs2 */
935            if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp);                                     /* 7.1ch */
936            if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(slev, fMult(FL2FXCONST_DBL(0.7f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]]))>>(DOWNMIX_SHIFT-1); /* S */
937            if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1);                              /* C */
938            tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]])>>DOWNMIX_SHIFT);                                                                   /* R */
939
940            peak[0] = fixMax(peak[0], fixp_abs(tmp));
941        }
942
943        peak[1] = fixMax(peak[0], peak[1]);
944
945        /* Mono Downmix - for comp_val only */
946        if (drcComp->fullChannels > 1) {
947            tmp = FL2FXCONST_DBL(0.f);
948            if (drcComp->channelIdx[LS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1);                            /* Ls */
949            if (drcComp->channelIdx[LS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1);                          /* Ls2 */
950            if (drcComp->channelIdx[RS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1);                            /* Rs */
951            if (drcComp->channelIdx[RS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1);                          /* Rs2 */
952            if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp);                                     /* 7.1ch */
953            /*if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp *=0.707f;*/                                                             /* 7.1ch */
954            if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(slev, fMult(FL2FXCONST_DBL(0.7f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]]))>>(DOWNMIX_SHIFT-1); /* S */
955            if (drcComp->channelIdx[C] >= 0) tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1);                                  /* C (2*clev) */
956            tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]])>>DOWNMIX_SHIFT);                                                                   /* L */
957            tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]])>>DOWNMIX_SHIFT);                                                                   /* R */
958
959            peak[1] = fixMax(peak[1], fixp_abs(tmp));
960        }
961    }
962
963    for (i=0; i<2; i++) {
964      FIXP_DBL tmp = drcComp->prevPeak[i];
965      drcComp->prevPeak[i] = peak[i];
966      peak[i] = fixMax(peak[i], tmp);
967
968      /*
969       * Convert to dBFS, apply dialnorm
970       */
971      /* descaled peak in ld64 representation */
972      FIXP_DBL ld_peak = CalcLdData(peak[i]) + (FIXP_DBL)((LONG)DOWNMIX_SHIFT<<(DFRACT_BITS-1-LD_DATA_SHIFT));
973
974      /* if (peak < 1e-6) level = 1e-6f; */
975      ld_peak = FDKmax(ld_peak, FL2FXCONST_DBL(-0.31143075889569022011284244651463f));
976
977      /* peak[i] = 20 * log(peak[i])/log(10) + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS)
978       * peak[i] = 20 * log(2)/log(10) * ld(peak[i]) + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS)
979       * peak[i] = 10 * 2*0.30102999566398119521373889472449 * ld(peak[i]) + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS)
980       *
981       *    additional scaling with METADATA_FRACT_BITS:
982       * peak[i] = (10 * 2*0.30102999566398119521373889472449 * ld64(peak[i]) * 64 + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS))*2^(-METADATA_FRACT_BITS)
983       * peak[i] = 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * 2*0.30102999566398119521373889472449 * ld64(peak[i])
984       *         + 0.2f*2^(-METADATA_FRACT_BITS) + drcComp->smoothGain[i]
985       */
986      peak[i] = fMult((FIXP_DBL)(10<<(METADATA_FRACT_BITS+LD_DATA_SHIFT)), fMult( FL2FX_DBL(2*0.30102999566398119521373889472449f), ld_peak));
987      peak[i] += (FL2FX_DBL(0.5f)>>METADATA_INT_BITS);           /* add a little bit headroom */
988      peak[i] +=  drcComp->smoothGain[i];
989    }
990
991    /* peak -= dialnorm + 31; */  /* this is Dolby style only */
992    peak[0] -= (FIXP_DBL)((dialnorm-drc_TargetRefLevel)<<(METADATA_FRACT_BITS-16)); /* peak[0] -= dialnorm - drc_TargetRefLevel */
993
994    /* peak += 11; */   /* this is Dolby style only */      /* RF mode output is 11dB higher */
995    /*peak += comp_TargetRefLevel - drc_TargetRefLevel;*/
996    peak[1] -= (FIXP_DBL)((dialnorm-comp_TargetRefLevel)<<(METADATA_FRACT_BITS-16)); /* peak[1] -= dialnorm - comp_TargetRefLevel */
997
998    /* limiter gain */
999    drcComp->limGain[0] += drcComp->limDecay;               /* linear limiter release */
1000    drcComp->limGain[0] = fixMin(drcComp->limGain[0], -peak[0]);
1001
1002    drcComp->limGain[1] += 2*drcComp->limDecay;             /* linear limiter release */
1003    drcComp->limGain[1] = fixMin(drcComp->limGain[1], -peak[1]);
1004
1005    /*************************************************************************/
1006
1007    /* apply limiting, return DRC gains*/
1008    {
1009        FIXP_DBL tmp;
1010
1011        tmp = drcComp->smoothGain[0];
1012        if (drcComp->limGain[0] < FL2FXCONST_DBL(0.f)) {
1013          tmp += drcComp->limGain[0];
1014        }
1015        *pDynrng = (LONG) scaleValue(tmp, -(METADATA_FRACT_BITS-16));
1016
1017        tmp = drcComp->smoothGain[1];
1018        if (drcComp->limGain[1] < FL2FXCONST_DBL(0.f)) {
1019          tmp += drcComp->limGain[1];
1020        }
1021        *pCompr  = (LONG) scaleValue(tmp, -(METADATA_FRACT_BITS-16));
1022    }
1023
1024    return 0;
1025}
1026
1027
1028DRC_PROFILE FDK_DRC_Generator_getDrcProfile(const HDRC_COMP drcComp)
1029{
1030    return drcComp->profile[0];
1031}
1032
1033DRC_PROFILE FDK_DRC_Generator_getCompProfile(const HDRC_COMP drcComp)
1034{
1035    return drcComp->profile[1];
1036}
1037
1038
1039