summaryrefslogtreecommitdiffstats
path: root/libAACenc/src/intensity.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libAACenc/src/intensity.cpp')
-rw-r--r--libAACenc/src/intensity.cpp761
1 files changed, 0 insertions, 761 deletions
diff --git a/libAACenc/src/intensity.cpp b/libAACenc/src/intensity.cpp
deleted file mode 100644
index 6d807f7..0000000
--- a/libAACenc/src/intensity.cpp
+++ /dev/null
@@ -1,761 +0,0 @@
-
-/* -----------------------------------------------------------------------------------------------------------
-Software License for The Fraunhofer FDK AAC Codec Library for Android
-
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
- All rights reserved.
-
- 1. INTRODUCTION
-The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
-the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
-This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
-
-AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
-audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
-independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
-of the MPEG specifications.
-
-Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
-may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
-individually for the purpose of encoding or decoding bit streams in products that are compliant with
-the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
-these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
-software may already be covered under those patent licenses when it is used for those licensed purposes only.
-
-Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
-are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
-applications information and documentation.
-
-2. COPYRIGHT LICENSE
-
-Redistribution and use in source and binary forms, with or without modification, are permitted without
-payment of copyright license fees provided that you satisfy the following conditions:
-
-You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
-your modifications thereto in source code form.
-
-You must retain the complete text of this software license in the documentation and/or other materials
-provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
-You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
-modifications thereto to recipients of copies in binary form.
-
-The name of Fraunhofer may not be used to endorse or promote products derived from this library without
-prior written permission.
-
-You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
-software or your modifications thereto.
-
-Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
-and the date of any change. For modified versions of the FDK AAC Codec, the term
-"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
-"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
-
-3. NO PATENT LICENSE
-
-NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
-ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
-respect to this software.
-
-You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
-by appropriate patent licenses.
-
-4. DISCLAIMER
-
-This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
-"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
-of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
-including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
-or business interruption, however caused and on any theory of liability, whether in contract, strict
-liability, or tort (including negligence), arising in any way out of the use of this software, even if
-advised of the possibility of such damage.
-
-5. CONTACT INFORMATION
-
-Fraunhofer Institute for Integrated Circuits IIS
-Attention: Audio and Multimedia Departments - FDK AAC LL
-Am Wolfsmantel 33
-91058 Erlangen, Germany
-
-www.iis.fraunhofer.de/amm
-amm-info@iis.fraunhofer.de
------------------------------------------------------------------------------------------------------------ */
-
-/******************************** MPEG Audio Encoder **************************
-
- Initial author: A. Horndasch (code originally from lwr) / Josef Hoepfl (FDK)
- contents/description: intensity stereo processing
-
-******************************************************************************/
-
-#include "intensity.h"
-#include "interface.h"
-#include "psy_configuration.h"
-#include "psy_const.h"
-#include "qc_main.h"
-#include "bit_cnt.h"
-
-/* only set an IS seed it left/right channel correlation is above IS_CORR_THRESH */
-#define IS_CORR_THRESH FL2FXCONST_DBL(0.95f)
-
-/* when expanding the IS region to more SFBs only accept an error that is
- * not more than IS_TOTAL_ERROR_THRESH overall and
- * not more than IS_LOCAL_ERROR_THRESH for the current SFB */
-#define IS_TOTAL_ERROR_THRESH FL2FXCONST_DBL(0.04f)
-#define IS_LOCAL_ERROR_THRESH FL2FXCONST_DBL(0.01f)
-
-/* the maximum allowed change of the intensity direction (unit: IS scale) - scaled with factor 0.25 - */
-#define IS_DIRECTION_DEVIATION_THRESH_SF 2
-#define IS_DIRECTION_DEVIATION_THRESH FL2FXCONST_DBL(2.0f/(1<<IS_DIRECTION_DEVIATION_THRESH_SF))
-
-/* IS regions need to have a minimal percentage of the overall loudness, e.g. 0.06 == 6% */
-#define IS_REGION_MIN_LOUDNESS FL2FXCONST_DBL(0.1f)
-
-/* only perform IS if IS_MIN_SFBS neighboring SFBs can be processed */
-#define IS_MIN_SFBS 6
-
-/* only do IS if
- * if IS_LEFT_RIGHT_RATIO_THRESH < sfbEnergyLeft[sfb]/sfbEnergyRight[sfb] < 1 / IS_LEFT_RIGHT_RATIO_THRESH
- * -> no IS if the panning angle is not far from the middle, MS will do */
-/* this is equivalent to a scale of +/-1.02914634566 */
-#define IS_LEFT_RIGHT_RATIO_THRESH FL2FXCONST_DBL(0.7f)
-
-/* scalefactor of realScale */
-#define REAL_SCALE_SF 1
-
-/* scalefactor overallLoudness */
-#define OVERALL_LOUDNESS_SF 6
-
-/* scalefactor for sum over max samples per goup */
-#define MAX_SFB_PER_GROUP_SF 6
-
-/* scalefactor for sum of mdct spectrum */
-#define MDCT_SPEC_SF 6
-
-
-typedef struct
-{
-
- FIXP_DBL corr_thresh; /*!< Only set an IS seed it left/right channel correlation is above corr_thresh */
-
- FIXP_DBL total_error_thresh; /*!< When expanding the IS region to more SFBs only accept an error that is
- not more than 'total_error_thresh' overall. */
-
- FIXP_DBL local_error_thresh; /*!< When expanding the IS region to more SFBs only accept an error that is
- not more than 'local_error_thresh' for the current SFB. */
-
- FIXP_DBL direction_deviation_thresh; /*!< The maximum allowed change of the intensity direction (unit: IS scale) */
-
- FIXP_DBL is_region_min_loudness; /*!< IS regions need to have a minimal percentage of the overall loudness, e.g. 0.06 == 6% */
-
- INT min_is_sfbs; /*!< Only perform IS if 'min_is_sfbs' neighboring SFBs can be processed */
-
- FIXP_DBL left_right_ratio_threshold; /*!< No IS if the panning angle is not far from the middle, MS will do */
-
-} INTENSITY_PARAMETERS;
-
-
-/*****************************************************************************
-
- functionname: calcSfbMaxScale
-
- description: Calc max value in scalefactor band
-
- input: *mdctSpectrum
- l1
- l2
-
- output: none
-
- returns: scalefactor
-
-*****************************************************************************/
-static INT
-calcSfbMaxScale(const FIXP_DBL *mdctSpectrum,
- const INT l1,
- const INT l2)
-{
- INT i;
- INT sfbMaxScale;
- FIXP_DBL maxSpc;
-
- maxSpc = FL2FXCONST_DBL(0.0);
- for (i=l1; i<l2; i++) {
- FIXP_DBL tmp = fixp_abs((FIXP_DBL)mdctSpectrum[i]);
- maxSpc = fixMax(maxSpc, tmp);
- }
- sfbMaxScale = (maxSpc==FL2FXCONST_DBL(0.0)) ? (DFRACT_BITS-2) : CntLeadingZeros(maxSpc)-1;
-
- return sfbMaxScale;
- }
-
-
-/*****************************************************************************
-
- functionname: FDKaacEnc_initIsParams
-
- description: Initialization of intensity parameters
-
- input: isParams
-
- output: isParams
-
- returns: none
-
-*****************************************************************************/
-static void
-FDKaacEnc_initIsParams(INTENSITY_PARAMETERS *isParams)
-{
- isParams->corr_thresh = IS_CORR_THRESH;
- isParams->total_error_thresh = IS_TOTAL_ERROR_THRESH;
- isParams->local_error_thresh = IS_LOCAL_ERROR_THRESH;
- isParams->direction_deviation_thresh = IS_DIRECTION_DEVIATION_THRESH;
- isParams->is_region_min_loudness = IS_REGION_MIN_LOUDNESS;
- isParams->min_is_sfbs = IS_MIN_SFBS;
- isParams->left_right_ratio_threshold = IS_LEFT_RIGHT_RATIO_THRESH;
-}
-
-
-/*****************************************************************************
-
- functionname: FDKaacEnc_prepareIntensityDecision
-
- description: Prepares intensity decision
-
- input: sfbEnergyLeft
- sfbEnergyRight
- sfbEnergyLdDataLeft
- sfbEnergyLdDataRight
- mdctSpectrumLeft
- sfbEnergyLdDataRight
- isParams
-
- output: hrrErr scale: none
- isMask scale: none
- realScale scale: LD_DATA_SHIFT + REAL_SCALE_SF
- normSfbLoudness scale: none
-
- returns: none
-
-*****************************************************************************/
-static void
-FDKaacEnc_prepareIntensityDecision(const FIXP_DBL *sfbEnergyLeft,
- const FIXP_DBL *sfbEnergyRight,
- const FIXP_DBL *sfbEnergyLdDataLeft,
- const FIXP_DBL *sfbEnergyLdDataRight,
- const FIXP_DBL *mdctSpectrumLeft,
- const FIXP_DBL *mdctSpectrumRight,
- const INTENSITY_PARAMETERS *isParams,
- FIXP_DBL *hrrErr,
- INT *isMask,
- FIXP_DBL *realScale,
- FIXP_DBL *normSfbLoudness,
- const INT sfbCnt,
- const INT sfbPerGroup,
- const INT maxSfbPerGroup,
- const INT *sfbOffset)
-{
- INT j,sfb,sfboffs;
- INT grpCounter;
-
- /* temporary variables to compute loudness */
- FIXP_DBL overallLoudness[MAX_NO_OF_GROUPS];
-
- /* temporary variables to compute correlation */
- FIXP_DBL channelCorr[MAX_GROUPED_SFB];
- FIXP_DBL ml, mr;
- FIXP_DBL prod_lr;
- FIXP_DBL square_l, square_r;
- FIXP_DBL tmp_l, tmp_r;
- FIXP_DBL inv_n;
-
- FDKmemclear(channelCorr, MAX_GROUPED_SFB*sizeof(FIXP_DBL));
- FDKmemclear(normSfbLoudness, MAX_GROUPED_SFB*sizeof(FIXP_DBL));
- FDKmemclear(overallLoudness, MAX_NO_OF_GROUPS*sizeof(FIXP_DBL));
- FDKmemclear(realScale, MAX_GROUPED_SFB*sizeof(FIXP_DBL));
-
- for (grpCounter = 0, sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup, grpCounter++) {
- overallLoudness[grpCounter] = FL2FXCONST_DBL(0.0f);
- for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
- INT sL,sR,s;
- FIXP_DBL isValue = sfbEnergyLdDataLeft[sfb+sfboffs]-sfbEnergyLdDataRight[sfb+sfboffs];
-
- /* delimitate intensity scale value to representable range */
- 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));
-
- sL = fixMax(0,(CntLeadingZeros(sfbEnergyLeft[sfb + sfboffs])-1));
- sR = fixMax(0,(CntLeadingZeros(sfbEnergyRight[sfb + sfboffs])-1));
- s = (fixMin(sL,sR)>>2)<<2;
- normSfbLoudness[sfb + sfboffs] = sqrtFixp(sqrtFixp(((sfbEnergyLeft[sfb + sfboffs]<<s) >> 1) + ((sfbEnergyRight[sfb + sfboffs]<<s) >> 1))) >> (s>>2);
-
- overallLoudness[grpCounter] += normSfbLoudness[sfb + sfboffs] >> OVERALL_LOUDNESS_SF;
- /* don't do intensity if
- * - panning angle is too close to the middle or
- * - one channel is non-existent or
- * - if it is dual mono */
- if( (sfbEnergyLeft[sfb + sfboffs] >= fMult(isParams->left_right_ratio_threshold,sfbEnergyRight[sfb + sfboffs]))
- && (fMult(isParams->left_right_ratio_threshold,sfbEnergyLeft[sfb + sfboffs]) <= sfbEnergyRight[sfb + sfboffs]) ) {
-
- /* this will prevent post processing from considering this SFB for merging */
- hrrErr[sfb + sfboffs] = FL2FXCONST_DBL(1.0/8.0);
- }
- }
- }
-
- for (grpCounter = 0, sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup, grpCounter++) {
- INT invOverallLoudnessSF;
- FIXP_DBL invOverallLoudness;
-
- if (overallLoudness[grpCounter] == FL2FXCONST_DBL(0.0)) {
- invOverallLoudness = FL2FXCONST_DBL(0.0);
- invOverallLoudnessSF = 0;
- }
- else {
- invOverallLoudness = fDivNorm((FIXP_DBL)MAXVAL_DBL, overallLoudness[grpCounter],&invOverallLoudnessSF);
- invOverallLoudnessSF = invOverallLoudnessSF - OVERALL_LOUDNESS_SF + 1; /* +1: compensate fMultDiv2() in subsequent loop */
- }
- invOverallLoudnessSF = fixMin(fixMax(invOverallLoudnessSF,-(DFRACT_BITS-1)),DFRACT_BITS-1);
-
- for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
- FIXP_DBL tmp;
-
- tmp = fMultDiv2((normSfbLoudness[sfb + sfboffs]>>OVERALL_LOUDNESS_SF)<<OVERALL_LOUDNESS_SF,invOverallLoudness);
-
- normSfbLoudness[sfb + sfboffs] = scaleValue(tmp, invOverallLoudnessSF);
-
- channelCorr[sfb + sfboffs] = FL2FXCONST_DBL(0.0f);
-
- FDK_ASSERT(50 >= 49);
- /* max width of scalefactorband is 96; width's are always even */
- /* inv_n is scaled with factor 2 to compensate fMultDiv2() in subsequent loops */
- inv_n = GetInvInt((sfbOffset[sfb + sfboffs + 1] - sfbOffset[sfb + sfboffs])>>1);
-
- if (inv_n > FL2FXCONST_DBL(0.0f)) {
- INT s,sL,sR;
-
- /* correlation := Pearson's product-moment coefficient */
- /* compute correlation between channels and check if it is over threshold */
- ml = FL2FXCONST_DBL(0.0f);
- mr = FL2FXCONST_DBL(0.0f);
- prod_lr = FL2FXCONST_DBL(0.0f);
- square_l = FL2FXCONST_DBL(0.0f);
- square_r = FL2FXCONST_DBL(0.0f);
-
- sL = calcSfbMaxScale(mdctSpectrumLeft,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]);
- sR = calcSfbMaxScale(mdctSpectrumRight,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]);
- s = fixMin(sL,sR);
-
- for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; j++) {
- ml += fMultDiv2((mdctSpectrumLeft[j] << s),inv_n); // scaled with mdctScale - s + inv_n
- mr += fMultDiv2((mdctSpectrumRight[j] << s),inv_n); // scaled with mdctScale - s + inv_n
- }
- ml = fMultDiv2(ml,inv_n); // scaled with mdctScale - s + inv_n
- mr = fMultDiv2(mr,inv_n); // scaled with mdctScale - s + inv_n
-
- for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; j++) {
- tmp_l = fMultDiv2((mdctSpectrumLeft[j] << s),inv_n) - ml; // scaled with mdctScale - s + inv_n
- tmp_r = fMultDiv2((mdctSpectrumRight[j] << s),inv_n) - mr; // scaled with mdctScale - s + inv_n
-
- prod_lr += fMultDiv2(tmp_l,tmp_r); // scaled with 2*(mdctScale - s + inv_n) + 1
- square_l += fPow2Div2(tmp_l); // scaled with 2*(mdctScale - s + inv_n) + 1
- square_r += fPow2Div2(tmp_r); // scaled with 2*(mdctScale - s + inv_n) + 1
- }
- prod_lr = prod_lr << 1; // scaled with 2*(mdctScale - s + inv_n)
- square_l = square_l << 1; // scaled with 2*(mdctScale - s + inv_n)
- square_r = square_r << 1; // scaled with 2*(mdctScale - s + inv_n)
-
- if (square_l > FL2FXCONST_DBL(0.0f) && square_r > FL2FXCONST_DBL(0.0f)) {
- INT channelCorrSF = 0;
-
- /* local scaling of square_l and square_r is compensated after sqrt calculation */
- sL = fixMax(0,(CntLeadingZeros(square_l)-1));
- sR = fixMax(0,(CntLeadingZeros(square_r)-1));
- s = ((sL + sR)>>1)<<1;
- sL = fixMin(sL,s);
- sR = s-sL;
- tmp = fMult(square_l<<sL,square_r<<sR);
- tmp = sqrtFixp(tmp);
-
- FDK_ASSERT(tmp > FL2FXCONST_DBL(0.0f));
-
- /* numerator and denominator have the same scaling */
- if (prod_lr < FL2FXCONST_DBL(0.0f) ) {
- channelCorr[sfb + sfboffs] = -(fDivNorm(-prod_lr,tmp,&channelCorrSF));
-
- }
- else {
- channelCorr[sfb + sfboffs] = (fDivNorm( prod_lr,tmp,&channelCorrSF));
- }
- channelCorrSF = fixMin(fixMax(( channelCorrSF + ((sL+sR)>>1)),-(DFRACT_BITS-1)),DFRACT_BITS-1);
-
- if (channelCorrSF < 0) {
- channelCorr[sfb + sfboffs] = channelCorr[sfb + sfboffs] >> (-channelCorrSF);
- }
- else {
- /* avoid overflows due to limited computational accuracy */
- if ( fAbs(channelCorr[sfb + sfboffs]) > (((FIXP_DBL)MAXVAL_DBL)>>channelCorrSF) ) {
- if (channelCorr[sfb + sfboffs] < FL2FXCONST_DBL(0.0f))
- channelCorr[sfb + sfboffs] = -(FIXP_DBL) MAXVAL_DBL;
- else
- channelCorr[sfb + sfboffs] = (FIXP_DBL) MAXVAL_DBL;
- }
- else {
- channelCorr[sfb + sfboffs] = channelCorr[sfb + sfboffs] << channelCorrSF;
- }
- }
- }
- }
-
- /* for post processing: hrrErr is the error in terms of (too little) correlation
- * weighted with the loudness of the SFB; SFBs with small hrrErr can be merged */
- if (hrrErr[sfb + sfboffs] == FL2FXCONST_DBL(1.0/8.0)) {
- continue;
- }
-
- hrrErr[sfb + sfboffs] = fMultDiv2((FL2FXCONST_DBL(0.25f)-(channelCorr[sfb + sfboffs]>>2)),normSfbLoudness[sfb + sfboffs]);
-
- /* set IS mask/vector to 1, if correlation is high enough */
- if (fAbs(channelCorr[sfb + sfboffs]) >= isParams->corr_thresh) {
- isMask[sfb + sfboffs] = 1;
- }
- }
- }
-}
-
-
-/*****************************************************************************
-
- functionname: FDKaacEnc_finalizeIntensityDecision
-
- description: Finalizes intensity decision
-
- input: isParams scale: none
- hrrErr scale: none
- realIsScale scale: LD_DATA_SHIFT + REAL_SCALE_SF
- normSfbLoudness scale: none
-
- output: isMask scale: none
-
- returns: none
-
-*****************************************************************************/
-static void
-FDKaacEnc_finalizeIntensityDecision(const FIXP_DBL *hrrErr,
- INT *isMask,
- const FIXP_DBL *realIsScale,
- const FIXP_DBL *normSfbLoudness,
- const INTENSITY_PARAMETERS *isParams,
- const INT sfbCnt,
- const INT sfbPerGroup,
- const INT maxSfbPerGroup)
-{
- INT sfb,sfboffs, j;
- FIXP_DBL isScaleLast = FL2FXCONST_DBL(0.0f);
- INT isStartValueFound = 0;
-
- for (sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup) {
- INT startIsSfb = 0;
- INT inIsBlock = 0;
- INT currentIsSfbCount = 0;
- FIXP_DBL overallHrrError = FL2FXCONST_DBL(0.0f);
- FIXP_DBL isRegionLoudness = FL2FXCONST_DBL(0.0f);
-
- for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
- if (isMask[sfboffs + sfb] == 1) {
- if (currentIsSfbCount == 0) {
- startIsSfb = sfboffs + sfb;
- }
- if (isStartValueFound==0) {
- isScaleLast = realIsScale[sfboffs + sfb];
- isStartValueFound = 1;
- }
- inIsBlock = 1;
- currentIsSfbCount++;
- overallHrrError += hrrErr[sfboffs + sfb] >> (MAX_SFB_PER_GROUP_SF-3);
- isRegionLoudness += normSfbLoudness[sfboffs + sfb] >> MAX_SFB_PER_GROUP_SF;
- }
- else {
- /* based on correlation, IS should not be used
- * -> use it anyway, if overall error is below threshold
- * and if local error does not exceed threshold
- * otherwise: check if there are enough IS SFBs
- */
- if (inIsBlock) {
- overallHrrError += hrrErr[sfboffs + sfb] >> (MAX_SFB_PER_GROUP_SF-3);
- isRegionLoudness += normSfbLoudness[sfboffs + sfb] >> MAX_SFB_PER_GROUP_SF;
-
- if ( (hrrErr[sfboffs + sfb] < (isParams->local_error_thresh>>3)) && (overallHrrError < (isParams->total_error_thresh>>MAX_SFB_PER_GROUP_SF)) ) {
- currentIsSfbCount++;
- /* overwrite correlation based decision */
- isMask[sfboffs + sfb] = 1;
- } else {
- inIsBlock = 0;
- }
- }
- }
- /* check for large direction deviation */
- if (inIsBlock) {
- if( fAbs(isScaleLast-realIsScale[sfboffs + sfb]) < (isParams->direction_deviation_thresh>>(REAL_SCALE_SF+LD_DATA_SHIFT-IS_DIRECTION_DEVIATION_THRESH_SF)) ) {
- isScaleLast = realIsScale[sfboffs + sfb];
- }
- else{
- isMask[sfboffs + sfb] = 0;
- inIsBlock = 0;
- currentIsSfbCount--;
- }
- }
-
- if (currentIsSfbCount > 0 && (!inIsBlock || sfb == maxSfbPerGroup - 1)) {
- /* not enough SFBs -> do not use IS */
- if (currentIsSfbCount < isParams->min_is_sfbs || (isRegionLoudness < isParams->is_region_min_loudness>>MAX_SFB_PER_GROUP_SF)) {
- for(j = startIsSfb; j <= sfboffs + sfb; j++) {
- isMask[j] = 0;
- }
- isScaleLast = FL2FXCONST_DBL(0.0f);
- isStartValueFound = 0;
- for (j=0; j < startIsSfb; j++) {
- if (isMask[j]!=0) {
- isScaleLast = realIsScale[j];
- isStartValueFound = 1;
- }
- }
- }
- currentIsSfbCount = 0;
- overallHrrError = FL2FXCONST_DBL(0.0f);
- isRegionLoudness = FL2FXCONST_DBL(0.0f);
- }
- }
- }
-}
-
-
-/*****************************************************************************
-
- functionname: FDKaacEnc_IntensityStereoProcessing
-
- description: Intensity stereo processing tool
-
- input: sfbEnergyLeft
- sfbEnergyRight
- mdctSpectrumLeft
- mdctSpectrumRight
- sfbThresholdLeft
- sfbThresholdRight
- sfbSpreadEnLeft
- sfbSpreadEnRight
- sfbEnergyLdDataLeft
- sfbEnergyLdDataRight
-
- output: isBook
- isScale
- pnsData->pnsFlag
- msDigest zeroed from start to sfbCnt
- msMask zeroed from start to sfbCnt
- mdctSpectrumRight zeroed where isBook!=0
- sfbEnergyRight zeroed where isBook!=0
- sfbSpreadEnRight zeroed where isBook!=0
- sfbThresholdRight zeroed where isBook!=0
- sfbEnergyLdDataRight FL2FXCONST_DBL(-1.0) where isBook!=0
- sfbThresholdLdDataRight FL2FXCONST_DBL(-0.515625f) where isBook!=0
-
- returns: none
-
-*****************************************************************************/
-void FDKaacEnc_IntensityStereoProcessing(
- FIXP_DBL *sfbEnergyLeft,
- FIXP_DBL *sfbEnergyRight,
- FIXP_DBL *mdctSpectrumLeft,
- FIXP_DBL *mdctSpectrumRight,
- FIXP_DBL *sfbThresholdLeft,
- FIXP_DBL *sfbThresholdRight,
- FIXP_DBL *sfbThresholdLdDataRight,
- FIXP_DBL *sfbSpreadEnLeft,
- FIXP_DBL *sfbSpreadEnRight,
- FIXP_DBL *sfbEnergyLdDataLeft,
- FIXP_DBL *sfbEnergyLdDataRight,
- INT *msDigest,
- INT *msMask,
- const INT sfbCnt,
- const INT sfbPerGroup,
- const INT maxSfbPerGroup,
- const INT *sfbOffset,
- const INT allowIS,
- INT *isBook,
- INT *isScale,
- PNS_DATA *RESTRICT pnsData[2]
- )
-{
- INT sfb,sfboffs, j;
- FIXP_DBL scale;
- FIXP_DBL lr;
- FIXP_DBL hrrErr[MAX_GROUPED_SFB];
- FIXP_DBL normSfbLoudness[MAX_GROUPED_SFB];
- FIXP_DBL realIsScale[MAX_GROUPED_SFB];
- INTENSITY_PARAMETERS isParams;
- INT isMask[MAX_GROUPED_SFB];
-
- FDKmemclear((void*)isBook,sfbCnt*sizeof(INT));
- FDKmemclear((void*)isMask,sfbCnt*sizeof(INT));
- FDKmemclear((void*)realIsScale,sfbCnt*sizeof(FIXP_DBL));
- FDKmemclear((void*)isScale,sfbCnt*sizeof(INT));
- FDKmemclear((void*)hrrErr,sfbCnt*sizeof(FIXP_DBL));
-
- if (!allowIS)
- return;
-
- FDKaacEnc_initIsParams(&isParams);
-
- /* compute / set the following values per SFB:
- * - left/right ratio between channels
- * - normalized loudness
- * + loudness == average of energy in channels to 0.25
- * + normalization: division by sum of all SFB loudnesses
- * - isMask (is set to 0 if channels are the same or one is 0)
- */
- FDKaacEnc_prepareIntensityDecision(sfbEnergyLeft,
- sfbEnergyRight,
- sfbEnergyLdDataLeft,
- sfbEnergyLdDataRight,
- mdctSpectrumLeft,
- mdctSpectrumRight,
- &isParams,
- hrrErr,
- isMask,
- realIsScale,
- normSfbLoudness,
- sfbCnt,
- sfbPerGroup,
- maxSfbPerGroup,
- sfbOffset);
-
- FDKaacEnc_finalizeIntensityDecision(hrrErr,
- isMask,
- realIsScale,
- normSfbLoudness,
- &isParams,
- sfbCnt,
- sfbPerGroup,
- maxSfbPerGroup);
-
- for (sfb=0; sfb<sfbCnt; sfb+=sfbPerGroup) {
- for (sfboffs=0; sfboffs<maxSfbPerGroup; sfboffs++) {
- INT sL, sR;
- FIXP_DBL inv_n;
-
- msMask[sfb+sfboffs] = 0;
- if (isMask[sfb+sfboffs] == 0) {
- continue;
- }
-
- if ( (sfbEnergyLeft[sfb+sfboffs] < sfbThresholdLeft[sfb+sfboffs])
- &&(fMult(FL2FXCONST_DBL(1.0f/1.5f),sfbEnergyRight[sfb+sfboffs]) > sfbThresholdRight[sfb+sfboffs]) ) {
- continue;
- }
- /* NEW: if there is a big-enough IS region, switch off PNS */
- if (pnsData[0]) {
- if(pnsData[0]->pnsFlag[sfb+sfboffs]) {
- pnsData[0]->pnsFlag[sfb+sfboffs] = 0;
- }
- if(pnsData[1]->pnsFlag[sfb+sfboffs]) {
- pnsData[1]->pnsFlag[sfb+sfboffs] = 0;
- }
- }
-
- inv_n = GetInvInt((sfbOffset[sfb + sfboffs + 1] - sfbOffset[sfb + sfboffs])>>1); // scaled with 2 to compensate fMultDiv2() in subsequent loop
- sL = calcSfbMaxScale(mdctSpectrumLeft,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]);
- sR = calcSfbMaxScale(mdctSpectrumRight,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]);
-
- lr = FL2FXCONST_DBL(0.0f);
- for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++)
- lr += fMultDiv2(fMultDiv2(mdctSpectrumLeft[j]<<sL,mdctSpectrumRight[j]<<sR),inv_n);
- lr = lr<<1;
-
- if (lr < FL2FXCONST_DBL(0.0f)) {
- /* This means OUT OF phase intensity stereo, cf. standard */
- INT s0, s1, s2;
- FIXP_DBL tmp, d, ed = FL2FXCONST_DBL(0.0f);
-
- s0 = fixMin(sL,sR);
- for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
- d = ((mdctSpectrumLeft[j]<<s0)>>1) - ((mdctSpectrumRight[j]<<s0)>>1);
- ed += fMultDiv2(d,d)>>(MDCT_SPEC_SF-1);
- }
- msMask[sfb+sfboffs] = 1;
- tmp = fDivNorm(sfbEnergyLeft[sfb+sfboffs],ed,&s1);
- s2 = (s1) + (2*s0) - 2 - MDCT_SPEC_SF;
- if (s2 & 1) {
- tmp = tmp>>1;
- s2 = s2+1;
- }
- s2 = (s2>>1) + 1; // +1 compensate fMultDiv2() in subsequent loop
- s2 = fixMin(fixMax(s2,-(DFRACT_BITS-1)),(DFRACT_BITS-1));
- scale = sqrtFixp(tmp);
- if (s2 < 0) {
- s2 = -s2;
- for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
- mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j],scale) - fMultDiv2(mdctSpectrumRight[j],scale)) >> s2;
- mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f);
- }
- }
- else {
- for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
- mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j],scale) - fMultDiv2(mdctSpectrumRight[j],scale)) << s2;
- mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f);
- }
- }
- }
- else {
- /* This means IN phase intensity stereo, cf. standard */
- INT s0,s1,s2;
- FIXP_DBL tmp, s, es = FL2FXCONST_DBL(0.0f);
-
- s0 = fixMin(sL,sR);
- for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
- s = ((mdctSpectrumLeft[j]<<s0)>>1) + ((mdctSpectrumRight[j]<<s0)>>1);
- es += fMultDiv2(s,s)>>(MDCT_SPEC_SF-1); // scaled 2*(mdctScale - s0 + 1) + MDCT_SPEC_SF
- }
- msMask[sfb+sfboffs] = 0;
- tmp = fDivNorm(sfbEnergyLeft[sfb+sfboffs],es,&s1);
- s2 = (s1) + (2*s0) - 2 - MDCT_SPEC_SF;
- if (s2 & 1) {
- tmp = tmp>>1;
- s2 = s2 + 1;
- }
- s2 = (s2>>1) + 1; // +1 compensate fMultDiv2() in subsequent loop
- s2 = fixMin(fixMax(s2,-(DFRACT_BITS-1)),(DFRACT_BITS-1));
- scale = sqrtFixp(tmp);
- if (s2 < 0) {
- s2 = -s2;
- for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
- mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j],scale) + fMultDiv2(mdctSpectrumRight[j],scale)) >> s2;
- mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f);
- }
- }
- else {
- for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
- mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j],scale) + fMultDiv2(mdctSpectrumRight[j],scale)) << s2;
- mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f);
- }
- }
- }
-
- isBook[sfb+sfboffs] = CODE_BOOK_IS_IN_PHASE_NO;
-
- if ( realIsScale[sfb+sfboffs] < FL2FXCONST_DBL(0.0f) ) {
- 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;
- }
- else {
- 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));
- }
-
- sfbEnergyRight[sfb+sfboffs] = FL2FXCONST_DBL(0.0f);
- sfbEnergyLdDataRight[sfb+sfboffs] = FL2FXCONST_DBL(-1.0f);
- sfbThresholdRight[sfb+sfboffs] = FL2FXCONST_DBL(0.0f);
- sfbThresholdLdDataRight[sfb+sfboffs] = FL2FXCONST_DBL(-0.515625f);
- sfbSpreadEnRight[sfb+sfboffs] = FL2FXCONST_DBL(0.0f);
-
- *msDigest = MS_SOME;
- }
- }
-}
-