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