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: A. Horndasch (code originally from lwr) / Josef Hoepfl (FDK)
87 contents/description: intensity stereo processing
89 ******************************************************************************/
91 #include "intensity.h"
92 #include "interface.h"
93 #include "psy_configuration.h"
94 #include "psy_const.h"
98 /* only set an IS seed it left/right channel correlation is above IS_CORR_THRESH */
99 #define IS_CORR_THRESH FL2FXCONST_DBL(0.95f)
101 /* when expanding the IS region to more SFBs only accept an error that is
102 * not more than IS_TOTAL_ERROR_THRESH overall and
103 * not more than IS_LOCAL_ERROR_THRESH for the current SFB */
104 #define IS_TOTAL_ERROR_THRESH FL2FXCONST_DBL(0.04f)
105 #define IS_LOCAL_ERROR_THRESH FL2FXCONST_DBL(0.01f)
107 /* the maximum allowed change of the intensity direction (unit: IS scale) - scaled with factor 0.25 - */
108 #define IS_DIRECTION_DEVIATION_THRESH_SF 2
109 #define IS_DIRECTION_DEVIATION_THRESH FL2FXCONST_DBL(2.0f/(1<<IS_DIRECTION_DEVIATION_THRESH_SF))
111 /* IS regions need to have a minimal percentage of the overall loudness, e.g. 0.06 == 6% */
112 #define IS_REGION_MIN_LOUDNESS FL2FXCONST_DBL(0.1f)
114 /* only perform IS if IS_MIN_SFBS neighboring SFBs can be processed */
115 #define IS_MIN_SFBS 6
118 * if IS_LEFT_RIGHT_RATIO_THRESH < sfbEnergyLeft[sfb]/sfbEnergyRight[sfb] < 1 / IS_LEFT_RIGHT_RATIO_THRESH
119 * -> no IS if the panning angle is not far from the middle, MS will do */
120 /* this is equivalent to a scale of +/-1.02914634566 */
121 #define IS_LEFT_RIGHT_RATIO_THRESH FL2FXCONST_DBL(0.7f)
123 /* scalefactor of realScale */
124 #define REAL_SCALE_SF 1
126 /* scalefactor overallLoudness */
127 #define OVERALL_LOUDNESS_SF 6
129 /* scalefactor for sum over max samples per goup */
130 #define MAX_SFB_PER_GROUP_SF 6
132 /* scalefactor for sum of mdct spectrum */
133 #define MDCT_SPEC_SF 6
139 FIXP_DBL corr_thresh
; /*!< Only set an IS seed it left/right channel correlation is above corr_thresh */
141 FIXP_DBL total_error_thresh
; /*!< When expanding the IS region to more SFBs only accept an error that is
142 not more than 'total_error_thresh' overall. */
144 FIXP_DBL local_error_thresh
; /*!< When expanding the IS region to more SFBs only accept an error that is
145 not more than 'local_error_thresh' for the current SFB. */
147 FIXP_DBL direction_deviation_thresh
; /*!< The maximum allowed change of the intensity direction (unit: IS scale) */
149 FIXP_DBL is_region_min_loudness
; /*!< IS regions need to have a minimal percentage of the overall loudness, e.g. 0.06 == 6% */
151 INT min_is_sfbs
; /*!< Only perform IS if 'min_is_sfbs' neighboring SFBs can be processed */
153 FIXP_DBL left_right_ratio_threshold
; /*!< No IS if the panning angle is not far from the middle, MS will do */
155 } INTENSITY_PARAMETERS
;
158 /*****************************************************************************
160 functionname: calcSfbMaxScale
162 description: Calc max value in scalefactor band
172 *****************************************************************************/
174 calcSfbMaxScale(const FIXP_DBL
*mdctSpectrum
,
182 maxSpc
= FL2FXCONST_DBL(0.0);
183 for (i
=l1
; i
<l2
; i
++) {
184 FIXP_DBL tmp
= fixp_abs((FIXP_DBL
)mdctSpectrum
[i
]);
185 maxSpc
= fixMax(maxSpc
, tmp
);
187 sfbMaxScale
= (maxSpc
==FL2FXCONST_DBL(0.0)) ? (DFRACT_BITS
-2) : CntLeadingZeros(maxSpc
)-1;
193 /*****************************************************************************
195 functionname: FDKaacEnc_initIsParams
197 description: Initialization of intensity parameters
205 *****************************************************************************/
207 FDKaacEnc_initIsParams(INTENSITY_PARAMETERS
*isParams
)
209 isParams
->corr_thresh
= IS_CORR_THRESH
;
210 isParams
->total_error_thresh
= IS_TOTAL_ERROR_THRESH
;
211 isParams
->local_error_thresh
= IS_LOCAL_ERROR_THRESH
;
212 isParams
->direction_deviation_thresh
= IS_DIRECTION_DEVIATION_THRESH
;
213 isParams
->is_region_min_loudness
= IS_REGION_MIN_LOUDNESS
;
214 isParams
->min_is_sfbs
= IS_MIN_SFBS
;
215 isParams
->left_right_ratio_threshold
= IS_LEFT_RIGHT_RATIO_THRESH
;
219 /*****************************************************************************
221 functionname: FDKaacEnc_prepareIntensityDecision
223 description: Prepares intensity decision
233 output: hrrErr scale: none
235 realScale scale: LD_DATA_SHIFT + REAL_SCALE_SF
236 normSfbLoudness scale: none
240 *****************************************************************************/
242 FDKaacEnc_prepareIntensityDecision(const FIXP_DBL
*sfbEnergyLeft
,
243 const FIXP_DBL
*sfbEnergyRight
,
244 const FIXP_DBL
*sfbEnergyLdDataLeft
,
245 const FIXP_DBL
*sfbEnergyLdDataRight
,
246 const FIXP_DBL
*mdctSpectrumLeft
,
247 const FIXP_DBL
*mdctSpectrumRight
,
248 const INTENSITY_PARAMETERS
*isParams
,
252 FIXP_DBL
*normSfbLoudness
,
254 const INT sfbPerGroup
,
255 const INT maxSfbPerGroup
,
256 const INT
*sfbOffset
)
261 /* temporary variables to compute loudness */
262 FIXP_DBL overallLoudness
[MAX_NO_OF_GROUPS
];
264 /* temporary variables to compute correlation */
265 FIXP_DBL channelCorr
[MAX_GROUPED_SFB
];
268 FIXP_DBL square_l
, square_r
;
269 FIXP_DBL tmp_l
, tmp_r
;
272 FDKmemclear(channelCorr
, MAX_GROUPED_SFB
*sizeof(FIXP_DBL
));
273 FDKmemclear(normSfbLoudness
, MAX_GROUPED_SFB
*sizeof(FIXP_DBL
));
274 FDKmemclear(overallLoudness
, MAX_NO_OF_GROUPS
*sizeof(FIXP_DBL
));
275 FDKmemclear(realScale
, MAX_GROUPED_SFB
*sizeof(FIXP_DBL
));
277 for (grpCounter
= 0, sfboffs
= 0; sfboffs
< sfbCnt
; sfboffs
+= sfbPerGroup
, grpCounter
++) {
278 overallLoudness
[grpCounter
] = FL2FXCONST_DBL(0.0f
);
279 for (sfb
= 0; sfb
< maxSfbPerGroup
; sfb
++) {
281 FIXP_DBL isValue
= sfbEnergyLdDataLeft
[sfb
+sfboffs
]-sfbEnergyLdDataRight
[sfb
+sfboffs
];
283 /* delimitate intensity scale value to representable range */
284 realScale
[sfb
+ sfboffs
] = fixMin(FL2FXCONST_DBL(60.f
/(1<<(REAL_SCALE_SF
+LD_DATA_SHIFT
))), fixMax(FL2FXCONST_DBL(-60.f
/(1<<(REAL_SCALE_SF
+LD_DATA_SHIFT
))), isValue
));
286 sL
= fixMax(0,(CntLeadingZeros(sfbEnergyLeft
[sfb
+ sfboffs
])-1));
287 sR
= fixMax(0,(CntLeadingZeros(sfbEnergyRight
[sfb
+ sfboffs
])-1));
288 s
= (fixMin(sL
,sR
)>>2)<<2;
289 normSfbLoudness
[sfb
+ sfboffs
] = sqrtFixp(sqrtFixp(((sfbEnergyLeft
[sfb
+ sfboffs
]<<s
) >> 1) + ((sfbEnergyRight
[sfb
+ sfboffs
]<<s
) >> 1))) >> (s
>>2);
291 overallLoudness
[grpCounter
] += normSfbLoudness
[sfb
+ sfboffs
] >> OVERALL_LOUDNESS_SF
;
292 /* don't do intensity if
293 * - panning angle is too close to the middle or
294 * - one channel is non-existent or
295 * - if it is dual mono */
296 if( (sfbEnergyLeft
[sfb
+ sfboffs
] >= fMult(isParams
->left_right_ratio_threshold
,sfbEnergyRight
[sfb
+ sfboffs
]))
297 && (fMult(isParams
->left_right_ratio_threshold
,sfbEnergyLeft
[sfb
+ sfboffs
]) <= sfbEnergyRight
[sfb
+ sfboffs
]) ) {
299 /* this will prevent post processing from considering this SFB for merging */
300 hrrErr
[sfb
+ sfboffs
] = FL2FXCONST_DBL(1.0/8.0);
305 for (grpCounter
= 0, sfboffs
= 0; sfboffs
< sfbCnt
; sfboffs
+= sfbPerGroup
, grpCounter
++) {
306 INT invOverallLoudnessSF
;
307 FIXP_DBL invOverallLoudness
;
309 if (overallLoudness
[grpCounter
] == FL2FXCONST_DBL(0.0)) {
310 invOverallLoudness
= FL2FXCONST_DBL(0.0);
311 invOverallLoudnessSF
= 0;
314 invOverallLoudness
= fDivNorm((FIXP_DBL
)MAXVAL_DBL
, overallLoudness
[grpCounter
],&invOverallLoudnessSF
);
315 invOverallLoudnessSF
= invOverallLoudnessSF
- OVERALL_LOUDNESS_SF
+ 1; /* +1: compensate fMultDiv2() in subsequent loop */
317 invOverallLoudnessSF
= fixMin(fixMax(invOverallLoudnessSF
,-(DFRACT_BITS
-1)),DFRACT_BITS
-1);
319 for (sfb
= 0; sfb
< maxSfbPerGroup
; sfb
++) {
322 tmp
= fMultDiv2((normSfbLoudness
[sfb
+ sfboffs
]>>OVERALL_LOUDNESS_SF
)<<OVERALL_LOUDNESS_SF
,invOverallLoudness
);
324 normSfbLoudness
[sfb
+ sfboffs
] = scaleValue(tmp
, invOverallLoudnessSF
);
326 channelCorr
[sfb
+ sfboffs
] = FL2FXCONST_DBL(0.0f
);
328 FDK_ASSERT(50 >= 49);
329 /* max width of scalefactorband is 96; width's are always even */
330 /* inv_n is scaled with factor 2 to compensate fMultDiv2() in subsequent loops */
331 inv_n
= GetInvInt((sfbOffset
[sfb
+ sfboffs
+ 1] - sfbOffset
[sfb
+ sfboffs
])>>1);
333 if (inv_n
> FL2FXCONST_DBL(0.0f
)) {
336 /* correlation := Pearson's product-moment coefficient */
337 /* compute correlation between channels and check if it is over threshold */
338 ml
= FL2FXCONST_DBL(0.0f
);
339 mr
= FL2FXCONST_DBL(0.0f
);
340 prod_lr
= FL2FXCONST_DBL(0.0f
);
341 square_l
= FL2FXCONST_DBL(0.0f
);
342 square_r
= FL2FXCONST_DBL(0.0f
);
344 sL
= calcSfbMaxScale(mdctSpectrumLeft
,sfbOffset
[sfb
+sfboffs
],sfbOffset
[sfb
+sfboffs
+1]);
345 sR
= calcSfbMaxScale(mdctSpectrumRight
,sfbOffset
[sfb
+sfboffs
],sfbOffset
[sfb
+sfboffs
+1]);
348 for (j
= sfbOffset
[sfb
+ sfboffs
]; j
< sfbOffset
[sfb
+ sfboffs
+ 1]; j
++) {
349 ml
+= fMultDiv2((mdctSpectrumLeft
[j
] << s
),inv_n
); // scaled with mdctScale - s + inv_n
350 mr
+= fMultDiv2((mdctSpectrumRight
[j
] << s
),inv_n
); // scaled with mdctScale - s + inv_n
352 ml
= fMultDiv2(ml
,inv_n
); // scaled with mdctScale - s + inv_n
353 mr
= fMultDiv2(mr
,inv_n
); // scaled with mdctScale - s + inv_n
355 for (j
= sfbOffset
[sfb
+ sfboffs
]; j
< sfbOffset
[sfb
+ sfboffs
+ 1]; j
++) {
356 tmp_l
= fMultDiv2((mdctSpectrumLeft
[j
] << s
),inv_n
) - ml
; // scaled with mdctScale - s + inv_n
357 tmp_r
= fMultDiv2((mdctSpectrumRight
[j
] << s
),inv_n
) - mr
; // scaled with mdctScale - s + inv_n
359 prod_lr
+= fMultDiv2(tmp_l
,tmp_r
); // scaled with 2*(mdctScale - s + inv_n) + 1
360 square_l
+= fPow2Div2(tmp_l
); // scaled with 2*(mdctScale - s + inv_n) + 1
361 square_r
+= fPow2Div2(tmp_r
); // scaled with 2*(mdctScale - s + inv_n) + 1
363 prod_lr
= prod_lr
<< 1; // scaled with 2*(mdctScale - s + inv_n)
364 square_l
= square_l
<< 1; // scaled with 2*(mdctScale - s + inv_n)
365 square_r
= square_r
<< 1; // scaled with 2*(mdctScale - s + inv_n)
367 if (square_l
> FL2FXCONST_DBL(0.0f
) && square_r
> FL2FXCONST_DBL(0.0f
)) {
368 INT channelCorrSF
= 0;
370 /* local scaling of square_l and square_r is compensated after sqrt calculation */
371 sL
= fixMax(0,(CntLeadingZeros(square_l
)-1));
372 sR
= fixMax(0,(CntLeadingZeros(square_r
)-1));
373 s
= ((sL
+ sR
)>>1)<<1;
376 tmp
= fMult(square_l
<<sL
,square_r
<<sR
);
379 FDK_ASSERT(tmp
> FL2FXCONST_DBL(0.0f
));
381 /* numerator and denominator have the same scaling */
382 if (prod_lr
< FL2FXCONST_DBL(0.0f
) ) {
383 channelCorr
[sfb
+ sfboffs
] = -(fDivNorm(-prod_lr
,tmp
,&channelCorrSF
));
387 channelCorr
[sfb
+ sfboffs
] = (fDivNorm( prod_lr
,tmp
,&channelCorrSF
));
389 channelCorrSF
= fixMin(fixMax(( channelCorrSF
+ ((sL
+sR
)>>1)),-(DFRACT_BITS
-1)),DFRACT_BITS
-1);
391 if (channelCorrSF
< 0) {
392 channelCorr
[sfb
+ sfboffs
] = channelCorr
[sfb
+ sfboffs
] >> (-channelCorrSF
);
395 /* avoid overflows due to limited computational accuracy */
396 if ( fAbs(channelCorr
[sfb
+ sfboffs
]) > (((FIXP_DBL
)MAXVAL_DBL
)>>channelCorrSF
) ) {
397 if (channelCorr
[sfb
+ sfboffs
] < FL2FXCONST_DBL(0.0f
))
398 channelCorr
[sfb
+ sfboffs
] = -(FIXP_DBL
) MAXVAL_DBL
;
400 channelCorr
[sfb
+ sfboffs
] = (FIXP_DBL
) MAXVAL_DBL
;
403 channelCorr
[sfb
+ sfboffs
] = channelCorr
[sfb
+ sfboffs
] << channelCorrSF
;
409 /* for post processing: hrrErr is the error in terms of (too little) correlation
410 * weighted with the loudness of the SFB; SFBs with small hrrErr can be merged */
411 if (hrrErr
[sfb
+ sfboffs
] == FL2FXCONST_DBL(1.0/8.0)) {
415 hrrErr
[sfb
+ sfboffs
] = fMultDiv2((FL2FXCONST_DBL(0.25f
)-(channelCorr
[sfb
+ sfboffs
]>>2)),normSfbLoudness
[sfb
+ sfboffs
]);
417 /* set IS mask/vector to 1, if correlation is high enough */
418 if (fAbs(channelCorr
[sfb
+ sfboffs
]) >= isParams
->corr_thresh
) {
419 isMask
[sfb
+ sfboffs
] = 1;
426 /*****************************************************************************
428 functionname: FDKaacEnc_finalizeIntensityDecision
430 description: Finalizes intensity decision
432 input: isParams scale: none
434 realIsScale scale: LD_DATA_SHIFT + REAL_SCALE_SF
435 normSfbLoudness scale: none
437 output: isMask scale: none
441 *****************************************************************************/
443 FDKaacEnc_finalizeIntensityDecision(const FIXP_DBL
*hrrErr
,
445 const FIXP_DBL
*realIsScale
,
446 const FIXP_DBL
*normSfbLoudness
,
447 const INTENSITY_PARAMETERS
*isParams
,
449 const INT sfbPerGroup
,
450 const INT maxSfbPerGroup
)
453 FIXP_DBL isScaleLast
= FL2FXCONST_DBL(0.0f
);
454 INT isStartValueFound
= 0;
456 for (sfboffs
= 0; sfboffs
< sfbCnt
; sfboffs
+= sfbPerGroup
) {
459 INT currentIsSfbCount
= 0;
460 FIXP_DBL overallHrrError
= FL2FXCONST_DBL(0.0f
);
461 FIXP_DBL isRegionLoudness
= FL2FXCONST_DBL(0.0f
);
463 for (sfb
= 0; sfb
< maxSfbPerGroup
; sfb
++) {
464 if (isMask
[sfboffs
+ sfb
] == 1) {
465 if (currentIsSfbCount
== 0) {
466 startIsSfb
= sfboffs
+ sfb
;
468 if (isStartValueFound
==0) {
469 isScaleLast
= realIsScale
[sfboffs
+ sfb
];
470 isStartValueFound
= 1;
474 overallHrrError
+= hrrErr
[sfboffs
+ sfb
] >> (MAX_SFB_PER_GROUP_SF
-3);
475 isRegionLoudness
+= normSfbLoudness
[sfboffs
+ sfb
] >> MAX_SFB_PER_GROUP_SF
;
478 /* based on correlation, IS should not be used
479 * -> use it anyway, if overall error is below threshold
480 * and if local error does not exceed threshold
481 * otherwise: check if there are enough IS SFBs
484 overallHrrError
+= hrrErr
[sfboffs
+ sfb
] >> (MAX_SFB_PER_GROUP_SF
-3);
485 isRegionLoudness
+= normSfbLoudness
[sfboffs
+ sfb
] >> MAX_SFB_PER_GROUP_SF
;
487 if ( (hrrErr
[sfboffs
+ sfb
] < (isParams
->local_error_thresh
>>3)) && (overallHrrError
< (isParams
->total_error_thresh
>>MAX_SFB_PER_GROUP_SF
)) ) {
489 /* overwrite correlation based decision */
490 isMask
[sfboffs
+ sfb
] = 1;
496 /* check for large direction deviation */
498 if( fAbs(isScaleLast
-realIsScale
[sfboffs
+ sfb
]) < (isParams
->direction_deviation_thresh
>>(REAL_SCALE_SF
+LD_DATA_SHIFT
-IS_DIRECTION_DEVIATION_THRESH_SF
)) ) {
499 isScaleLast
= realIsScale
[sfboffs
+ sfb
];
502 isMask
[sfboffs
+ sfb
] = 0;
508 if (currentIsSfbCount
> 0 && (!inIsBlock
|| sfb
== maxSfbPerGroup
- 1)) {
509 /* not enough SFBs -> do not use IS */
510 if (currentIsSfbCount
< isParams
->min_is_sfbs
|| (isRegionLoudness
< isParams
->is_region_min_loudness
>>MAX_SFB_PER_GROUP_SF
)) {
511 for(j
= startIsSfb
; j
<= sfboffs
+ sfb
; j
++) {
514 isScaleLast
= FL2FXCONST_DBL(0.0f
);
515 isStartValueFound
= 0;
516 for (j
=0; j
< startIsSfb
; j
++) {
518 isScaleLast
= realIsScale
[j
];
519 isStartValueFound
= 1;
523 currentIsSfbCount
= 0;
524 overallHrrError
= FL2FXCONST_DBL(0.0f
);
525 isRegionLoudness
= FL2FXCONST_DBL(0.0f
);
532 /*****************************************************************************
534 functionname: FDKaacEnc_IntensityStereoProcessing
536 description: Intensity stereo processing tool
552 msDigest zeroed from start to sfbCnt
553 msMask zeroed from start to sfbCnt
554 mdctSpectrumRight zeroed where isBook!=0
555 sfbEnergyRight zeroed where isBook!=0
556 sfbSpreadEnRight zeroed where isBook!=0
557 sfbThresholdRight zeroed where isBook!=0
558 sfbEnergyLdDataRight FL2FXCONST_DBL(-1.0) where isBook!=0
559 sfbThresholdLdDataRight FL2FXCONST_DBL(-0.515625f) where isBook!=0
563 *****************************************************************************/
564 void FDKaacEnc_IntensityStereoProcessing(
565 FIXP_DBL
*sfbEnergyLeft
,
566 FIXP_DBL
*sfbEnergyRight
,
567 FIXP_DBL
*mdctSpectrumLeft
,
568 FIXP_DBL
*mdctSpectrumRight
,
569 FIXP_DBL
*sfbThresholdLeft
,
570 FIXP_DBL
*sfbThresholdRight
,
571 FIXP_DBL
*sfbThresholdLdDataRight
,
572 FIXP_DBL
*sfbSpreadEnLeft
,
573 FIXP_DBL
*sfbSpreadEnRight
,
574 FIXP_DBL
*sfbEnergyLdDataLeft
,
575 FIXP_DBL
*sfbEnergyLdDataRight
,
579 const INT sfbPerGroup
,
580 const INT maxSfbPerGroup
,
581 const INT
*sfbOffset
,
585 PNS_DATA
*RESTRICT pnsData
[2]
591 FIXP_DBL hrrErr
[MAX_GROUPED_SFB
];
592 FIXP_DBL normSfbLoudness
[MAX_GROUPED_SFB
];
593 FIXP_DBL realIsScale
[MAX_GROUPED_SFB
];
594 INTENSITY_PARAMETERS isParams
;
595 INT isMask
[MAX_GROUPED_SFB
];
597 FDKmemclear((void*)isBook
,sfbCnt
*sizeof(INT
));
598 FDKmemclear((void*)isMask
,sfbCnt
*sizeof(INT
));
599 FDKmemclear((void*)realIsScale
,sfbCnt
*sizeof(FIXP_DBL
));
600 FDKmemclear((void*)isScale
,sfbCnt
*sizeof(INT
));
601 FDKmemclear((void*)hrrErr
,sfbCnt
*sizeof(FIXP_DBL
));
606 FDKaacEnc_initIsParams(&isParams
);
608 /* compute / set the following values per SFB:
609 * - left/right ratio between channels
610 * - normalized loudness
611 * + loudness == average of energy in channels to 0.25
612 * + normalization: division by sum of all SFB loudnesses
613 * - isMask (is set to 0 if channels are the same or one is 0)
615 FDKaacEnc_prepareIntensityDecision(sfbEnergyLeft
,
618 sfbEnergyLdDataRight
,
631 FDKaacEnc_finalizeIntensityDecision(hrrErr
,
640 for (sfb
=0; sfb
<sfbCnt
; sfb
+=sfbPerGroup
) {
641 for (sfboffs
=0; sfboffs
<maxSfbPerGroup
; sfboffs
++) {
645 msMask
[sfb
+sfboffs
] = 0;
646 if (isMask
[sfb
+sfboffs
] == 0) {
650 if ( (sfbEnergyLeft
[sfb
+sfboffs
] < sfbThresholdLeft
[sfb
+sfboffs
])
651 &&(fMult(FL2FXCONST_DBL(1.0f
/1.5f
),sfbEnergyRight
[sfb
+sfboffs
]) > sfbThresholdRight
[sfb
+sfboffs
]) ) {
654 /* NEW: if there is a big-enough IS region, switch off PNS */
656 if(pnsData
[0]->pnsFlag
[sfb
+sfboffs
]) {
657 pnsData
[0]->pnsFlag
[sfb
+sfboffs
] = 0;
659 if(pnsData
[1]->pnsFlag
[sfb
+sfboffs
]) {
660 pnsData
[1]->pnsFlag
[sfb
+sfboffs
] = 0;
664 inv_n
= GetInvInt((sfbOffset
[sfb
+ sfboffs
+ 1] - sfbOffset
[sfb
+ sfboffs
])>>1); // scaled with 2 to compensate fMultDiv2() in subsequent loop
665 sL
= calcSfbMaxScale(mdctSpectrumLeft
,sfbOffset
[sfb
+sfboffs
],sfbOffset
[sfb
+sfboffs
+1]);
666 sR
= calcSfbMaxScale(mdctSpectrumRight
,sfbOffset
[sfb
+sfboffs
],sfbOffset
[sfb
+sfboffs
+1]);
668 lr
= FL2FXCONST_DBL(0.0f
);
669 for (j
=sfbOffset
[sfb
+sfboffs
]; j
<sfbOffset
[sfb
+sfboffs
+1]; j
++)
670 lr
+= fMultDiv2(fMultDiv2(mdctSpectrumLeft
[j
]<<sL
,mdctSpectrumRight
[j
]<<sR
),inv_n
);
673 if (lr
< FL2FXCONST_DBL(0.0f
)) {
674 /* This means OUT OF phase intensity stereo, cf. standard */
676 FIXP_DBL tmp
, d
, ed
= FL2FXCONST_DBL(0.0f
);
679 for (j
=sfbOffset
[sfb
+sfboffs
]; j
<sfbOffset
[sfb
+sfboffs
+1]; j
++) {
680 d
= ((mdctSpectrumLeft
[j
]<<s0
)>>1) - ((mdctSpectrumRight
[j
]<<s0
)>>1);
681 ed
+= fMultDiv2(d
,d
)>>(MDCT_SPEC_SF
-1);
683 msMask
[sfb
+sfboffs
] = 1;
684 tmp
= fDivNorm(sfbEnergyLeft
[sfb
+sfboffs
],ed
,&s1
);
685 s2
= (s1
) + (2*s0
) - 2 - MDCT_SPEC_SF
;
690 s2
= (s2
>>1) + 1; // +1 compensate fMultDiv2() in subsequent loop
691 s2
= fixMin(fixMax(s2
,-(DFRACT_BITS
-1)),(DFRACT_BITS
-1));
692 scale
= sqrtFixp(tmp
);
695 for (j
=sfbOffset
[sfb
+sfboffs
]; j
<sfbOffset
[sfb
+sfboffs
+1]; j
++) {
696 mdctSpectrumLeft
[j
] = (fMultDiv2(mdctSpectrumLeft
[j
],scale
) - fMultDiv2(mdctSpectrumRight
[j
],scale
)) >> s2
;
697 mdctSpectrumRight
[j
] = FL2FXCONST_DBL(0.0f
);
701 for (j
=sfbOffset
[sfb
+sfboffs
]; j
<sfbOffset
[sfb
+sfboffs
+1]; j
++) {
702 mdctSpectrumLeft
[j
] = (fMultDiv2(mdctSpectrumLeft
[j
],scale
) - fMultDiv2(mdctSpectrumRight
[j
],scale
)) << s2
;
703 mdctSpectrumRight
[j
] = FL2FXCONST_DBL(0.0f
);
708 /* This means IN phase intensity stereo, cf. standard */
710 FIXP_DBL tmp
, s
, es
= FL2FXCONST_DBL(0.0f
);
713 for (j
=sfbOffset
[sfb
+sfboffs
]; j
<sfbOffset
[sfb
+sfboffs
+1]; j
++) {
714 s
= ((mdctSpectrumLeft
[j
]<<s0
)>>1) + ((mdctSpectrumRight
[j
]<<s0
)>>1);
715 es
+= fMultDiv2(s
,s
)>>(MDCT_SPEC_SF
-1); // scaled 2*(mdctScale - s0 + 1) + MDCT_SPEC_SF
717 msMask
[sfb
+sfboffs
] = 0;
718 tmp
= fDivNorm(sfbEnergyLeft
[sfb
+sfboffs
],es
,&s1
);
719 s2
= (s1
) + (2*s0
) - 2 - MDCT_SPEC_SF
;
724 s2
= (s2
>>1) + 1; // +1 compensate fMultDiv2() in subsequent loop
725 s2
= fixMin(fixMax(s2
,-(DFRACT_BITS
-1)),(DFRACT_BITS
-1));
726 scale
= sqrtFixp(tmp
);
729 for (j
=sfbOffset
[sfb
+sfboffs
]; j
<sfbOffset
[sfb
+sfboffs
+1]; j
++) {
730 mdctSpectrumLeft
[j
] = (fMultDiv2(mdctSpectrumLeft
[j
],scale
) + fMultDiv2(mdctSpectrumRight
[j
],scale
)) >> s2
;
731 mdctSpectrumRight
[j
] = FL2FXCONST_DBL(0.0f
);
735 for (j
=sfbOffset
[sfb
+sfboffs
]; j
<sfbOffset
[sfb
+sfboffs
+1]; j
++) {
736 mdctSpectrumLeft
[j
] = (fMultDiv2(mdctSpectrumLeft
[j
],scale
) + fMultDiv2(mdctSpectrumRight
[j
],scale
)) << s2
;
737 mdctSpectrumRight
[j
] = FL2FXCONST_DBL(0.0f
);
742 isBook
[sfb
+sfboffs
] = CODE_BOOK_IS_IN_PHASE_NO
;
744 if ( realIsScale
[sfb
+sfboffs
] < FL2FXCONST_DBL(0.0f
) ) {
745 isScale
[sfb
+sfboffs
] = (INT
)(((realIsScale
[sfb
+sfboffs
]>>1)-FL2FXCONST_DBL(0.5f
/(1<<(REAL_SCALE_SF
+LD_DATA_SHIFT
+1))))>>(DFRACT_BITS
-1-REAL_SCALE_SF
-LD_DATA_SHIFT
-1)) + 1;
748 isScale
[sfb
+sfboffs
] = (INT
)(((realIsScale
[sfb
+sfboffs
]>>1)+FL2FXCONST_DBL(0.5f
/(1<<(REAL_SCALE_SF
+LD_DATA_SHIFT
+1))))>>(DFRACT_BITS
-1-REAL_SCALE_SF
-LD_DATA_SHIFT
-1));
751 sfbEnergyRight
[sfb
+sfboffs
] = FL2FXCONST_DBL(0.0f
);
752 sfbEnergyLdDataRight
[sfb
+sfboffs
] = FL2FXCONST_DBL(-1.0f
);
753 sfbThresholdRight
[sfb
+sfboffs
] = FL2FXCONST_DBL(0.0f
);
754 sfbThresholdLdDataRight
[sfb
+sfboffs
] = FL2FXCONST_DBL(-0.515625f
);
755 sfbSpreadEnRight
[sfb
+sfboffs
] = FL2FXCONST_DBL(0.0f
);