2 /* -----------------------------------------------------------------------------------------------------------
3 Software License for The Fraunhofer FDK AAC Codec Library for Android
5 © Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16 of the MPEG specifications.
18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27 applications information and documentation.
31 Redistribution and use in source and binary forms, with or without modification, are permitted without
32 payment of copyright license fees provided that you satisfy the following conditions:
34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35 your modifications thereto in source code form.
37 You must retain the complete text of this software license in the documentation and/or other materials
38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40 modifications thereto to recipients of copies in binary form.
42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43 prior written permission.
45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46 software or your modifications thereto.
48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49 and the date of any change. For modified versions of the FDK AAC Codec, the term
50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57 respect to this software.
59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60 by appropriate patent licenses.
64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69 or business interruption, however caused and on any theory of liability, whether in contract, strict
70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
71 advised of the possibility of such damage.
73 5. CONTACT INFORMATION
75 Fraunhofer Institute for Integrated Circuits IIS
76 Attention: Audio and Multimedia Departments - FDK AAC LL
78 91058 Erlangen, Germany
80 www.iis.fraunhofer.de/amm
81 amm-info@iis.fraunhofer.de
82 ----------------------------------------------------------------------------------------------------------- */
84 /******************************** MPEG Audio Encoder **************************
86 Initial author: M. Lohwasser
87 contents/description: pns.c
89 ******************************************************************************/
91 #include "aacenc_pns.h"
96 #include "interface.h"
99 /* minCorrelationEnergy = (1.0e-10f)^2 ~ 2^-67 = 2^-47 * 2^-20 */
100 static const FIXP_DBL minCorrelationEnergy
= FL2FXCONST_DBL(0.0); /* FL2FXCONST_DBL((float)FDKpow(2.0,-47)); */
101 /* noiseCorrelationThresh = 0.6^2 */
102 static const FIXP_DBL noiseCorrelationThresh
= FL2FXCONST_DBL(0.36);
104 static void FDKaacEnc_FDKaacEnc_noiseDetection( PNS_CONFIG
*pnsConf
,
107 const INT
*sfbOffset
,
109 INT tnsPredictionGain
,
111 FIXP_DBL
*mdctSpectrum
,
112 INT
*sfbMaxScaleSpec
,
113 FIXP_SGL
*sfbtonality
);
115 static void FDKaacEnc_CalcNoiseNrgs( const INT sfbActive
,
117 FIXP_DBL
*sfbEnergyLdData
,
120 /*****************************************************************************
122 functionname: initPnsConfiguration
123 description: fill pnsConf with pns parameters
124 returns: error status
125 input: PNS Config struct (modified)
126 bitrate, samplerate, usePns,
127 number of sfb's, pointer to sfb offset
130 *****************************************************************************/
132 AAC_ENCODER_ERROR
FDKaacEnc_InitPnsConfiguration(PNS_CONFIG
*pnsConf
,
137 const INT
*sfbOffset
,
141 AAC_ENCODER_ERROR ErrorStatus
;
143 /* init noise detection */
144 ErrorStatus
= FDKaacEnc_GetPnsParam(&pnsConf
->np
,
152 if (ErrorStatus
!= AAC_ENC_OK
)
155 pnsConf
->minCorrelationEnergy
= minCorrelationEnergy
;
156 pnsConf
->noiseCorrelationThresh
= noiseCorrelationThresh
;
158 pnsConf
->usePns
= usePns
;
165 /*****************************************************************************
167 functionname: FDKaacEnc_PnsDetect
168 description: do decision, if PNS shall used or not
170 input: pns config structure
171 pns data structure (modified),
172 lastWindowSequence (long or short blocks)
174 pointer to Sfb Energy, Threshold, Offset
175 pointer to mdct Spectrum
177 pointer to tonality calculated in chaosmeasure
178 tns order and prediction gain
179 calculated noiseNrg at active PNS
180 output: pnsFlag in pns data structure
182 *****************************************************************************/
183 void FDKaacEnc_PnsDetect(PNS_CONFIG
*pnsConf
,
185 const INT lastWindowSequence
,
187 const INT maxSfbPerGroup
,
188 FIXP_DBL
*sfbThresholdLdData
,
189 const INT
*sfbOffset
,
190 FIXP_DBL
*mdctSpectrum
,
191 INT
*sfbMaxScaleSpec
,
192 FIXP_SGL
*sfbtonality
,
194 INT tnsPredictionGain
,
196 FIXP_DBL
*sfbEnergyLdData
,
203 if (pnsConf
->np
.detectionAlgorithmFlags
& IS_LOW_COMLEXITY
) {
204 if ( (!pnsConf
->usePns
) || /* pns enabled? */
205 (lastWindowSequence
== SHORT_WINDOW
) ) /* currently only long blocks */
207 FDKmemclear(pnsData
->pnsFlag
, MAX_GROUPED_SFB
*sizeof(INT
)); /* clear all pnsFlags */
208 for (sfb
=0; sfb
<MAX_GROUPED_SFB
; sfb
++) {
209 noiseNrg
[sfb
] = NO_NOISE_PNS
; /* clear nrg's of previous frame */
218 /* PNS only for long Windows */
219 if (pnsConf
->np
.detectionAlgorithmFlags
& JUST_LONG_WINDOW
) {
220 if(lastWindowSequence
!= LONG_WINDOW
) {
221 for (sfb
= 0; sfb
< sfbActive
; sfb
++) {
222 pnsData
->pnsFlag
[sfb
] = 0; /* clear all pnsFlags */
231 FDKaacEnc_FDKaacEnc_noiseDetection( pnsConf
,
242 /* set startNoiseSfb (long) */
243 startNoiseSfb
= pnsConf
->np
.startSfb
;
245 /* Set noise substitution status */
246 for(sfb
= 0; sfb
< sfbActive
; sfb
++) {
248 /* No PNS below startNoiseSfb */
249 if(sfb
< startNoiseSfb
){
250 pnsData
->pnsFlag
[sfb
] = 0;
255 do noise substitution if
256 fuzzy measure is high enough
257 sfb freq > minimum sfb freq
258 signal in coder band is not masked
261 if((pnsData
->noiseFuzzyMeasure
[sfb
] > FL2FXCONST_SGL(0.5)) &&
262 ( (sfbThresholdLdData
[sfb
] + FL2FXCONST_DBL(0.5849625f
/64.0f
)) /* thr * 1.5 = thrLd +ld(1.5)/64 */
263 < sfbEnergyLdData
[sfb
] ) )
266 mark in psyout flag array that we will code
269 pnsData
->pnsFlag
[sfb
] = 1; /* PNS_ON */
272 pnsData
->pnsFlag
[sfb
] = 0; /* PNS_OFF */
275 /* no PNS if LTP is active */
278 /* avoid PNS holes */
279 if((pnsData
->noiseFuzzyMeasure
[0]>FL2FXCONST_SGL(0.5f
)) && (pnsData
->pnsFlag
[1])) {
280 pnsData
->pnsFlag
[0] = 1;
283 for(sfb
=1; sfb
<maxSfbPerGroup
-1; sfb
++) {
284 if((pnsData
->noiseFuzzyMeasure
[sfb
]>pnsConf
->np
.gapFillThr
) &&
285 (pnsData
->pnsFlag
[sfb
-1]) && (pnsData
->pnsFlag
[sfb
+1])) {
286 pnsData
->pnsFlag
[sfb
] = 1;
290 if(maxSfbPerGroup
>0) {
292 if((pnsData
->noiseFuzzyMeasure
[maxSfbPerGroup
-1]>pnsConf
->np
.gapFillThr
) && (pnsData
->pnsFlag
[maxSfbPerGroup
-2])) {
293 pnsData
->pnsFlag
[maxSfbPerGroup
-1] = 1;
295 /* avoid single PNS band */
296 if(pnsData
->pnsFlag
[maxSfbPerGroup
-2]==0) {
297 pnsData
->pnsFlag
[maxSfbPerGroup
-1] = 0;
301 /* avoid single PNS bands */
302 if(pnsData
->pnsFlag
[1]==0) {
303 pnsData
->pnsFlag
[0] = 0;
306 for(sfb
=1; sfb
<maxSfbPerGroup
-1; sfb
++) {
307 if((pnsData
->pnsFlag
[sfb
-1]==0)&&(pnsData
->pnsFlag
[sfb
+1]==0)) {
308 pnsData
->pnsFlag
[sfb
] = 0;
316 FDKaacEnc_CalcNoiseNrgs( sfbActive
,
323 /*****************************************************************************
325 functionname:FDKaacEnc_FDKaacEnc_noiseDetection
326 description: wrapper for noisedet.c
328 input: pns config structure
329 pns data structure (modified),
331 tns order and prediction gain
332 pointer to mdct Spectrumand Sfb Energy
333 pointer to Sfb tonality
334 output: noiseFuzzyMeasure in structure pnsData
335 flags tonal / nontonal
337 *****************************************************************************/
338 static void FDKaacEnc_FDKaacEnc_noiseDetection( PNS_CONFIG
*pnsConf
,
341 const INT
*sfbOffset
,
343 INT tnsPredictionGain
,
345 FIXP_DBL
*mdctSpectrum
,
346 INT
*sfbMaxScaleSpec
,
347 FIXP_SGL
*sfbtonality
)
349 INT condition
= TRUE
;
350 if ( !(pnsConf
->np
.detectionAlgorithmFlags
& IS_LOW_COMLEXITY
) ) {
351 condition
= (tnsOrder
> 3);
354 no PNS if heavy TNS activity
355 clear pnsData->noiseFuzzyMeasure
357 if((pnsConf
->np
.detectionAlgorithmFlags
& USE_TNS_GAIN_THR
) &&
358 (tnsPredictionGain
>= pnsConf
->np
.tnsGainThreshold
) && condition
&&
359 !((pnsConf
->np
.detectionAlgorithmFlags
& USE_TNS_PNS
) && (tnsPredictionGain
>= pnsConf
->np
.tnsPNSGainThreshold
) && (tnsActive
)) )
361 /* clear all noiseFuzzyMeasure */
362 FDKmemclear(pnsData
->noiseFuzzyMeasure
, sfbActive
*sizeof(FIXP_SGL
));
367 call noise detection, output in pnsData->noiseFuzzyMeasure,
368 use real mdct spectral data
370 FDKaacEnc_noiseDetect( mdctSpectrum
,
374 pnsData
->noiseFuzzyMeasure
,
381 /*****************************************************************************
383 functionname:FDKaacEnc_CalcNoiseNrgs
384 description: Calculate the NoiseNrg's
387 if pnsFlag calculate NoiseNrg
388 pointer to sfbEnergy and groupLen
389 pointer to noiseNrg (modified)
390 output: noiseNrg's in pnsFlaged sfb's
392 *****************************************************************************/
394 static void FDKaacEnc_CalcNoiseNrgs( const INT sfbActive
,
395 INT
*RESTRICT pnsFlag
,
396 FIXP_DBL
*RESTRICT sfbEnergyLdData
,
397 INT
*RESTRICT noiseNrg
)
400 INT tmp
= (-LOG_NORM_PCM
)<<2;
402 for(sfb
= 0; sfb
< sfbActive
; sfb
++) {
404 INT nrg
= (-sfbEnergyLdData
[sfb
]+FL2FXCONST_DBL(0.5f
/64.0f
))>>(DFRACT_BITS
-1-7);
405 noiseNrg
[sfb
] = tmp
- nrg
;
411 /*****************************************************************************
413 functionname:FDKaacEnc_CodePnsChannel
414 description: Execute pns decission
419 pointer to Sfb Energy, noiseNrg, Threshold
420 output: set sfbThreshold high to code pe with 0,
421 noiseNrg marks flag for pns coding
423 *****************************************************************************/
425 void FDKaacEnc_CodePnsChannel(const INT sfbActive
,
427 INT
*RESTRICT pnsFlag
,
428 FIXP_DBL
*RESTRICT sfbEnergyLdData
,
429 INT
*RESTRICT noiseNrg
,
430 FIXP_DBL
*RESTRICT sfbThresholdLdData
)
433 INT lastiNoiseEnergy
= 0;
434 INT firstPNSband
= 1; /* TRUE for first PNS-coded band */
437 if(!pnsConf
->usePns
) {
438 for(sfb
= 0; sfb
< sfbActive
; sfb
++) {
440 noiseNrg
[sfb
] = NO_NOISE_PNS
;
446 for(sfb
= 0; sfb
< sfbActive
; sfb
++) {
448 /* high sfbThreshold causes pe = 0 */
449 if(noiseNrg
[sfb
] != NO_NOISE_PNS
)
450 sfbThresholdLdData
[sfb
] = sfbEnergyLdData
[sfb
] + FL2FXCONST_DBL(1.0f
/LD_DATA_SCALING
);
452 /* set noiseNrg in valid region */
454 INT deltaiNoiseEnergy
= noiseNrg
[sfb
] - lastiNoiseEnergy
;
456 if(deltaiNoiseEnergy
> CODE_BOOK_PNS_LAV
)
457 noiseNrg
[sfb
] -= deltaiNoiseEnergy
- CODE_BOOK_PNS_LAV
;
458 else if(deltaiNoiseEnergy
< -CODE_BOOK_PNS_LAV
)
459 noiseNrg
[sfb
] -= deltaiNoiseEnergy
+ CODE_BOOK_PNS_LAV
;
464 lastiNoiseEnergy
= noiseNrg
[sfb
];
468 noiseNrg
[sfb
] = NO_NOISE_PNS
;
474 /*****************************************************************************
476 functionname:FDKaacEnc_PreProcessPnsChannelPair
477 description: Calculate the correlation of noise in a channel pair
481 pointer to sfb energies left, right and mid channel
483 pns data structure left and right (modified)
485 output: noiseEnergyCorrelation in pns data structure
487 *****************************************************************************/
489 void FDKaacEnc_PreProcessPnsChannelPair(const INT sfbActive
,
490 FIXP_DBL
*RESTRICT sfbEnergyLeft
,
491 FIXP_DBL
*RESTRICT sfbEnergyRight
,
492 FIXP_DBL
*RESTRICT sfbEnergyLeftLD
,
493 FIXP_DBL
*RESTRICT sfbEnergyRightLD
,
494 FIXP_DBL
*RESTRICT sfbEnergyMid
,
495 PNS_CONFIG
*RESTRICT pnsConf
,
496 PNS_DATA
*pnsDataLeft
,
497 PNS_DATA
*pnsDataRight
)
505 FIXP_DBL
*RESTRICT pNoiseEnergyCorrelationL
= pnsDataLeft
->noiseEnergyCorrelation
;
506 FIXP_DBL
*RESTRICT pNoiseEnergyCorrelationR
= pnsDataRight
->noiseEnergyCorrelation
;
508 for(sfb
=0;sfb
< sfbActive
;sfb
++) {
509 FIXP_DBL quot
= (sfbEnergyLeftLD
[sfb
]>>1) + (sfbEnergyRightLD
[sfb
]>>1);
511 if(quot
< FL2FXCONST_DBL(-32.0f
/(float)LD_DATA_SCALING
))
512 ccf
= FL2FXCONST_DBL(0.0f
);
514 FIXP_DBL accu
= sfbEnergyMid
[sfb
]- (((sfbEnergyLeft
[sfb
]>>1)+(sfbEnergyRight
[sfb
]>>1))>>1);
515 INT sign
= (accu
< FL2FXCONST_DBL(0.0f
)) ? 1 : 0 ;
516 accu
= fixp_abs(accu
);
518 ccf
= CalcLdData(accu
) + FL2FXCONST_DBL((float)1.0f
/(float)LD_DATA_SCALING
) - quot
; /* ld(accu*2) = ld(accu) + 1 */
519 ccf
= (ccf
>=FL2FXCONST_DBL(0.0)) ? ((FIXP_DBL
)MAXVAL_DBL
) : (sign
) ? -CalcInvLdData(ccf
) : CalcInvLdData(ccf
);
522 pNoiseEnergyCorrelationL
[sfb
] = ccf
;
523 pNoiseEnergyCorrelationR
[sfb
] = ccf
;
529 /*****************************************************************************
531 functionname:FDKaacEnc_PostProcessPnsChannelPair
532 description: if PNS used at left and right channel,
533 use msMask to flag correlation
537 pns data structure left and right (modified)
538 pointer to msMask, flags correlation by pns coding (modified)
540 output: pnsFlag in pns data structure,
541 msFlag in msMask (flags correlation)
543 *****************************************************************************/
545 void FDKaacEnc_PostProcessPnsChannelPair(const INT sfbActive
,
547 PNS_DATA
*pnsDataLeft
,
548 PNS_DATA
*pnsDataRight
,
549 INT
*RESTRICT msMask
,
557 for(sfb
=0;sfb
<sfbActive
;sfb
++) {
562 if( (pnsDataLeft
->pnsFlag
[sfb
]) &&
563 (pnsDataRight
->pnsFlag
[sfb
]) ) {
564 /* AAC only: Standard */
565 /* do this to avoid ms flags in layers that should not have it */
566 if(pnsDataLeft
->noiseEnergyCorrelation
[sfb
] <= pnsConf
->noiseCorrelationThresh
){
575 pnsDataLeft
->pnsFlag
[sfb
] = 0;
576 pnsDataRight
->pnsFlag
[sfb
] = 0;
581 Use MS flag to signal noise correlation if
582 pns is active in both channels
584 if( (pnsDataLeft
->pnsFlag
[sfb
]) && (pnsDataRight
->pnsFlag
[sfb
]) ) {
585 if(pnsDataLeft
->noiseEnergyCorrelation
[sfb
] > pnsConf
->noiseCorrelationThresh
) {