1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3
4 © Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
5 Forschung e.V. All rights reserved.
6
7 1. INTRODUCTION
8 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9 that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10 scheme for digital audio. This FDK AAC Codec software is intended to be used on
11 a wide variety of Android devices.
12
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14 general perceptual audio codecs. AAC-ELD is considered the best-performing
15 full-bandwidth communications codec by independent studies and is widely
16 deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17 specifications.
18
19 Patent licenses for necessary patent claims for the FDK AAC Codec (including
20 those of Fraunhofer) may be obtained through Via Licensing
21 (www.vialicensing.com) or through the respective patent owners individually for
22 the purpose of encoding or decoding bit streams in products that are compliant
23 with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24 Android devices already license these patent claims through Via Licensing or
25 directly from the patent owners, and therefore FDK AAC Codec software may
26 already be covered under those patent licenses when it is used for those
27 licensed purposes only.
28
29 Commercially-licensed AAC software libraries, including floating-point versions
30 with enhanced sound quality, are also available from Fraunhofer. Users are
31 encouraged to check the Fraunhofer website for additional applications
32 information and documentation.
33
34 2. COPYRIGHT LICENSE
35
36 Redistribution and use in source and binary forms, with or without modification,
37 are permitted without payment of copyright license fees provided that you
38 satisfy the following conditions:
39
40 You must retain the complete text of this software license in redistributions of
41 the FDK AAC Codec or your modifications thereto in source code form.
42
43 You must retain the complete text of this software license in the documentation
44 and/or other materials provided with redistributions of the FDK AAC Codec or
45 your modifications thereto in binary form. You must make available free of
46 charge copies of the complete source code of the FDK AAC Codec and your
47 modifications thereto to recipients of copies in binary form.
48
49 The name of Fraunhofer may not be used to endorse or promote products derived
50 from this library without prior written permission.
51
52 You may not charge copyright license fees for anyone to use, copy or distribute
53 the FDK AAC Codec software or your modifications thereto.
54
55 Your modified versions of the FDK AAC Codec must carry prominent notices stating
56 that you changed the software and the date of any change. For modified versions
57 of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58 must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59 AAC Codec Library for Android."
60
61 3. NO PATENT LICENSE
62
63 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64 limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65 Fraunhofer provides no warranty of patent non-infringement with respect to this
66 software.
67
68 You may use this FDK AAC Codec software or modifications thereto only for
69 purposes that are authorized by appropriate patent licenses.
70
71 4. DISCLAIMER
72
73 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74 holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75 including but not limited to the implied warranties of merchantability and
76 fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78 or consequential damages, including but not limited to procurement of substitute
79 goods or services; loss of use, data, or profits, or business interruption,
80 however caused and on any theory of liability, whether in contract, strict
81 liability, or tort (including negligence), arising in any way out of the use of
82 this software, even if advised of the possibility of such damage.
83
84 5. CONTACT INFORMATION
85
86 Fraunhofer Institute for Integrated Circuits IIS
87 Attention: Audio and Multimedia Departments - FDK AAC LL
88 Am Wolfsmantel 33
89 91058 Erlangen, Germany
90
91 www.iis.fraunhofer.de/amm
92 amm-info@iis.fraunhofer.de
93 ----------------------------------------------------------------------------- */
94
95 /**************************** PCM utility library ******************************
96
97 Author(s): Matthias Neusinger
98
99 Description: Hard limiter for clipping prevention
100
101 *******************************************************************************/
102
103 #include "limiter.h"
104 #include "FDK_core.h"
105
106 /* library version */
107 #include "version.h"
108 /* library title */
109 #define TDLIMIT_LIB_TITLE "TD Limiter Lib"
110
111 /* create limiter */
pcmLimiter_Create(unsigned int maxAttackMs,unsigned int releaseMs,FIXP_DBL threshold,unsigned int maxChannels,UINT maxSampleRate)112 TDLimiterPtr pcmLimiter_Create(unsigned int maxAttackMs, unsigned int releaseMs,
113 FIXP_DBL threshold, unsigned int maxChannels,
114 UINT maxSampleRate) {
115 TDLimiterPtr limiter = NULL;
116 unsigned int attack, release;
117 FIXP_DBL attackConst, releaseConst, exponent;
118 INT e_ans;
119
120 /* calc attack and release time in samples */
121 attack = (unsigned int)(maxAttackMs * maxSampleRate / 1000);
122 release = (unsigned int)(releaseMs * maxSampleRate / 1000);
123
124 /* alloc limiter struct */
125 limiter = (TDLimiterPtr)FDKcalloc(1, sizeof(struct TDLimiter));
126 if (!limiter) return NULL;
127
128 /* alloc max and delay buffers */
129 limiter->maxBuf = (FIXP_DBL*)FDKcalloc(attack + 1, sizeof(FIXP_DBL));
130 limiter->delayBuf =
131 (FIXP_DBL*)FDKcalloc(attack * maxChannels, sizeof(FIXP_DBL));
132
133 if (!limiter->maxBuf || !limiter->delayBuf) {
134 pcmLimiter_Destroy(limiter);
135 return NULL;
136 }
137
138 /* attackConst = pow(0.1, 1.0 / (attack + 1)) */
139 exponent = invFixp(attack + 1);
140 attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
141 attackConst = scaleValue(attackConst, e_ans);
142
143 /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */
144 exponent = invFixp(release + 1);
145 releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
146 releaseConst = scaleValue(releaseConst, e_ans);
147
148 /* init parameters */
149 limiter->attackMs = maxAttackMs;
150 limiter->maxAttackMs = maxAttackMs;
151 limiter->releaseMs = releaseMs;
152 limiter->attack = attack;
153 limiter->attackConst = attackConst;
154 limiter->releaseConst = releaseConst;
155 limiter->threshold = threshold;
156 limiter->channels = maxChannels;
157 limiter->maxChannels = maxChannels;
158 limiter->sampleRate = maxSampleRate;
159 limiter->maxSampleRate = maxSampleRate;
160
161 pcmLimiter_Reset(limiter);
162
163 return limiter;
164 }
165
166 /* apply limiter */
pcmLimiter_Apply(TDLimiterPtr limiter,PCM_LIM * samplesIn,INT_PCM * samplesOut,FIXP_DBL * pGainPerSample,const INT scaling,const UINT nSamples)167 TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
168 INT_PCM* samplesOut, FIXP_DBL* pGainPerSample,
169 const INT scaling, const UINT nSamples) {
170 unsigned int i, j;
171 FIXP_DBL tmp2;
172 FIXP_DBL tmp, old, gain, additionalGain = 0;
173 FIXP_DBL minGain = FL2FXCONST_DBL(1.0f / (1 << 1));
174 UINT additionalGainAvailable = 1;
175
176 if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
177
178 {
179 unsigned int channels = limiter->channels;
180 unsigned int attack = limiter->attack;
181 FIXP_DBL attackConst = limiter->attackConst;
182 FIXP_DBL releaseConst = limiter->releaseConst;
183 FIXP_DBL threshold = limiter->threshold >> scaling;
184
185 FIXP_DBL max = limiter->max;
186 FIXP_DBL* maxBuf = limiter->maxBuf;
187 unsigned int maxBufIdx = limiter->maxBufIdx;
188 FIXP_DBL cor = limiter->cor;
189 FIXP_DBL* delayBuf = limiter->delayBuf;
190 unsigned int delayBufIdx = limiter->delayBufIdx;
191
192 FIXP_DBL smoothState0 = limiter->smoothState0;
193
194 if (limiter->scaling != scaling) {
195 scaleValuesSaturate(delayBuf, attack * channels,
196 limiter->scaling - scaling);
197 scaleValuesSaturate(maxBuf, attack + 1, limiter->scaling - scaling);
198 max = scaleValueSaturate(max, limiter->scaling - scaling);
199 limiter->scaling = scaling;
200 }
201
202 if (pGainPerSample == NULL) {
203 additionalGainAvailable = 0;
204 }
205
206 for (i = 0; i < nSamples; i++) {
207 /* get maximum absolute sample value of all channels, including the
208 * additional gain. */
209 tmp = (FIXP_DBL)0;
210 for (j = 0; j < channels; j++) {
211 tmp2 = PCM_LIM2FIXP_DBL(samplesIn[j]);
212 tmp2 =
213 (tmp2 == (FIXP_DBL)MINVAL_DBL) ? (FIXP_DBL)MAXVAL_DBL : fAbs(tmp2);
214 tmp = fMax(tmp, tmp2);
215 }
216
217 if (additionalGainAvailable) {
218 additionalGain = pGainPerSample[i];
219 tmp = fMult(tmp, additionalGain);
220 }
221
222 /* set threshold as lower border to save calculations in running maximum
223 * algorithm */
224 tmp = fMax(tmp, threshold);
225
226 /* running maximum */
227 old = maxBuf[maxBufIdx];
228 maxBuf[maxBufIdx] = tmp;
229
230 if (tmp >= max) {
231 /* new sample is greater than old maximum, so it is the new maximum */
232 max = tmp;
233 } else if (old < max) {
234 /* maximum does not change, as the sample, which has left the window was
235 not the maximum */
236 } else {
237 /* the old maximum has left the window, we have to search the complete
238 buffer for the new max */
239 max = maxBuf[0];
240 for (j = 1; j <= attack; j++) {
241 max = fMax(max, maxBuf[j]);
242 }
243 }
244 maxBufIdx++;
245 if (maxBufIdx >= attack + 1) maxBufIdx = 0;
246
247 /* calc gain */
248 /* gain is downscaled by one, so that gain = 1.0 can be represented */
249 if (max > threshold) {
250 gain = fDivNorm(threshold, max) >> 1;
251 } else {
252 gain = FL2FXCONST_DBL(1.0f / (1 << 1));
253 }
254
255 /* gain smoothing, method: TDL_EXPONENTIAL */
256 /* first order IIR filter with attack correction to avoid overshoots */
257
258 /* correct the 'aiming' value of the exponential attack to avoid the
259 * remaining overshoot */
260 if (gain < smoothState0) {
261 cor = fMin(cor,
262 fMultDiv2((gain - fMultDiv2(FL2FXCONST_SGL(0.1f * (1 << 1)),
263 smoothState0)),
264 FL2FXCONST_SGL(1.11111111f / (1 << 1)))
265 << 2);
266 } else {
267 cor = gain;
268 }
269
270 /* smoothing filter */
271 if (cor < smoothState0) {
272 smoothState0 =
273 fMult(attackConst, (smoothState0 - cor)) + cor; /* attack */
274 smoothState0 = fMax(smoothState0, gain); /* avoid overshooting target */
275 } else {
276 /* sign inversion twice to round towards +infinity,
277 so that gain can converge to 1.0 again,
278 for bit-identical output when limiter is not active */
279 smoothState0 =
280 -fMult(releaseConst, -(smoothState0 - cor)) + cor; /* release */
281 }
282
283 gain = smoothState0;
284
285 FIXP_DBL* p_delayBuf = &delayBuf[delayBufIdx * channels + 0];
286 if (gain < FL2FXCONST_DBL(1.0f / (1 << 1))) {
287 gain <<= 1;
288 /* lookahead delay, apply gain */
289 for (j = 0; j < channels; j++) {
290 tmp = p_delayBuf[j];
291
292 if (additionalGainAvailable) {
293 p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain);
294 } else {
295 p_delayBuf[j] = PCM_LIM2FIXP_DBL(samplesIn[j]);
296 }
297
298 /* Apply gain to delayed signal */
299 tmp = fMultDiv2(tmp, gain);
300 #if (SAMPLE_BITS == DFRACT_BITS)
301 samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM(
302 (FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling + 1, DFRACT_BITS));
303 #else
304 samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT(
305 tmp + ((FIXP_DBL)0x8000 >> (scaling + 1)), scaling + 1,
306 DFRACT_BITS));
307 #endif
308 }
309 gain >>= 1;
310 } else {
311 /* lookahead delay, apply gain=1.0f */
312 for (j = 0; j < channels; j++) {
313 tmp = p_delayBuf[j];
314 if (additionalGainAvailable) {
315 p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain);
316 } else {
317 p_delayBuf[j] = PCM_LIM2FIXP_DBL(samplesIn[j]);
318 }
319
320 #if (SAMPLE_BITS == DFRACT_BITS)
321 samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM(
322 (FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling, DFRACT_BITS));
323 #else
324 samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT(
325 tmp + ((FIXP_DBL)0x8000 >> scaling), scaling, DFRACT_BITS));
326 #endif
327 }
328 }
329
330 delayBufIdx++;
331 if (delayBufIdx >= attack) {
332 delayBufIdx = 0;
333 }
334
335 /* save minimum gain factor */
336 if (gain < minGain) {
337 minGain = gain;
338 }
339
340 /* advance sample pointer by <channel> samples */
341 samplesIn += channels;
342 samplesOut += channels;
343 }
344
345 limiter->max = max;
346 limiter->maxBufIdx = maxBufIdx;
347 limiter->cor = cor;
348 limiter->delayBufIdx = delayBufIdx;
349
350 limiter->smoothState0 = smoothState0;
351
352 limiter->minGain = minGain;
353
354 return TDLIMIT_OK;
355 }
356 }
357
358 /* set limiter threshold */
pcmLimiter_SetThreshold(TDLimiterPtr limiter,FIXP_DBL threshold)359 TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter,
360 FIXP_DBL threshold) {
361 if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
362
363 limiter->threshold = threshold;
364
365 return TDLIMIT_OK;
366 }
367
368 /* reset limiter */
pcmLimiter_Reset(TDLimiterPtr limiter)369 TDLIMITER_ERROR pcmLimiter_Reset(TDLimiterPtr limiter) {
370 if (limiter != NULL) {
371 limiter->maxBufIdx = 0;
372 limiter->delayBufIdx = 0;
373 limiter->max = (FIXP_DBL)0;
374 limiter->cor = FL2FXCONST_DBL(1.0f / (1 << 1));
375 limiter->smoothState0 = FL2FXCONST_DBL(1.0f / (1 << 1));
376 limiter->minGain = FL2FXCONST_DBL(1.0f / (1 << 1));
377 limiter->scaling = 0;
378
379 FDKmemset(limiter->maxBuf, 0, (limiter->attack + 1) * sizeof(FIXP_DBL));
380 FDKmemset(limiter->delayBuf, 0,
381 limiter->attack * limiter->channels * sizeof(FIXP_DBL));
382 } else {
383 return TDLIMIT_INVALID_HANDLE;
384 }
385
386 return TDLIMIT_OK;
387 }
388
389 /* destroy limiter */
pcmLimiter_Destroy(TDLimiterPtr limiter)390 TDLIMITER_ERROR pcmLimiter_Destroy(TDLimiterPtr limiter) {
391 if (limiter != NULL) {
392 FDKfree(limiter->maxBuf);
393 FDKfree(limiter->delayBuf);
394
395 FDKfree(limiter);
396 } else {
397 return TDLIMIT_INVALID_HANDLE;
398 }
399 return TDLIMIT_OK;
400 }
401
402 /* get delay in samples */
pcmLimiter_GetDelay(TDLimiterPtr limiter)403 unsigned int pcmLimiter_GetDelay(TDLimiterPtr limiter) {
404 FDK_ASSERT(limiter != NULL);
405 return limiter->attack;
406 }
407
408 /* get maximum gain reduction of last processed block */
pcmLimiter_GetMaxGainReduction(TDLimiterPtr limiter)409 INT pcmLimiter_GetMaxGainReduction(TDLimiterPtr limiter) {
410 /* maximum gain reduction in dB = -20 * log10(limiter->minGain)
411 = -20 * log2(limiter->minGain)/log2(10) = -6.0206*log2(limiter->minGain) */
412 int e_ans;
413 FIXP_DBL loggain, maxGainReduction;
414
415 FDK_ASSERT(limiter != NULL);
416
417 loggain = fLog2(limiter->minGain, 1, &e_ans);
418
419 maxGainReduction = fMult(loggain, FL2FXCONST_DBL(-6.0206f / (1 << 3)));
420
421 return fixp_roundToInt(maxGainReduction, (e_ans + 3));
422 }
423
424 /* set number of channels */
pcmLimiter_SetNChannels(TDLimiterPtr limiter,unsigned int nChannels)425 TDLIMITER_ERROR pcmLimiter_SetNChannels(TDLimiterPtr limiter,
426 unsigned int nChannels) {
427 if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
428
429 if (nChannels > limiter->maxChannels) return TDLIMIT_INVALID_PARAMETER;
430
431 limiter->channels = nChannels;
432 // pcmLimiter_Reset(limiter);
433
434 return TDLIMIT_OK;
435 }
436
437 /* set sampling rate */
pcmLimiter_SetSampleRate(TDLimiterPtr limiter,UINT sampleRate)438 TDLIMITER_ERROR pcmLimiter_SetSampleRate(TDLimiterPtr limiter,
439 UINT sampleRate) {
440 unsigned int attack, release;
441 FIXP_DBL attackConst, releaseConst, exponent;
442 INT e_ans;
443
444 if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
445
446 if (sampleRate > limiter->maxSampleRate) return TDLIMIT_INVALID_PARAMETER;
447
448 /* update attack and release time in samples */
449 attack = (unsigned int)(limiter->attackMs * sampleRate / 1000);
450 release = (unsigned int)(limiter->releaseMs * sampleRate / 1000);
451
452 /* attackConst = pow(0.1, 1.0 / (attack + 1)) */
453 exponent = invFixp(attack + 1);
454 attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
455 attackConst = scaleValue(attackConst, e_ans);
456
457 /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */
458 exponent = invFixp(release + 1);
459 releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
460 releaseConst = scaleValue(releaseConst, e_ans);
461
462 limiter->attack = attack;
463 limiter->attackConst = attackConst;
464 limiter->releaseConst = releaseConst;
465 limiter->sampleRate = sampleRate;
466
467 /* reset */
468 // pcmLimiter_Reset(limiter);
469
470 return TDLIMIT_OK;
471 }
472
473 /* set attack time */
pcmLimiter_SetAttack(TDLimiterPtr limiter,unsigned int attackMs)474 TDLIMITER_ERROR pcmLimiter_SetAttack(TDLimiterPtr limiter,
475 unsigned int attackMs) {
476 unsigned int attack;
477 FIXP_DBL attackConst, exponent;
478 INT e_ans;
479
480 if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
481
482 if (attackMs > limiter->maxAttackMs) return TDLIMIT_INVALID_PARAMETER;
483
484 /* calculate attack time in samples */
485 attack = (unsigned int)(attackMs * limiter->sampleRate / 1000);
486
487 /* attackConst = pow(0.1, 1.0 / (attack + 1)) */
488 exponent = invFixp(attack + 1);
489 attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
490 attackConst = scaleValue(attackConst, e_ans);
491
492 limiter->attack = attack;
493 limiter->attackConst = attackConst;
494 limiter->attackMs = attackMs;
495
496 return TDLIMIT_OK;
497 }
498
499 /* set release time */
pcmLimiter_SetRelease(TDLimiterPtr limiter,unsigned int releaseMs)500 TDLIMITER_ERROR pcmLimiter_SetRelease(TDLimiterPtr limiter,
501 unsigned int releaseMs) {
502 unsigned int release;
503 FIXP_DBL releaseConst, exponent;
504 INT e_ans;
505
506 if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
507
508 /* calculate release time in samples */
509 release = (unsigned int)(releaseMs * limiter->sampleRate / 1000);
510
511 /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */
512 exponent = invFixp(release + 1);
513 releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
514 releaseConst = scaleValue(releaseConst, e_ans);
515
516 limiter->releaseConst = releaseConst;
517 limiter->releaseMs = releaseMs;
518
519 return TDLIMIT_OK;
520 }
521
522 /* Get library info for this module. */
pcmLimiter_GetLibInfo(LIB_INFO * info)523 TDLIMITER_ERROR pcmLimiter_GetLibInfo(LIB_INFO* info) {
524 int i;
525
526 if (info == NULL) {
527 return TDLIMIT_INVALID_PARAMETER;
528 }
529
530 /* Search for next free tab */
531 for (i = 0; i < FDK_MODULE_LAST; i++) {
532 if (info[i].module_id == FDK_NONE) break;
533 }
534 if (i == FDK_MODULE_LAST) {
535 return TDLIMIT_UNKNOWN;
536 }
537
538 /* Add the library info */
539 info[i].module_id = FDK_TDLIMIT;
540 info[i].version =
541 LIB_VERSION(PCMUTIL_LIB_VL0, PCMUTIL_LIB_VL1, PCMUTIL_LIB_VL2);
542 LIB_VERSION_STRING(info + i);
543 info[i].build_date = PCMUTIL_LIB_BUILD_DATE;
544 info[i].build_time = PCMUTIL_LIB_BUILD_TIME;
545 info[i].title = TDLIMIT_LIB_TITLE;
546
547 /* Set flags */
548 info[i].flags = CAPF_LIMITER;
549
550 /* Add lib info for FDK tools (if not yet done). */
551 FDK_toolsGetLibInfo(info);
552
553 return TDLIMIT_OK;
554 }
555