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 - 2020 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 /**************************** PCM utility library ******************************
96*e5436536SAndroid Build Coastguard Worker
97*e5436536SAndroid Build Coastguard Worker Author(s): Matthias Neusinger
98*e5436536SAndroid Build Coastguard Worker
99*e5436536SAndroid Build Coastguard Worker Description: Hard limiter for clipping prevention
100*e5436536SAndroid Build Coastguard Worker
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker
103*e5436536SAndroid Build Coastguard Worker #include "limiter.h"
104*e5436536SAndroid Build Coastguard Worker #include "FDK_core.h"
105*e5436536SAndroid Build Coastguard Worker
106*e5436536SAndroid Build Coastguard Worker /* library version */
107*e5436536SAndroid Build Coastguard Worker #include "version.h"
108*e5436536SAndroid Build Coastguard Worker /* library title */
109*e5436536SAndroid Build Coastguard Worker #define TDLIMIT_LIB_TITLE "TD Limiter Lib"
110*e5436536SAndroid Build Coastguard Worker
111*e5436536SAndroid Build Coastguard Worker /* create limiter */
pcmLimiter_Create(unsigned int maxAttackMs,unsigned int releaseMs,FIXP_DBL threshold,unsigned int maxChannels,UINT maxSampleRate)112*e5436536SAndroid Build Coastguard Worker TDLimiterPtr pcmLimiter_Create(unsigned int maxAttackMs, unsigned int releaseMs,
113*e5436536SAndroid Build Coastguard Worker FIXP_DBL threshold, unsigned int maxChannels,
114*e5436536SAndroid Build Coastguard Worker UINT maxSampleRate) {
115*e5436536SAndroid Build Coastguard Worker TDLimiterPtr limiter = NULL;
116*e5436536SAndroid Build Coastguard Worker unsigned int attack, release;
117*e5436536SAndroid Build Coastguard Worker FIXP_DBL attackConst, releaseConst, exponent;
118*e5436536SAndroid Build Coastguard Worker INT e_ans;
119*e5436536SAndroid Build Coastguard Worker
120*e5436536SAndroid Build Coastguard Worker /* calc attack and release time in samples */
121*e5436536SAndroid Build Coastguard Worker attack = (unsigned int)(maxAttackMs * maxSampleRate / 1000);
122*e5436536SAndroid Build Coastguard Worker release = (unsigned int)(releaseMs * maxSampleRate / 1000);
123*e5436536SAndroid Build Coastguard Worker
124*e5436536SAndroid Build Coastguard Worker /* alloc limiter struct */
125*e5436536SAndroid Build Coastguard Worker limiter = (TDLimiterPtr)FDKcalloc(1, sizeof(struct TDLimiter));
126*e5436536SAndroid Build Coastguard Worker if (!limiter) return NULL;
127*e5436536SAndroid Build Coastguard Worker
128*e5436536SAndroid Build Coastguard Worker /* alloc max and delay buffers */
129*e5436536SAndroid Build Coastguard Worker limiter->maxBuf = (FIXP_DBL*)FDKcalloc(attack + 1, sizeof(FIXP_DBL));
130*e5436536SAndroid Build Coastguard Worker limiter->delayBuf =
131*e5436536SAndroid Build Coastguard Worker (FIXP_DBL*)FDKcalloc(attack * maxChannels, sizeof(FIXP_DBL));
132*e5436536SAndroid Build Coastguard Worker
133*e5436536SAndroid Build Coastguard Worker if (!limiter->maxBuf || !limiter->delayBuf) {
134*e5436536SAndroid Build Coastguard Worker pcmLimiter_Destroy(limiter);
135*e5436536SAndroid Build Coastguard Worker return NULL;
136*e5436536SAndroid Build Coastguard Worker }
137*e5436536SAndroid Build Coastguard Worker
138*e5436536SAndroid Build Coastguard Worker /* attackConst = pow(0.1, 1.0 / (attack + 1)) */
139*e5436536SAndroid Build Coastguard Worker exponent = invFixp(attack + 1);
140*e5436536SAndroid Build Coastguard Worker attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
141*e5436536SAndroid Build Coastguard Worker attackConst = scaleValue(attackConst, e_ans);
142*e5436536SAndroid Build Coastguard Worker
143*e5436536SAndroid Build Coastguard Worker /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */
144*e5436536SAndroid Build Coastguard Worker exponent = invFixp(release + 1);
145*e5436536SAndroid Build Coastguard Worker releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
146*e5436536SAndroid Build Coastguard Worker releaseConst = scaleValue(releaseConst, e_ans);
147*e5436536SAndroid Build Coastguard Worker
148*e5436536SAndroid Build Coastguard Worker /* init parameters */
149*e5436536SAndroid Build Coastguard Worker limiter->attackMs = maxAttackMs;
150*e5436536SAndroid Build Coastguard Worker limiter->maxAttackMs = maxAttackMs;
151*e5436536SAndroid Build Coastguard Worker limiter->releaseMs = releaseMs;
152*e5436536SAndroid Build Coastguard Worker limiter->attack = attack;
153*e5436536SAndroid Build Coastguard Worker limiter->attackConst = attackConst;
154*e5436536SAndroid Build Coastguard Worker limiter->releaseConst = releaseConst;
155*e5436536SAndroid Build Coastguard Worker limiter->threshold = threshold;
156*e5436536SAndroid Build Coastguard Worker limiter->channels = maxChannels;
157*e5436536SAndroid Build Coastguard Worker limiter->maxChannels = maxChannels;
158*e5436536SAndroid Build Coastguard Worker limiter->sampleRate = maxSampleRate;
159*e5436536SAndroid Build Coastguard Worker limiter->maxSampleRate = maxSampleRate;
160*e5436536SAndroid Build Coastguard Worker
161*e5436536SAndroid Build Coastguard Worker pcmLimiter_Reset(limiter);
162*e5436536SAndroid Build Coastguard Worker
163*e5436536SAndroid Build Coastguard Worker return limiter;
164*e5436536SAndroid Build Coastguard Worker }
165*e5436536SAndroid Build Coastguard Worker
166*e5436536SAndroid Build Coastguard Worker /* apply limiter */
pcmLimiter_Apply(TDLimiterPtr limiter,PCM_LIM * samplesIn,INT_PCM * samplesOut,FIXP_DBL * pGainPerSample,const INT scaling,const UINT nSamples)167*e5436536SAndroid Build Coastguard Worker TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
168*e5436536SAndroid Build Coastguard Worker INT_PCM* samplesOut, FIXP_DBL* pGainPerSample,
169*e5436536SAndroid Build Coastguard Worker const INT scaling, const UINT nSamples) {
170*e5436536SAndroid Build Coastguard Worker unsigned int i, j;
171*e5436536SAndroid Build Coastguard Worker FIXP_DBL tmp2;
172*e5436536SAndroid Build Coastguard Worker FIXP_DBL tmp, old, gain, additionalGain = 0;
173*e5436536SAndroid Build Coastguard Worker FIXP_DBL minGain = FL2FXCONST_DBL(1.0f / (1 << 1));
174*e5436536SAndroid Build Coastguard Worker UINT additionalGainAvailable = 1;
175*e5436536SAndroid Build Coastguard Worker
176*e5436536SAndroid Build Coastguard Worker if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
177*e5436536SAndroid Build Coastguard Worker
178*e5436536SAndroid Build Coastguard Worker {
179*e5436536SAndroid Build Coastguard Worker unsigned int channels = limiter->channels;
180*e5436536SAndroid Build Coastguard Worker unsigned int attack = limiter->attack;
181*e5436536SAndroid Build Coastguard Worker FIXP_DBL attackConst = limiter->attackConst;
182*e5436536SAndroid Build Coastguard Worker FIXP_DBL releaseConst = limiter->releaseConst;
183*e5436536SAndroid Build Coastguard Worker FIXP_DBL threshold = limiter->threshold >> scaling;
184*e5436536SAndroid Build Coastguard Worker
185*e5436536SAndroid Build Coastguard Worker FIXP_DBL max = limiter->max;
186*e5436536SAndroid Build Coastguard Worker FIXP_DBL* maxBuf = limiter->maxBuf;
187*e5436536SAndroid Build Coastguard Worker unsigned int maxBufIdx = limiter->maxBufIdx;
188*e5436536SAndroid Build Coastguard Worker FIXP_DBL cor = limiter->cor;
189*e5436536SAndroid Build Coastguard Worker FIXP_DBL* delayBuf = limiter->delayBuf;
190*e5436536SAndroid Build Coastguard Worker unsigned int delayBufIdx = limiter->delayBufIdx;
191*e5436536SAndroid Build Coastguard Worker
192*e5436536SAndroid Build Coastguard Worker FIXP_DBL smoothState0 = limiter->smoothState0;
193*e5436536SAndroid Build Coastguard Worker
194*e5436536SAndroid Build Coastguard Worker if (limiter->scaling != scaling) {
195*e5436536SAndroid Build Coastguard Worker scaleValuesSaturate(delayBuf, attack * channels,
196*e5436536SAndroid Build Coastguard Worker limiter->scaling - scaling);
197*e5436536SAndroid Build Coastguard Worker scaleValuesSaturate(maxBuf, attack + 1, limiter->scaling - scaling);
198*e5436536SAndroid Build Coastguard Worker max = scaleValueSaturate(max, limiter->scaling - scaling);
199*e5436536SAndroid Build Coastguard Worker limiter->scaling = scaling;
200*e5436536SAndroid Build Coastguard Worker }
201*e5436536SAndroid Build Coastguard Worker
202*e5436536SAndroid Build Coastguard Worker if (pGainPerSample == NULL) {
203*e5436536SAndroid Build Coastguard Worker additionalGainAvailable = 0;
204*e5436536SAndroid Build Coastguard Worker }
205*e5436536SAndroid Build Coastguard Worker
206*e5436536SAndroid Build Coastguard Worker for (i = 0; i < nSamples; i++) {
207*e5436536SAndroid Build Coastguard Worker /* get maximum absolute sample value of all channels, including the
208*e5436536SAndroid Build Coastguard Worker * additional gain. */
209*e5436536SAndroid Build Coastguard Worker tmp = (FIXP_DBL)0;
210*e5436536SAndroid Build Coastguard Worker for (j = 0; j < channels; j++) {
211*e5436536SAndroid Build Coastguard Worker tmp2 = PCM_LIM2FIXP_DBL(samplesIn[j]);
212*e5436536SAndroid Build Coastguard Worker tmp2 =
213*e5436536SAndroid Build Coastguard Worker (tmp2 == (FIXP_DBL)MINVAL_DBL) ? (FIXP_DBL)MAXVAL_DBL : fAbs(tmp2);
214*e5436536SAndroid Build Coastguard Worker tmp = fMax(tmp, tmp2);
215*e5436536SAndroid Build Coastguard Worker }
216*e5436536SAndroid Build Coastguard Worker
217*e5436536SAndroid Build Coastguard Worker if (additionalGainAvailable) {
218*e5436536SAndroid Build Coastguard Worker additionalGain = pGainPerSample[i];
219*e5436536SAndroid Build Coastguard Worker tmp = fMult(tmp, additionalGain);
220*e5436536SAndroid Build Coastguard Worker }
221*e5436536SAndroid Build Coastguard Worker
222*e5436536SAndroid Build Coastguard Worker /* set threshold as lower border to save calculations in running maximum
223*e5436536SAndroid Build Coastguard Worker * algorithm */
224*e5436536SAndroid Build Coastguard Worker tmp = fMax(tmp, threshold);
225*e5436536SAndroid Build Coastguard Worker
226*e5436536SAndroid Build Coastguard Worker /* running maximum */
227*e5436536SAndroid Build Coastguard Worker old = maxBuf[maxBufIdx];
228*e5436536SAndroid Build Coastguard Worker maxBuf[maxBufIdx] = tmp;
229*e5436536SAndroid Build Coastguard Worker
230*e5436536SAndroid Build Coastguard Worker if (tmp >= max) {
231*e5436536SAndroid Build Coastguard Worker /* new sample is greater than old maximum, so it is the new maximum */
232*e5436536SAndroid Build Coastguard Worker max = tmp;
233*e5436536SAndroid Build Coastguard Worker } else if (old < max) {
234*e5436536SAndroid Build Coastguard Worker /* maximum does not change, as the sample, which has left the window was
235*e5436536SAndroid Build Coastguard Worker not the maximum */
236*e5436536SAndroid Build Coastguard Worker } else {
237*e5436536SAndroid Build Coastguard Worker /* the old maximum has left the window, we have to search the complete
238*e5436536SAndroid Build Coastguard Worker buffer for the new max */
239*e5436536SAndroid Build Coastguard Worker max = maxBuf[0];
240*e5436536SAndroid Build Coastguard Worker for (j = 1; j <= attack; j++) {
241*e5436536SAndroid Build Coastguard Worker max = fMax(max, maxBuf[j]);
242*e5436536SAndroid Build Coastguard Worker }
243*e5436536SAndroid Build Coastguard Worker }
244*e5436536SAndroid Build Coastguard Worker maxBufIdx++;
245*e5436536SAndroid Build Coastguard Worker if (maxBufIdx >= attack + 1) maxBufIdx = 0;
246*e5436536SAndroid Build Coastguard Worker
247*e5436536SAndroid Build Coastguard Worker /* calc gain */
248*e5436536SAndroid Build Coastguard Worker /* gain is downscaled by one, so that gain = 1.0 can be represented */
249*e5436536SAndroid Build Coastguard Worker if (max > threshold) {
250*e5436536SAndroid Build Coastguard Worker gain = fDivNorm(threshold, max) >> 1;
251*e5436536SAndroid Build Coastguard Worker } else {
252*e5436536SAndroid Build Coastguard Worker gain = FL2FXCONST_DBL(1.0f / (1 << 1));
253*e5436536SAndroid Build Coastguard Worker }
254*e5436536SAndroid Build Coastguard Worker
255*e5436536SAndroid Build Coastguard Worker /* gain smoothing, method: TDL_EXPONENTIAL */
256*e5436536SAndroid Build Coastguard Worker /* first order IIR filter with attack correction to avoid overshoots */
257*e5436536SAndroid Build Coastguard Worker
258*e5436536SAndroid Build Coastguard Worker /* correct the 'aiming' value of the exponential attack to avoid the
259*e5436536SAndroid Build Coastguard Worker * remaining overshoot */
260*e5436536SAndroid Build Coastguard Worker if (gain < smoothState0) {
261*e5436536SAndroid Build Coastguard Worker cor = fMin(cor,
262*e5436536SAndroid Build Coastguard Worker fMultDiv2((gain - fMultDiv2(FL2FXCONST_SGL(0.1f * (1 << 1)),
263*e5436536SAndroid Build Coastguard Worker smoothState0)),
264*e5436536SAndroid Build Coastguard Worker FL2FXCONST_SGL(1.11111111f / (1 << 1)))
265*e5436536SAndroid Build Coastguard Worker << 2);
266*e5436536SAndroid Build Coastguard Worker } else {
267*e5436536SAndroid Build Coastguard Worker cor = gain;
268*e5436536SAndroid Build Coastguard Worker }
269*e5436536SAndroid Build Coastguard Worker
270*e5436536SAndroid Build Coastguard Worker /* smoothing filter */
271*e5436536SAndroid Build Coastguard Worker if (cor < smoothState0) {
272*e5436536SAndroid Build Coastguard Worker smoothState0 =
273*e5436536SAndroid Build Coastguard Worker fMult(attackConst, (smoothState0 - cor)) + cor; /* attack */
274*e5436536SAndroid Build Coastguard Worker smoothState0 = fMax(smoothState0, gain); /* avoid overshooting target */
275*e5436536SAndroid Build Coastguard Worker } else {
276*e5436536SAndroid Build Coastguard Worker /* sign inversion twice to round towards +infinity,
277*e5436536SAndroid Build Coastguard Worker so that gain can converge to 1.0 again,
278*e5436536SAndroid Build Coastguard Worker for bit-identical output when limiter is not active */
279*e5436536SAndroid Build Coastguard Worker smoothState0 =
280*e5436536SAndroid Build Coastguard Worker -fMult(releaseConst, -(smoothState0 - cor)) + cor; /* release */
281*e5436536SAndroid Build Coastguard Worker }
282*e5436536SAndroid Build Coastguard Worker
283*e5436536SAndroid Build Coastguard Worker gain = smoothState0;
284*e5436536SAndroid Build Coastguard Worker
285*e5436536SAndroid Build Coastguard Worker FIXP_DBL* p_delayBuf = &delayBuf[delayBufIdx * channels + 0];
286*e5436536SAndroid Build Coastguard Worker if (gain < FL2FXCONST_DBL(1.0f / (1 << 1))) {
287*e5436536SAndroid Build Coastguard Worker gain <<= 1;
288*e5436536SAndroid Build Coastguard Worker /* lookahead delay, apply gain */
289*e5436536SAndroid Build Coastguard Worker for (j = 0; j < channels; j++) {
290*e5436536SAndroid Build Coastguard Worker tmp = p_delayBuf[j];
291*e5436536SAndroid Build Coastguard Worker
292*e5436536SAndroid Build Coastguard Worker if (additionalGainAvailable) {
293*e5436536SAndroid Build Coastguard Worker p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain);
294*e5436536SAndroid Build Coastguard Worker } else {
295*e5436536SAndroid Build Coastguard Worker p_delayBuf[j] = PCM_LIM2FIXP_DBL(samplesIn[j]);
296*e5436536SAndroid Build Coastguard Worker }
297*e5436536SAndroid Build Coastguard Worker
298*e5436536SAndroid Build Coastguard Worker /* Apply gain to delayed signal */
299*e5436536SAndroid Build Coastguard Worker tmp = fMultDiv2(tmp, gain);
300*e5436536SAndroid Build Coastguard Worker #if (SAMPLE_BITS == DFRACT_BITS)
301*e5436536SAndroid Build Coastguard Worker samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM(
302*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling + 1, DFRACT_BITS));
303*e5436536SAndroid Build Coastguard Worker #else
304*e5436536SAndroid Build Coastguard Worker samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT(
305*e5436536SAndroid Build Coastguard Worker tmp + ((FIXP_DBL)0x8000 >> (scaling + 1)), scaling + 1,
306*e5436536SAndroid Build Coastguard Worker DFRACT_BITS));
307*e5436536SAndroid Build Coastguard Worker #endif
308*e5436536SAndroid Build Coastguard Worker }
309*e5436536SAndroid Build Coastguard Worker gain >>= 1;
310*e5436536SAndroid Build Coastguard Worker } else {
311*e5436536SAndroid Build Coastguard Worker /* lookahead delay, apply gain=1.0f */
312*e5436536SAndroid Build Coastguard Worker for (j = 0; j < channels; j++) {
313*e5436536SAndroid Build Coastguard Worker tmp = p_delayBuf[j];
314*e5436536SAndroid Build Coastguard Worker if (additionalGainAvailable) {
315*e5436536SAndroid Build Coastguard Worker p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain);
316*e5436536SAndroid Build Coastguard Worker } else {
317*e5436536SAndroid Build Coastguard Worker p_delayBuf[j] = PCM_LIM2FIXP_DBL(samplesIn[j]);
318*e5436536SAndroid Build Coastguard Worker }
319*e5436536SAndroid Build Coastguard Worker
320*e5436536SAndroid Build Coastguard Worker #if (SAMPLE_BITS == DFRACT_BITS)
321*e5436536SAndroid Build Coastguard Worker samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM(
322*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling, DFRACT_BITS));
323*e5436536SAndroid Build Coastguard Worker #else
324*e5436536SAndroid Build Coastguard Worker samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT(
325*e5436536SAndroid Build Coastguard Worker (tmp >> 1) + ((FIXP_DBL)0x8000 >> (scaling + 1)), scaling + 1,
326*e5436536SAndroid Build Coastguard Worker DFRACT_BITS));
327*e5436536SAndroid Build Coastguard Worker #endif
328*e5436536SAndroid Build Coastguard Worker }
329*e5436536SAndroid Build Coastguard Worker }
330*e5436536SAndroid Build Coastguard Worker
331*e5436536SAndroid Build Coastguard Worker delayBufIdx++;
332*e5436536SAndroid Build Coastguard Worker if (delayBufIdx >= attack) {
333*e5436536SAndroid Build Coastguard Worker delayBufIdx = 0;
334*e5436536SAndroid Build Coastguard Worker }
335*e5436536SAndroid Build Coastguard Worker
336*e5436536SAndroid Build Coastguard Worker /* save minimum gain factor */
337*e5436536SAndroid Build Coastguard Worker if (gain < minGain) {
338*e5436536SAndroid Build Coastguard Worker minGain = gain;
339*e5436536SAndroid Build Coastguard Worker }
340*e5436536SAndroid Build Coastguard Worker
341*e5436536SAndroid Build Coastguard Worker /* advance sample pointer by <channel> samples */
342*e5436536SAndroid Build Coastguard Worker samplesIn += channels;
343*e5436536SAndroid Build Coastguard Worker samplesOut += channels;
344*e5436536SAndroid Build Coastguard Worker }
345*e5436536SAndroid Build Coastguard Worker
346*e5436536SAndroid Build Coastguard Worker limiter->max = max;
347*e5436536SAndroid Build Coastguard Worker limiter->maxBufIdx = maxBufIdx;
348*e5436536SAndroid Build Coastguard Worker limiter->cor = cor;
349*e5436536SAndroid Build Coastguard Worker limiter->delayBufIdx = delayBufIdx;
350*e5436536SAndroid Build Coastguard Worker
351*e5436536SAndroid Build Coastguard Worker limiter->smoothState0 = smoothState0;
352*e5436536SAndroid Build Coastguard Worker
353*e5436536SAndroid Build Coastguard Worker limiter->minGain = minGain;
354*e5436536SAndroid Build Coastguard Worker
355*e5436536SAndroid Build Coastguard Worker return TDLIMIT_OK;
356*e5436536SAndroid Build Coastguard Worker }
357*e5436536SAndroid Build Coastguard Worker }
358*e5436536SAndroid Build Coastguard Worker
359*e5436536SAndroid Build Coastguard Worker /* set limiter threshold */
pcmLimiter_SetThreshold(TDLimiterPtr limiter,FIXP_DBL threshold)360*e5436536SAndroid Build Coastguard Worker TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter,
361*e5436536SAndroid Build Coastguard Worker FIXP_DBL threshold) {
362*e5436536SAndroid Build Coastguard Worker if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
363*e5436536SAndroid Build Coastguard Worker
364*e5436536SAndroid Build Coastguard Worker limiter->threshold = threshold;
365*e5436536SAndroid Build Coastguard Worker
366*e5436536SAndroid Build Coastguard Worker return TDLIMIT_OK;
367*e5436536SAndroid Build Coastguard Worker }
368*e5436536SAndroid Build Coastguard Worker
369*e5436536SAndroid Build Coastguard Worker /* reset limiter */
pcmLimiter_Reset(TDLimiterPtr limiter)370*e5436536SAndroid Build Coastguard Worker TDLIMITER_ERROR pcmLimiter_Reset(TDLimiterPtr limiter) {
371*e5436536SAndroid Build Coastguard Worker if (limiter != NULL) {
372*e5436536SAndroid Build Coastguard Worker limiter->maxBufIdx = 0;
373*e5436536SAndroid Build Coastguard Worker limiter->delayBufIdx = 0;
374*e5436536SAndroid Build Coastguard Worker limiter->max = (FIXP_DBL)0;
375*e5436536SAndroid Build Coastguard Worker limiter->cor = FL2FXCONST_DBL(1.0f / (1 << 1));
376*e5436536SAndroid Build Coastguard Worker limiter->smoothState0 = FL2FXCONST_DBL(1.0f / (1 << 1));
377*e5436536SAndroid Build Coastguard Worker limiter->minGain = FL2FXCONST_DBL(1.0f / (1 << 1));
378*e5436536SAndroid Build Coastguard Worker limiter->scaling = 0;
379*e5436536SAndroid Build Coastguard Worker
380*e5436536SAndroid Build Coastguard Worker FDKmemset(limiter->maxBuf, 0, (limiter->attack + 1) * sizeof(FIXP_DBL));
381*e5436536SAndroid Build Coastguard Worker FDKmemset(limiter->delayBuf, 0,
382*e5436536SAndroid Build Coastguard Worker limiter->attack * limiter->channels * sizeof(FIXP_DBL));
383*e5436536SAndroid Build Coastguard Worker } else {
384*e5436536SAndroid Build Coastguard Worker return TDLIMIT_INVALID_HANDLE;
385*e5436536SAndroid Build Coastguard Worker }
386*e5436536SAndroid Build Coastguard Worker
387*e5436536SAndroid Build Coastguard Worker return TDLIMIT_OK;
388*e5436536SAndroid Build Coastguard Worker }
389*e5436536SAndroid Build Coastguard Worker
390*e5436536SAndroid Build Coastguard Worker /* destroy limiter */
pcmLimiter_Destroy(TDLimiterPtr limiter)391*e5436536SAndroid Build Coastguard Worker TDLIMITER_ERROR pcmLimiter_Destroy(TDLimiterPtr limiter) {
392*e5436536SAndroid Build Coastguard Worker if (limiter != NULL) {
393*e5436536SAndroid Build Coastguard Worker FDKfree(limiter->maxBuf);
394*e5436536SAndroid Build Coastguard Worker FDKfree(limiter->delayBuf);
395*e5436536SAndroid Build Coastguard Worker
396*e5436536SAndroid Build Coastguard Worker FDKfree(limiter);
397*e5436536SAndroid Build Coastguard Worker } else {
398*e5436536SAndroid Build Coastguard Worker return TDLIMIT_INVALID_HANDLE;
399*e5436536SAndroid Build Coastguard Worker }
400*e5436536SAndroid Build Coastguard Worker return TDLIMIT_OK;
401*e5436536SAndroid Build Coastguard Worker }
402*e5436536SAndroid Build Coastguard Worker
403*e5436536SAndroid Build Coastguard Worker /* get delay in samples */
pcmLimiter_GetDelay(TDLimiterPtr limiter)404*e5436536SAndroid Build Coastguard Worker unsigned int pcmLimiter_GetDelay(TDLimiterPtr limiter) {
405*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(limiter != NULL);
406*e5436536SAndroid Build Coastguard Worker return limiter->attack;
407*e5436536SAndroid Build Coastguard Worker }
408*e5436536SAndroid Build Coastguard Worker
409*e5436536SAndroid Build Coastguard Worker /* get maximum gain reduction of last processed block */
pcmLimiter_GetMaxGainReduction(TDLimiterPtr limiter)410*e5436536SAndroid Build Coastguard Worker INT pcmLimiter_GetMaxGainReduction(TDLimiterPtr limiter) {
411*e5436536SAndroid Build Coastguard Worker /* maximum gain reduction in dB = -20 * log10(limiter->minGain)
412*e5436536SAndroid Build Coastguard Worker = -20 * log2(limiter->minGain)/log2(10) = -6.0206*log2(limiter->minGain) */
413*e5436536SAndroid Build Coastguard Worker int e_ans;
414*e5436536SAndroid Build Coastguard Worker FIXP_DBL loggain, maxGainReduction;
415*e5436536SAndroid Build Coastguard Worker
416*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(limiter != NULL);
417*e5436536SAndroid Build Coastguard Worker
418*e5436536SAndroid Build Coastguard Worker loggain = fLog2(limiter->minGain, 1, &e_ans);
419*e5436536SAndroid Build Coastguard Worker
420*e5436536SAndroid Build Coastguard Worker maxGainReduction = fMult(loggain, FL2FXCONST_DBL(-6.0206f / (1 << 3)));
421*e5436536SAndroid Build Coastguard Worker
422*e5436536SAndroid Build Coastguard Worker return fixp_roundToInt(maxGainReduction, (e_ans + 3));
423*e5436536SAndroid Build Coastguard Worker }
424*e5436536SAndroid Build Coastguard Worker
425*e5436536SAndroid Build Coastguard Worker /* set number of channels */
pcmLimiter_SetNChannels(TDLimiterPtr limiter,unsigned int nChannels)426*e5436536SAndroid Build Coastguard Worker TDLIMITER_ERROR pcmLimiter_SetNChannels(TDLimiterPtr limiter,
427*e5436536SAndroid Build Coastguard Worker unsigned int nChannels) {
428*e5436536SAndroid Build Coastguard Worker if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
429*e5436536SAndroid Build Coastguard Worker
430*e5436536SAndroid Build Coastguard Worker if (nChannels > limiter->maxChannels) return TDLIMIT_INVALID_PARAMETER;
431*e5436536SAndroid Build Coastguard Worker
432*e5436536SAndroid Build Coastguard Worker limiter->channels = nChannels;
433*e5436536SAndroid Build Coastguard Worker // pcmLimiter_Reset(limiter);
434*e5436536SAndroid Build Coastguard Worker
435*e5436536SAndroid Build Coastguard Worker return TDLIMIT_OK;
436*e5436536SAndroid Build Coastguard Worker }
437*e5436536SAndroid Build Coastguard Worker
438*e5436536SAndroid Build Coastguard Worker /* set sampling rate */
pcmLimiter_SetSampleRate(TDLimiterPtr limiter,UINT sampleRate)439*e5436536SAndroid Build Coastguard Worker TDLIMITER_ERROR pcmLimiter_SetSampleRate(TDLimiterPtr limiter,
440*e5436536SAndroid Build Coastguard Worker UINT sampleRate) {
441*e5436536SAndroid Build Coastguard Worker unsigned int attack, release;
442*e5436536SAndroid Build Coastguard Worker FIXP_DBL attackConst, releaseConst, exponent;
443*e5436536SAndroid Build Coastguard Worker INT e_ans;
444*e5436536SAndroid Build Coastguard Worker
445*e5436536SAndroid Build Coastguard Worker if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
446*e5436536SAndroid Build Coastguard Worker
447*e5436536SAndroid Build Coastguard Worker if (sampleRate > limiter->maxSampleRate) return TDLIMIT_INVALID_PARAMETER;
448*e5436536SAndroid Build Coastguard Worker
449*e5436536SAndroid Build Coastguard Worker /* update attack and release time in samples */
450*e5436536SAndroid Build Coastguard Worker attack = (unsigned int)(limiter->attackMs * sampleRate / 1000);
451*e5436536SAndroid Build Coastguard Worker release = (unsigned int)(limiter->releaseMs * sampleRate / 1000);
452*e5436536SAndroid Build Coastguard Worker
453*e5436536SAndroid Build Coastguard Worker /* attackConst = pow(0.1, 1.0 / (attack + 1)) */
454*e5436536SAndroid Build Coastguard Worker exponent = invFixp(attack + 1);
455*e5436536SAndroid Build Coastguard Worker attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
456*e5436536SAndroid Build Coastguard Worker attackConst = scaleValue(attackConst, e_ans);
457*e5436536SAndroid Build Coastguard Worker
458*e5436536SAndroid Build Coastguard Worker /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */
459*e5436536SAndroid Build Coastguard Worker exponent = invFixp(release + 1);
460*e5436536SAndroid Build Coastguard Worker releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
461*e5436536SAndroid Build Coastguard Worker releaseConst = scaleValue(releaseConst, e_ans);
462*e5436536SAndroid Build Coastguard Worker
463*e5436536SAndroid Build Coastguard Worker limiter->attack = attack;
464*e5436536SAndroid Build Coastguard Worker limiter->attackConst = attackConst;
465*e5436536SAndroid Build Coastguard Worker limiter->releaseConst = releaseConst;
466*e5436536SAndroid Build Coastguard Worker limiter->sampleRate = sampleRate;
467*e5436536SAndroid Build Coastguard Worker
468*e5436536SAndroid Build Coastguard Worker /* reset */
469*e5436536SAndroid Build Coastguard Worker // pcmLimiter_Reset(limiter);
470*e5436536SAndroid Build Coastguard Worker
471*e5436536SAndroid Build Coastguard Worker return TDLIMIT_OK;
472*e5436536SAndroid Build Coastguard Worker }
473*e5436536SAndroid Build Coastguard Worker
474*e5436536SAndroid Build Coastguard Worker /* set attack time */
pcmLimiter_SetAttack(TDLimiterPtr limiter,unsigned int attackMs)475*e5436536SAndroid Build Coastguard Worker TDLIMITER_ERROR pcmLimiter_SetAttack(TDLimiterPtr limiter,
476*e5436536SAndroid Build Coastguard Worker unsigned int attackMs) {
477*e5436536SAndroid Build Coastguard Worker unsigned int attack;
478*e5436536SAndroid Build Coastguard Worker FIXP_DBL attackConst, exponent;
479*e5436536SAndroid Build Coastguard Worker INT e_ans;
480*e5436536SAndroid Build Coastguard Worker
481*e5436536SAndroid Build Coastguard Worker if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
482*e5436536SAndroid Build Coastguard Worker
483*e5436536SAndroid Build Coastguard Worker if (attackMs > limiter->maxAttackMs) return TDLIMIT_INVALID_PARAMETER;
484*e5436536SAndroid Build Coastguard Worker
485*e5436536SAndroid Build Coastguard Worker /* calculate attack time in samples */
486*e5436536SAndroid Build Coastguard Worker attack = (unsigned int)(attackMs * limiter->sampleRate / 1000);
487*e5436536SAndroid Build Coastguard Worker
488*e5436536SAndroid Build Coastguard Worker /* attackConst = pow(0.1, 1.0 / (attack + 1)) */
489*e5436536SAndroid Build Coastguard Worker exponent = invFixp(attack + 1);
490*e5436536SAndroid Build Coastguard Worker attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
491*e5436536SAndroid Build Coastguard Worker attackConst = scaleValue(attackConst, e_ans);
492*e5436536SAndroid Build Coastguard Worker
493*e5436536SAndroid Build Coastguard Worker limiter->attack = attack;
494*e5436536SAndroid Build Coastguard Worker limiter->attackConst = attackConst;
495*e5436536SAndroid Build Coastguard Worker limiter->attackMs = attackMs;
496*e5436536SAndroid Build Coastguard Worker
497*e5436536SAndroid Build Coastguard Worker return TDLIMIT_OK;
498*e5436536SAndroid Build Coastguard Worker }
499*e5436536SAndroid Build Coastguard Worker
500*e5436536SAndroid Build Coastguard Worker /* set release time */
pcmLimiter_SetRelease(TDLimiterPtr limiter,unsigned int releaseMs)501*e5436536SAndroid Build Coastguard Worker TDLIMITER_ERROR pcmLimiter_SetRelease(TDLimiterPtr limiter,
502*e5436536SAndroid Build Coastguard Worker unsigned int releaseMs) {
503*e5436536SAndroid Build Coastguard Worker unsigned int release;
504*e5436536SAndroid Build Coastguard Worker FIXP_DBL releaseConst, exponent;
505*e5436536SAndroid Build Coastguard Worker INT e_ans;
506*e5436536SAndroid Build Coastguard Worker
507*e5436536SAndroid Build Coastguard Worker if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
508*e5436536SAndroid Build Coastguard Worker
509*e5436536SAndroid Build Coastguard Worker /* calculate release time in samples */
510*e5436536SAndroid Build Coastguard Worker release = (unsigned int)(releaseMs * limiter->sampleRate / 1000);
511*e5436536SAndroid Build Coastguard Worker
512*e5436536SAndroid Build Coastguard Worker /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */
513*e5436536SAndroid Build Coastguard Worker exponent = invFixp(release + 1);
514*e5436536SAndroid Build Coastguard Worker releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
515*e5436536SAndroid Build Coastguard Worker releaseConst = scaleValue(releaseConst, e_ans);
516*e5436536SAndroid Build Coastguard Worker
517*e5436536SAndroid Build Coastguard Worker limiter->releaseConst = releaseConst;
518*e5436536SAndroid Build Coastguard Worker limiter->releaseMs = releaseMs;
519*e5436536SAndroid Build Coastguard Worker
520*e5436536SAndroid Build Coastguard Worker return TDLIMIT_OK;
521*e5436536SAndroid Build Coastguard Worker }
522*e5436536SAndroid Build Coastguard Worker
523*e5436536SAndroid Build Coastguard Worker /* Get library info for this module. */
pcmLimiter_GetLibInfo(LIB_INFO * info)524*e5436536SAndroid Build Coastguard Worker TDLIMITER_ERROR pcmLimiter_GetLibInfo(LIB_INFO* info) {
525*e5436536SAndroid Build Coastguard Worker int i;
526*e5436536SAndroid Build Coastguard Worker
527*e5436536SAndroid Build Coastguard Worker if (info == NULL) {
528*e5436536SAndroid Build Coastguard Worker return TDLIMIT_INVALID_PARAMETER;
529*e5436536SAndroid Build Coastguard Worker }
530*e5436536SAndroid Build Coastguard Worker
531*e5436536SAndroid Build Coastguard Worker /* Search for next free tab */
532*e5436536SAndroid Build Coastguard Worker for (i = 0; i < FDK_MODULE_LAST; i++) {
533*e5436536SAndroid Build Coastguard Worker if (info[i].module_id == FDK_NONE) break;
534*e5436536SAndroid Build Coastguard Worker }
535*e5436536SAndroid Build Coastguard Worker if (i == FDK_MODULE_LAST) {
536*e5436536SAndroid Build Coastguard Worker return TDLIMIT_UNKNOWN;
537*e5436536SAndroid Build Coastguard Worker }
538*e5436536SAndroid Build Coastguard Worker
539*e5436536SAndroid Build Coastguard Worker /* Add the library info */
540*e5436536SAndroid Build Coastguard Worker info[i].module_id = FDK_TDLIMIT;
541*e5436536SAndroid Build Coastguard Worker info[i].version =
542*e5436536SAndroid Build Coastguard Worker LIB_VERSION(PCMUTIL_LIB_VL0, PCMUTIL_LIB_VL1, PCMUTIL_LIB_VL2);
543*e5436536SAndroid Build Coastguard Worker LIB_VERSION_STRING(info + i);
544*e5436536SAndroid Build Coastguard Worker info[i].build_date = PCMUTIL_LIB_BUILD_DATE;
545*e5436536SAndroid Build Coastguard Worker info[i].build_time = PCMUTIL_LIB_BUILD_TIME;
546*e5436536SAndroid Build Coastguard Worker info[i].title = TDLIMIT_LIB_TITLE;
547*e5436536SAndroid Build Coastguard Worker
548*e5436536SAndroid Build Coastguard Worker /* Set flags */
549*e5436536SAndroid Build Coastguard Worker info[i].flags = CAPF_LIMITER;
550*e5436536SAndroid Build Coastguard Worker
551*e5436536SAndroid Build Coastguard Worker /* Add lib info for FDK tools (if not yet done). */
552*e5436536SAndroid Build Coastguard Worker FDK_toolsGetLibInfo(info);
553*e5436536SAndroid Build Coastguard Worker
554*e5436536SAndroid Build Coastguard Worker return TDLIMIT_OK;
555*e5436536SAndroid Build Coastguard Worker }
556