summaryrefslogtreecommitdiffstats
path: root/libAACenc/src/aacenc_tns.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libAACenc/src/aacenc_tns.cpp')
-rw-r--r--libAACenc/src/aacenc_tns.cpp1370
1 files changed, 0 insertions, 1370 deletions
diff --git a/libAACenc/src/aacenc_tns.cpp b/libAACenc/src/aacenc_tns.cpp
deleted file mode 100644
index e0f59bd..0000000
--- a/libAACenc/src/aacenc_tns.cpp
+++ /dev/null
@@ -1,1370 +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: Alex Groeschel, Tobias Chalupka
- contents/description: Temporal noise shaping
-
-******************************************************************************/
-
-#include "aacenc_tns.h"
-#include "psy_const.h"
-#include "psy_configuration.h"
-#include "tns_func.h"
-#include "aacEnc_rom.h"
-#include "aacenc_tns.h"
-
-enum {
- HIFILT = 0, /* index of higher filter */
- LOFILT = 1 /* index of lower filter */
-};
-
-
-#define FILTER_DIRECTION 0
-
-static const FIXP_DBL acfWindowLong[12+3+1] = {
- 0x7fffffff,0x7fb80000,0x7ee00000,0x7d780000,0x7b800000,0x78f80000,0x75e00000,0x72380000,
- 0x6e000000,0x69380000,0x63e00000,0x5df80000,0x57800000,0x50780000,0x48e00000,0x40b80000
-};
-
-static const FIXP_DBL acfWindowShort[4+3+1] = {
- 0x7fffffff,0x7e000000,0x78000000,0x6e000000,0x60000000,0x4e000000,0x38000000,0x1e000000
-};
-
-
-typedef struct {
- INT filterEnabled[MAX_NUM_OF_FILTERS];
- INT threshOn[MAX_NUM_OF_FILTERS]; /* min. prediction gain for using tns TABUL*/
- INT filterStartFreq[MAX_NUM_OF_FILTERS]; /* lowest freq for lpc TABUL*/
- INT tnsLimitOrder[MAX_NUM_OF_FILTERS]; /* Limit for TNS order TABUL*/
- INT tnsFilterDirection[MAX_NUM_OF_FILTERS]; /* Filtering direction, 0=up, 1=down TABUL */
- INT acfSplit[MAX_NUM_OF_FILTERS];
- FIXP_DBL tnsTimeResolution[MAX_NUM_OF_FILTERS]; /* TNS max. time resolution TABUL. Should be fract but MSVC won't compile then */
- INT seperateFiltersAllowed;
-
-} TNS_PARAMETER_TABULATED;
-
-
-typedef struct{
- INT bitRateFrom[2]; /* noneSbr=0, useSbr=1 */
- INT bitRateTo[2]; /* noneSbr=0, useSbr=1 */
- TNS_PARAMETER_TABULATED paramTab[2]; /* mono=0, stereo=1 */
-
-} TNS_INFO_TAB;
-
-#define TNS_TIMERES_SCALE (1)
-#define FL2_TIMERES_FIX(a) ( FL2FXCONST_DBL(a/(float)(1<<TNS_TIMERES_SCALE)) )
-
-static const TNS_INFO_TAB tnsInfoTab[] =
-{
- {
- { 16000, 13500},
- { 32000, 28000},
- {
- { {1, 1}, {1437, 1500}, {1400, 600}, {12, 12}, {FILTER_DIRECTION, FILTER_DIRECTION}, {3, 1}, {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.2f)}, 1 },
- { {1, 1}, {1437, 1500}, {1400, 600}, {12, 12}, {FILTER_DIRECTION, FILTER_DIRECTION}, {3, 1}, {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.2f)}, 1 }
- }
- },
- {
- { 32001, 28001},
- { 60000, 52000},
- {
- { {1, 1}, {1437, 1500}, {1400, 600}, {12, 10}, {FILTER_DIRECTION, FILTER_DIRECTION}, {3, 1}, {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, 1 },
- { {1, 1}, {1437, 1500}, {1400, 600}, {12, 10}, {FILTER_DIRECTION, FILTER_DIRECTION}, {3, 1}, {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, 1 }
- }
- },
- {
- { 60001, 52001},
- { 384000, 384000},
- {
- { {1, 1}, {1437, 1500}, {1400, 600}, {12, 8}, {FILTER_DIRECTION, FILTER_DIRECTION}, {3, 1}, {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, 1 },
- { {1, 1}, {1437, 1500}, {1400, 600}, {12, 8}, {FILTER_DIRECTION, FILTER_DIRECTION}, {3, 1}, {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, 1 }
- }
- }
-};
-
-typedef struct {
- INT samplingRate;
- SCHAR maxBands[2]; /* long=0; short=1 */
-
-} TNS_MAX_TAB_ENTRY;
-
-static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab1024[] =
-{
- { 96000, { 31, 9}},
- { 88200, { 31, 9}},
- { 64000, { 34, 10}},
- { 48000, { 40, 14}},
- { 44100, { 42, 14}},
- { 32000, { 51, 14}},
- { 24000, { 46, 14}},
- { 22050, { 46, 14}},
- { 16000, { 42, 14}},
- { 12000, { 42, 14}},
- { 11025, { 42, 14}},
- { 8000, { 39, 14}}
-};
-
-static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab960[] =
-{
- { 96000, { 31, 9}},
- { 88200, { 31, 9}},
- { 64000, { 34, 10}},
- { 48000, { 49, 14}},
- { 44100, { 49, 14}},
- { 32000, { 49, 14}},
- { 24000, { 46, 15}},
- { 22050, { 46, 14}},
- { 16000, { 46, 15}},
- { 12000, { 42, 15}},
- { 11025, { 42, 15}},
- { 8000, { 40, 15}}
-};
-
-static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab480[] =
-{
- { 48000, { 31, -1}},
- { 44100, { 32, -1}},
- { 32000, { 37, -1}},
- { 24000, { 30, -1}},
- { 22050, { 30, -1}}
-};
-
-static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab512[] =
-{
- { 48000, { 31, -1}},
- { 44100, { 32, -1}},
- { 32000, { 37, -1}},
- { 24000, { 31, -1}},
- { 22050, { 31, -1}}
-};
-
-static INT FDKaacEnc_AutoToParcor(
- FIXP_DBL *RESTRICT input,
- FIXP_DBL *RESTRICT reflCoeff,
- const INT numOfCoeff
- );
-
-static void FDKaacEnc_Parcor2Index(
- const FIXP_DBL *parcor,
- INT *RESTRICT index,
- const INT order,
- const INT bitsPerCoeff
- );
-
-static void FDKaacEnc_Index2Parcor(
- const INT *index,
- FIXP_DBL *RESTRICT parcor,
- const INT order,
- const INT bitsPerCoeff
- );
-
-static INT FDKaacEnc_ParcorToLpc(
- const FIXP_DBL *reflCoeff,
- FIXP_DBL *RESTRICT LpcCoeff,
- const INT numOfCoeff,
- FIXP_DBL *RESTRICT workBuffer
- );
-
-static void FDKaacEnc_AnalysisFilter(
- FIXP_DBL *RESTRICT signal,
- const INT numOfLines,
- const FIXP_DBL *predictorCoeff,
- const INT order,
- const INT lpcGainFactor
- );
-
-static void FDKaacEnc_CalcGaussWindow(
- FIXP_DBL *win,
- const int winSize,
- const INT samplingRate,
- const INT transformResolution,
- const FIXP_DBL timeResolution,
- const INT timeResolution_e
- );
-
-static const TNS_PARAMETER_TABULATED* FDKaacEnc_GetTnsParam(
- const INT bitRate,
- const INT channels,
- const INT sbrLd
- )
-{
- int i;
- const TNS_PARAMETER_TABULATED *tnsConfigTab = NULL;
-
- for (i = 0; i < (int) (sizeof(tnsInfoTab)/sizeof(TNS_INFO_TAB)); i++) {
- if ((bitRate >= tnsInfoTab[i].bitRateFrom[sbrLd?1:0]) &&
- bitRate <= tnsInfoTab[i].bitRateTo[sbrLd?1:0])
- {
- tnsConfigTab = &tnsInfoTab[i].paramTab[(channels==1)?0:1];
- }
- }
-
- return tnsConfigTab;
-}
-
-
-static INT getTnsMaxBands(
- const INT sampleRate,
- const INT granuleLength,
- const INT isShortBlock
- )
-{
- int i;
- INT numBands = -1;
- const TNS_MAX_TAB_ENTRY *pMaxBandsTab = NULL;
- int maxBandsTabSize = 0;
-
- switch (granuleLength) {
- case 960:
- pMaxBandsTab = tnsMaxBandsTab960;
- maxBandsTabSize = sizeof(tnsMaxBandsTab960)/sizeof(TNS_MAX_TAB_ENTRY);
- break;
- case 1024:
- pMaxBandsTab = tnsMaxBandsTab1024;
- maxBandsTabSize = sizeof(tnsMaxBandsTab1024)/sizeof(TNS_MAX_TAB_ENTRY);
- break;
- case 480:
- pMaxBandsTab = tnsMaxBandsTab480;
- maxBandsTabSize = sizeof(tnsMaxBandsTab480)/sizeof(TNS_MAX_TAB_ENTRY);
- break;
- case 512:
- pMaxBandsTab = tnsMaxBandsTab512;
- maxBandsTabSize = sizeof(tnsMaxBandsTab512)/sizeof(TNS_MAX_TAB_ENTRY);
- break;
- default:
- numBands = -1;
- }
-
- if (pMaxBandsTab!=NULL) {
- for (i=0; i<maxBandsTabSize; i++) {
- numBands = pMaxBandsTab[i].maxBands[(!isShortBlock)?0:1];
- if (sampleRate >= pMaxBandsTab[i].samplingRate) {
- break;
- }
- }
- }
-
- return numBands;
-}
-
-/***************************************************************************/
-/*!
- \brief FDKaacEnc_FreqToBandWithRounding
-
- Returns index of nearest band border
-
- \param frequency
- \param sampling frequency
- \param total number of bands
- \param pointer to table of band borders
-
- \return band border
-****************************************************************************/
-
-INT FDKaacEnc_FreqToBandWithRounding(
- const INT freq,
- const INT fs,
- const INT numOfBands,
- const INT *bandStartOffset
- )
-{
- INT lineNumber, band;
-
- /* assert(freq >= 0); */
- lineNumber = (freq*bandStartOffset[numOfBands]*4/fs+1)/2;
-
- /* freq > fs/2 */
- if (lineNumber >= bandStartOffset[numOfBands])
- return numOfBands;
-
- /* find band the line number lies in */
- for (band=0; band<numOfBands; band++) {
- if (bandStartOffset[band+1]>lineNumber) break;
- }
-
- /* round to nearest band border */
- if (lineNumber - bandStartOffset[band] >
- bandStartOffset[band+1] - lineNumber )
- {
- band++;
- }
-
- return(band);
-}
-
-
-/*****************************************************************************
-
- functionname: FDKaacEnc_InitTnsConfiguration
- description: fill TNS_CONFIG structure with sensible content
- returns:
- input: bitrate, samplerate, number of channels,
- blocktype (long or short),
- TNS Config struct (modified),
- psy config struct,
- tns active flag
- output:
-
-*****************************************************************************/
-AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitRate,
- INT sampleRate,
- INT channels,
- INT blockType,
- INT granuleLength,
- INT ldSbrPresent,
- TNS_CONFIG *tC,
- PSY_CONFIGURATION *pC,
- INT active,
- INT useTnsPeak)
-{
- int i;
- //float acfTimeRes = (blockType == SHORT_WINDOW) ? 0.125f : 0.046875f;
-
- if (channels <= 0)
- return (AAC_ENCODER_ERROR)1;
-
- /* initialize TNS filter flag, order, and coefficient resolution (in bits per coeff) */
- tC->tnsActive = (active) ? TRUE : FALSE;
- tC->maxOrder = (blockType == SHORT_WINDOW) ? 5 : 12; /* maximum: 7, 20 */
- if (bitRate < 16000)
- tC->maxOrder -= 2;
- tC->coefRes = (blockType == SHORT_WINDOW) ? 3 : 4;
-
- /* LPC stop line: highest MDCT line to be coded, but do not go beyond TNS_MAX_BANDS! */
- tC->lpcStopBand = getTnsMaxBands(sampleRate, granuleLength, (blockType == SHORT_WINDOW) ? 1 : 0);
-
- if (tC->lpcStopBand < 0) {
- return (AAC_ENCODER_ERROR)1;
- }
-
- tC->lpcStopBand = FDKmin(tC->lpcStopBand, pC->sfbActive);
- tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand];
-
- switch (granuleLength) {
- case 960:
- case 1024:
- /* TNS start line: skip lower MDCT lines to prevent artifacts due to filter mismatch */
- tC->lpcStartBand[LOFILT] = (blockType == SHORT_WINDOW) ? 0 : ((sampleRate < 18783) ? 4 : 8);
- tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]];
-
- i = tC->lpcStopBand;
- while (pC->sfbOffset[i] > (tC->lpcStartLine[LOFILT] + (tC->lpcStopLine - tC->lpcStartLine[LOFILT]) / 4)) i--;
- tC->lpcStartBand[HIFILT] = i;
- tC->lpcStartLine[HIFILT] = pC->sfbOffset[i];
-
- tC->confTab.threshOn[HIFILT] = 1437;
- tC->confTab.threshOn[LOFILT] = 1500;
-
- tC->confTab.tnsLimitOrder[HIFILT] = tC->maxOrder;
- tC->confTab.tnsLimitOrder[LOFILT] = tC->maxOrder - 7;
-
- tC->confTab.tnsFilterDirection[HIFILT] = FILTER_DIRECTION;
- tC->confTab.tnsFilterDirection[LOFILT] = FILTER_DIRECTION;
-
- tC->confTab.acfSplit[HIFILT] = -1; /* signal Merged4to2QuartersAutoCorrelation in FDKaacEnc_MergedAutoCorrelation*/
- tC->confTab.acfSplit[LOFILT] = -1; /* signal Merged4to2QuartersAutoCorrelation in FDKaacEnc_MergedAutoCorrelation */
-
- tC->confTab.filterEnabled[HIFILT] = 1;
- tC->confTab.filterEnabled[LOFILT] = 1;
- tC->confTab.seperateFiltersAllowed = 1;
-
- /* compute autocorrelation window based on maximum filter order for given block type */
- /* for (i = 0; i <= tC->maxOrder + 3; i++) {
- float acfWinTemp = acfTimeRes * i;
- acfWindow[i] = FL2FXCONST_DBL(1.0f - acfWinTemp * acfWinTemp);
- }
- */
- if (blockType == SHORT_WINDOW) {
- FDKmemcpy(tC->acfWindow[HIFILT], acfWindowShort, FDKmin(sizeof(acfWindowShort), sizeof(tC->acfWindow[HIFILT])));
- FDKmemcpy(tC->acfWindow[LOFILT], acfWindowShort, FDKmin(sizeof(acfWindowShort), sizeof(tC->acfWindow[HIFILT])));
- }
- else {
- FDKmemcpy(tC->acfWindow[HIFILT], acfWindowLong, FDKmin(sizeof(acfWindowLong), sizeof(tC->acfWindow[HIFILT])));
- FDKmemcpy(tC->acfWindow[LOFILT], acfWindowLong, FDKmin(sizeof(acfWindowLong), sizeof(tC->acfWindow[HIFILT])));
- }
- break;
- case 480:
- case 512:
- {
- const TNS_PARAMETER_TABULATED* pCfg = FDKaacEnc_GetTnsParam(bitRate, channels, ldSbrPresent);
-
- if ( pCfg != NULL ) {
- tC->lpcStartBand[HIFILT] = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[HIFILT], sampleRate, pC->sfbCnt, pC->sfbOffset);
- tC->lpcStartLine[HIFILT] = pC->sfbOffset[tC->lpcStartBand[HIFILT]];
- tC->lpcStartBand[LOFILT] = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[LOFILT], sampleRate, pC->sfbCnt, pC->sfbOffset);
- tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]];
-
- tC->confTab.threshOn[HIFILT] = pCfg->threshOn[HIFILT];
- tC->confTab.threshOn[LOFILT] = pCfg->threshOn[LOFILT];
-
- tC->confTab.tnsLimitOrder[HIFILT] = pCfg->tnsLimitOrder[HIFILT];
- tC->confTab.tnsLimitOrder[LOFILT] = pCfg->tnsLimitOrder[LOFILT];
-
- tC->confTab.tnsFilterDirection[HIFILT] = pCfg->tnsFilterDirection[HIFILT];
- tC->confTab.tnsFilterDirection[LOFILT] = pCfg->tnsFilterDirection[LOFILT];
-
- tC->confTab.acfSplit[HIFILT] = pCfg->acfSplit[HIFILT];
- tC->confTab.acfSplit[LOFILT] = pCfg->acfSplit[LOFILT];
-
- tC->confTab.filterEnabled[HIFILT] = pCfg->filterEnabled[HIFILT];
- tC->confTab.filterEnabled[LOFILT] = pCfg->filterEnabled[LOFILT];
- tC->confTab.seperateFiltersAllowed = pCfg->seperateFiltersAllowed;
-
- FDKaacEnc_CalcGaussWindow(tC->acfWindow[HIFILT], tC->maxOrder+1, sampleRate, granuleLength, pCfg->tnsTimeResolution[HIFILT], TNS_TIMERES_SCALE);
- FDKaacEnc_CalcGaussWindow(tC->acfWindow[LOFILT], tC->maxOrder+1, sampleRate, granuleLength, pCfg->tnsTimeResolution[LOFILT], TNS_TIMERES_SCALE);
- }
- else {
- tC->tnsActive = FALSE; /* no configuration available, disable tns tool */
- }
- }
- break;
- default:
- tC->tnsActive = FALSE; /* no configuration available, disable tns tool */
- }
-
- return AAC_ENC_OK;
-
-}
-
-/***************************************************************************/
-/*!
- \brief FDKaacEnc_ScaleUpSpectrum
-
- Scales up spectrum lines in a given frequency section
-
- \param scaled spectrum
- \param original spectrum
- \param frequency line to start scaling
- \param frequency line to enc scaling
-
- \return scale factor
-
-****************************************************************************/
-static inline INT FDKaacEnc_ScaleUpSpectrum(
- FIXP_DBL *dest,
- const FIXP_DBL *src,
- const INT startLine,
- const INT stopLine
- )
-{
- INT i, scale;
-
- FIXP_DBL maxVal = FL2FXCONST_DBL(0.f);
-
- /* Get highest value in given spectrum */
- for (i=startLine; i<stopLine; i++) {
- maxVal = fixMax(maxVal,fixp_abs(src[i]));
- }
- scale = CountLeadingBits(maxVal);
-
- /* Scale spectrum according to highest value */
- for (i=startLine; i<stopLine; i++) {
- dest[i] = src[i]<<scale;
- }
-
- return scale;
-}
-
-/***************************************************************************/
-/*!
- \brief FDKaacEnc_CalcAutoCorrValue
-
- Calculate autocorellation value for one lag
-
- \param pointer to spectrum
- \param start line
- \param stop line
- \param lag to be calculated
- \param scaling of the lag
-
-****************************************************************************/
-static inline FIXP_DBL FDKaacEnc_CalcAutoCorrValue(
- const FIXP_DBL *spectrum,
- const INT startLine,
- const INT stopLine,
- const INT lag,
- const INT scale
- )
-{
- int i;
- FIXP_DBL result = FL2FXCONST_DBL(0.f);
-
- if (lag==0) {
- for (i=startLine; i<stopLine; i++) {
- result += (fPow2(spectrum[i])>>scale);
- }
- }
- else {
- for (i=startLine; i<(stopLine-lag); i++) {
- result += (fMult(spectrum[i], spectrum[i+lag])>>scale);
- }
- }
-
- return result;
-}
-
-/***************************************************************************/
-/*!
- \brief FDKaacEnc_AutoCorrNormFac
-
- Autocorrelation function for 1st and 2nd half of the spectrum
-
- \param pointer to spectrum
- \param pointer to autocorrelation window
- \param filter start line
-
-****************************************************************************/
-static inline FIXP_DBL FDKaacEnc_AutoCorrNormFac(
- const FIXP_DBL value,
- const INT scale,
- INT *sc
- )
-{
- #define HLM_MIN_NRG 0.0000000037252902984619140625f /* 2^-28 */
- #define MAX_INV_NRGFAC (1.f/HLM_MIN_NRG)
-
- FIXP_DBL retValue;
- FIXP_DBL A, B;
-
- if (scale>=0) {
- A = value;
- B = FL2FXCONST_DBL(HLM_MIN_NRG)>>fixMin(DFRACT_BITS-1,scale);
- }
- else {
- A = value>>fixMin(DFRACT_BITS-1,(-scale));
- B = FL2FXCONST_DBL(HLM_MIN_NRG);
- }
-
- if (A > B) {
- int shift = 0;
- FIXP_DBL tmp = invSqrtNorm2(value,&shift);
-
- retValue = fMult(tmp,tmp);
- *sc += (2*shift);
- }
- else {
- /* MAX_INV_NRGFAC*FDKpow(2,-28) = 1/2^-28 * 2^-28 = 1.0 */
- retValue = /*FL2FXCONST_DBL(MAX_INV_NRGFAC*FDKpow(2,-28))*/ (FIXP_DBL)MAXVAL_DBL;
- *sc += scale+28;
- }
-
- return retValue;
-}
-
-static void FDKaacEnc_MergedAutoCorrelation(
- const FIXP_DBL *spectrum,
- const FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER+3+1],
- const INT lpcStartLine[MAX_NUM_OF_FILTERS],
- const INT lpcStopLine,
- const INT maxOrder,
- const INT acfSplit[MAX_NUM_OF_FILTERS],
- FIXP_DBL *_rxx1,
- FIXP_DBL *_rxx2
- )
-{
- int i, idx0, idx1, idx2, idx3, idx4, lag;
- FIXP_DBL rxx1_0, rxx2_0, rxx3_0, rxx4_0;
-
- /* buffer for temporal spectrum */
- C_ALLOC_SCRATCH_START(pSpectrum, FIXP_DBL, (1024));
-
- /* pre-initialization output */
- FDKmemclear(&_rxx1[0], sizeof(FIXP_DBL)*(maxOrder+1));
- FDKmemclear(&_rxx2[0], sizeof(FIXP_DBL)*(maxOrder+1));
-
- /* MDCT line indices separating the 1st, 2nd, 3rd, and 4th analysis quarters */
- if ( (acfSplit[LOFILT]==-1) || (acfSplit[HIFILT]==-1) ) {
- /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the spectrum */
- idx0 = lpcStartLine[LOFILT];
- i = lpcStopLine - lpcStartLine[LOFILT];
- idx1 = idx0 + i / 4;
- idx2 = idx0 + i / 2;
- idx3 = idx0 + i * 3 / 4;
- idx4 = lpcStopLine;
- }
- else {
- FDK_ASSERT(acfSplit[LOFILT]==1);
- FDK_ASSERT(acfSplit[HIFILT]==3);
- i = (lpcStopLine - lpcStartLine[HIFILT]) / 3;
- idx0 = lpcStartLine[LOFILT];
- idx1 = lpcStartLine[HIFILT];
- idx2 = idx1 + i;
- idx3 = idx2 + i;
- idx4 = lpcStopLine;
- }
-
- /* copy spectrum to temporal buffer and scale up as much as possible */
- INT sc1 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx0, idx1);
- INT sc2 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx1, idx2);
- INT sc3 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx2, idx3);
- INT sc4 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx3, idx4);
-
- /* get scaling values for summation */
- INT nsc1, nsc2, nsc3, nsc4;
- for (nsc1=1; (1<<nsc1)<(idx1-idx0); nsc1++);
- for (nsc2=1; (1<<nsc2)<(idx2-idx1); nsc2++);
- for (nsc3=1; (1<<nsc3)<(idx3-idx2); nsc3++);
- for (nsc4=1; (1<<nsc4)<(idx4-idx3); nsc4++);
-
- /* compute autocorrelation value at lag zero, i. e. energy, for each quarter */
- rxx1_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, 0, nsc1);
- rxx2_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx1, idx2, 0, nsc2);
- rxx3_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx2, idx3, 0, nsc3);
- rxx4_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx3, idx4, 0, nsc4);
-
- /* compute energy normalization factors, i. e. 1/energy (saves some divisions) */
- if (rxx1_0 != FL2FXCONST_DBL(0.f))
- {
- INT sc_fac1 = -1;
- FIXP_DBL fac1 = FDKaacEnc_AutoCorrNormFac(rxx1_0, ((-2*sc1)+nsc1), &sc_fac1);
- _rxx1[0] = scaleValue(fMult(rxx1_0,fac1),sc_fac1);
-
- for (lag = 1; lag <= maxOrder; lag++) {
- /* compute energy-normalized and windowed autocorrelation values at this lag */
- if ((3 * lag) <= maxOrder + 3) {
- FIXP_DBL x1 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1);
- _rxx1[lag] = fMult(scaleValue(fMult(x1,fac1),sc_fac1), acfWindow[LOFILT][3*lag]);
- }
- }
- }
-
- /* auto corr over upper 3/4 of spectrum */
- if ( !((rxx2_0 == FL2FXCONST_DBL(0.f)) && (rxx3_0 == FL2FXCONST_DBL(0.f)) && (rxx4_0 == FL2FXCONST_DBL(0.f))) )
- {
- FIXP_DBL fac2, fac3, fac4;
- fac2 = fac3 = fac4 = FL2FXCONST_DBL(0.f);
- INT sc_fac2, sc_fac3, sc_fac4;
- sc_fac2 = sc_fac3 = sc_fac4 = 0;
-
- if (rxx2_0!=FL2FXCONST_DBL(0.f)) {
- fac2 = FDKaacEnc_AutoCorrNormFac(rxx2_0, ((-2*sc2)+nsc2), &sc_fac2);
- sc_fac2 -= 2;
- }
- if (rxx3_0!=FL2FXCONST_DBL(0.f)) {
- fac3 = FDKaacEnc_AutoCorrNormFac(rxx3_0, ((-2*sc3)+nsc3), &sc_fac3);
- sc_fac3 -= 2;
- }
- if (rxx4_0!=FL2FXCONST_DBL(0.f)) {
- fac4 = FDKaacEnc_AutoCorrNormFac(rxx4_0, ((-2*sc4)+nsc4), &sc_fac4);
- sc_fac4 -= 2;
- }
-
- _rxx2[0] = scaleValue(fMult(rxx2_0,fac2),sc_fac2) +
- scaleValue(fMult(rxx3_0,fac3),sc_fac3) +
- scaleValue(fMult(rxx4_0,fac4),sc_fac4);
-
- for (lag = 1; lag <= maxOrder; lag++) {
- /* merge quarters 2, 3, 4 into one autocorrelation; quarter 1 stays separate */
- FIXP_DBL x2 = scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx1, idx2, lag, nsc2), fac2),sc_fac2) +
- scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx2, idx3, lag, nsc3), fac3),sc_fac3) +
- scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx3, idx4, lag, nsc4), fac4),sc_fac4);
-
- _rxx2[lag] = fMult(x2, acfWindow[HIFILT][lag]);
- }
- }
-
- C_ALLOC_SCRATCH_END(pSpectrum, FIXP_DBL, (1024));
-}
-
-
-/*****************************************************************************
- functionname: FDKaacEnc_TnsDetect
- description: do decision, if TNS shall be used or not
- returns:
- input: tns data structure (modified),
- tns config structure,
- scalefactor size and table,
- spectrum,
- subblock num, blocktype,
- sfb-wise energy.
-
-*****************************************************************************/
-INT FDKaacEnc_TnsDetect(
- TNS_DATA *tnsData,
- const TNS_CONFIG *tC,
- TNS_INFO* tnsInfo,
- INT sfbCnt,
- FIXP_DBL *spectrum,
- INT subBlockNumber,
- INT blockType
- )
-{
- /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the spectrum. */
- FIXP_DBL rxx1[TNS_MAX_ORDER+1]; /* higher part */
- FIXP_DBL rxx2[TNS_MAX_ORDER+1]; /* lower part */
- FIXP_DBL parcor_tmp[TNS_MAX_ORDER];
-
- int i;
-
- TNS_SUBBLOCK_INFO *tsbi = (blockType == SHORT_WINDOW)
- ? &tnsData->dataRaw.Short.subBlockInfo[subBlockNumber]
- : &tnsData->dataRaw.Long.subBlockInfo;
-
- tnsData->filtersMerged = FALSE;
- tsbi->tnsActive = FALSE;
- tsbi->predictionGain = 1000;
- tnsInfo->numOfFilters[subBlockNumber] = 0;
- tnsInfo->coefRes[subBlockNumber] = tC->coefRes;
- for (i = 0; i < tC->maxOrder; i++) {
- tnsInfo->coef[subBlockNumber][HIFILT][i] = tnsInfo->coef[subBlockNumber][LOFILT][i] = 0;
- }
-
- tnsInfo->length[subBlockNumber][HIFILT] = tnsInfo->length[subBlockNumber][LOFILT] = 0;
- tnsInfo->order [subBlockNumber][HIFILT] = tnsInfo->order [subBlockNumber][LOFILT] = 0;
-
- if ( (tC->tnsActive) && (tC->maxOrder>0) )
- {
- int sumSqrCoef;
-
- FDKaacEnc_MergedAutoCorrelation(
- spectrum,
- tC->acfWindow,
- tC->lpcStartLine,
- tC->lpcStopLine,
- tC->maxOrder,
- tC->confTab.acfSplit,
- rxx1,
- rxx2);
-
- /* compute higher TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */
- tsbi->predictionGain = FDKaacEnc_AutoToParcor(rxx2, parcor_tmp, tC->confTab.tnsLimitOrder[HIFILT]);
-
- /* non-linear quantization of TNS lattice coefficients with given resolution */
- FDKaacEnc_Parcor2Index(
- parcor_tmp,
- tnsInfo->coef[subBlockNumber][HIFILT],
- tC->confTab.tnsLimitOrder[HIFILT],
- tC->coefRes);
-
- /* reduce filter order by truncating trailing zeros, compute sum(abs(coefs)) */
- for (i = tC->confTab.tnsLimitOrder[HIFILT] - 1; i >= 0; i--) {
- if (tnsInfo->coef[subBlockNumber][HIFILT][i] != 0) {
- break;
- }
- }
-
- tnsInfo->order[subBlockNumber][HIFILT] = i + 1;
-
- sumSqrCoef = 0;
- for (; i >= 0; i--) {
- sumSqrCoef += tnsInfo->coef[subBlockNumber][HIFILT][i] * tnsInfo->coef[subBlockNumber][HIFILT][i];
- }
-
- tnsInfo->direction[subBlockNumber][HIFILT] = tC->confTab.tnsFilterDirection[HIFILT];
- tnsInfo->length[subBlockNumber][HIFILT] = sfbCnt - tC->lpcStartBand[HIFILT];
-
- /* disable TNS if predictionGain is less than 3dB or sumSqrCoef is too small */
- if ((tsbi->predictionGain > tC->confTab.threshOn[HIFILT]) || (sumSqrCoef > (tC->confTab.tnsLimitOrder[HIFILT]/2 + 2)))
- {
- tsbi->tnsActive = TRUE;
- tnsInfo->numOfFilters[subBlockNumber]++;
-
- /* compute second filter for lower quarter; only allowed for long windows! */
- if ( (blockType != SHORT_WINDOW) &&
- (tC->confTab.filterEnabled[LOFILT]) && (tC->confTab.seperateFiltersAllowed) )
- {
- /* compute second filter for lower frequencies */
-
- /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */
- INT predGain = FDKaacEnc_AutoToParcor(rxx1, parcor_tmp, tC->confTab.tnsLimitOrder[LOFILT]);
-
- /* non-linear quantization of TNS lattice coefficients with given resolution */
- FDKaacEnc_Parcor2Index(
- parcor_tmp,
- tnsInfo->coef[subBlockNumber][LOFILT],
- tC->confTab.tnsLimitOrder[LOFILT],
- tC->coefRes);
-
- /* reduce filter order by truncating trailing zeros, compute sum(abs(coefs)) */
- for (i = tC->confTab.tnsLimitOrder[LOFILT] - 1; i >= 0; i--) {
- if (tnsInfo->coef[subBlockNumber][LOFILT][i] != 0) {
- break;
- }
- }
- tnsInfo->order[subBlockNumber][LOFILT] = i + 1;
-
- sumSqrCoef = 0;
- for (; i >= 0; i--) {
- sumSqrCoef += tnsInfo->coef[subBlockNumber][LOFILT][i] * tnsInfo->coef[subBlockNumber][LOFILT][i];
- }
-
- tnsInfo->direction[subBlockNumber][LOFILT] = tC->confTab.tnsFilterDirection[LOFILT];
- tnsInfo->length[subBlockNumber][LOFILT] = tC->lpcStartBand[HIFILT] - tC->lpcStartBand[LOFILT];
-
- /* filter lower quarter if gain is high enough, but not if it's too high */
- if ( ( (predGain > tC->confTab.threshOn[LOFILT]) && (predGain < (16000 * tC->confTab.tnsLimitOrder[LOFILT])) )
- || ( (sumSqrCoef > 9) && (sumSqrCoef < 22 * tC->confTab.tnsLimitOrder[LOFILT]) ) )
- {
- /* compare lower to upper filter; if they are very similar, merge them */
- sumSqrCoef = 0;
- for (i = 0; i < tC->confTab.tnsLimitOrder[LOFILT]; i++) {
- sumSqrCoef += FDKabs(tnsInfo->coef[subBlockNumber][HIFILT][i] - tnsInfo->coef[subBlockNumber][LOFILT][i]);
- }
- if ( (sumSqrCoef < 2) &&
- (tnsInfo->direction[subBlockNumber][LOFILT] == tnsInfo->direction[subBlockNumber][HIFILT]) )
- {
- tnsData->filtersMerged = TRUE;
- tnsInfo->length[subBlockNumber][HIFILT] = sfbCnt - tC->lpcStartBand[LOFILT];
- for (; i < tnsInfo->order[subBlockNumber][HIFILT]; i++) {
- if (FDKabs(tnsInfo->coef[subBlockNumber][HIFILT][i]) > 1) {
- break;
- }
- }
- for (i--; i >= 0; i--) {
- if (tnsInfo->coef[subBlockNumber][HIFILT][i] != 0) {
- break;
- }
- }
- if (i < tnsInfo->order[subBlockNumber][HIFILT]) {
- tnsInfo->order[subBlockNumber][HIFILT] = i + 1;
- }
- }
- else {
- tnsInfo->numOfFilters[subBlockNumber]++;
- }
- } /* filter lower part */
- } /* second filter allowed */
- } /* if predictionGain > 1437 ... */
- } /* maxOrder > 0 && tnsActive */
-
- return 0;
-
-}
-
-
-/***************************************************************************/
-/*!
- \brief FDKaacLdEnc_TnsSync
-
- synchronize TNS parameters when TNS gain difference small (relative)
-
- \param pointer to TNS data structure (destination)
- \param pointer to TNS data structure (source)
- \param pointer to TNS config structure
- \param number of sub-block
- \param block type
-
- \return void
-****************************************************************************/
-void FDKaacEnc_TnsSync(
- TNS_DATA *tnsDataDest,
- const TNS_DATA *tnsDataSrc,
- TNS_INFO *tnsInfoDest,
- TNS_INFO *tnsInfoSrc,
- const INT blockTypeDest,
- const INT blockTypeSrc,
- const TNS_CONFIG *tC
- )
-{
- int i, w, absDiff, nWindows;
- TNS_SUBBLOCK_INFO *sbInfoDest;
- const TNS_SUBBLOCK_INFO *sbInfoSrc;
-
- /* if one channel contains short blocks and the other not, do not synchronize */
- if ( (blockTypeSrc == SHORT_WINDOW && blockTypeDest != SHORT_WINDOW) ||
- (blockTypeDest == SHORT_WINDOW && blockTypeSrc != SHORT_WINDOW) )
- {
- return;
- }
-
- if (blockTypeDest != SHORT_WINDOW) {
- sbInfoDest = &tnsDataDest->dataRaw.Long.subBlockInfo;
- sbInfoSrc = &tnsDataSrc->dataRaw.Long.subBlockInfo;
- nWindows = 1;
- } else {
- sbInfoDest = &tnsDataDest->dataRaw.Short.subBlockInfo[0];
- sbInfoSrc = &tnsDataSrc->dataRaw.Short.subBlockInfo[0];
- nWindows = 8;
- }
-
- for (w=0; w<nWindows; w++) {
- const TNS_SUBBLOCK_INFO *pSbInfoSrcW = sbInfoSrc + w;
- TNS_SUBBLOCK_INFO *pSbInfoDestW = sbInfoDest + w;
- INT doSync = 1, absDiffSum = 0;
-
- /* if TNS is active in at least one channel, check if ParCor coefficients of higher filter are similar */
- if (pSbInfoDestW->tnsActive || pSbInfoSrcW->tnsActive) {
- for (i = 0; i < tC->maxOrder; i++) {
- absDiff = FDKabs(tnsInfoDest->coef[w][HIFILT][i] - tnsInfoSrc->coef[w][HIFILT][i]);
- absDiffSum += absDiff;
- /* if coefficients diverge too much between channels, do not synchronize */
- if ((absDiff > 1) || (absDiffSum > 2)) {
- doSync = 0;
- break;
- }
- }
-
- if (doSync) {
- /* if no significant difference was detected, synchronize coefficient sets */
- if (pSbInfoSrcW->tnsActive) {
- /* no dest filter, or more dest than source filters: use one dest filter */
- if ((!pSbInfoDestW->tnsActive) ||
- ((pSbInfoDestW->tnsActive) && (tnsInfoDest->numOfFilters[w] > tnsInfoSrc->numOfFilters[w])))
- {
- pSbInfoDestW->tnsActive = tnsInfoDest->numOfFilters[w] = 1;
- }
- tnsDataDest->filtersMerged = tnsDataSrc->filtersMerged;
- tnsInfoDest->order [w][HIFILT] = tnsInfoSrc->order [w][HIFILT];
- tnsInfoDest->length [w][HIFILT] = tnsInfoSrc->length [w][HIFILT];
- tnsInfoDest->direction [w][HIFILT] = tnsInfoSrc->direction [w][HIFILT];
- tnsInfoDest->coefCompress[w][HIFILT] = tnsInfoSrc->coefCompress[w][HIFILT];
-
- for (i = 0; i < tC->maxOrder; i++) {
- tnsInfoDest->coef[w][HIFILT][i] = tnsInfoSrc->coef[w][HIFILT][i];
- }
- }
- else
- pSbInfoDestW->tnsActive = tnsInfoDest->numOfFilters[w] = 0;
- }
- }
-
- }
-}
-
-/***************************************************************************/
-/*!
- \brief FDKaacEnc_TnsEncode
-
- perform TNS encoding
-
- \param pointer to TNS info structure
- \param pointer to TNS data structure
- \param number of sfbs
- \param pointer to TNS config structure
- \param low-pass line
- \param pointer to spectrum
- \param number of sub-block
- \param block type
-
- \return ERROR STATUS
-****************************************************************************/
-INT FDKaacEnc_TnsEncode(
- TNS_INFO* tnsInfo,
- TNS_DATA* tnsData,
- const INT numOfSfb,
- const TNS_CONFIG *tC,
- const INT lowPassLine,
- FIXP_DBL* spectrum,
- const INT subBlockNumber,
- const INT blockType
- )
-{
- INT i, startLine, stopLine;
-
- if ( ( (blockType == SHORT_WINDOW) && (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber].tnsActive) )
- || ( (blockType != SHORT_WINDOW) && (!tnsData->dataRaw.Long.subBlockInfo.tnsActive) ) )
- {
- return 1;
- }
-
- startLine = (tnsData->filtersMerged) ? tC->lpcStartLine[LOFILT] : tC->lpcStartLine[HIFILT];
- stopLine = tC->lpcStopLine;
-
- for (i=0; i<tnsInfo->numOfFilters[subBlockNumber]; i++) {
-
- INT lpcGainFactor;
- FIXP_DBL LpcCoeff[TNS_MAX_ORDER];
- FIXP_DBL workBuffer[TNS_MAX_ORDER];
- FIXP_DBL parcor_tmp[TNS_MAX_ORDER];
-
- FDKaacEnc_Index2Parcor(
- tnsInfo->coef[subBlockNumber][i],
- parcor_tmp,
- tnsInfo->order[subBlockNumber][i],
- tC->coefRes);
-
- lpcGainFactor = FDKaacEnc_ParcorToLpc(
- parcor_tmp,
- LpcCoeff,
- tnsInfo->order[subBlockNumber][i],
- workBuffer);
-
- FDKaacEnc_AnalysisFilter(
- &spectrum[startLine],
- stopLine - startLine,
- LpcCoeff,
- tnsInfo->order[subBlockNumber][i],
- lpcGainFactor);
-
- /* update for second filter */
- startLine = tC->lpcStartLine[LOFILT];
- stopLine = tC->lpcStartLine[HIFILT];
- }
-
- return(0);
-
-}
-
-static void FDKaacEnc_CalcGaussWindow(
- FIXP_DBL *win,
- const int winSize,
- const INT samplingRate,
- const INT transformResolution,
- const FIXP_DBL timeResolution,
- const INT timeResolution_e
- )
-{
- #define PI_E (2)
- #define PI_M FL2FXCONST_DBL(3.1416f/(float)(1<<PI_E))
-
- #define EULER_E (2)
- #define EULER_M FL2FXCONST_DBL(2.7183/(float)(1<<EULER_E))
-
- #define COEFF_LOOP_SCALE (4)
-
- INT i, e1, e2, gaussExp_e;
- FIXP_DBL gaussExp_m;
-
- /* calc. window exponent from time resolution:
- *
- * gaussExp = PI * samplingRate * 0.001f * timeResolution / transformResolution;
- * gaussExp = -0.5f * gaussExp * gaussExp;
- */
- gaussExp_m = fMultNorm(timeResolution, fMult(PI_M, fDivNorm( (FIXP_DBL)(samplingRate), (FIXP_DBL)(LONG)(transformResolution*1000.f), &e1)), &e2);
- gaussExp_m = -fPow2Div2(gaussExp_m);
- gaussExp_e = 2*(e1+e2+timeResolution_e+PI_E);
-
- FDK_ASSERT( winSize < (1<<COEFF_LOOP_SCALE) );
-
- /* calc. window coefficients
- * win[i] = (float)exp( gaussExp * (i+0.5) * (i+0.5) );
- */
- for( i=0; i<winSize; i++) {
-
- win[i] = fPow(
- EULER_M,
- EULER_E,
- fMult(gaussExp_m, fPow2((i*FL2FXCONST_DBL(1.f/(float)(1<<COEFF_LOOP_SCALE)) + FL2FXCONST_DBL(.5f/(float)(1<<COEFF_LOOP_SCALE))))),
- gaussExp_e + 2*COEFF_LOOP_SCALE,
- &e1);
-
- win[i] = scaleValueSaturate(win[i], e1);
- }
-}
-
-
-/***************************************************************************/
-/*!
- \brief FDKaacEnc_AutoToParcor
-
- conversion autocorrelation to reflection coefficients
-
- \param pointer to input (acf)
- \param pointer to output (reflection coefficients)
- \param number of coefficients
-
- \return prediction gain
-****************************************************************************/
-static INT FDKaacEnc_AutoToParcor(
- FIXP_DBL *RESTRICT input,
- FIXP_DBL *RESTRICT reflCoeff,
- const INT numOfCoeff
- )
-{
- INT i, j, scale=0;
- FIXP_DBL tmp, parcorWorkBuffer[TNS_MAX_ORDER];
- INT predictionGain = (INT)(TNS_PREDGAIN_SCALE);
-
- FIXP_DBL *RESTRICT workBuffer = parcorWorkBuffer;
- const FIXP_DBL autoCorr_0 = input[0];
-
- if((FIXP_DBL)input[0] == FL2FXCONST_DBL(0.0)) {
- FDKmemclear(reflCoeff,numOfCoeff*sizeof(FIXP_DBL));
- return(predictionGain);
- }
-
- FDKmemcpy(workBuffer,&input[1],numOfCoeff*sizeof(FIXP_DBL));
- for(i=0; i<numOfCoeff; i++) {
- LONG sign = ((LONG)workBuffer[0] >> (DFRACT_BITS-1));
- tmp = (FIXP_DBL)((LONG)workBuffer[0]^sign);
-
- if(input[0]<tmp)
- break;
-
- tmp = (FIXP_DBL)((LONG)schur_div(tmp, input[0], FRACT_BITS)^(~sign));
- reflCoeff[i] = tmp;
-
- for(j=numOfCoeff-i-1; j>=0; j--) {
- FIXP_DBL accu1 = fMult(tmp, input[j]);
- FIXP_DBL accu2 = fMult(tmp, workBuffer[j]);
- workBuffer[j] += accu1;
- input[j] += accu2;
- }
-
- workBuffer++;
- }
-
- tmp = fMult((FIXP_DBL)((LONG)TNS_PREDGAIN_SCALE<<21), fDivNorm(fAbs(autoCorr_0), fAbs(input[0]), &scale));
- if ( fMultDiv2(autoCorr_0, input[0])<FL2FXCONST_DBL(0.0f) ) {
- tmp = -tmp;
- }
- predictionGain = (LONG)scaleValue(tmp,scale-21);
-
- return (predictionGain);
-}
-
-
-static INT FDKaacEnc_Search3(FIXP_DBL parcor)
-{
- INT i, index=0;
-
- for(i=0;i<8;i++){
- if(parcor > FDKaacEnc_tnsCoeff3Borders[i])
- index=i;
- }
- return(index-4);
-}
-
-static INT FDKaacEnc_Search4(FIXP_DBL parcor)
-{
- INT i, index=0;
-
- for(i=0;i<16;i++){
- if(parcor > FDKaacEnc_tnsCoeff4Borders[i])
- index=i;
- }
- return(index-8);
-}
-
-
-/*****************************************************************************
-
- functionname: FDKaacEnc_Parcor2Index
-
-*****************************************************************************/
-static void FDKaacEnc_Parcor2Index(
- const FIXP_DBL *parcor,
- INT *RESTRICT index,
- const INT order,
- const INT bitsPerCoeff
- )
-{
- INT i;
- for(i=0; i<order; i++) {
- if(bitsPerCoeff == 3)
- index[i] = FDKaacEnc_Search3(parcor[i]);
- else
- index[i] = FDKaacEnc_Search4(parcor[i]);
- }
-}
-
-
-/*****************************************************************************
-
- functionname: FDKaacEnc_Index2Parcor
- description: inverse quantization for reflection coefficients
- returns: -
- input: quantized values, ptr. to reflection coefficients,
- no. of coefficients, resolution
- output: reflection coefficients
-
-*****************************************************************************/
-static void FDKaacEnc_Index2Parcor(
- const INT *index,
- FIXP_DBL *RESTRICT parcor,
- const INT order,
- const INT bitsPerCoeff
- )
-{
- INT i;
- for(i=0; i<order; i++)
- parcor[i] = bitsPerCoeff == 4 ? FDKaacEnc_tnsEncCoeff4[index[i]+8] : FDKaacEnc_tnsEncCoeff3[index[i]+4];
-}
-
-
-/*****************************************************************************
-
- functionname: FDKaacEnc_ParcorToLpc
- description: conversion reflection coefficients to LPC coefficients
- returns: Gain factor
- input: reflection coefficients, no. of reflection coefficients <order>,
- ptr. to work buffer (required size: order)
- output: <order> LPC coefficients
-
-*****************************************************************************/
-static INT FDKaacEnc_ParcorToLpc(
- const FIXP_DBL *reflCoeff,
- FIXP_DBL *RESTRICT LpcCoeff,
- const INT numOfCoeff,
- FIXP_DBL *RESTRICT workBuffer
- )
-{
- INT i, j;
- INT shiftval, par2LpcShiftVal = 6; /* 6 should be enough, bec. max(numOfCoeff) = 20 */
- FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f);
-
- LpcCoeff[0] = reflCoeff[0] >> par2LpcShiftVal;
- for(i=1; i<numOfCoeff; i++) {
- for(j=0; j<i; j++) {
- workBuffer[j] = LpcCoeff[i-1-j];
- }
-
- for(j=0; j<i; j++) {
- LpcCoeff[j] += fMult(reflCoeff[i],workBuffer[j]);
- }
-
- LpcCoeff[i] = reflCoeff[i] >> par2LpcShiftVal;
- }
-
- /* normalize LpcCoeff and calc shiftfactor */
- for(i=0; i<numOfCoeff; i++) {
- maxVal = fixMax(maxVal,(FIXP_DBL)fixp_abs(LpcCoeff[i]));
- }
-
- shiftval = CountLeadingBits(maxVal);
- shiftval = (shiftval>=par2LpcShiftVal) ? par2LpcShiftVal : shiftval;
-
- for(i=0; i<numOfCoeff; i++)
- LpcCoeff[i] = LpcCoeff[i]<<shiftval;
-
- return (par2LpcShiftVal - shiftval);
-}
-
-/***************************************************************************/
-/*!
- \brief FDKaacEnc_AnalysisFilter
-
- TNS analysis filter (all-zero filter)
-
- \param pointer to signal spectrum
- \param number of lines
- \param pointer to lpc coefficients
- \param filter order
- \param lpc gain factor
-
- \return void
-****************************************************************************/
-/* Note: in-place computation possible */
-static void FDKaacEnc_AnalysisFilter(
- FIXP_DBL *RESTRICT signal,
- const INT numOfLines,
- const FIXP_DBL *predictorCoeff,
- const INT order,
- const INT lpcGainFactor
- )
-{
- FIXP_DBL statusVar[TNS_MAX_ORDER];
- INT i, j;
- const INT shift = lpcGainFactor + 1; /* +1, because fMultDiv2 */
- FIXP_DBL tmp;
-
- if (order>0) {
-
- INT idx = 0;
-
- /* keep filter coefficients twice and save memory copy operation in
- modulo state buffer */
-#if defined(ARCH_PREFER_MULT_32x16)
- FIXP_SGL coeff[2*TNS_MAX_ORDER];
- const FIXP_SGL *pCoeff;
- for(i=0;i<order;i++) {
- coeff[i] = FX_DBL2FX_SGL(predictorCoeff[i]);
- }
- FDKmemcpy(&coeff[order], coeff, order*sizeof(FIXP_SGL));
-#else
- FIXP_DBL coeff[2*TNS_MAX_ORDER];
- const FIXP_DBL *pCoeff;
- FDKmemcpy(&coeff[0], predictorCoeff, order*sizeof(FIXP_DBL));
- FDKmemcpy(&coeff[order], predictorCoeff, order*sizeof(FIXP_DBL));
-#endif
- FDKmemclear(statusVar, order*sizeof(FIXP_DBL));
-
- for(j=0; j<numOfLines; j++) {
- pCoeff = &coeff[(order-idx)];
- tmp = FL2FXCONST_DBL(0);
- for(i=0; i<order; i++) {
- tmp = fMultAddDiv2(tmp, pCoeff[i], statusVar[i]) ;
- }
-
- if(--idx<0) { idx = order-1; }
- statusVar[idx] = signal[j];
-
- FDK_ASSERT(lpcGainFactor>=0);
- signal[j] = (tmp<<shift) + signal[j];
- }
- }
-}
-
-