diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2019-11-11 11:38:02 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2019-11-11 11:38:02 +0100 |
commit | 0e5af65c467b2423a0b857ae3ad98c91acc1e190 (patch) | |
tree | d07f69550d8886271e44fe79c4dcfb299cafbd38 /fdk-aac/libSBRenc/src/invf_est.cpp | |
parent | efe406d9724f959c8bc2a31802559ca6d41fd897 (diff) | |
download | ODR-AudioEnc-0e5af65c467b2423a0b857ae3ad98c91acc1e190.tar.gz ODR-AudioEnc-0e5af65c467b2423a0b857ae3ad98c91acc1e190.tar.bz2 ODR-AudioEnc-0e5af65c467b2423a0b857ae3ad98c91acc1e190.zip |
Include patched FDK-AAC in the repository
The initial idea was to get the DAB+ patch into upstream, but since
that follows the android source releases, there is no place for a custom
DAB+ patch there.
So instead of having to maintain a patched fdk-aac that has to have the
same .so version as the distribution package on which it is installed,
we prefer having a separate fdk-aac-dab library to avoid collision.
At that point, there's no reason to keep fdk-aac in a separate
repository, as odr-audioenc is the only tool that needs DAB+ encoding
support. Including it here simplifies installation, and makes it
consistent with toolame-dab, also shipped in this repository.
DAB+ decoding support (needed by ODR-SourceCompanion, dablin, etisnoop,
welle.io and others) can be done using upstream FDK-AAC.
Diffstat (limited to 'fdk-aac/libSBRenc/src/invf_est.cpp')
-rw-r--r-- | fdk-aac/libSBRenc/src/invf_est.cpp | 610 |
1 files changed, 610 insertions, 0 deletions
diff --git a/fdk-aac/libSBRenc/src/invf_est.cpp b/fdk-aac/libSBRenc/src/invf_est.cpp new file mode 100644 index 0000000..53b47ac --- /dev/null +++ b/fdk-aac/libSBRenc/src/invf_est.cpp @@ -0,0 +1,610 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 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 +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#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 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, detectorParams->quantStepsSbr, + numRegionsSbr * sizeof(FIXP_DBL)); + FDKmemcpy(quantStepsOrigTmp, detectorParams->quantStepsOrig, + numRegionsOrig * sizeof(FIXP_DBL)); + + if (*prevRegionSbr < numRegionsSbr) + quantStepsSbrTmp[*prevRegionSbr] = + detectorParams->quantStepsSbr[*prevRegionSbr] + hysteresis; + if (*prevRegionSbr > 0) + quantStepsSbrTmp[*prevRegionSbr - 1] = + detectorParams->quantStepsSbr[*prevRegionSbr - 1] - hysteresis; + + if (*prevRegionOrig < numRegionsOrig) + quantStepsOrigTmp[*prevRegionOrig] = + detectorParams->quantStepsOrig[*prevRegionOrig] + hysteresis; + if (*prevRegionOrig > 0) + quantStepsOrigTmp[*prevRegionOrig - 1] = + detectorParams->quantStepsOrig[*prevRegionOrig - 1] - hysteresis; + + regionSbr = findRegion(sbrQuotaMeanFilt, quantStepsSbrTmp, numRegionsSbr); + regionOrig = findRegion(origQuotaMeanFilt, quantStepsOrigTmp, numRegionsOrig); + regionNrg = findRegion(nrg, detectorParams->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); +} |