Imported Debian version 0.1.3.1
[deb_fdk-aac.git] / libAACenc / src / aacenc_pns.cpp
1
2 /* -----------------------------------------------------------------------------------------------------------
3 Software License for The Fraunhofer FDK AAC Codec Library for Android
4
5 © Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
6 All rights reserved.
7
8 1. INTRODUCTION
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.
12
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.
17
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.
24
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.
28
29 2. COPYRIGHT LICENSE
30
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:
33
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.
36
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.
41
42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43 prior written permission.
44
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.
47
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."
52
53 3. NO PATENT LICENSE
54
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.
58
59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60 by appropriate patent licenses.
61
62 4. DISCLAIMER
63
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.
72
73 5. CONTACT INFORMATION
74
75 Fraunhofer Institute for Integrated Circuits IIS
76 Attention: Audio and Multimedia Departments - FDK AAC LL
77 Am Wolfsmantel 33
78 91058 Erlangen, Germany
79
80 www.iis.fraunhofer.de/amm
81 amm-info@iis.fraunhofer.de
82 ----------------------------------------------------------------------------------------------------------- */
83
84 /******************************** MPEG Audio Encoder **************************
85
86 Initial author: M. Lohwasser
87 contents/description: pns.c
88
89 ******************************************************************************/
90
91 #include "aacenc_pns.h"
92 #include "psy_data.h"
93 #include "pnsparam.h"
94 #include "noisedet.h"
95 #include "bit_cnt.h"
96 #include "interface.h"
97
98
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);
103
104 static void FDKaacEnc_FDKaacEnc_noiseDetection( PNS_CONFIG *pnsConf,
105 PNS_DATA *pnsData,
106 const INT sfbActive,
107 const INT *sfbOffset,
108 INT tnsOrder,
109 INT tnsPredictionGain,
110 INT tnsActive,
111 FIXP_DBL *mdctSpectrum,
112 INT *sfbMaxScaleSpec,
113 FIXP_SGL *sfbtonality );
114
115 static void FDKaacEnc_CalcNoiseNrgs( const INT sfbActive,
116 INT *pnsFlag,
117 FIXP_DBL *sfbEnergyLdData,
118 INT *noiseNrg );
119
120 /*****************************************************************************
121
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
128 output: error code
129
130 *****************************************************************************/
131
132 AAC_ENCODER_ERROR FDKaacEnc_InitPnsConfiguration(PNS_CONFIG *pnsConf,
133 INT bitRate,
134 INT sampleRate,
135 INT usePns,
136 INT sfbCnt,
137 const INT *sfbOffset,
138 const INT numChan,
139 const INT isLC)
140 {
141 AAC_ENCODER_ERROR ErrorStatus;
142
143 /* init noise detection */
144 ErrorStatus = FDKaacEnc_GetPnsParam(&pnsConf->np,
145 bitRate,
146 sampleRate,
147 sfbCnt,
148 sfbOffset,
149 &usePns,
150 numChan,
151 isLC);
152 if (ErrorStatus != AAC_ENC_OK)
153 return ErrorStatus;
154
155 pnsConf->minCorrelationEnergy = minCorrelationEnergy;
156 pnsConf->noiseCorrelationThresh = noiseCorrelationThresh;
157
158 pnsConf->usePns = usePns;
159
160 return AAC_ENC_OK;
161 }
162
163
164
165 /*****************************************************************************
166
167 functionname: FDKaacEnc_PnsDetect
168 description: do decision, if PNS shall used or not
169 returns:
170 input: pns config structure
171 pns data structure (modified),
172 lastWindowSequence (long or short blocks)
173 sfbActive
174 pointer to Sfb Energy, Threshold, Offset
175 pointer to mdct Spectrum
176 length of each group
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
181
182 *****************************************************************************/
183 void FDKaacEnc_PnsDetect(PNS_CONFIG *pnsConf,
184 PNS_DATA *pnsData,
185 const INT lastWindowSequence,
186 const INT sfbActive,
187 const INT maxSfbPerGroup,
188 FIXP_DBL *sfbThresholdLdData,
189 const INT *sfbOffset,
190 FIXP_DBL *mdctSpectrum,
191 INT *sfbMaxScaleSpec,
192 FIXP_SGL *sfbtonality,
193 INT tnsOrder,
194 INT tnsPredictionGain,
195 INT tnsActive,
196 FIXP_DBL *sfbEnergyLdData,
197 INT *noiseNrg )
198
199 {
200 int sfb;
201 int startNoiseSfb;
202
203 if (pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMLEXITY) {
204 if ( (!pnsConf->usePns) || /* pns enabled? */
205 (lastWindowSequence == SHORT_WINDOW) ) /* currently only long blocks */
206 {
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 */
210 }
211 return;
212 }
213 }
214 else {
215 if(!pnsConf->usePns)
216 return;
217
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 */
223 }
224 return;
225 }
226 }
227 }
228 /*
229 call noise detection
230 */
231 FDKaacEnc_FDKaacEnc_noiseDetection( pnsConf,
232 pnsData,
233 sfbActive,
234 sfbOffset,
235 tnsOrder,
236 tnsPredictionGain,
237 tnsActive,
238 mdctSpectrum,
239 sfbMaxScaleSpec,
240 sfbtonality );
241
242 /* set startNoiseSfb (long) */
243 startNoiseSfb = pnsConf->np.startSfb;
244
245 /* Set noise substitution status */
246 for(sfb = 0; sfb < sfbActive; sfb++) {
247
248 /* No PNS below startNoiseSfb */
249 if(sfb < startNoiseSfb){
250 pnsData->pnsFlag[sfb] = 0;
251 continue;
252 }
253
254 /*
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
259 */
260
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] ) )
264 {
265 /*
266 mark in psyout flag array that we will code
267 this band with PNS
268 */
269 pnsData->pnsFlag[sfb] = 1; /* PNS_ON */
270 }
271 else{
272 pnsData->pnsFlag[sfb] = 0; /* PNS_OFF */
273 }
274
275 /* no PNS if LTP is active */
276 }
277
278 /* avoid PNS holes */
279 if((pnsData->noiseFuzzyMeasure[0]>FL2FXCONST_SGL(0.5f)) && (pnsData->pnsFlag[1])) {
280 pnsData->pnsFlag[0] = 1;
281 }
282
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;
287 }
288 }
289
290 if(maxSfbPerGroup>0) {
291 /* avoid PNS hole */
292 if((pnsData->noiseFuzzyMeasure[maxSfbPerGroup-1]>pnsConf->np.gapFillThr) && (pnsData->pnsFlag[maxSfbPerGroup-2])) {
293 pnsData->pnsFlag[maxSfbPerGroup-1] = 1;
294 }
295 /* avoid single PNS band */
296 if(pnsData->pnsFlag[maxSfbPerGroup-2]==0) {
297 pnsData->pnsFlag[maxSfbPerGroup-1] = 0;
298 }
299 }
300
301 /* avoid single PNS bands */
302 if(pnsData->pnsFlag[1]==0) {
303 pnsData->pnsFlag[0] = 0;
304 }
305
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;
309 }
310 }
311
312
313 /*
314 calculate noiseNrg's
315 */
316 FDKaacEnc_CalcNoiseNrgs( sfbActive,
317 pnsData->pnsFlag,
318 sfbEnergyLdData,
319 noiseNrg );
320 }
321
322
323 /*****************************************************************************
324
325 functionname:FDKaacEnc_FDKaacEnc_noiseDetection
326 description: wrapper for noisedet.c
327 returns:
328 input: pns config structure
329 pns data structure (modified),
330 sfbActive
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
336
337 *****************************************************************************/
338 static void FDKaacEnc_FDKaacEnc_noiseDetection( PNS_CONFIG *pnsConf,
339 PNS_DATA *pnsData,
340 const INT sfbActive,
341 const INT *sfbOffset,
342 int tnsOrder,
343 INT tnsPredictionGain,
344 INT tnsActive,
345 FIXP_DBL *mdctSpectrum,
346 INT *sfbMaxScaleSpec,
347 FIXP_SGL *sfbtonality )
348 {
349 INT condition = TRUE;
350 if ( !(pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMLEXITY) ) {
351 condition = (tnsOrder > 3);
352 }
353 /*
354 no PNS if heavy TNS activity
355 clear pnsData->noiseFuzzyMeasure
356 */
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)) )
360 {
361 /* clear all noiseFuzzyMeasure */
362 FDKmemclear(pnsData->noiseFuzzyMeasure, sfbActive*sizeof(FIXP_SGL));
363 }
364 else
365 {
366 /*
367 call noise detection, output in pnsData->noiseFuzzyMeasure,
368 use real mdct spectral data
369 */
370 FDKaacEnc_noiseDetect( mdctSpectrum,
371 sfbMaxScaleSpec,
372 sfbActive,
373 sfbOffset,
374 pnsData->noiseFuzzyMeasure,
375 &pnsConf->np,
376 sfbtonality);
377 }
378 }
379
380
381 /*****************************************************************************
382
383 functionname:FDKaacEnc_CalcNoiseNrgs
384 description: Calculate the NoiseNrg's
385 returns:
386 input: sfbActive
387 if pnsFlag calculate NoiseNrg
388 pointer to sfbEnergy and groupLen
389 pointer to noiseNrg (modified)
390 output: noiseNrg's in pnsFlaged sfb's
391
392 *****************************************************************************/
393
394 static void FDKaacEnc_CalcNoiseNrgs( const INT sfbActive,
395 INT *RESTRICT pnsFlag,
396 FIXP_DBL *RESTRICT sfbEnergyLdData,
397 INT *RESTRICT noiseNrg )
398 {
399 int sfb;
400 INT tmp = (-LOG_NORM_PCM)<<2;
401
402 for(sfb = 0; sfb < sfbActive; sfb++) {
403 if(pnsFlag[sfb]) {
404 INT nrg = (-sfbEnergyLdData[sfb]+FL2FXCONST_DBL(0.5f/64.0f))>>(DFRACT_BITS-1-7);
405 noiseNrg[sfb] = tmp - nrg;
406 }
407 }
408 }
409
410
411 /*****************************************************************************
412
413 functionname:FDKaacEnc_CodePnsChannel
414 description: Execute pns decission
415 returns:
416 input: sfbActive
417 pns config structure
418 use PNS if pnsFlag
419 pointer to Sfb Energy, noiseNrg, Threshold
420 output: set sfbThreshold high to code pe with 0,
421 noiseNrg marks flag for pns coding
422
423 *****************************************************************************/
424
425 void FDKaacEnc_CodePnsChannel(const INT sfbActive,
426 PNS_CONFIG *pnsConf,
427 INT *RESTRICT pnsFlag,
428 FIXP_DBL *RESTRICT sfbEnergyLdData,
429 INT *RESTRICT noiseNrg,
430 FIXP_DBL *RESTRICT sfbThresholdLdData)
431 {
432 INT sfb;
433 INT lastiNoiseEnergy = 0;
434 INT firstPNSband = 1; /* TRUE for first PNS-coded band */
435
436 /* no PNS */
437 if(!pnsConf->usePns) {
438 for(sfb = 0; sfb < sfbActive; sfb++) {
439 /* no PNS coding */
440 noiseNrg[sfb] = NO_NOISE_PNS;
441 }
442 return;
443 }
444
445 /* code PNS */
446 for(sfb = 0; sfb < sfbActive; sfb++) {
447 if(pnsFlag[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);
451
452 /* set noiseNrg in valid region */
453 if(!firstPNSband) {
454 INT deltaiNoiseEnergy = noiseNrg[sfb] - lastiNoiseEnergy;
455
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;
460 }
461 else {
462 firstPNSband = 0;
463 }
464 lastiNoiseEnergy = noiseNrg[sfb];
465 }
466 else {
467 /* no PNS coding */
468 noiseNrg[sfb] = NO_NOISE_PNS;
469 }
470 }
471 }
472
473
474 /*****************************************************************************
475
476 functionname:FDKaacEnc_PreProcessPnsChannelPair
477 description: Calculate the correlation of noise in a channel pair
478
479 returns:
480 input: sfbActive
481 pointer to sfb energies left, right and mid channel
482 pns config structure
483 pns data structure left and right (modified)
484
485 output: noiseEnergyCorrelation in pns data structure
486
487 *****************************************************************************/
488
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)
498 {
499 INT sfb;
500 FIXP_DBL ccf;
501
502 if(!pnsConf->usePns)
503 return;
504
505 FIXP_DBL *RESTRICT pNoiseEnergyCorrelationL = pnsDataLeft->noiseEnergyCorrelation;
506 FIXP_DBL *RESTRICT pNoiseEnergyCorrelationR = pnsDataRight->noiseEnergyCorrelation;
507
508 for(sfb=0;sfb< sfbActive;sfb++) {
509 FIXP_DBL quot = (sfbEnergyLeftLD[sfb]>>1) + (sfbEnergyRightLD[sfb]>>1);
510
511 if(quot < FL2FXCONST_DBL(-32.0f/(float)LD_DATA_SCALING))
512 ccf = FL2FXCONST_DBL(0.0f);
513 else {
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);
517
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);
520 }
521
522 pNoiseEnergyCorrelationL[sfb] = ccf;
523 pNoiseEnergyCorrelationR[sfb] = ccf;
524 }
525 }
526
527
528
529 /*****************************************************************************
530
531 functionname:FDKaacEnc_PostProcessPnsChannelPair
532 description: if PNS used at left and right channel,
533 use msMask to flag correlation
534 returns:
535 input: sfbActive
536 pns config structure
537 pns data structure left and right (modified)
538 pointer to msMask, flags correlation by pns coding (modified)
539 Digest of MS coding
540 output: pnsFlag in pns data structure,
541 msFlag in msMask (flags correlation)
542
543 *****************************************************************************/
544
545 void FDKaacEnc_PostProcessPnsChannelPair(const INT sfbActive,
546 PNS_CONFIG *pnsConf,
547 PNS_DATA *pnsDataLeft,
548 PNS_DATA *pnsDataRight,
549 INT *RESTRICT msMask,
550 INT *msDigest )
551 {
552 INT sfb;
553
554 if(!pnsConf->usePns)
555 return;
556
557 for(sfb=0;sfb<sfbActive;sfb++) {
558 /*
559 MS post processing
560 */
561 if( msMask[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){
567 msMask[sfb] = 0;
568 *msDigest = MS_SOME;
569 }
570 }
571 else {
572 /*
573 No PNS coding
574 */
575 pnsDataLeft->pnsFlag[sfb] = 0;
576 pnsDataRight->pnsFlag[sfb] = 0;
577 }
578 }
579
580 /*
581 Use MS flag to signal noise correlation if
582 pns is active in both channels
583 */
584 if( (pnsDataLeft->pnsFlag[sfb]) && (pnsDataRight->pnsFlag[sfb]) ) {
585 if(pnsDataLeft->noiseEnergyCorrelation[sfb] > pnsConf->noiseCorrelationThresh) {
586 msMask[sfb] = 1;
587 *msDigest = MS_SOME;
588 }
589 }
590 }
591 }