| |
| /* ----------------------------------------------------------------------------------------------------------- |
| Software License for The Fraunhofer FDK AAC Codec Library for Android |
| |
| © Copyright 1995 - 2012 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 |
| ----------------------------------------------------------------------------------------------------------- */ |
| |
| #include "invf_est.h" |
| #include "sbr_misc.h" |
| |
| #include "genericStds.h" |
| |
| #define MAX_NUM_REGIONS 10 |
| #define SCALE_FAC_QUO 512.0f |
| #define SCALE_FAC_NRG 256.0f |
| |
| #ifndef min |
| #define min(a,b) ( a < b ? a:b) |
| #endif |
| |
| #ifndef max |
| #define max(a,b) ( a > b ? a:b) |
| #endif |
| |
| static const FIXP_DBL quantStepsSbr[4] = { 0x00400000, 0x02800000, 0x03800000, 0x04c00000 } ; /* table scaled with SCALE_FAC_QUO */ |
| static const FIXP_DBL quantStepsOrig[4] = { 0x00000000, 0x00c00000, 0x01c00000, 0x02800000 } ; /* table scaled with SCALE_FAC_QUO */ |
| static const FIXP_DBL nrgBorders[4] = { 0x0c800000, 0x0f000000, 0x11800000, 0x14000000 } ; /* table scaled with SCALE_FAC_NRG */ |
| |
| static const DETECTOR_PARAMETERS detectorParamsAAC = { |
| quantStepsSbr, |
| quantStepsOrig, |
| nrgBorders, |
| 4, /* Number of borders SBR. */ |
| 4, /* Number of borders orig. */ |
| 4, /* Number of borders Nrg. */ |
| { /* Region space. */ |
| {INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF, INVF_OFF}, /* | */ |
| {INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF, INVF_OFF}, /* | */ |
| {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF}, /* regionSbr */ |
| {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF}, /* | */ |
| {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF} /* | */ |
| },/*------------------------ regionOrig ---------------------------------*/ |
| { /* Region space transient. */ |
| {INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF}, /* | */ |
| {INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF}, /* | */ |
| {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF}, /* regionSbr */ |
| {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF}, /* | */ |
| {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF} /* | */ |
| },/*------------------------ regionOrig ---------------------------------*/ |
| {-4, -3, -2, -1, 0} /* Reduction factor of the inverse filtering for low energies.*/ |
| }; |
| |
| static const FIXP_DBL hysteresis = 0x00400000 ; /* Delta value for hysteresis. scaled with SCALE_FAC_QUO */ |
| |
| /* |
| * AAC+SBR PARAMETERS for Speech |
| *********************************/ |
| static const DETECTOR_PARAMETERS detectorParamsAACSpeech = { |
| quantStepsSbr, |
| quantStepsOrig, |
| nrgBorders, |
| 4, /* Number of borders SBR. */ |
| 4, /* Number of borders orig. */ |
| 4, /* Number of borders Nrg. */ |
| { /* Region space. */ |
| {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF}, /* | */ |
| {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF}, /* | */ |
| {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF}, /* regionSbr */ |
| {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF}, /* | */ |
| {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF} /* | */ |
| },/*------------------------ regionOrig ---------------------------------*/ |
| { /* Region space transient. */ |
| {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF}, /* | */ |
| {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF}, /* | */ |
| {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF}, /* regionSbr */ |
| {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF}, /* | */ |
| {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF} /* | */ |
| },/*------------------------ regionOrig ---------------------------------*/ |
| {-4, -3, -2, -1, 0} /* Reduction factor of the inverse filtering for low energies.*/ |
| }; |
| |
| /* |
| * Smoothing filters. |
| ************************/ |
| typedef const FIXP_DBL FIR_FILTER[5]; |
| |
| static const FIR_FILTER fir_0 = { 0x7fffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } ; |
| static const FIR_FILTER fir_1 = { 0x2aaaaa80, 0x555554ff, 0x00000000, 0x00000000, 0x00000000 } ; |
| static const FIR_FILTER fir_2 = { 0x10000000, 0x30000000, 0x40000000, 0x00000000, 0x00000000 } ; |
| static const FIR_FILTER fir_3 = { 0x077f80e8, 0x199999a0, 0x2bb3b240, 0x33333340, 0x00000000 } ; |
| static const FIR_FILTER fir_4 = { 0x04130598, 0x0ebdb000, 0x1becfa60, 0x2697a4c0, 0x2aaaaa80 } ; |
| |
| |
| static const FIR_FILTER *const fir_table[5] = { |
| &fir_0, |
| &fir_1, |
| &fir_2, |
| &fir_3, |
| &fir_4 |
| }; |
| |
| /**************************************************************************/ |
| /*! |
| \brief Calculates the values used for the detector. |
| |
| |
| \return none |
| |
| */ |
| /**************************************************************************/ |
| static void |
| calculateDetectorValues(FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the tonality values of the original. */ |
| SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ |
| FIXP_DBL *nrgVector, /*!< Energy vector. */ |
| DETECTOR_VALUES *detectorValues, /*!< pointer to DETECTOR_VALUES struct. */ |
| INT startChannel, /*!< Start channel. */ |
| INT stopChannel, /*!< Stop channel. */ |
| INT startIndex, /*!< Start index. */ |
| INT stopIndex, /*!< Stop index. */ |
| INT numberOfStrongest /*!< The number of sorted tonal components to be considered. */ |
| ) |
| { |
| INT i,temp, j; |
| |
| const FIXP_DBL* filter = *fir_table[INVF_SMOOTHING_LENGTH]; |
| FIXP_DBL origQuotaMeanStrongest, sbrQuotaMeanStrongest; |
| FIXP_DBL origQuota, sbrQuota; |
| FIXP_DBL invIndex, invChannel, invTemp; |
| FIXP_DBL quotaVecOrig[64], quotaVecSbr[64]; |
| |
| FDKmemclear(quotaVecOrig,64*sizeof(FIXP_DBL)); |
| FDKmemclear(quotaVecSbr,64*sizeof(FIXP_DBL)); |
| |
| invIndex = GetInvInt(stopIndex-startIndex); |
| invChannel = GetInvInt(stopChannel-startChannel); |
| |
| /* |
| Calculate the mean value, over the current time segment, for the original, the HFR |
| and the difference, over all channels in the current frequency range. |
| NOTE: the averaging is done on the values quota/(1 - quota + RELAXATION). |
| */ |
| |
| /* The original, the sbr signal and the total energy */ |
| detectorValues->avgNrg = FL2FXCONST_DBL(0.0f); |
| for(j=startIndex; j<stopIndex; j++) { |
| for(i=startChannel; i<stopChannel; i++) { |
| quotaVecOrig[i] += fMult(quotaMatrixOrig[j][i], invIndex); |
| |
| if(indexVector[i] != -1) |
| quotaVecSbr[i] += fMult(quotaMatrixOrig[j][indexVector[i]], invIndex); |
| } |
| detectorValues->avgNrg += fMult(nrgVector[j], invIndex); |
| } |
| |
| /* |
| Calculate the mean value, over the current frequency range, for the original, the HFR |
| and the difference. Also calculate the same mean values for the three vectors, but only |
| includeing the x strongest copmponents. |
| */ |
| |
| origQuota = FL2FXCONST_DBL(0.0f); |
| sbrQuota = FL2FXCONST_DBL(0.0f); |
| for(i=startChannel; i<stopChannel; i++) { |
| origQuota += fMultDiv2(quotaVecOrig[i], invChannel); |
| sbrQuota += fMultDiv2(quotaVecSbr[i], invChannel); |
| } |
| |
| /* |
| Calculate the mean value for the x strongest components |
| */ |
| FDKsbrEnc_Shellsort_fract(quotaVecOrig+startChannel,stopChannel-startChannel); |
| FDKsbrEnc_Shellsort_fract(quotaVecSbr+startChannel,stopChannel-startChannel); |
| |
| origQuotaMeanStrongest = FL2FXCONST_DBL(0.0f); |
| sbrQuotaMeanStrongest = FL2FXCONST_DBL(0.0f); |
| |
| temp = min(stopChannel - startChannel, numberOfStrongest); |
| invTemp = GetInvInt(temp); |
| |
| for(i=0; i<temp; i++) { |
| origQuotaMeanStrongest += fMultDiv2(quotaVecOrig[i + stopChannel - temp], invTemp); |
| sbrQuotaMeanStrongest += fMultDiv2(quotaVecSbr[i + stopChannel - temp], invTemp); |
| } |
| |
| /* |
| The value for the strongest component |
| */ |
| detectorValues->origQuotaMax = quotaVecOrig[stopChannel - 1]; |
| detectorValues->sbrQuotaMax = quotaVecSbr[stopChannel - 1]; |
| |
| /* |
| Buffer values |
| */ |
| FDKmemmove(detectorValues->origQuotaMean, detectorValues->origQuotaMean + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL)); |
| FDKmemmove(detectorValues->sbrQuotaMean, detectorValues->sbrQuotaMean + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL)); |
| FDKmemmove(detectorValues->origQuotaMeanStrongest, detectorValues->origQuotaMeanStrongest + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL)); |
| FDKmemmove(detectorValues->sbrQuotaMeanStrongest, detectorValues->sbrQuotaMeanStrongest + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL)); |
| |
| detectorValues->origQuotaMean[INVF_SMOOTHING_LENGTH] = origQuota<<1; |
| detectorValues->sbrQuotaMean[INVF_SMOOTHING_LENGTH] = sbrQuota<<1; |
| detectorValues->origQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] = origQuotaMeanStrongest<<1; |
| detectorValues->sbrQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] = sbrQuotaMeanStrongest<<1; |
| |
| /* |
| Filter values |
| */ |
| detectorValues->origQuotaMeanFilt = FL2FXCONST_DBL(0.0f); |
| detectorValues->sbrQuotaMeanFilt = FL2FXCONST_DBL(0.0f); |
| detectorValues->origQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f); |
| detectorValues->sbrQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f); |
| |
| for(i=0;i<INVF_SMOOTHING_LENGTH+1;i++) { |
| detectorValues->origQuotaMeanFilt += fMult(detectorValues->origQuotaMean[i], filter[i]); |
| detectorValues->sbrQuotaMeanFilt += fMult(detectorValues->sbrQuotaMean[i], filter[i]); |
| detectorValues->origQuotaMeanStrongestFilt += fMult(detectorValues->origQuotaMeanStrongest[i], filter[i]); |
| detectorValues->sbrQuotaMeanStrongestFilt += fMult(detectorValues->sbrQuotaMeanStrongest[i], filter[i]); |
| } |
| } |
| |
| /**************************************************************************/ |
| /*! |
| \brief Returns the region in which the input value belongs. |
| |
| |
| |
| \return region. |
| |
| */ |
| /**************************************************************************/ |
| static INT |
| findRegion(FIXP_DBL currVal, /*!< The current value. */ |
| const FIXP_DBL *borders, /*!< The border of the regions. */ |
| const INT numBorders /*!< The number of borders. */ |
| ) |
| { |
| INT i; |
| |
| if(currVal < borders[0]){ |
| return 0; |
| } |
| |
| for(i = 1; i < numBorders; i++){ |
| if( currVal >= borders[i-1] && currVal < borders[i]){ |
| return i; |
| } |
| } |
| |
| if(currVal >= borders[numBorders-1]){ |
| return numBorders; |
| } |
| |
| return 0; /* We never get here, it's just to avoid compiler warnings.*/ |
| } |
| |
| /**************************************************************************/ |
| /*! |
| \brief Makes a clever decision based on the quota vector. |
| |
| |
| \return decision on which invf mode to use |
| |
| */ |
| /**************************************************************************/ |
| static INVF_MODE |
| decisionAlgorithm(const DETECTOR_PARAMETERS *detectorParams, /*!< Struct with the detector parameters. */ |
| DETECTOR_VALUES *detectorValues, /*!< Struct with the detector values. */ |
| INT transientFlag, /*!< Flag indicating if there is a transient present.*/ |
| INT* prevRegionSbr, /*!< The previous region in which the Sbr value was. */ |
| INT* prevRegionOrig /*!< The previous region in which the Orig value was. */ |
| ) |
| { |
| INT invFiltLevel, regionSbr, regionOrig, regionNrg; |
| |
| /* |
| Current thresholds. |
| */ |
| const FIXP_DBL *quantStepsSbr = detectorParams->quantStepsSbr; |
| const FIXP_DBL *quantStepsOrig = detectorParams->quantStepsOrig; |
| const FIXP_DBL *nrgBorders = detectorParams->nrgBorders; |
| const INT numRegionsSbr = detectorParams->numRegionsSbr; |
| const INT numRegionsOrig = detectorParams->numRegionsOrig; |
| const INT numRegionsNrg = detectorParams->numRegionsNrg; |
| |
| FIXP_DBL quantStepsSbrTmp[MAX_NUM_REGIONS]; |
| FIXP_DBL quantStepsOrigTmp[MAX_NUM_REGIONS]; |
| |
| /* |
| Current detector values. |
| */ |
| FIXP_DBL origQuotaMeanFilt; |
| FIXP_DBL sbrQuotaMeanFilt; |
| FIXP_DBL nrg; |
| |
| /* 0.375 = 3.0 / 8.0; 0.31143075889 = log2(RELAXATION)/64.0; 0.625 = log(16)/64.0; 0.6875 = 44/64.0 */ |
| origQuotaMeanFilt = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(max(detectorValues->origQuotaMeanFilt,(FIXP_DBL)1)) + FL2FXCONST_DBL(0.31143075889f)))) << 0; /* scaled by 1/2^9 */ |
| sbrQuotaMeanFilt = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(max(detectorValues->sbrQuotaMeanFilt,(FIXP_DBL)1)) + FL2FXCONST_DBL(0.31143075889f)))) << 0; /* scaled by 1/2^9 */ |
| /* If energy is zero then we will get different results for different word lengths. */ |
| nrg = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(detectorValues->avgNrg+(FIXP_DBL)1) + FL2FXCONST_DBL(0.0625f) + FL2FXCONST_DBL(0.6875f)))) << 0; /* scaled by 1/2^8; 2^44 -> qmf energy scale */ |
| |
| FDKmemcpy(quantStepsSbrTmp,quantStepsSbr,numRegionsSbr*sizeof(FIXP_DBL)); |
| FDKmemcpy(quantStepsOrigTmp,quantStepsOrig,numRegionsOrig*sizeof(FIXP_DBL)); |
| |
| if(*prevRegionSbr < numRegionsSbr) |
| quantStepsSbrTmp[*prevRegionSbr] = quantStepsSbr[*prevRegionSbr] + hysteresis; |
| if(*prevRegionSbr > 0) |
| quantStepsSbrTmp[*prevRegionSbr - 1] = quantStepsSbr[*prevRegionSbr - 1] - hysteresis; |
| |
| if(*prevRegionOrig < numRegionsOrig) |
| quantStepsOrigTmp[*prevRegionOrig] = quantStepsOrig[*prevRegionOrig] + hysteresis; |
| if(*prevRegionOrig > 0) |
| quantStepsOrigTmp[*prevRegionOrig - 1] = quantStepsOrig[*prevRegionOrig - 1] - hysteresis; |
| |
| regionSbr = findRegion(sbrQuotaMeanFilt, quantStepsSbrTmp, numRegionsSbr); |
| regionOrig = findRegion(origQuotaMeanFilt, quantStepsOrigTmp, numRegionsOrig); |
| regionNrg = findRegion(nrg,nrgBorders,numRegionsNrg); |
| |
| *prevRegionSbr = regionSbr; |
| *prevRegionOrig = regionOrig; |
| |
| /* Use different settings if a transient is present*/ |
| invFiltLevel = (transientFlag == 1) ? detectorParams->regionSpaceTransient[regionSbr][regionOrig] |
| : detectorParams->regionSpace[regionSbr][regionOrig]; |
| |
| /* Compensate for low energy.*/ |
| invFiltLevel = max(invFiltLevel + detectorParams->EnergyCompFactor[regionNrg],0); |
| |
| return (INVF_MODE) (invFiltLevel); |
| } |
| |
| /**************************************************************************/ |
| /*! |
| \brief Estiamtion of the inverse filtering level required |
| in the decoder. |
| |
| A second order LPC is calculated for every filterbank channel, using |
| the covariance method. THe ratio between the energy of the predicted |
| signal and the energy of the non-predictable signal is calcualted. |
| |
| \return none. |
| |
| */ |
| /**************************************************************************/ |
| void |
| FDKsbrEnc_qmfInverseFilteringDetector(HANDLE_SBR_INV_FILT_EST hInvFilt, /*!< Handle to the SBR_INV_FILT_EST struct. */ |
| FIXP_DBL **quotaMatrix, /*!< The matrix holding the tonality values of the original. */ |
| FIXP_DBL *nrgVector, /*!< The energy vector. */ |
| SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ |
| INT startIndex, /*!< Start index. */ |
| INT stopIndex, /*!< Stop index. */ |
| INT transientFlag, /*!< Flag indicating if a transient is present or not.*/ |
| INVF_MODE* infVec /*!< Vector holding the inverse filtering levels. */ |
| ) |
| { |
| INT band; |
| |
| /* |
| * Do the inverse filtering level estimation. |
| *****************************************************/ |
| for(band = 0 ; band < hInvFilt->noDetectorBands; band++){ |
| INT startChannel = hInvFilt->freqBandTableInvFilt[band]; |
| INT stopChannel = hInvFilt->freqBandTableInvFilt[band+1]; |
| |
| |
| calculateDetectorValues( quotaMatrix, |
| indexVector, |
| nrgVector, |
| &hInvFilt->detectorValues[band], |
| startChannel, |
| stopChannel, |
| startIndex, |
| stopIndex, |
| hInvFilt->numberOfStrongest); |
| |
| infVec[band]= decisionAlgorithm( hInvFilt->detectorParams, |
| &hInvFilt->detectorValues[band], |
| transientFlag, |
| &hInvFilt->prevRegionSbr[band], |
| &hInvFilt->prevRegionOrig[band]); |
| } |
| |
| } |
| |
| |
| /**************************************************************************/ |
| /*! |
| \brief Initialize an instance of the inverse filtering level estimator. |
| |
| |
| \return errorCode, noError if successful. |
| |
| */ |
| /**************************************************************************/ |
| INT |
| FDKsbrEnc_initInvFiltDetector (HANDLE_SBR_INV_FILT_EST hInvFilt, /*!< Pointer to a handle to the SBR_INV_FILT_EST struct. */ |
| INT* freqBandTableDetector, /*!< Frequency band table for the inverse filtering. */ |
| INT numDetectorBands, /*!< Number of inverse filtering bands. */ |
| UINT useSpeechConfig /*!< Flag: adapt tuning parameters according to speech*/ |
| ) |
| { |
| INT i; |
| |
| FDKmemclear( hInvFilt,sizeof(SBR_INV_FILT_EST)); |
| |
| hInvFilt->detectorParams = (useSpeechConfig) ? &detectorParamsAACSpeech |
| : &detectorParamsAAC ; |
| |
| hInvFilt->noDetectorBandsMax = numDetectorBands; |
| |
| /* |
| Memory initialisation |
| */ |
| for(i=0;i<hInvFilt->noDetectorBandsMax;i++){ |
| FDKmemclear(&hInvFilt->detectorValues[i], sizeof(DETECTOR_VALUES)); |
| hInvFilt->prevInvfMode[i] = INVF_OFF; |
| hInvFilt->prevRegionOrig[i] = 0; |
| hInvFilt->prevRegionSbr[i] = 0; |
| } |
| |
| /* |
| Reset the inverse fltering detector. |
| */ |
| FDKsbrEnc_resetInvFiltDetector(hInvFilt, |
| freqBandTableDetector, |
| hInvFilt->noDetectorBandsMax); |
| |
| return (0); |
| } |
| |
| |
| /**************************************************************************/ |
| /*! |
| \brief resets sbr inverse filtering structure. |
| |
| |
| |
| \return errorCode, noError if successful. |
| |
| */ |
| /**************************************************************************/ |
| INT |
| FDKsbrEnc_resetInvFiltDetector(HANDLE_SBR_INV_FILT_EST hInvFilt, /*!< Handle to the SBR_INV_FILT_EST struct. */ |
| INT* freqBandTableDetector, /*!< Frequency band table for the inverse filtering. */ |
| INT numDetectorBands) /*!< Number of inverse filtering bands. */ |
| { |
| |
| hInvFilt->numberOfStrongest = 1; |
| FDKmemcpy(hInvFilt->freqBandTableInvFilt,freqBandTableDetector,(numDetectorBands+1)*sizeof(INT)); |
| hInvFilt->noDetectorBands = numDetectorBands; |
| |
| return (0); |
| } |
| |
| |