aboutsummaryrefslogtreecommitdiffstats
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.cpp102
1 files changed, 47 insertions, 55 deletions
diff --git a/libAACenc/src/aacenc_tns.cpp b/libAACenc/src/aacenc_tns.cpp
index 85aea65..9a07e8f 100644
--- a/libAACenc/src/aacenc_tns.cpp
+++ b/libAACenc/src/aacenc_tns.cpp
@@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@@ -95,13 +95,7 @@ amm-info@iis.fraunhofer.de
#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
+#define FILTER_DIRECTION 0 /* 0 = up, 1 = down */
static const FIXP_DBL acfWindowLong[12+3+1] = {
0x7fffffff,0x7fb80000,0x7ee00000,0x7d780000,0x7b800000,0x78f80000,0x75e00000,0x72380000,
@@ -112,20 +106,6 @@ 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 */
@@ -373,6 +353,7 @@ AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitRate,
INT channels,
INT blockType,
INT granuleLength,
+ INT isLowDelay,
INT ldSbrPresent,
TNS_CONFIG *tC,
PSY_CONFIGURATION *pC,
@@ -385,6 +366,8 @@ AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitRate,
if (channels <= 0)
return (AAC_ENCODER_ERROR)1;
+ tC->isLowDelay = isLowDelay;
+
/* 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 */
@@ -450,27 +433,14 @@ AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitRate,
const TNS_PARAMETER_TABULATED* pCfg = FDKaacEnc_GetTnsParam(bitRate, channels, ldSbrPresent);
if ( pCfg != NULL ) {
+
+ FDKmemcpy(&(tC->confTab), pCfg, sizeof(tC->confTab));
+
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);
}
@@ -614,6 +584,7 @@ static inline FIXP_DBL FDKaacEnc_AutoCorrNormFac(
static void FDKaacEnc_MergedAutoCorrelation(
const FIXP_DBL *spectrum,
+ const INT isLowDelay,
const FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER+3+1],
const INT lpcStartLine[MAX_NUM_OF_FILTERS],
const INT lpcStopLine,
@@ -633,6 +604,8 @@ static void FDKaacEnc_MergedAutoCorrelation(
FDKmemclear(&_rxx1[0], sizeof(FIXP_DBL)*(maxOrder+1));
FDKmemclear(&_rxx2[0], sizeof(FIXP_DBL)*(maxOrder+1));
+ idx0 = idx1 = idx2 = idx3 = idx4 = 0;
+
/* 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 */
@@ -676,17 +649,27 @@ static void FDKaacEnc_MergedAutoCorrelation(
/* 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);
+ 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);
+ if (isLowDelay)
+ {
for (lag = 1; lag <= maxOrder; lag++) {
/* compute energy-normalized and windowed autocorrelation values at this lag */
+ FIXP_DBL x1 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1);
+ _rxx1[lag] = fMult(scaleValue(fMult(x1,fac1),sc_fac1), acfWindow[LOFILT][lag]);
+ }
+ }
+ else
+ {
+ for (lag = 1; lag <= maxOrder; 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 */
@@ -762,8 +745,12 @@ INT FDKaacEnc_TnsDetect(
: &tnsData->dataRaw.Long.subBlockInfo;
tnsData->filtersMerged = FALSE;
- tsbi->tnsActive = FALSE;
- tsbi->predictionGain = 1000;
+
+ tsbi->tnsActive[HIFILT] = FALSE;
+ tsbi->predictionGain[HIFILT] = 1000;
+ tsbi->tnsActive[LOFILT] = FALSE;
+ tsbi->predictionGain[LOFILT] = 1000;
+
tnsInfo->numOfFilters[subBlockNumber] = 0;
tnsInfo->coefRes[subBlockNumber] = tC->coefRes;
for (i = 0; i < tC->maxOrder; i++) {
@@ -779,6 +766,7 @@ INT FDKaacEnc_TnsDetect(
FDKaacEnc_MergedAutoCorrelation(
spectrum,
+ tC->isLowDelay,
tC->acfWindow,
tC->lpcStartLine,
tC->lpcStopLine,
@@ -788,7 +776,7 @@ INT FDKaacEnc_TnsDetect(
rxx2);
/* compute higher TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */
- tsbi->predictionGain = FDKaacEnc_AutoToParcor(rxx2, parcor_tmp, tC->confTab.tnsLimitOrder[HIFILT]);
+ tsbi->predictionGain[HIFILT] = FDKaacEnc_AutoToParcor(rxx2, parcor_tmp, tC->confTab.tnsLimitOrder[HIFILT]);
/* non-linear quantization of TNS lattice coefficients with given resolution */
FDKaacEnc_Parcor2Index(
@@ -815,9 +803,9 @@ INT FDKaacEnc_TnsDetect(
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)))
+ if ((tsbi->predictionGain[HIFILT] > tC->confTab.threshOn[HIFILT]) || (sumSqrCoef > (tC->confTab.tnsLimitOrder[HIFILT]/2 + 2)))
{
- tsbi->tnsActive = TRUE;
+ tsbi->tnsActive[HIFILT] = TRUE;
tnsInfo->numOfFilters[subBlockNumber]++;
/* compute second filter for lower quarter; only allowed for long windows! */
@@ -857,6 +845,7 @@ INT FDKaacEnc_TnsDetect(
|| ( (sumSqrCoef > 9) && (sumSqrCoef < 22 * tC->confTab.tnsLimitOrder[LOFILT]) ) )
{
/* compare lower to upper filter; if they are very similar, merge them */
+ tsbi->tnsActive[LOFILT] = TRUE;
sumSqrCoef = 0;
for (i = 0; i < tC->confTab.tnsLimitOrder[LOFILT]; i++) {
sumSqrCoef += FDKabs(tnsInfo->coef[subBlockNumber][HIFILT][i] - tnsInfo->coef[subBlockNumber][LOFILT][i]);
@@ -884,6 +873,8 @@ INT FDKaacEnc_TnsDetect(
tnsInfo->numOfFilters[subBlockNumber]++;
}
} /* filter lower part */
+ tsbi->predictionGain[LOFILT]=predGain;
+
} /* second filter allowed */
} /* if predictionGain > 1437 ... */
} /* maxOrder > 0 && tnsActive */
@@ -944,7 +935,7 @@ void FDKaacEnc_TnsSync(
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) {
+ if (pSbInfoDestW->tnsActive[HIFILT] || pSbInfoSrcW->tnsActive[HIFILT]) {
for (i = 0; i < tC->maxOrder; i++) {
absDiff = FDKabs(tnsInfoDest->coef[w][HIFILT][i] - tnsInfoSrc->coef[w][HIFILT][i]);
absDiffSum += absDiff;
@@ -957,12 +948,12 @@ void FDKaacEnc_TnsSync(
if (doSync) {
/* if no significant difference was detected, synchronize coefficient sets */
- if (pSbInfoSrcW->tnsActive) {
+ if (pSbInfoSrcW->tnsActive[HIFILT]) {
/* no dest filter, or more dest than source filters: use one dest filter */
- if ((!pSbInfoDestW->tnsActive) ||
- ((pSbInfoDestW->tnsActive) && (tnsInfoDest->numOfFilters[w] > tnsInfoSrc->numOfFilters[w])))
+ if ((!pSbInfoDestW->tnsActive[HIFILT]) ||
+ ((pSbInfoDestW->tnsActive[HIFILT]) && (tnsInfoDest->numOfFilters[w] > tnsInfoSrc->numOfFilters[w])))
{
- pSbInfoDestW->tnsActive = tnsInfoDest->numOfFilters[w] = 1;
+ pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 1;
}
tnsDataDest->filtersMerged = tnsDataSrc->filtersMerged;
tnsInfoDest->order [w][HIFILT] = tnsInfoSrc->order [w][HIFILT];
@@ -975,7 +966,7 @@ void FDKaacEnc_TnsSync(
}
}
else
- pSbInfoDestW->tnsActive = tnsInfoDest->numOfFilters[w] = 0;
+ pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 0;
}
}
@@ -1012,8 +1003,8 @@ INT FDKaacEnc_TnsEncode(
{
INT i, startLine, stopLine;
- if ( ( (blockType == SHORT_WINDOW) && (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber].tnsActive) )
- || ( (blockType != SHORT_WINDOW) && (!tnsData->dataRaw.Long.subBlockInfo.tnsActive) ) )
+ if ( ( (blockType == SHORT_WINDOW) && (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber].tnsActive[HIFILT]) )
+ || ( (blockType != SHORT_WINDOW) && (!tnsData->dataRaw.Long.subBlockInfo.tnsActive[HIFILT]) ) )
{
return 1;
}
@@ -1129,8 +1120,9 @@ static INT FDKaacEnc_AutoToParcor(
FIXP_DBL *RESTRICT workBuffer = parcorWorkBuffer;
const FIXP_DBL autoCorr_0 = input[0];
+ FDKmemclear(reflCoeff,numOfCoeff*sizeof(FIXP_DBL));
+
if((FIXP_DBL)input[0] == FL2FXCONST_DBL(0.0)) {
- FDKmemclear(reflCoeff,numOfCoeff*sizeof(FIXP_DBL));
return(predictionGain);
}