• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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