1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker
4*e5436536SAndroid Build Coastguard Worker © Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
5*e5436536SAndroid Build Coastguard Worker Forschung e.V. All rights reserved.
6*e5436536SAndroid Build Coastguard Worker
7*e5436536SAndroid Build Coastguard Worker 1. INTRODUCTION
8*e5436536SAndroid Build Coastguard Worker The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9*e5436536SAndroid Build Coastguard Worker that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10*e5436536SAndroid Build Coastguard Worker scheme for digital audio. This FDK AAC Codec software is intended to be used on
11*e5436536SAndroid Build Coastguard Worker a wide variety of Android devices.
12*e5436536SAndroid Build Coastguard Worker
13*e5436536SAndroid Build Coastguard Worker AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14*e5436536SAndroid Build Coastguard Worker general perceptual audio codecs. AAC-ELD is considered the best-performing
15*e5436536SAndroid Build Coastguard Worker full-bandwidth communications codec by independent studies and is widely
16*e5436536SAndroid Build Coastguard Worker deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17*e5436536SAndroid Build Coastguard Worker specifications.
18*e5436536SAndroid Build Coastguard Worker
19*e5436536SAndroid Build Coastguard Worker Patent licenses for necessary patent claims for the FDK AAC Codec (including
20*e5436536SAndroid Build Coastguard Worker those of Fraunhofer) may be obtained through Via Licensing
21*e5436536SAndroid Build Coastguard Worker (www.vialicensing.com) or through the respective patent owners individually for
22*e5436536SAndroid Build Coastguard Worker the purpose of encoding or decoding bit streams in products that are compliant
23*e5436536SAndroid Build Coastguard Worker with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24*e5436536SAndroid Build Coastguard Worker Android devices already license these patent claims through Via Licensing or
25*e5436536SAndroid Build Coastguard Worker directly from the patent owners, and therefore FDK AAC Codec software may
26*e5436536SAndroid Build Coastguard Worker already be covered under those patent licenses when it is used for those
27*e5436536SAndroid Build Coastguard Worker licensed purposes only.
28*e5436536SAndroid Build Coastguard Worker
29*e5436536SAndroid Build Coastguard Worker Commercially-licensed AAC software libraries, including floating-point versions
30*e5436536SAndroid Build Coastguard Worker with enhanced sound quality, are also available from Fraunhofer. Users are
31*e5436536SAndroid Build Coastguard Worker encouraged to check the Fraunhofer website for additional applications
32*e5436536SAndroid Build Coastguard Worker information and documentation.
33*e5436536SAndroid Build Coastguard Worker
34*e5436536SAndroid Build Coastguard Worker 2. COPYRIGHT LICENSE
35*e5436536SAndroid Build Coastguard Worker
36*e5436536SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification,
37*e5436536SAndroid Build Coastguard Worker are permitted without payment of copyright license fees provided that you
38*e5436536SAndroid Build Coastguard Worker satisfy the following conditions:
39*e5436536SAndroid Build Coastguard Worker
40*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in redistributions of
41*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec or your modifications thereto in source code form.
42*e5436536SAndroid Build Coastguard Worker
43*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in the documentation
44*e5436536SAndroid Build Coastguard Worker and/or other materials provided with redistributions of the FDK AAC Codec or
45*e5436536SAndroid Build Coastguard Worker your modifications thereto in binary form. You must make available free of
46*e5436536SAndroid Build Coastguard Worker charge copies of the complete source code of the FDK AAC Codec and your
47*e5436536SAndroid Build Coastguard Worker modifications thereto to recipients of copies in binary form.
48*e5436536SAndroid Build Coastguard Worker
49*e5436536SAndroid Build Coastguard Worker The name of Fraunhofer may not be used to endorse or promote products derived
50*e5436536SAndroid Build Coastguard Worker from this library without prior written permission.
51*e5436536SAndroid Build Coastguard Worker
52*e5436536SAndroid Build Coastguard Worker You may not charge copyright license fees for anyone to use, copy or distribute
53*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec software or your modifications thereto.
54*e5436536SAndroid Build Coastguard Worker
55*e5436536SAndroid Build Coastguard Worker Your modified versions of the FDK AAC Codec must carry prominent notices stating
56*e5436536SAndroid Build Coastguard Worker that you changed the software and the date of any change. For modified versions
57*e5436536SAndroid Build Coastguard Worker of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58*e5436536SAndroid Build Coastguard Worker must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59*e5436536SAndroid Build Coastguard Worker AAC Codec Library for Android."
60*e5436536SAndroid Build Coastguard Worker
61*e5436536SAndroid Build Coastguard Worker 3. NO PATENT LICENSE
62*e5436536SAndroid Build Coastguard Worker
63*e5436536SAndroid Build Coastguard Worker NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64*e5436536SAndroid Build Coastguard Worker limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65*e5436536SAndroid Build Coastguard Worker Fraunhofer provides no warranty of patent non-infringement with respect to this
66*e5436536SAndroid Build Coastguard Worker software.
67*e5436536SAndroid Build Coastguard Worker
68*e5436536SAndroid Build Coastguard Worker You may use this FDK AAC Codec software or modifications thereto only for
69*e5436536SAndroid Build Coastguard Worker purposes that are authorized by appropriate patent licenses.
70*e5436536SAndroid Build Coastguard Worker
71*e5436536SAndroid Build Coastguard Worker 4. DISCLAIMER
72*e5436536SAndroid Build Coastguard Worker
73*e5436536SAndroid Build Coastguard Worker This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74*e5436536SAndroid Build Coastguard Worker holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75*e5436536SAndroid Build Coastguard Worker including but not limited to the implied warranties of merchantability and
76*e5436536SAndroid Build Coastguard Worker fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77*e5436536SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78*e5436536SAndroid Build Coastguard Worker or consequential damages, including but not limited to procurement of substitute
79*e5436536SAndroid Build Coastguard Worker goods or services; loss of use, data, or profits, or business interruption,
80*e5436536SAndroid Build Coastguard Worker however caused and on any theory of liability, whether in contract, strict
81*e5436536SAndroid Build Coastguard Worker liability, or tort (including negligence), arising in any way out of the use of
82*e5436536SAndroid Build Coastguard Worker this software, even if advised of the possibility of such damage.
83*e5436536SAndroid Build Coastguard Worker
84*e5436536SAndroid Build Coastguard Worker 5. CONTACT INFORMATION
85*e5436536SAndroid Build Coastguard Worker
86*e5436536SAndroid Build Coastguard Worker Fraunhofer Institute for Integrated Circuits IIS
87*e5436536SAndroid Build Coastguard Worker Attention: Audio and Multimedia Departments - FDK AAC LL
88*e5436536SAndroid Build Coastguard Worker Am Wolfsmantel 33
89*e5436536SAndroid Build Coastguard Worker 91058 Erlangen, Germany
90*e5436536SAndroid Build Coastguard Worker
91*e5436536SAndroid Build Coastguard Worker www.iis.fraunhofer.de/amm
92*e5436536SAndroid Build Coastguard Worker [email protected]
93*e5436536SAndroid Build Coastguard Worker ----------------------------------------------------------------------------- */
94*e5436536SAndroid Build Coastguard Worker
95*e5436536SAndroid Build Coastguard Worker /************************* MPEG-D DRC decoder library **************************
96*e5436536SAndroid Build Coastguard Worker
97*e5436536SAndroid Build Coastguard Worker Author(s):
98*e5436536SAndroid Build Coastguard Worker
99*e5436536SAndroid Build Coastguard Worker Description:
100*e5436536SAndroid Build Coastguard Worker
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker
103*e5436536SAndroid Build Coastguard Worker #include "drcDec_types.h"
104*e5436536SAndroid Build Coastguard Worker #include "drcDec_gainDecoder.h"
105*e5436536SAndroid Build Coastguard Worker #include "drcGainDec_preprocess.h"
106*e5436536SAndroid Build Coastguard Worker #include "drcDec_tools.h"
107*e5436536SAndroid Build Coastguard Worker #include "FDK_matrixCalloc.h"
108*e5436536SAndroid Build Coastguard Worker #include "drcDec_rom.h"
109*e5436536SAndroid Build Coastguard Worker
110*e5436536SAndroid Build Coastguard Worker #define SLOPE_FACTOR_DB_TO_LINEAR \
111*e5436536SAndroid Build Coastguard Worker FL2FXCONST_DBL(0.1151f * (float)(1 << 3)) /* ln(10) / 20 */
112*e5436536SAndroid Build Coastguard Worker
113*e5436536SAndroid Build Coastguard Worker typedef struct {
114*e5436536SAndroid Build Coastguard Worker int drcSetEffect;
115*e5436536SAndroid Build Coastguard Worker DUCKING_MODIFICATION* pDMod;
116*e5436536SAndroid Build Coastguard Worker GAIN_MODIFICATION* pGMod;
117*e5436536SAndroid Build Coastguard Worker int drcCharacteristicPresent;
118*e5436536SAndroid Build Coastguard Worker CHARACTERISTIC_FORMAT characteristicFormatSource[2];
119*e5436536SAndroid Build Coastguard Worker const CUSTOM_DRC_CHAR* pCCharSource[2];
120*e5436536SAndroid Build Coastguard Worker CHARACTERISTIC_FORMAT characteristicFormatTarget[2];
121*e5436536SAndroid Build Coastguard Worker const CUSTOM_DRC_CHAR* pCCharTarget[2];
122*e5436536SAndroid Build Coastguard Worker int slopeIsNegative;
123*e5436536SAndroid Build Coastguard Worker int limiterPeakTargetPresent;
124*e5436536SAndroid Build Coastguard Worker FIXP_SGL limiterPeakTarget;
125*e5436536SAndroid Build Coastguard Worker FIXP_DBL loudnessNormalizationGainDb;
126*e5436536SAndroid Build Coastguard Worker FIXP_SGL compress;
127*e5436536SAndroid Build Coastguard Worker FIXP_SGL boost;
128*e5436536SAndroid Build Coastguard Worker } NODE_MODIFICATION;
129*e5436536SAndroid Build Coastguard Worker
_getCicpCharacteristic(const int cicpCharacteristic,CHARACTERISTIC_FORMAT pCharacteristicFormat[2],const CUSTOM_DRC_CHAR * pCCharSource[2])130*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _getCicpCharacteristic(
131*e5436536SAndroid Build Coastguard Worker const int cicpCharacteristic,
132*e5436536SAndroid Build Coastguard Worker CHARACTERISTIC_FORMAT pCharacteristicFormat[2],
133*e5436536SAndroid Build Coastguard Worker const CUSTOM_DRC_CHAR* pCCharSource[2]) {
134*e5436536SAndroid Build Coastguard Worker if ((cicpCharacteristic < 1) || (cicpCharacteristic > 11)) {
135*e5436536SAndroid Build Coastguard Worker return DE_NOT_OK;
136*e5436536SAndroid Build Coastguard Worker }
137*e5436536SAndroid Build Coastguard Worker
138*e5436536SAndroid Build Coastguard Worker if (cicpCharacteristic < 7) { /* sigmoid characteristic */
139*e5436536SAndroid Build Coastguard Worker pCharacteristicFormat[CS_LEFT] = CF_SIGMOID;
140*e5436536SAndroid Build Coastguard Worker pCCharSource[CS_LEFT] =
141*e5436536SAndroid Build Coastguard Worker (const CUSTOM_DRC_CHAR*)(&cicpDrcCharSigmoidLeft[cicpCharacteristic -
142*e5436536SAndroid Build Coastguard Worker 1]);
143*e5436536SAndroid Build Coastguard Worker pCharacteristicFormat[CS_RIGHT] = CF_SIGMOID;
144*e5436536SAndroid Build Coastguard Worker pCCharSource[CS_RIGHT] =
145*e5436536SAndroid Build Coastguard Worker (const CUSTOM_DRC_CHAR*)(&cicpDrcCharSigmoidRight[cicpCharacteristic -
146*e5436536SAndroid Build Coastguard Worker 1]);
147*e5436536SAndroid Build Coastguard Worker } else { /* nodes characteristic */
148*e5436536SAndroid Build Coastguard Worker pCharacteristicFormat[CS_LEFT] = CF_NODES;
149*e5436536SAndroid Build Coastguard Worker pCCharSource[CS_LEFT] =
150*e5436536SAndroid Build Coastguard Worker (const CUSTOM_DRC_CHAR*)(&cicpDrcCharNodesLeft[cicpCharacteristic - 7]);
151*e5436536SAndroid Build Coastguard Worker pCharacteristicFormat[CS_RIGHT] = CF_NODES;
152*e5436536SAndroid Build Coastguard Worker pCCharSource[CS_RIGHT] =
153*e5436536SAndroid Build Coastguard Worker (const CUSTOM_DRC_CHAR*)(&cicpDrcCharNodesRight[cicpCharacteristic -
154*e5436536SAndroid Build Coastguard Worker 7]);
155*e5436536SAndroid Build Coastguard Worker }
156*e5436536SAndroid Build Coastguard Worker return DE_OK;
157*e5436536SAndroid Build Coastguard Worker }
158*e5436536SAndroid Build Coastguard Worker
_getSign(FIXP_SGL in)159*e5436536SAndroid Build Coastguard Worker static int _getSign(FIXP_SGL in) {
160*e5436536SAndroid Build Coastguard Worker if (in > (FIXP_DBL)0) return 1;
161*e5436536SAndroid Build Coastguard Worker if (in < (FIXP_DBL)0) return -1;
162*e5436536SAndroid Build Coastguard Worker return 0;
163*e5436536SAndroid Build Coastguard Worker }
164*e5436536SAndroid Build Coastguard Worker
_getSlopeSign(const CHARACTERISTIC_FORMAT drcCharFormat,const CUSTOM_DRC_CHAR * pCChar,int * pSlopeSign)165*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _getSlopeSign(const CHARACTERISTIC_FORMAT drcCharFormat,
166*e5436536SAndroid Build Coastguard Worker const CUSTOM_DRC_CHAR* pCChar, int* pSlopeSign) {
167*e5436536SAndroid Build Coastguard Worker if (drcCharFormat == CF_SIGMOID) {
168*e5436536SAndroid Build Coastguard Worker *pSlopeSign = (pCChar->sigmoid.flipSign ? 1 : -1);
169*e5436536SAndroid Build Coastguard Worker } else {
170*e5436536SAndroid Build Coastguard Worker int k, slopeSign = 0, tmp_slopeSign;
171*e5436536SAndroid Build Coastguard Worker for (k = 0; k < pCChar->nodes.characteristicNodeCount; k++) {
172*e5436536SAndroid Build Coastguard Worker if (pCChar->nodes.nodeLevel[k + 1] > pCChar->nodes.nodeLevel[k]) {
173*e5436536SAndroid Build Coastguard Worker tmp_slopeSign =
174*e5436536SAndroid Build Coastguard Worker _getSign(pCChar->nodes.nodeGain[k + 1] - pCChar->nodes.nodeGain[k]);
175*e5436536SAndroid Build Coastguard Worker } else {
176*e5436536SAndroid Build Coastguard Worker tmp_slopeSign = -_getSign(pCChar->nodes.nodeGain[k + 1] -
177*e5436536SAndroid Build Coastguard Worker pCChar->nodes.nodeGain[k]);
178*e5436536SAndroid Build Coastguard Worker }
179*e5436536SAndroid Build Coastguard Worker if ((slopeSign || tmp_slopeSign) && (slopeSign == -tmp_slopeSign))
180*e5436536SAndroid Build Coastguard Worker return DE_NOT_OK; /* DRC characteristic is not invertible */
181*e5436536SAndroid Build Coastguard Worker else
182*e5436536SAndroid Build Coastguard Worker slopeSign = tmp_slopeSign;
183*e5436536SAndroid Build Coastguard Worker }
184*e5436536SAndroid Build Coastguard Worker *pSlopeSign = slopeSign;
185*e5436536SAndroid Build Coastguard Worker }
186*e5436536SAndroid Build Coastguard Worker return DE_OK;
187*e5436536SAndroid Build Coastguard Worker }
188*e5436536SAndroid Build Coastguard Worker
_isSlopeNegative(const CHARACTERISTIC_FORMAT drcCharFormat[2],const CUSTOM_DRC_CHAR * pCChar[2],int * pSlopeIsNegative)189*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _isSlopeNegative(const CHARACTERISTIC_FORMAT drcCharFormat[2],
190*e5436536SAndroid Build Coastguard Worker const CUSTOM_DRC_CHAR* pCChar[2],
191*e5436536SAndroid Build Coastguard Worker int* pSlopeIsNegative) {
192*e5436536SAndroid Build Coastguard Worker DRC_ERROR err = DE_OK;
193*e5436536SAndroid Build Coastguard Worker int slopeSign[2] = {0, 0};
194*e5436536SAndroid Build Coastguard Worker
195*e5436536SAndroid Build Coastguard Worker err = _getSlopeSign(drcCharFormat[CS_LEFT], pCChar[CS_LEFT],
196*e5436536SAndroid Build Coastguard Worker &slopeSign[CS_LEFT]);
197*e5436536SAndroid Build Coastguard Worker if (err) return err;
198*e5436536SAndroid Build Coastguard Worker
199*e5436536SAndroid Build Coastguard Worker err = _getSlopeSign(drcCharFormat[CS_RIGHT], pCChar[CS_RIGHT],
200*e5436536SAndroid Build Coastguard Worker &slopeSign[CS_RIGHT]);
201*e5436536SAndroid Build Coastguard Worker if (err) return err;
202*e5436536SAndroid Build Coastguard Worker
203*e5436536SAndroid Build Coastguard Worker if ((slopeSign[CS_LEFT] || slopeSign[CS_RIGHT]) &&
204*e5436536SAndroid Build Coastguard Worker (slopeSign[CS_LEFT] == -slopeSign[CS_RIGHT]))
205*e5436536SAndroid Build Coastguard Worker return DE_NOT_OK; /* DRC characteristic is not invertible */
206*e5436536SAndroid Build Coastguard Worker
207*e5436536SAndroid Build Coastguard Worker *pSlopeIsNegative = (slopeSign[CS_LEFT] < 0);
208*e5436536SAndroid Build Coastguard Worker return DE_OK;
209*e5436536SAndroid Build Coastguard Worker }
210*e5436536SAndroid Build Coastguard Worker
_prepareDrcCharacteristic(const DRC_CHARACTERISTIC * pDChar,DRC_COEFFICIENTS_UNI_DRC * pCoef,const int b,NODE_MODIFICATION * pNodeMod)211*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _prepareDrcCharacteristic(const DRC_CHARACTERISTIC* pDChar,
212*e5436536SAndroid Build Coastguard Worker DRC_COEFFICIENTS_UNI_DRC* pCoef,
213*e5436536SAndroid Build Coastguard Worker const int b,
214*e5436536SAndroid Build Coastguard Worker NODE_MODIFICATION* pNodeMod) {
215*e5436536SAndroid Build Coastguard Worker DRC_ERROR err = DE_OK;
216*e5436536SAndroid Build Coastguard Worker pNodeMod->drcCharacteristicPresent = pDChar->present;
217*e5436536SAndroid Build Coastguard Worker if (pNodeMod->drcCharacteristicPresent) {
218*e5436536SAndroid Build Coastguard Worker if (pDChar->isCICP == 1) {
219*e5436536SAndroid Build Coastguard Worker err = _getCicpCharacteristic(pDChar->cicpIndex,
220*e5436536SAndroid Build Coastguard Worker pNodeMod->characteristicFormatSource,
221*e5436536SAndroid Build Coastguard Worker pNodeMod->pCCharSource);
222*e5436536SAndroid Build Coastguard Worker if (err) return err;
223*e5436536SAndroid Build Coastguard Worker } else {
224*e5436536SAndroid Build Coastguard Worker pNodeMod->characteristicFormatSource[CS_LEFT] =
225*e5436536SAndroid Build Coastguard Worker (CHARACTERISTIC_FORMAT)
226*e5436536SAndroid Build Coastguard Worker pCoef->characteristicLeftFormat[pDChar->custom.left];
227*e5436536SAndroid Build Coastguard Worker pNodeMod->pCCharSource[CS_LEFT] =
228*e5436536SAndroid Build Coastguard Worker &(pCoef->customCharacteristicLeft[pDChar->custom.left]);
229*e5436536SAndroid Build Coastguard Worker pNodeMod->characteristicFormatSource[CS_RIGHT] =
230*e5436536SAndroid Build Coastguard Worker (CHARACTERISTIC_FORMAT)
231*e5436536SAndroid Build Coastguard Worker pCoef->characteristicRightFormat[pDChar->custom.right];
232*e5436536SAndroid Build Coastguard Worker pNodeMod->pCCharSource[CS_RIGHT] =
233*e5436536SAndroid Build Coastguard Worker &(pCoef->customCharacteristicRight[pDChar->custom.right]);
234*e5436536SAndroid Build Coastguard Worker }
235*e5436536SAndroid Build Coastguard Worker err = _isSlopeNegative(pNodeMod->characteristicFormatSource,
236*e5436536SAndroid Build Coastguard Worker pNodeMod->pCCharSource, &pNodeMod->slopeIsNegative);
237*e5436536SAndroid Build Coastguard Worker if (err) return err;
238*e5436536SAndroid Build Coastguard Worker
239*e5436536SAndroid Build Coastguard Worker if (pNodeMod->pGMod != NULL) {
240*e5436536SAndroid Build Coastguard Worker if (pNodeMod->pGMod[b].targetCharacteristicLeftPresent) {
241*e5436536SAndroid Build Coastguard Worker pNodeMod->characteristicFormatTarget[CS_LEFT] =
242*e5436536SAndroid Build Coastguard Worker (CHARACTERISTIC_FORMAT)pCoef->characteristicLeftFormat
243*e5436536SAndroid Build Coastguard Worker [pNodeMod->pGMod[b].targetCharacteristicLeftIndex];
244*e5436536SAndroid Build Coastguard Worker pNodeMod->pCCharTarget[CS_LEFT] =
245*e5436536SAndroid Build Coastguard Worker &(pCoef->customCharacteristicLeft
246*e5436536SAndroid Build Coastguard Worker [pNodeMod->pGMod[b].targetCharacteristicLeftIndex]);
247*e5436536SAndroid Build Coastguard Worker }
248*e5436536SAndroid Build Coastguard Worker if (pNodeMod->pGMod[b].targetCharacteristicRightPresent) {
249*e5436536SAndroid Build Coastguard Worker pNodeMod->characteristicFormatTarget[CS_RIGHT] =
250*e5436536SAndroid Build Coastguard Worker (CHARACTERISTIC_FORMAT)pCoef->characteristicRightFormat
251*e5436536SAndroid Build Coastguard Worker [pNodeMod->pGMod[b].targetCharacteristicRightIndex];
252*e5436536SAndroid Build Coastguard Worker pNodeMod->pCCharTarget[CS_RIGHT] =
253*e5436536SAndroid Build Coastguard Worker &(pCoef->customCharacteristicRight
254*e5436536SAndroid Build Coastguard Worker [pNodeMod->pGMod[b].targetCharacteristicRightIndex]);
255*e5436536SAndroid Build Coastguard Worker }
256*e5436536SAndroid Build Coastguard Worker }
257*e5436536SAndroid Build Coastguard Worker }
258*e5436536SAndroid Build Coastguard Worker return DE_OK;
259*e5436536SAndroid Build Coastguard Worker }
260*e5436536SAndroid Build Coastguard Worker
_compressorIO_sigmoid_common(const FIXP_DBL tmp,const FIXP_DBL gainDbLimit,const FIXP_DBL exp,const int inverse,FIXP_DBL * out)261*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _compressorIO_sigmoid_common(
262*e5436536SAndroid Build Coastguard Worker const FIXP_DBL tmp, /* e = 7 */
263*e5436536SAndroid Build Coastguard Worker const FIXP_DBL gainDbLimit, /* e = 6 */
264*e5436536SAndroid Build Coastguard Worker const FIXP_DBL exp, /* e = 5 */
265*e5436536SAndroid Build Coastguard Worker const int inverse, FIXP_DBL* out) /* e = 7 */
266*e5436536SAndroid Build Coastguard Worker {
267*e5436536SAndroid Build Coastguard Worker FIXP_DBL x, tmp1, tmp2, invExp, denom;
268*e5436536SAndroid Build Coastguard Worker int e_x, e_tmp1, e_tmp2, e_invExp, e_denom, e_out;
269*e5436536SAndroid Build Coastguard Worker
270*e5436536SAndroid Build Coastguard Worker if (exp < FL2FXCONST_DBL(1.0f / (float)(1 << 5))) {
271*e5436536SAndroid Build Coastguard Worker return DE_NOT_OK;
272*e5436536SAndroid Build Coastguard Worker }
273*e5436536SAndroid Build Coastguard Worker
274*e5436536SAndroid Build Coastguard Worker /* x = tmp / gainDbLimit; */
275*e5436536SAndroid Build Coastguard Worker x = fDivNormSigned(tmp, gainDbLimit, &e_x);
276*e5436536SAndroid Build Coastguard Worker e_x += 7 - 6;
277*e5436536SAndroid Build Coastguard Worker if (x < (FIXP_DBL)0) {
278*e5436536SAndroid Build Coastguard Worker return DE_NOT_OK;
279*e5436536SAndroid Build Coastguard Worker }
280*e5436536SAndroid Build Coastguard Worker
281*e5436536SAndroid Build Coastguard Worker /* out = tmp / pow(1.0f +/- pow(x, exp), 1.0f/exp); */
282*e5436536SAndroid Build Coastguard Worker tmp1 = fPow(x, e_x, exp, 5, &e_tmp1);
283*e5436536SAndroid Build Coastguard Worker if (inverse) tmp1 = -tmp1;
284*e5436536SAndroid Build Coastguard Worker tmp2 = fAddNorm(FL2FXCONST_DBL(1.0f / (float)(1 << 1)), 1, tmp1, e_tmp1,
285*e5436536SAndroid Build Coastguard Worker &e_tmp2);
286*e5436536SAndroid Build Coastguard Worker invExp = fDivNorm(FL2FXCONST_DBL(1.0f / (float)(1 << 1)), exp, &e_invExp);
287*e5436536SAndroid Build Coastguard Worker e_invExp += 1 - 5;
288*e5436536SAndroid Build Coastguard Worker if (tmp2 < (FIXP_DBL)0) {
289*e5436536SAndroid Build Coastguard Worker return DE_NOT_OK;
290*e5436536SAndroid Build Coastguard Worker }
291*e5436536SAndroid Build Coastguard Worker denom = fPow(tmp2, e_tmp2, invExp, e_invExp, &e_denom);
292*e5436536SAndroid Build Coastguard Worker *out = fDivNormSigned(tmp, denom, &e_out);
293*e5436536SAndroid Build Coastguard Worker e_out += 7 - e_denom;
294*e5436536SAndroid Build Coastguard Worker *out = scaleValueSaturate(*out, e_out - 7);
295*e5436536SAndroid Build Coastguard Worker return DE_OK;
296*e5436536SAndroid Build Coastguard Worker }
297*e5436536SAndroid Build Coastguard Worker
_compressorIO_sigmoid(const CUSTOM_DRC_CHAR_SIGMOID * pCChar,const FIXP_DBL inLevelDb,FIXP_DBL * outGainDb)298*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _compressorIO_sigmoid(const CUSTOM_DRC_CHAR_SIGMOID* pCChar,
299*e5436536SAndroid Build Coastguard Worker const FIXP_DBL inLevelDb, /* e = 7 */
300*e5436536SAndroid Build Coastguard Worker FIXP_DBL* outGainDb) /* e = 7 */
301*e5436536SAndroid Build Coastguard Worker {
302*e5436536SAndroid Build Coastguard Worker FIXP_DBL tmp;
303*e5436536SAndroid Build Coastguard Worker FIXP_SGL exp = pCChar->exp;
304*e5436536SAndroid Build Coastguard Worker DRC_ERROR err = DE_OK;
305*e5436536SAndroid Build Coastguard Worker
306*e5436536SAndroid Build Coastguard Worker tmp = fMultDiv2((DRC_INPUT_LOUDNESS_TARGET >> 1) - (inLevelDb >> 1),
307*e5436536SAndroid Build Coastguard Worker pCChar->ioRatio);
308*e5436536SAndroid Build Coastguard Worker tmp = SATURATE_LEFT_SHIFT(tmp, 2 + 1 + 1, DFRACT_BITS);
309*e5436536SAndroid Build Coastguard Worker if (exp < (FIXP_SGL)MAXVAL_SGL) {
310*e5436536SAndroid Build Coastguard Worker /* x = tmp / gainDbLimit; */
311*e5436536SAndroid Build Coastguard Worker /* *outGainDb = tmp / pow(1.0f + pow(x, exp), 1.0f/exp); */
312*e5436536SAndroid Build Coastguard Worker err = _compressorIO_sigmoid_common(tmp, FX_SGL2FX_DBL(pCChar->gain),
313*e5436536SAndroid Build Coastguard Worker FX_SGL2FX_DBL(exp), 0, outGainDb);
314*e5436536SAndroid Build Coastguard Worker if (err) return err;
315*e5436536SAndroid Build Coastguard Worker } else {
316*e5436536SAndroid Build Coastguard Worker *outGainDb =
317*e5436536SAndroid Build Coastguard Worker tmp; /* scaling of outGainDb (7) is equal to scaling of tmp (7) */
318*e5436536SAndroid Build Coastguard Worker }
319*e5436536SAndroid Build Coastguard Worker if (pCChar->flipSign == 1) {
320*e5436536SAndroid Build Coastguard Worker *outGainDb = -*outGainDb;
321*e5436536SAndroid Build Coastguard Worker }
322*e5436536SAndroid Build Coastguard Worker return err;
323*e5436536SAndroid Build Coastguard Worker }
324*e5436536SAndroid Build Coastguard Worker
_compressorIO_sigmoid_inverse(const CUSTOM_DRC_CHAR_SIGMOID * pCChar,const FIXP_SGL gainDb,FIXP_DBL * inLev)325*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _compressorIO_sigmoid_inverse(
326*e5436536SAndroid Build Coastguard Worker const CUSTOM_DRC_CHAR_SIGMOID* pCChar, const FIXP_SGL gainDb,
327*e5436536SAndroid Build Coastguard Worker FIXP_DBL* inLev) {
328*e5436536SAndroid Build Coastguard Worker DRC_ERROR err = DE_OK;
329*e5436536SAndroid Build Coastguard Worker FIXP_SGL ioRatio = pCChar->ioRatio;
330*e5436536SAndroid Build Coastguard Worker FIXP_SGL exp = pCChar->exp;
331*e5436536SAndroid Build Coastguard Worker FIXP_DBL tmp = FX_SGL2FX_DBL(gainDb), tmp_out;
332*e5436536SAndroid Build Coastguard Worker int e_out;
333*e5436536SAndroid Build Coastguard Worker
334*e5436536SAndroid Build Coastguard Worker if (pCChar->flipSign == 1) {
335*e5436536SAndroid Build Coastguard Worker tmp = -tmp;
336*e5436536SAndroid Build Coastguard Worker }
337*e5436536SAndroid Build Coastguard Worker if (exp < (FIXP_SGL)MAXVAL_SGL) {
338*e5436536SAndroid Build Coastguard Worker /* x = tmp / gainDbLimit; */
339*e5436536SAndroid Build Coastguard Worker /* tmp = tmp / pow(1.0f - pow(x, exp), 1.0f / exp); */
340*e5436536SAndroid Build Coastguard Worker err = _compressorIO_sigmoid_common(tmp, FX_SGL2FX_DBL(pCChar->gain),
341*e5436536SAndroid Build Coastguard Worker FX_SGL2FX_DBL(exp), 1, &tmp);
342*e5436536SAndroid Build Coastguard Worker if (err) return err;
343*e5436536SAndroid Build Coastguard Worker }
344*e5436536SAndroid Build Coastguard Worker if (ioRatio == (FIXP_SGL)0) {
345*e5436536SAndroid Build Coastguard Worker return DE_NOT_OK;
346*e5436536SAndroid Build Coastguard Worker }
347*e5436536SAndroid Build Coastguard Worker tmp_out = fDivNormSigned(tmp, FX_SGL2FX_DBL(ioRatio), &e_out);
348*e5436536SAndroid Build Coastguard Worker e_out += 7 - 2;
349*e5436536SAndroid Build Coastguard Worker tmp_out = fAddNorm(DRC_INPUT_LOUDNESS_TARGET, 7, -tmp_out, e_out, &e_out);
350*e5436536SAndroid Build Coastguard Worker *inLev = scaleValueSaturate(tmp_out, e_out - 7);
351*e5436536SAndroid Build Coastguard Worker
352*e5436536SAndroid Build Coastguard Worker return err;
353*e5436536SAndroid Build Coastguard Worker }
354*e5436536SAndroid Build Coastguard Worker
_compressorIO_nodes(const CUSTOM_DRC_CHAR_NODES * pCChar,const FIXP_DBL inLevelDb,FIXP_DBL * outGainDb)355*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _compressorIO_nodes(const CUSTOM_DRC_CHAR_NODES* pCChar,
356*e5436536SAndroid Build Coastguard Worker const FIXP_DBL inLevelDb, /* e = 7 */
357*e5436536SAndroid Build Coastguard Worker FIXP_DBL* outGainDb) /* e = 7 */
358*e5436536SAndroid Build Coastguard Worker {
359*e5436536SAndroid Build Coastguard Worker int n;
360*e5436536SAndroid Build Coastguard Worker FIXP_DBL w;
361*e5436536SAndroid Build Coastguard Worker const FIXP_SGL* nodeLevel = pCChar->nodeLevel;
362*e5436536SAndroid Build Coastguard Worker const FIXP_SGL* nodeGain = pCChar->nodeGain;
363*e5436536SAndroid Build Coastguard Worker
364*e5436536SAndroid Build Coastguard Worker if (inLevelDb < DRC_INPUT_LOUDNESS_TARGET) {
365*e5436536SAndroid Build Coastguard Worker for (n = 0; n < pCChar->characteristicNodeCount; n++) {
366*e5436536SAndroid Build Coastguard Worker if ((inLevelDb <= FX_SGL2FX_DBL(nodeLevel[n])) &&
367*e5436536SAndroid Build Coastguard Worker (inLevelDb > FX_SGL2FX_DBL(nodeLevel[n + 1]))) {
368*e5436536SAndroid Build Coastguard Worker w = fDivNorm(inLevelDb - FX_SGL2FX_DBL(nodeLevel[n + 1]),
369*e5436536SAndroid Build Coastguard Worker FX_SGL2FX_DBL(nodeLevel[n] - nodeLevel[n + 1]));
370*e5436536SAndroid Build Coastguard Worker *outGainDb = fMult(w, nodeGain[n]) +
371*e5436536SAndroid Build Coastguard Worker fMult((FIXP_DBL)MAXVAL_DBL - w, nodeGain[n + 1]);
372*e5436536SAndroid Build Coastguard Worker /* *outGainDb = (w * nodeGain[n] + (1.0-w) * nodeGain[n+1]); */
373*e5436536SAndroid Build Coastguard Worker return DE_OK;
374*e5436536SAndroid Build Coastguard Worker }
375*e5436536SAndroid Build Coastguard Worker }
376*e5436536SAndroid Build Coastguard Worker } else {
377*e5436536SAndroid Build Coastguard Worker for (n = 0; n < pCChar->characteristicNodeCount; n++) {
378*e5436536SAndroid Build Coastguard Worker if ((inLevelDb >= FX_SGL2FX_DBL(nodeLevel[n])) &&
379*e5436536SAndroid Build Coastguard Worker (inLevelDb < FX_SGL2FX_DBL(nodeLevel[n + 1]))) {
380*e5436536SAndroid Build Coastguard Worker w = fDivNorm(FX_SGL2FX_DBL(nodeLevel[n + 1]) - inLevelDb,
381*e5436536SAndroid Build Coastguard Worker FX_SGL2FX_DBL(nodeLevel[n + 1] - nodeLevel[n]));
382*e5436536SAndroid Build Coastguard Worker *outGainDb = fMult(w, nodeGain[n]) +
383*e5436536SAndroid Build Coastguard Worker fMult((FIXP_DBL)MAXVAL_DBL - w, nodeGain[n + 1]);
384*e5436536SAndroid Build Coastguard Worker /* *outGainDb = (w * nodeGain[n] + (1.0-w) * nodeGain[n+1]); */
385*e5436536SAndroid Build Coastguard Worker return DE_OK;
386*e5436536SAndroid Build Coastguard Worker }
387*e5436536SAndroid Build Coastguard Worker }
388*e5436536SAndroid Build Coastguard Worker }
389*e5436536SAndroid Build Coastguard Worker *outGainDb = FX_SGL2FX_DBL(nodeGain[pCChar->characteristicNodeCount]);
390*e5436536SAndroid Build Coastguard Worker return DE_OK;
391*e5436536SAndroid Build Coastguard Worker }
392*e5436536SAndroid Build Coastguard Worker
_compressorIO_nodes_inverse(const CUSTOM_DRC_CHAR_NODES * pCChar,const FIXP_SGL gainDb,FIXP_DBL * inLev)393*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _compressorIO_nodes_inverse(
394*e5436536SAndroid Build Coastguard Worker const CUSTOM_DRC_CHAR_NODES* pCChar, const FIXP_SGL gainDb, /* e = 7 */
395*e5436536SAndroid Build Coastguard Worker FIXP_DBL* inLev) /* e = 7 */
396*e5436536SAndroid Build Coastguard Worker {
397*e5436536SAndroid Build Coastguard Worker int n;
398*e5436536SAndroid Build Coastguard Worker int k;
399*e5436536SAndroid Build Coastguard Worker FIXP_DBL w;
400*e5436536SAndroid Build Coastguard Worker int gainIsNegative = 0;
401*e5436536SAndroid Build Coastguard Worker const FIXP_SGL* nodeLevel = pCChar->nodeLevel;
402*e5436536SAndroid Build Coastguard Worker const FIXP_SGL* nodeGain = pCChar->nodeGain;
403*e5436536SAndroid Build Coastguard Worker int nodeCount = pCChar->characteristicNodeCount;
404*e5436536SAndroid Build Coastguard Worker for (k = 0; k < nodeCount; k++) {
405*e5436536SAndroid Build Coastguard Worker if (pCChar->nodeGain[k + 1] < (FIXP_SGL)0) {
406*e5436536SAndroid Build Coastguard Worker gainIsNegative = 1;
407*e5436536SAndroid Build Coastguard Worker }
408*e5436536SAndroid Build Coastguard Worker }
409*e5436536SAndroid Build Coastguard Worker if (gainIsNegative == 1) {
410*e5436536SAndroid Build Coastguard Worker if (gainDb <= nodeGain[nodeCount]) {
411*e5436536SAndroid Build Coastguard Worker *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]);
412*e5436536SAndroid Build Coastguard Worker } else {
413*e5436536SAndroid Build Coastguard Worker if (gainDb >= (FIXP_SGL)0) {
414*e5436536SAndroid Build Coastguard Worker *inLev = DRC_INPUT_LOUDNESS_TARGET;
415*e5436536SAndroid Build Coastguard Worker } else {
416*e5436536SAndroid Build Coastguard Worker for (n = 0; n < nodeCount; n++) {
417*e5436536SAndroid Build Coastguard Worker if ((gainDb <= nodeGain[n]) && (gainDb > nodeGain[n + 1])) {
418*e5436536SAndroid Build Coastguard Worker FIXP_SGL gainDelta = nodeGain[n] - nodeGain[n + 1];
419*e5436536SAndroid Build Coastguard Worker if (gainDelta == (FIXP_SGL)0) {
420*e5436536SAndroid Build Coastguard Worker *inLev = FX_SGL2FX_DBL(nodeLevel[n]);
421*e5436536SAndroid Build Coastguard Worker return DE_OK;
422*e5436536SAndroid Build Coastguard Worker }
423*e5436536SAndroid Build Coastguard Worker w = fDivNorm(gainDb - nodeGain[n + 1], gainDelta);
424*e5436536SAndroid Build Coastguard Worker *inLev = fMult(w, nodeLevel[n]) +
425*e5436536SAndroid Build Coastguard Worker fMult((FIXP_DBL)MAXVAL_DBL - w, nodeLevel[n + 1]);
426*e5436536SAndroid Build Coastguard Worker /* *inLev = (w * nodeLevel[n] + (1.0-w) * nodeLevel[n+1]); */
427*e5436536SAndroid Build Coastguard Worker return DE_OK;
428*e5436536SAndroid Build Coastguard Worker }
429*e5436536SAndroid Build Coastguard Worker }
430*e5436536SAndroid Build Coastguard Worker *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]);
431*e5436536SAndroid Build Coastguard Worker }
432*e5436536SAndroid Build Coastguard Worker }
433*e5436536SAndroid Build Coastguard Worker } else {
434*e5436536SAndroid Build Coastguard Worker if (gainDb >= nodeGain[nodeCount]) {
435*e5436536SAndroid Build Coastguard Worker *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]);
436*e5436536SAndroid Build Coastguard Worker } else {
437*e5436536SAndroid Build Coastguard Worker if (gainDb <= (FIXP_SGL)0) {
438*e5436536SAndroid Build Coastguard Worker *inLev = DRC_INPUT_LOUDNESS_TARGET;
439*e5436536SAndroid Build Coastguard Worker } else {
440*e5436536SAndroid Build Coastguard Worker for (n = 0; n < nodeCount; n++) {
441*e5436536SAndroid Build Coastguard Worker if ((gainDb >= nodeGain[n]) && (gainDb < nodeGain[n + 1])) {
442*e5436536SAndroid Build Coastguard Worker FIXP_SGL gainDelta = nodeGain[n + 1] - nodeGain[n];
443*e5436536SAndroid Build Coastguard Worker if (gainDelta == (FIXP_SGL)0) {
444*e5436536SAndroid Build Coastguard Worker *inLev = FX_SGL2FX_DBL(nodeLevel[n]);
445*e5436536SAndroid Build Coastguard Worker return DE_OK;
446*e5436536SAndroid Build Coastguard Worker }
447*e5436536SAndroid Build Coastguard Worker w = fDivNorm(nodeGain[n + 1] - gainDb, gainDelta);
448*e5436536SAndroid Build Coastguard Worker *inLev = fMult(w, nodeLevel[n]) +
449*e5436536SAndroid Build Coastguard Worker fMult((FIXP_DBL)MAXVAL_DBL - w, nodeLevel[n + 1]);
450*e5436536SAndroid Build Coastguard Worker /* *inLev = (w * nodeLevel[n] + (1.0-w) * nodeLevel[n+1]); */
451*e5436536SAndroid Build Coastguard Worker return DE_OK;
452*e5436536SAndroid Build Coastguard Worker }
453*e5436536SAndroid Build Coastguard Worker }
454*e5436536SAndroid Build Coastguard Worker *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]);
455*e5436536SAndroid Build Coastguard Worker }
456*e5436536SAndroid Build Coastguard Worker }
457*e5436536SAndroid Build Coastguard Worker }
458*e5436536SAndroid Build Coastguard Worker return DE_OK;
459*e5436536SAndroid Build Coastguard Worker }
460*e5436536SAndroid Build Coastguard Worker
_mapGain(const CHARACTERISTIC_FORMAT pCCharFormatSource,const CUSTOM_DRC_CHAR * pCCharSource,const CHARACTERISTIC_FORMAT pCCharFormatTarget,const CUSTOM_DRC_CHAR * pCCharTarget,const FIXP_SGL gainInDb,FIXP_DBL * gainOutDb)461*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _mapGain(const CHARACTERISTIC_FORMAT pCCharFormatSource,
462*e5436536SAndroid Build Coastguard Worker const CUSTOM_DRC_CHAR* pCCharSource,
463*e5436536SAndroid Build Coastguard Worker const CHARACTERISTIC_FORMAT pCCharFormatTarget,
464*e5436536SAndroid Build Coastguard Worker const CUSTOM_DRC_CHAR* pCCharTarget,
465*e5436536SAndroid Build Coastguard Worker const FIXP_SGL gainInDb, /* e = 7 */
466*e5436536SAndroid Build Coastguard Worker FIXP_DBL* gainOutDb) /* e = 7 */
467*e5436536SAndroid Build Coastguard Worker {
468*e5436536SAndroid Build Coastguard Worker FIXP_DBL inLevel = (FIXP_DBL)0;
469*e5436536SAndroid Build Coastguard Worker DRC_ERROR err = DE_OK;
470*e5436536SAndroid Build Coastguard Worker
471*e5436536SAndroid Build Coastguard Worker switch (pCCharFormatSource) {
472*e5436536SAndroid Build Coastguard Worker case CF_SIGMOID:
473*e5436536SAndroid Build Coastguard Worker err = _compressorIO_sigmoid_inverse(
474*e5436536SAndroid Build Coastguard Worker (const CUSTOM_DRC_CHAR_SIGMOID*)pCCharSource, gainInDb, &inLevel);
475*e5436536SAndroid Build Coastguard Worker if (err) return err;
476*e5436536SAndroid Build Coastguard Worker break;
477*e5436536SAndroid Build Coastguard Worker case CF_NODES:
478*e5436536SAndroid Build Coastguard Worker err = _compressorIO_nodes_inverse(
479*e5436536SAndroid Build Coastguard Worker (const CUSTOM_DRC_CHAR_NODES*)pCCharSource, gainInDb, &inLevel);
480*e5436536SAndroid Build Coastguard Worker if (err) return err;
481*e5436536SAndroid Build Coastguard Worker break;
482*e5436536SAndroid Build Coastguard Worker default:
483*e5436536SAndroid Build Coastguard Worker return DE_NOT_OK;
484*e5436536SAndroid Build Coastguard Worker }
485*e5436536SAndroid Build Coastguard Worker switch (pCCharFormatTarget) {
486*e5436536SAndroid Build Coastguard Worker case CF_SIGMOID:
487*e5436536SAndroid Build Coastguard Worker err = _compressorIO_sigmoid((const CUSTOM_DRC_CHAR_SIGMOID*)pCCharTarget,
488*e5436536SAndroid Build Coastguard Worker inLevel, gainOutDb);
489*e5436536SAndroid Build Coastguard Worker if (err) return err;
490*e5436536SAndroid Build Coastguard Worker break;
491*e5436536SAndroid Build Coastguard Worker case CF_NODES:
492*e5436536SAndroid Build Coastguard Worker err = _compressorIO_nodes((const CUSTOM_DRC_CHAR_NODES*)pCCharTarget,
493*e5436536SAndroid Build Coastguard Worker inLevel, gainOutDb);
494*e5436536SAndroid Build Coastguard Worker if (err) return err;
495*e5436536SAndroid Build Coastguard Worker break;
496*e5436536SAndroid Build Coastguard Worker default:
497*e5436536SAndroid Build Coastguard Worker break;
498*e5436536SAndroid Build Coastguard Worker }
499*e5436536SAndroid Build Coastguard Worker return DE_OK;
500*e5436536SAndroid Build Coastguard Worker }
501*e5436536SAndroid Build Coastguard Worker
_toLinear(const NODE_MODIFICATION * nodeMod,const int drcBand,const FIXP_SGL gainDb,const FIXP_SGL slopeDb,FIXP_DBL * gainLin,FIXP_DBL * slopeLin)502*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _toLinear(
503*e5436536SAndroid Build Coastguard Worker const NODE_MODIFICATION* nodeMod, const int drcBand,
504*e5436536SAndroid Build Coastguard Worker const FIXP_SGL gainDb, /* in: gain value in dB, e = 7 */
505*e5436536SAndroid Build Coastguard Worker const FIXP_SGL slopeDb, /* in: slope value in dB/deltaTmin, e = 2 */
506*e5436536SAndroid Build Coastguard Worker FIXP_DBL* gainLin, /* out: linear gain value, e = 7 */
507*e5436536SAndroid Build Coastguard Worker FIXP_DBL* slopeLin) /* out: linear slope value, e = 7 */
508*e5436536SAndroid Build Coastguard Worker {
509*e5436536SAndroid Build Coastguard Worker FIXP_DBL gainRatio_m = FL2FXCONST_DBL(1.0f / (float)(1 << 1));
510*e5436536SAndroid Build Coastguard Worker GAIN_MODIFICATION* pGMod = NULL;
511*e5436536SAndroid Build Coastguard Worker DUCKING_MODIFICATION* pDMod = nodeMod->pDMod;
512*e5436536SAndroid Build Coastguard Worker FIXP_DBL tmp_dbl, gainDb_modified, gainDb_offset, gainDb_out, gainLin_m,
513*e5436536SAndroid Build Coastguard Worker slopeLin_m;
514*e5436536SAndroid Build Coastguard Worker int gainLin_e, gainRatio_e = 1, gainDb_out_e;
515*e5436536SAndroid Build Coastguard Worker if (nodeMod->pGMod != NULL) {
516*e5436536SAndroid Build Coastguard Worker pGMod = &(nodeMod->pGMod[drcBand]);
517*e5436536SAndroid Build Coastguard Worker }
518*e5436536SAndroid Build Coastguard Worker if (((nodeMod->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) == 0) &&
519*e5436536SAndroid Build Coastguard Worker (nodeMod->drcSetEffect != EB_FADE) &&
520*e5436536SAndroid Build Coastguard Worker (nodeMod->drcSetEffect != EB_CLIPPING)) {
521*e5436536SAndroid Build Coastguard Worker DRC_ERROR err = DE_OK;
522*e5436536SAndroid Build Coastguard Worker FIXP_DBL gainDbMapped;
523*e5436536SAndroid Build Coastguard Worker
524*e5436536SAndroid Build Coastguard Worker if ((pGMod != NULL) && (nodeMod->drcCharacteristicPresent)) {
525*e5436536SAndroid Build Coastguard Worker if (((gainDb > (FIXP_SGL)0) && nodeMod->slopeIsNegative) ||
526*e5436536SAndroid Build Coastguard Worker ((gainDb < (FIXP_SGL)0) && !nodeMod->slopeIsNegative)) {
527*e5436536SAndroid Build Coastguard Worker /* left side */
528*e5436536SAndroid Build Coastguard Worker if (pGMod->targetCharacteristicLeftPresent == 1) {
529*e5436536SAndroid Build Coastguard Worker err = _mapGain(nodeMod->characteristicFormatSource[CS_LEFT],
530*e5436536SAndroid Build Coastguard Worker nodeMod->pCCharSource[CS_LEFT],
531*e5436536SAndroid Build Coastguard Worker nodeMod->characteristicFormatTarget[CS_LEFT],
532*e5436536SAndroid Build Coastguard Worker nodeMod->pCCharTarget[CS_LEFT], gainDb, &gainDbMapped);
533*e5436536SAndroid Build Coastguard Worker if (err) return err;
534*e5436536SAndroid Build Coastguard Worker gainRatio_m = fDivNormSigned(
535*e5436536SAndroid Build Coastguard Worker gainDbMapped, FX_SGL2FX_DBL(gainDb),
536*e5436536SAndroid Build Coastguard Worker &gainRatio_e); /* target characteristic in payload */
537*e5436536SAndroid Build Coastguard Worker }
538*e5436536SAndroid Build Coastguard Worker }
539*e5436536SAndroid Build Coastguard Worker
540*e5436536SAndroid Build Coastguard Worker else { /* if (((gainDb < (FIXP_SGL)0) && nodeMod->slopeIsNegative) ||
541*e5436536SAndroid Build Coastguard Worker ((gainDb > (FIXP_SGL)0) && !nodeMod->slopeIsNegative)) */
542*e5436536SAndroid Build Coastguard Worker
543*e5436536SAndroid Build Coastguard Worker /* right side */
544*e5436536SAndroid Build Coastguard Worker if (pGMod->targetCharacteristicRightPresent == 1) {
545*e5436536SAndroid Build Coastguard Worker err =
546*e5436536SAndroid Build Coastguard Worker _mapGain(nodeMod->characteristicFormatSource[CS_RIGHT],
547*e5436536SAndroid Build Coastguard Worker nodeMod->pCCharSource[CS_RIGHT],
548*e5436536SAndroid Build Coastguard Worker nodeMod->characteristicFormatTarget[CS_RIGHT],
549*e5436536SAndroid Build Coastguard Worker nodeMod->pCCharTarget[CS_RIGHT], gainDb, &gainDbMapped);
550*e5436536SAndroid Build Coastguard Worker if (err) return err;
551*e5436536SAndroid Build Coastguard Worker gainRatio_m = fDivNormSigned(
552*e5436536SAndroid Build Coastguard Worker gainDbMapped, FX_SGL2FX_DBL(gainDb),
553*e5436536SAndroid Build Coastguard Worker &gainRatio_e); /* target characteristic in payload */
554*e5436536SAndroid Build Coastguard Worker }
555*e5436536SAndroid Build Coastguard Worker }
556*e5436536SAndroid Build Coastguard Worker }
557*e5436536SAndroid Build Coastguard Worker if (gainDb < (FIXP_SGL)0) {
558*e5436536SAndroid Build Coastguard Worker gainRatio_m = fMultDiv2(gainRatio_m, nodeMod->compress);
559*e5436536SAndroid Build Coastguard Worker } else {
560*e5436536SAndroid Build Coastguard Worker gainRatio_m = fMultDiv2(gainRatio_m, nodeMod->boost);
561*e5436536SAndroid Build Coastguard Worker }
562*e5436536SAndroid Build Coastguard Worker gainRatio_e += 2;
563*e5436536SAndroid Build Coastguard Worker }
564*e5436536SAndroid Build Coastguard Worker if ((pGMod != NULL) && (pGMod->gainScalingPresent == 1)) {
565*e5436536SAndroid Build Coastguard Worker if (gainDb < (FIXP_SGL)0) {
566*e5436536SAndroid Build Coastguard Worker gainRatio_m = fMultDiv2(gainRatio_m, pGMod->attenuationScaling);
567*e5436536SAndroid Build Coastguard Worker } else {
568*e5436536SAndroid Build Coastguard Worker gainRatio_m = fMultDiv2(gainRatio_m, pGMod->amplificationScaling);
569*e5436536SAndroid Build Coastguard Worker }
570*e5436536SAndroid Build Coastguard Worker gainRatio_e += 3;
571*e5436536SAndroid Build Coastguard Worker }
572*e5436536SAndroid Build Coastguard Worker if ((pDMod != NULL) &&
573*e5436536SAndroid Build Coastguard Worker (nodeMod->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) &&
574*e5436536SAndroid Build Coastguard Worker (pDMod->duckingScalingPresent == 1)) {
575*e5436536SAndroid Build Coastguard Worker gainRatio_m = fMultDiv2(gainRatio_m, pDMod->duckingScaling);
576*e5436536SAndroid Build Coastguard Worker gainRatio_e += 3;
577*e5436536SAndroid Build Coastguard Worker }
578*e5436536SAndroid Build Coastguard Worker
579*e5436536SAndroid Build Coastguard Worker gainDb_modified =
580*e5436536SAndroid Build Coastguard Worker fMultDiv2(gainDb, gainRatio_m); /* resulting e: 7 + gainRatio_e + 1*/
581*e5436536SAndroid Build Coastguard Worker gainDb_offset = (FIXP_DBL)0;
582*e5436536SAndroid Build Coastguard Worker
583*e5436536SAndroid Build Coastguard Worker if ((pGMod != NULL) && (pGMod->gainOffsetPresent == 1)) {
584*e5436536SAndroid Build Coastguard Worker /* *gainLin *= (float)pow(2.0, (double)(pGMod->gainOffset/6.0f)); */
585*e5436536SAndroid Build Coastguard Worker gainDb_offset += FX_SGL2FX_DBL(pGMod->gainOffset) >> 4; /* resulting e: 8 */
586*e5436536SAndroid Build Coastguard Worker }
587*e5436536SAndroid Build Coastguard Worker if ((nodeMod->limiterPeakTargetPresent == 1) &&
588*e5436536SAndroid Build Coastguard Worker (nodeMod->drcSetEffect ==
589*e5436536SAndroid Build Coastguard Worker EB_CLIPPING)) { /* The only drcSetEffect is "clipping prevention" */
590*e5436536SAndroid Build Coastguard Worker /* loudnessNormalizationGainModificationDb is included in
591*e5436536SAndroid Build Coastguard Worker * loudnessNormalizationGainDb */
592*e5436536SAndroid Build Coastguard Worker /* *gainLin *= (float)pow(2.0, max(0.0, -nodeModification->limiterPeakTarget
593*e5436536SAndroid Build Coastguard Worker * - nodeModification->loudnessNormalizationGainDb)/6.0); */
594*e5436536SAndroid Build Coastguard Worker gainDb_offset += fMax(
595*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)0,
596*e5436536SAndroid Build Coastguard Worker (FX_SGL2FX_DBL(-nodeMod->limiterPeakTarget) >> 3) -
597*e5436536SAndroid Build Coastguard Worker (nodeMod->loudnessNormalizationGainDb >> 1)); /* resulting e: 8 */
598*e5436536SAndroid Build Coastguard Worker }
599*e5436536SAndroid Build Coastguard Worker if (gainDb_offset != (FIXP_DBL)0) {
600*e5436536SAndroid Build Coastguard Worker gainDb_out = fAddNorm(gainDb_modified, 7 + gainRatio_e + 1, gainDb_offset,
601*e5436536SAndroid Build Coastguard Worker 8, &gainDb_out_e);
602*e5436536SAndroid Build Coastguard Worker } else {
603*e5436536SAndroid Build Coastguard Worker gainDb_out = gainDb_modified;
604*e5436536SAndroid Build Coastguard Worker gainDb_out_e = 7 + gainRatio_e + 1;
605*e5436536SAndroid Build Coastguard Worker }
606*e5436536SAndroid Build Coastguard Worker
607*e5436536SAndroid Build Coastguard Worker /* *gainLin = (float)pow(2.0, (double)(gainDb_modified[1] / 6.0f)); */
608*e5436536SAndroid Build Coastguard Worker gainLin_m = approxDb2lin(gainDb_out, gainDb_out_e, &gainLin_e);
609*e5436536SAndroid Build Coastguard Worker *gainLin = scaleValueSaturate(gainLin_m, gainLin_e - 7);
610*e5436536SAndroid Build Coastguard Worker
611*e5436536SAndroid Build Coastguard Worker /* *slopeLin = SLOPE_FACTOR_DB_TO_LINEAR * gainRatio * *gainLin * slopeDb; */
612*e5436536SAndroid Build Coastguard Worker if (slopeDb == (FIXP_SGL)0) {
613*e5436536SAndroid Build Coastguard Worker *slopeLin = (FIXP_DBL)0;
614*e5436536SAndroid Build Coastguard Worker } else {
615*e5436536SAndroid Build Coastguard Worker tmp_dbl =
616*e5436536SAndroid Build Coastguard Worker fMult(slopeDb, SLOPE_FACTOR_DB_TO_LINEAR); /* resulting e: 2 - 3 = -1 */
617*e5436536SAndroid Build Coastguard Worker tmp_dbl = fMult(tmp_dbl, gainRatio_m); /* resulting e: -1 + gainRatio_e */
618*e5436536SAndroid Build Coastguard Worker if (gainDb_offset !=
619*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)0) { /* recalculate gainLin from gainDb that wasn't modified
620*e5436536SAndroid Build Coastguard Worker by gainOffset and limiterPeakTarget */
621*e5436536SAndroid Build Coastguard Worker gainLin_m = approxDb2lin(gainDb_modified, 7 + gainRatio_e, &gainLin_e);
622*e5436536SAndroid Build Coastguard Worker }
623*e5436536SAndroid Build Coastguard Worker slopeLin_m = fMult(tmp_dbl, gainLin_m);
624*e5436536SAndroid Build Coastguard Worker *slopeLin =
625*e5436536SAndroid Build Coastguard Worker scaleValueSaturate(slopeLin_m, -1 + gainRatio_e + gainLin_e - 7);
626*e5436536SAndroid Build Coastguard Worker }
627*e5436536SAndroid Build Coastguard Worker
628*e5436536SAndroid Build Coastguard Worker if ((nodeMod->limiterPeakTargetPresent == 1) &&
629*e5436536SAndroid Build Coastguard Worker (nodeMod->drcSetEffect == EB_CLIPPING)) {
630*e5436536SAndroid Build Coastguard Worker if (*gainLin >= FL2FXCONST_DBL(1.0f / (float)(1 << 7))) {
631*e5436536SAndroid Build Coastguard Worker *gainLin = FL2FXCONST_DBL(1.0f / (float)(1 << 7));
632*e5436536SAndroid Build Coastguard Worker *slopeLin = (FIXP_DBL)0;
633*e5436536SAndroid Build Coastguard Worker }
634*e5436536SAndroid Build Coastguard Worker }
635*e5436536SAndroid Build Coastguard Worker
636*e5436536SAndroid Build Coastguard Worker return DE_OK;
637*e5436536SAndroid Build Coastguard Worker }
638*e5436536SAndroid Build Coastguard Worker
639*e5436536SAndroid Build Coastguard Worker /* prepare buffers containing linear nodes for each gain sequence */
640*e5436536SAndroid Build Coastguard Worker DRC_ERROR
prepareDrcGain(HANDLE_DRC_GAIN_DECODER hGainDec,HANDLE_UNI_DRC_GAIN hUniDrcGain,const FIXP_SGL compress,const FIXP_SGL boost,const FIXP_DBL loudnessNormalizationGainDb,const int activeDrcIndex)641*e5436536SAndroid Build Coastguard Worker prepareDrcGain(HANDLE_DRC_GAIN_DECODER hGainDec,
642*e5436536SAndroid Build Coastguard Worker HANDLE_UNI_DRC_GAIN hUniDrcGain, const FIXP_SGL compress,
643*e5436536SAndroid Build Coastguard Worker const FIXP_SGL boost, const FIXP_DBL loudnessNormalizationGainDb,
644*e5436536SAndroid Build Coastguard Worker const int activeDrcIndex) {
645*e5436536SAndroid Build Coastguard Worker int b, g, gainElementIndex;
646*e5436536SAndroid Build Coastguard Worker DRC_GAIN_BUFFERS* drcGainBuffers = &(hGainDec->drcGainBuffers);
647*e5436536SAndroid Build Coastguard Worker NODE_MODIFICATION nodeMod;
648*e5436536SAndroid Build Coastguard Worker FDKmemclear(&nodeMod, sizeof(NODE_MODIFICATION));
649*e5436536SAndroid Build Coastguard Worker ACTIVE_DRC* pActiveDrc = &(hGainDec->activeDrc[activeDrcIndex]);
650*e5436536SAndroid Build Coastguard Worker DRC_INSTRUCTIONS_UNI_DRC* pInst = pActiveDrc->pInst;
651*e5436536SAndroid Build Coastguard Worker if (pInst == NULL) return DE_NOT_OK;
652*e5436536SAndroid Build Coastguard Worker
653*e5436536SAndroid Build Coastguard Worker nodeMod.drcSetEffect = pInst->drcSetEffect;
654*e5436536SAndroid Build Coastguard Worker
655*e5436536SAndroid Build Coastguard Worker nodeMod.compress = compress;
656*e5436536SAndroid Build Coastguard Worker nodeMod.boost = boost;
657*e5436536SAndroid Build Coastguard Worker nodeMod.loudnessNormalizationGainDb = loudnessNormalizationGainDb;
658*e5436536SAndroid Build Coastguard Worker nodeMod.limiterPeakTargetPresent = pInst->limiterPeakTargetPresent;
659*e5436536SAndroid Build Coastguard Worker nodeMod.limiterPeakTarget = pInst->limiterPeakTarget;
660*e5436536SAndroid Build Coastguard Worker
661*e5436536SAndroid Build Coastguard Worker gainElementIndex = 0;
662*e5436536SAndroid Build Coastguard Worker for (g = 0; g < pInst->nDrcChannelGroups; g++) {
663*e5436536SAndroid Build Coastguard Worker int gainSetIndex = 0;
664*e5436536SAndroid Build Coastguard Worker int nDrcBands = 0;
665*e5436536SAndroid Build Coastguard Worker DRC_COEFFICIENTS_UNI_DRC* pCoef = pActiveDrc->pCoef;
666*e5436536SAndroid Build Coastguard Worker if (pCoef == NULL) return DE_NOT_OK;
667*e5436536SAndroid Build Coastguard Worker
668*e5436536SAndroid Build Coastguard Worker if (!pActiveDrc->channelGroupIsParametricDrc[g]) {
669*e5436536SAndroid Build Coastguard Worker gainSetIndex = pInst->gainSetIndexForChannelGroup[g];
670*e5436536SAndroid Build Coastguard Worker
671*e5436536SAndroid Build Coastguard Worker if (nodeMod.drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) {
672*e5436536SAndroid Build Coastguard Worker nodeMod.pDMod = &(pActiveDrc->duckingModificationForChannelGroup[g]);
673*e5436536SAndroid Build Coastguard Worker nodeMod.pGMod = NULL;
674*e5436536SAndroid Build Coastguard Worker } else {
675*e5436536SAndroid Build Coastguard Worker nodeMod.pGMod = pInst->gainModificationForChannelGroup[g];
676*e5436536SAndroid Build Coastguard Worker nodeMod.pDMod = NULL;
677*e5436536SAndroid Build Coastguard Worker }
678*e5436536SAndroid Build Coastguard Worker
679*e5436536SAndroid Build Coastguard Worker nDrcBands = pActiveDrc->bandCountForChannelGroup[g];
680*e5436536SAndroid Build Coastguard Worker for (b = 0; b < nDrcBands; b++) {
681*e5436536SAndroid Build Coastguard Worker DRC_ERROR err = DE_OK;
682*e5436536SAndroid Build Coastguard Worker GAIN_SET* pGainSet = &(pCoef->gainSet[gainSetIndex]);
683*e5436536SAndroid Build Coastguard Worker int seq = pGainSet->gainSequenceIndex[b];
684*e5436536SAndroid Build Coastguard Worker DRC_CHARACTERISTIC* pDChar = &(pGainSet->drcCharacteristic[b]);
685*e5436536SAndroid Build Coastguard Worker
686*e5436536SAndroid Build Coastguard Worker /* linearNodeBuffer contains a copy of the gain sequences (consisting of
687*e5436536SAndroid Build Coastguard Worker nodes) that are relevant for decoding. It also contains gain
688*e5436536SAndroid Build Coastguard Worker sequences of previous frames. */
689*e5436536SAndroid Build Coastguard Worker LINEAR_NODE_BUFFER* pLnb =
690*e5436536SAndroid Build Coastguard Worker &(drcGainBuffers->linearNodeBuffer[pActiveDrc->activeDrcOffset +
691*e5436536SAndroid Build Coastguard Worker gainElementIndex]);
692*e5436536SAndroid Build Coastguard Worker int i, lnbp;
693*e5436536SAndroid Build Coastguard Worker lnbp = drcGainBuffers->lnbPointer;
694*e5436536SAndroid Build Coastguard Worker pLnb->gainInterpolationType =
695*e5436536SAndroid Build Coastguard Worker (GAIN_INTERPOLATION_TYPE)pGainSet->gainInterpolationType;
696*e5436536SAndroid Build Coastguard Worker
697*e5436536SAndroid Build Coastguard Worker err = _prepareDrcCharacteristic(pDChar, pCoef, b, &nodeMod);
698*e5436536SAndroid Build Coastguard Worker if (err) return err;
699*e5436536SAndroid Build Coastguard Worker
700*e5436536SAndroid Build Coastguard Worker /* copy a node buffer and convert from dB to linear */
701*e5436536SAndroid Build Coastguard Worker pLnb->nNodes[lnbp] = fMin((int)hUniDrcGain->nNodes[seq], 16);
702*e5436536SAndroid Build Coastguard Worker for (i = 0; i < pLnb->nNodes[lnbp]; i++) {
703*e5436536SAndroid Build Coastguard Worker FIXP_DBL gainLin, slopeLin;
704*e5436536SAndroid Build Coastguard Worker err = _toLinear(&nodeMod, b, hUniDrcGain->gainNode[seq][i].gainDb,
705*e5436536SAndroid Build Coastguard Worker (FIXP_SGL)0, &gainLin, &slopeLin);
706*e5436536SAndroid Build Coastguard Worker if (err) return err;
707*e5436536SAndroid Build Coastguard Worker pLnb->linearNode[lnbp][i].gainLin = gainLin;
708*e5436536SAndroid Build Coastguard Worker pLnb->linearNode[lnbp][i].time = hUniDrcGain->gainNode[seq][i].time;
709*e5436536SAndroid Build Coastguard Worker }
710*e5436536SAndroid Build Coastguard Worker gainElementIndex++;
711*e5436536SAndroid Build Coastguard Worker }
712*e5436536SAndroid Build Coastguard Worker } else {
713*e5436536SAndroid Build Coastguard Worker /* parametric DRC not supported */
714*e5436536SAndroid Build Coastguard Worker gainElementIndex++;
715*e5436536SAndroid Build Coastguard Worker }
716*e5436536SAndroid Build Coastguard Worker }
717*e5436536SAndroid Build Coastguard Worker return DE_OK;
718*e5436536SAndroid Build Coastguard Worker }
719