1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3
4 © Copyright 1995 - 2020 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 >> 1) + ((FIXP_DBL)0x8000 >> (scaling + 1)), scaling + 1,
326 DFRACT_BITS));
327 #endif
328 }
329 }
330
331 delayBufIdx++;
332 if (delayBufIdx >= attack) {
333 delayBufIdx = 0;
334 }
335
336 /* save minimum gain factor */
337 if (gain < minGain) {
338 minGain = gain;
339 }
340
341 /* advance sample pointer by <channel> samples */
342 samplesIn += channels;
343 samplesOut += channels;
344 }
345
346 limiter->max = max;
347 limiter->maxBufIdx = maxBufIdx;
348 limiter->cor = cor;
349 limiter->delayBufIdx = delayBufIdx;
350
351 limiter->smoothState0 = smoothState0;
352
353 limiter->minGain = minGain;
354
355 return TDLIMIT_OK;
356 }
357 }
358
359 /* set limiter threshold */
pcmLimiter_SetThreshold(TDLimiterPtr limiter,FIXP_DBL threshold)360 TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter,
361 FIXP_DBL threshold) {
362 if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
363
364 limiter->threshold = threshold;
365
366 return TDLIMIT_OK;
367 }
368
369 /* reset limiter */
pcmLimiter_Reset(TDLimiterPtr limiter)370 TDLIMITER_ERROR pcmLimiter_Reset(TDLimiterPtr limiter) {
371 if (limiter != NULL) {
372 limiter->maxBufIdx = 0;
373 limiter->delayBufIdx = 0;
374 limiter->max = (FIXP_DBL)0;
375 limiter->cor = FL2FXCONST_DBL(1.0f / (1 << 1));
376 limiter->smoothState0 = FL2FXCONST_DBL(1.0f / (1 << 1));
377 limiter->minGain = FL2FXCONST_DBL(1.0f / (1 << 1));
378 limiter->scaling = 0;
379
380 FDKmemset(limiter->maxBuf, 0, (limiter->attack + 1) * sizeof(FIXP_DBL));
381 FDKmemset(limiter->delayBuf, 0,
382 limiter->attack * limiter->channels * sizeof(FIXP_DBL));
383 } else {
384 return TDLIMIT_INVALID_HANDLE;
385 }
386
387 return TDLIMIT_OK;
388 }
389
390 /* destroy limiter */
pcmLimiter_Destroy(TDLimiterPtr limiter)391 TDLIMITER_ERROR pcmLimiter_Destroy(TDLimiterPtr limiter) {
392 if (limiter != NULL) {
393 FDKfree(limiter->maxBuf);
394 FDKfree(limiter->delayBuf);
395
396 FDKfree(limiter);
397 } else {
398 return TDLIMIT_INVALID_HANDLE;
399 }
400 return TDLIMIT_OK;
401 }
402
403 /* get delay in samples */
pcmLimiter_GetDelay(TDLimiterPtr limiter)404 unsigned int pcmLimiter_GetDelay(TDLimiterPtr limiter) {
405 FDK_ASSERT(limiter != NULL);
406 return limiter->attack;
407 }
408
409 /* get maximum gain reduction of last processed block */
pcmLimiter_GetMaxGainReduction(TDLimiterPtr limiter)410 INT pcmLimiter_GetMaxGainReduction(TDLimiterPtr limiter) {
411 /* maximum gain reduction in dB = -20 * log10(limiter->minGain)
412 = -20 * log2(limiter->minGain)/log2(10) = -6.0206*log2(limiter->minGain) */
413 int e_ans;
414 FIXP_DBL loggain, maxGainReduction;
415
416 FDK_ASSERT(limiter != NULL);
417
418 loggain = fLog2(limiter->minGain, 1, &e_ans);
419
420 maxGainReduction = fMult(loggain, FL2FXCONST_DBL(-6.0206f / (1 << 3)));
421
422 return fixp_roundToInt(maxGainReduction, (e_ans + 3));
423 }
424
425 /* set number of channels */
pcmLimiter_SetNChannels(TDLimiterPtr limiter,unsigned int nChannels)426 TDLIMITER_ERROR pcmLimiter_SetNChannels(TDLimiterPtr limiter,
427 unsigned int nChannels) {
428 if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
429
430 if (nChannels > limiter->maxChannels) return TDLIMIT_INVALID_PARAMETER;
431
432 limiter->channels = nChannels;
433 // pcmLimiter_Reset(limiter);
434
435 return TDLIMIT_OK;
436 }
437
438 /* set sampling rate */
pcmLimiter_SetSampleRate(TDLimiterPtr limiter,UINT sampleRate)439 TDLIMITER_ERROR pcmLimiter_SetSampleRate(TDLimiterPtr limiter,
440 UINT sampleRate) {
441 unsigned int attack, release;
442 FIXP_DBL attackConst, releaseConst, exponent;
443 INT e_ans;
444
445 if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
446
447 if (sampleRate > limiter->maxSampleRate) return TDLIMIT_INVALID_PARAMETER;
448
449 /* update attack and release time in samples */
450 attack = (unsigned int)(limiter->attackMs * sampleRate / 1000);
451 release = (unsigned int)(limiter->releaseMs * sampleRate / 1000);
452
453 /* attackConst = pow(0.1, 1.0 / (attack + 1)) */
454 exponent = invFixp(attack + 1);
455 attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
456 attackConst = scaleValue(attackConst, e_ans);
457
458 /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */
459 exponent = invFixp(release + 1);
460 releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
461 releaseConst = scaleValue(releaseConst, e_ans);
462
463 limiter->attack = attack;
464 limiter->attackConst = attackConst;
465 limiter->releaseConst = releaseConst;
466 limiter->sampleRate = sampleRate;
467
468 /* reset */
469 // pcmLimiter_Reset(limiter);
470
471 return TDLIMIT_OK;
472 }
473
474 /* set attack time */
pcmLimiter_SetAttack(TDLimiterPtr limiter,unsigned int attackMs)475 TDLIMITER_ERROR pcmLimiter_SetAttack(TDLimiterPtr limiter,
476 unsigned int attackMs) {
477 unsigned int attack;
478 FIXP_DBL attackConst, exponent;
479 INT e_ans;
480
481 if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
482
483 if (attackMs > limiter->maxAttackMs) return TDLIMIT_INVALID_PARAMETER;
484
485 /* calculate attack time in samples */
486 attack = (unsigned int)(attackMs * limiter->sampleRate / 1000);
487
488 /* attackConst = pow(0.1, 1.0 / (attack + 1)) */
489 exponent = invFixp(attack + 1);
490 attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
491 attackConst = scaleValue(attackConst, e_ans);
492
493 limiter->attack = attack;
494 limiter->attackConst = attackConst;
495 limiter->attackMs = attackMs;
496
497 return TDLIMIT_OK;
498 }
499
500 /* set release time */
pcmLimiter_SetRelease(TDLimiterPtr limiter,unsigned int releaseMs)501 TDLIMITER_ERROR pcmLimiter_SetRelease(TDLimiterPtr limiter,
502 unsigned int releaseMs) {
503 unsigned int release;
504 FIXP_DBL releaseConst, exponent;
505 INT e_ans;
506
507 if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
508
509 /* calculate release time in samples */
510 release = (unsigned int)(releaseMs * limiter->sampleRate / 1000);
511
512 /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */
513 exponent = invFixp(release + 1);
514 releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
515 releaseConst = scaleValue(releaseConst, e_ans);
516
517 limiter->releaseConst = releaseConst;
518 limiter->releaseMs = releaseMs;
519
520 return TDLIMIT_OK;
521 }
522
523 /* Get library info for this module. */
pcmLimiter_GetLibInfo(LIB_INFO * info)524 TDLIMITER_ERROR pcmLimiter_GetLibInfo(LIB_INFO* info) {
525 int i;
526
527 if (info == NULL) {
528 return TDLIMIT_INVALID_PARAMETER;
529 }
530
531 /* Search for next free tab */
532 for (i = 0; i < FDK_MODULE_LAST; i++) {
533 if (info[i].module_id == FDK_NONE) break;
534 }
535 if (i == FDK_MODULE_LAST) {
536 return TDLIMIT_UNKNOWN;
537 }
538
539 /* Add the library info */
540 info[i].module_id = FDK_TDLIMIT;
541 info[i].version =
542 LIB_VERSION(PCMUTIL_LIB_VL0, PCMUTIL_LIB_VL1, PCMUTIL_LIB_VL2);
543 LIB_VERSION_STRING(info + i);
544 info[i].build_date = PCMUTIL_LIB_BUILD_DATE;
545 info[i].build_time = PCMUTIL_LIB_BUILD_TIME;
546 info[i].title = TDLIMIT_LIB_TITLE;
547
548 /* Set flags */
549 info[i].flags = CAPF_LIMITER;
550
551 /* Add lib info for FDK tools (if not yet done). */
552 FDK_toolsGetLibInfo(info);
553
554 return TDLIMIT_OK;
555 }
556