AAC/SBR encoder improvements

* AAC-Encoder

  - AAC-ELD core encoder audio quality tuning. Update tuning tables, configure
    bitreservoir size and adapt afterburner iteration value.
     Modified file(s):
        libAACenc/src/aacenc.h
        libAACenc/src/aacenc_lib.cpp
        libAACenc/src/adj_thr.cpp
        libAACenc/src/adj_thr.h
        libAACenc/src/adj_thr_data.h
        libAACenc/src/bandwidth.cpp
        libAACenc/src/pnsparam.cpp
        libAACenc/src/qc_main.cpp

   - Introduze dead zone quantizer for ELD to improve audio quality at certain
     configurations.
     Modified file(s):
        libAACenc/src/aacenc_lib.cpp
        libAACenc/src/adj_thr.cpp
        libAACenc/src/adj_thr.h
        libAACenc/src/qc_data.h
        libAACenc/src/qc_main.cpp
        libAACenc/src/quantize.cpp
        libAACenc/src/quantize.h
        libAACenc/src/sf_estim.cpp
        libAACenc/src/sf_estim.h

   - Revise TNS module to improve ELD audio quality.
   - Use new window function and separate prediction gain according TNS filters.
   - Add missing memory initilization to TNS configuration.
     Modified file(s):
        libAACenc/src/aacenc_lib.cpp
        libAACenc/src/aacenc_tns.cpp
        libAACenc/src/aacenc_tns.h
        libAACenc/src/psy_main.cpp
        libAACenc/src/tns_func.h

* SBR-Encoder

   - Revise frequency resolution calculation and handle differently depending
     on number of envelopes and split frames decision.
   - Add and adjust ELD SBR tuning tables.
     Modified file(s):
        libSBRenc/include/sbr_encoder.h
        libSBRenc/src/bit_sbr.h
        libSBRenc/src/env_est.cpp
        libSBRenc/src/fram_gen.cpp
        libSBRenc/src/fram_gen.h
        libSBRenc/src/mh_det.cpp
        libSBRenc/src/sbr_def.h
        libSBRenc/src/sbr_encoder.cpp
        libSBRenc/src/sbr_rom.cpp
        libSBRenc/src/tran_det.cpp

   - Replace ELD transient detector with fast implementation.
     Modified file(s):
        libSBRenc/src/env_est.cpp
        libSBRenc/src/env_est.h
        libSBRenc/src/fram_gen.cpp
        libSBRenc/src/sbr_def.h
        libSBRenc/src/sbr_encoder.cpp
        libSBRenc/src/tran_det.cpp
        libSBRenc/src/tran_det.h

* FDK-Library
   - Introduce generic compare function in tools library.
     Modified file(s):
        libFDK/include/fixpoint_math.h
        libFDK/src/FDK_core.cpp

* SBR-Encoder

  -  Revise ELD frame splitter to improve bit distribution.
     Modified file(s):
        libSBRenc/include/sbr_encoder.h
        libSBRenc/src/bit_sbr.h
        libSBRenc/src/env_est.cpp
        libSBRenc/src/fram_gen.cpp
        libSBRenc/src/fram_gen.h
        libSBRenc/src/sbr_encoder.cpp
        libSBRenc/src/tran_det.cpp
        libSBRenc/src/tran_det.h

   - Configure amplitude resolution according the tonality of the audio signal.
     Modified file(s):
        libSBRenc/include/sbr_encoder.h
        libSBRenc/src/bit_sbr.h
        libSBRenc/src/env_est.cpp
        libSBRenc/src/nf_est.cpp
        libSBRenc/src/nf_est.h
        libSBRenc/src/sbr_def.h
        libSBRenc/src/sbr_encoder.cpp
        libSBRenc/src/ton_corr.cpp
        libSBRenc/src/ton_corr.h
        libSBRenc/src/tran_det.cpp
        libSBRenc/src/tran_det.h

Change-Id: Ie0672b989a06ee63b50240616b8d1d4b790b6cb2
This commit is contained in:
Jean-Michel Trivi 2016-04-08 10:52:42 -07:00
parent 4834f01bdf
commit 46ba3676b8
35 changed files with 1206 additions and 327 deletions

View File

@ -98,6 +98,11 @@ amm-info@iis.fraunhofer.de
#include "sbr_encoder.h" #include "sbr_encoder.h"
#define BITRES_MAX_LD 4000
#define BITRES_MIN_LD 500
#define BITRATE_MAX_LD 70000 /* Max assumed bitrate for bitres calculation */
#define BITRATE_MIN_LD 12000 /* Min assumed bitrate for bitres calculation */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View File

@ -98,7 +98,7 @@ amm-info@iis.fraunhofer.de
/* Encoder library info */ /* Encoder library info */
#define AACENCODER_LIB_VL0 3 #define AACENCODER_LIB_VL0 3
#define AACENCODER_LIB_VL1 4 #define AACENCODER_LIB_VL1 4
#define AACENCODER_LIB_VL2 19 #define AACENCODER_LIB_VL2 22
#define AACENCODER_LIB_TITLE "AAC Encoder" #define AACENCODER_LIB_TITLE "AAC Encoder"
#ifdef __ANDROID__ #ifdef __ANDROID__
#define AACENCODER_LIB_BUILD_DATE "" #define AACENCODER_LIB_BUILD_DATE ""
@ -813,11 +813,16 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder,
switch ( hAacConfig->audioObjectType ) { switch ( hAacConfig->audioObjectType ) {
case AOT_ER_AAC_LD: case AOT_ER_AAC_LD:
case AOT_ER_AAC_ELD: case AOT_ER_AAC_ELD:
if (config->userBitrateMode==8) {
hAacConfig->bitrateMode = 0;
}
if (config->userBitrateMode==0) { if (config->userBitrateMode==0) {
hAacConfig->bitreservoir = 100*config->nChannels; /* default, reduced bitreservoir */ /* bitreservoir = (maxBitRes-minBitRes)/(maxBitRate-minBitrate)*(bitRate-minBitrate)+minBitRes; */
if ( isLowDelay(hAacConfig->audioObjectType) ) {
INT bitreservoir;
INT brPerChannel = hAacConfig->bitRate/hAacConfig->nChannels;
brPerChannel = fMin(BITRATE_MAX_LD, fMax(BITRATE_MIN_LD, brPerChannel));
FIXP_DBL slope = fDivNorm((brPerChannel-BITRATE_MIN_LD), BITRATE_MAX_LD-BITRATE_MIN_LD); /* calc slope for interpolation */
bitreservoir = fMultI(slope, (INT)(BITRES_MAX_LD-BITRES_MIN_LD)) + BITRES_MIN_LD; /* interpolate */
hAacConfig->bitreservoir = bitreservoir & ~7; /* align to bytes */
}
} }
if (hAacConfig->bitrateMode!=0) { if (hAacConfig->bitrateMode!=0) {
return AACENC_INVALID_CONFIG; return AACENC_INVALID_CONFIG;

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -95,13 +95,7 @@ amm-info@iis.fraunhofer.de
#include "aacEnc_rom.h" #include "aacEnc_rom.h"
#include "aacenc_tns.h" #include "aacenc_tns.h"
enum { #define FILTER_DIRECTION 0 /* 0 = up, 1 = down */
HIFILT = 0, /* index of higher filter */
LOFILT = 1 /* index of lower filter */
};
#define FILTER_DIRECTION 0
static const FIXP_DBL acfWindowLong[12+3+1] = { static const FIXP_DBL acfWindowLong[12+3+1] = {
0x7fffffff,0x7fb80000,0x7ee00000,0x7d780000,0x7b800000,0x78f80000,0x75e00000,0x72380000, 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 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{ typedef struct{
INT bitRateFrom[2]; /* noneSbr=0, useSbr=1 */ INT bitRateFrom[2]; /* noneSbr=0, useSbr=1 */
INT bitRateTo[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 channels,
INT blockType, INT blockType,
INT granuleLength, INT granuleLength,
INT isLowDelay,
INT ldSbrPresent, INT ldSbrPresent,
TNS_CONFIG *tC, TNS_CONFIG *tC,
PSY_CONFIGURATION *pC, PSY_CONFIGURATION *pC,
@ -385,6 +366,8 @@ AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitRate,
if (channels <= 0) if (channels <= 0)
return (AAC_ENCODER_ERROR)1; return (AAC_ENCODER_ERROR)1;
tC->isLowDelay = isLowDelay;
/* initialize TNS filter flag, order, and coefficient resolution (in bits per coeff) */ /* initialize TNS filter flag, order, and coefficient resolution (in bits per coeff) */
tC->tnsActive = (active) ? TRUE : FALSE; tC->tnsActive = (active) ? TRUE : FALSE;
tC->maxOrder = (blockType == SHORT_WINDOW) ? 5 : 12; /* maximum: 7, 20 */ 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); const TNS_PARAMETER_TABULATED* pCfg = FDKaacEnc_GetTnsParam(bitRate, channels, ldSbrPresent);
if ( pCfg != NULL ) { if ( pCfg != NULL ) {
FDKmemcpy(&(tC->confTab), pCfg, sizeof(tC->confTab));
tC->lpcStartBand[HIFILT] = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[HIFILT], sampleRate, pC->sfbCnt, pC->sfbOffset); tC->lpcStartBand[HIFILT] = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[HIFILT], sampleRate, pC->sfbCnt, pC->sfbOffset);
tC->lpcStartLine[HIFILT] = pC->sfbOffset[tC->lpcStartBand[HIFILT]]; tC->lpcStartLine[HIFILT] = pC->sfbOffset[tC->lpcStartBand[HIFILT]];
tC->lpcStartBand[LOFILT] = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[LOFILT], sampleRate, pC->sfbCnt, pC->sfbOffset); tC->lpcStartBand[LOFILT] = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[LOFILT], sampleRate, pC->sfbCnt, pC->sfbOffset);
tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]]; 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[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); 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( static void FDKaacEnc_MergedAutoCorrelation(
const FIXP_DBL *spectrum, const FIXP_DBL *spectrum,
const INT isLowDelay,
const FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER+3+1], const FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER+3+1],
const INT lpcStartLine[MAX_NUM_OF_FILTERS], const INT lpcStartLine[MAX_NUM_OF_FILTERS],
const INT lpcStopLine, const INT lpcStopLine,
@ -633,6 +604,8 @@ static void FDKaacEnc_MergedAutoCorrelation(
FDKmemclear(&_rxx1[0], sizeof(FIXP_DBL)*(maxOrder+1)); FDKmemclear(&_rxx1[0], sizeof(FIXP_DBL)*(maxOrder+1));
FDKmemclear(&_rxx2[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 */ /* MDCT line indices separating the 1st, 2nd, 3rd, and 4th analysis quarters */
if ( (acfSplit[LOFILT]==-1) || (acfSplit[HIFILT]==-1) ) { if ( (acfSplit[LOFILT]==-1) || (acfSplit[HIFILT]==-1) ) {
/* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the spectrum */ /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the spectrum */
@ -680,14 +653,24 @@ static void FDKaacEnc_MergedAutoCorrelation(
FIXP_DBL fac1 = FDKaacEnc_AutoCorrNormFac(rxx1_0, ((-2*sc1)+nsc1), &sc_fac1); FIXP_DBL fac1 = FDKaacEnc_AutoCorrNormFac(rxx1_0, ((-2*sc1)+nsc1), &sc_fac1);
_rxx1[0] = scaleValue(fMult(rxx1_0,fac1),sc_fac1); _rxx1[0] = scaleValue(fMult(rxx1_0,fac1),sc_fac1);
if (isLowDelay)
{
for (lag = 1; lag <= maxOrder; lag++) { for (lag = 1; lag <= maxOrder; lag++) {
/* compute energy-normalized and windowed autocorrelation values at this 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) { if ((3 * lag) <= maxOrder + 3) {
FIXP_DBL x1 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1); FIXP_DBL x1 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1);
_rxx1[lag] = fMult(scaleValue(fMult(x1,fac1),sc_fac1), acfWindow[LOFILT][3*lag]); _rxx1[lag] = fMult(scaleValue(fMult(x1,fac1),sc_fac1), acfWindow[LOFILT][3*lag]);
} }
} }
} }
}
/* auto corr over upper 3/4 of spectrum */ /* 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))) ) if ( !((rxx2_0 == FL2FXCONST_DBL(0.f)) && (rxx3_0 == FL2FXCONST_DBL(0.f)) && (rxx4_0 == FL2FXCONST_DBL(0.f))) )
@ -762,8 +745,12 @@ INT FDKaacEnc_TnsDetect(
: &tnsData->dataRaw.Long.subBlockInfo; : &tnsData->dataRaw.Long.subBlockInfo;
tnsData->filtersMerged = FALSE; 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->numOfFilters[subBlockNumber] = 0;
tnsInfo->coefRes[subBlockNumber] = tC->coefRes; tnsInfo->coefRes[subBlockNumber] = tC->coefRes;
for (i = 0; i < tC->maxOrder; i++) { for (i = 0; i < tC->maxOrder; i++) {
@ -779,6 +766,7 @@ INT FDKaacEnc_TnsDetect(
FDKaacEnc_MergedAutoCorrelation( FDKaacEnc_MergedAutoCorrelation(
spectrum, spectrum,
tC->isLowDelay,
tC->acfWindow, tC->acfWindow,
tC->lpcStartLine, tC->lpcStartLine,
tC->lpcStopLine, tC->lpcStopLine,
@ -788,7 +776,7 @@ INT FDKaacEnc_TnsDetect(
rxx2); rxx2);
/* compute higher TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */ /* 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 */ /* non-linear quantization of TNS lattice coefficients with given resolution */
FDKaacEnc_Parcor2Index( FDKaacEnc_Parcor2Index(
@ -815,9 +803,9 @@ INT FDKaacEnc_TnsDetect(
tnsInfo->length[subBlockNumber][HIFILT] = sfbCnt - tC->lpcStartBand[HIFILT]; tnsInfo->length[subBlockNumber][HIFILT] = sfbCnt - tC->lpcStartBand[HIFILT];
/* disable TNS if predictionGain is less than 3dB or sumSqrCoef is too small */ /* 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]++; tnsInfo->numOfFilters[subBlockNumber]++;
/* compute second filter for lower quarter; only allowed for long windows! */ /* 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]) ) ) || ( (sumSqrCoef > 9) && (sumSqrCoef < 22 * tC->confTab.tnsLimitOrder[LOFILT]) ) )
{ {
/* compare lower to upper filter; if they are very similar, merge them */ /* compare lower to upper filter; if they are very similar, merge them */
tsbi->tnsActive[LOFILT] = TRUE;
sumSqrCoef = 0; sumSqrCoef = 0;
for (i = 0; i < tC->confTab.tnsLimitOrder[LOFILT]; i++) { for (i = 0; i < tC->confTab.tnsLimitOrder[LOFILT]; i++) {
sumSqrCoef += FDKabs(tnsInfo->coef[subBlockNumber][HIFILT][i] - tnsInfo->coef[subBlockNumber][LOFILT][i]); sumSqrCoef += FDKabs(tnsInfo->coef[subBlockNumber][HIFILT][i] - tnsInfo->coef[subBlockNumber][LOFILT][i]);
@ -884,6 +873,8 @@ INT FDKaacEnc_TnsDetect(
tnsInfo->numOfFilters[subBlockNumber]++; tnsInfo->numOfFilters[subBlockNumber]++;
} }
} /* filter lower part */ } /* filter lower part */
tsbi->predictionGain[LOFILT]=predGain;
} /* second filter allowed */ } /* second filter allowed */
} /* if predictionGain > 1437 ... */ } /* if predictionGain > 1437 ... */
} /* maxOrder > 0 && tnsActive */ } /* maxOrder > 0 && tnsActive */
@ -944,7 +935,7 @@ void FDKaacEnc_TnsSync(
INT doSync = 1, absDiffSum = 0; INT doSync = 1, absDiffSum = 0;
/* if TNS is active in at least one channel, check if ParCor coefficients of higher filter are similar */ /* 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++) { for (i = 0; i < tC->maxOrder; i++) {
absDiff = FDKabs(tnsInfoDest->coef[w][HIFILT][i] - tnsInfoSrc->coef[w][HIFILT][i]); absDiff = FDKabs(tnsInfoDest->coef[w][HIFILT][i] - tnsInfoSrc->coef[w][HIFILT][i]);
absDiffSum += absDiff; absDiffSum += absDiff;
@ -957,12 +948,12 @@ void FDKaacEnc_TnsSync(
if (doSync) { if (doSync) {
/* if no significant difference was detected, synchronize coefficient sets */ /* 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 */ /* no dest filter, or more dest than source filters: use one dest filter */
if ((!pSbInfoDestW->tnsActive) || if ((!pSbInfoDestW->tnsActive[HIFILT]) ||
((pSbInfoDestW->tnsActive) && (tnsInfoDest->numOfFilters[w] > tnsInfoSrc->numOfFilters[w]))) ((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; tnsDataDest->filtersMerged = tnsDataSrc->filtersMerged;
tnsInfoDest->order [w][HIFILT] = tnsInfoSrc->order [w][HIFILT]; tnsInfoDest->order [w][HIFILT] = tnsInfoSrc->order [w][HIFILT];
@ -975,7 +966,7 @@ void FDKaacEnc_TnsSync(
} }
} }
else 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; INT i, startLine, stopLine;
if ( ( (blockType == SHORT_WINDOW) && (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber].tnsActive) ) if ( ( (blockType == SHORT_WINDOW) && (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber].tnsActive[HIFILT]) )
|| ( (blockType != SHORT_WINDOW) && (!tnsData->dataRaw.Long.subBlockInfo.tnsActive) ) ) || ( (blockType != SHORT_WINDOW) && (!tnsData->dataRaw.Long.subBlockInfo.tnsActive[HIFILT]) ) )
{ {
return 1; return 1;
} }
@ -1129,8 +1120,9 @@ static INT FDKaacEnc_AutoToParcor(
FIXP_DBL *RESTRICT workBuffer = parcorWorkBuffer; FIXP_DBL *RESTRICT workBuffer = parcorWorkBuffer;
const FIXP_DBL autoCorr_0 = input[0]; const FIXP_DBL autoCorr_0 = input[0];
if((FIXP_DBL)input[0] == FL2FXCONST_DBL(0.0)) {
FDKmemclear(reflCoeff,numOfCoeff*sizeof(FIXP_DBL)); FDKmemclear(reflCoeff,numOfCoeff*sizeof(FIXP_DBL));
if((FIXP_DBL)input[0] == FL2FXCONST_DBL(0.0)) {
return(predictionGain); return(predictionGain);
} }

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -117,21 +117,25 @@ amm-info@iis.fraunhofer.de
#define MAX_NUM_OF_FILTERS 2 #define MAX_NUM_OF_FILTERS 2
#define HIFILT 0 /* index of higher filter */
#define LOFILT 1 /* index of lower filter */
typedef struct{ /* stuff that is tabulated dependent on bitrate etc. */ typedef struct{ /* stuff that is tabulated dependent on bitrate etc. */
INT filterEnabled[MAX_NUM_OF_FILTERS]; INT filterEnabled[MAX_NUM_OF_FILTERS];
INT threshOn[MAX_NUM_OF_FILTERS]; /* min. prediction gain for using tns TABUL*/ 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 tnsLimitOrder[MAX_NUM_OF_FILTERS]; /* Limit for TNS order TABUL*/
INT tnsFilterDirection[MAX_NUM_OF_FILTERS]; /* Filtering direction, 0=up, 1=down TABUL */ INT tnsFilterDirection[MAX_NUM_OF_FILTERS]; /* Filtering direction, 0=up, 1=down TABUL */
INT acfSplit[MAX_NUM_OF_FILTERS]; 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; INT seperateFiltersAllowed;
} TNS_PARAMETER_TABULATED;
}TNS_CONFIG_TABULATED;
typedef struct { /*assigned at InitTime*/ typedef struct { /*assigned at InitTime*/
TNS_CONFIG_TABULATED confTab; TNS_PARAMETER_TABULATED confTab;
INT isLowDelay;
INT tnsActive; INT tnsActive;
INT maxOrder; /* max. order of tns filter */ INT maxOrder; /* max. order of tns filter */
INT coefRes; INT coefRes;
@ -148,8 +152,8 @@ typedef struct { /*assigned at InitTime*/
typedef struct { typedef struct {
INT tnsActive; INT tnsActive[MAX_NUM_OF_FILTERS];
INT predictionGain; INT predictionGain[MAX_NUM_OF_FILTERS];
} TNS_SUBBLOCK_INFO; } TNS_SUBBLOCK_INFO;
typedef struct{ /*changed at runTime*/ typedef struct{ /*changed at runTime*/

View File

@ -153,10 +153,10 @@ static const BIT_PE_SFAC S_Bits2PeTab16000[] = {
{ 24000, 0x23D70A3D, 0x029F16B1, 0x2199999A, 0x07DD4413, 0x23D70A3D, 0x029F16B1, 0x2199999A, 0x07DD4413}, { 24000, 0x23D70A3D, 0x029F16B1, 0x2199999A, 0x07DD4413, 0x23D70A3D, 0x029F16B1, 0x2199999A, 0x07DD4413},
{ 32000, 0x247AE148, 0x11B1D92B, 0x23851EB8, 0x01F75105, 0x247AE148, 0x110A137F, 0x23851EB8, 0x01F75105}, { 32000, 0x247AE148, 0x11B1D92B, 0x23851EB8, 0x01F75105, 0x247AE148, 0x110A137F, 0x23851EB8, 0x01F75105},
{ 48000, 0x2D1EB852, 0x6833C600, 0x247AE148, 0x014F8B59, 0x2CCCCCCD, 0x68DB8BAC, 0x247AE148, 0x01F75105}, { 48000, 0x2D1EB852, 0x6833C600, 0x247AE148, 0x014F8B59, 0x2CCCCCCD, 0x68DB8BAC, 0x247AE148, 0x01F75105},
{ 64000, 0x60000000, 0x00000000, 0x251EB852, 0x154C985F, 0x60000000, 0x00000000, 0x2570A3D7, 0x154C985F}, { 64000, 0x25c28f40, 0x00000000, 0x251EB852, 0x01480000, 0x25c28f40, 0x00000000, 0x2570A3D7, 0x01480000},
{ 96000, 0x60000000, 0x00000000, 0x39EB851F, 0x088509C0, 0x60000000, 0x00000000, 0x3A3D70A4, 0x088509C0}, { 96000, 0x25c28f40, 0x00000000, 0x26000000, 0x01000000, 0x25c28f40, 0x00000000, 0x26000000, 0x01000000},
{128000, 0x60000000, 0x00000000, 0x423D70A4, 0x18A43BB4, 0x60000000, 0x00000000, 0x428F5C29, 0x181E03F7}, {128000, 0x25c28f40, 0x00000000, 0x270a3d80, 0x01000000, 0x25c28f40, 0x00000000, 0x270a3d80, 0x01000000},
{148000, 0x60000000, 0x00000000, 0x5147AE14, 0x00000000, 0x60000000, 0x00000000, 0x5147AE14, 0x00000000} {148000, 0x25c28f40, 0x00000000, 0x28000000, 0x00000000, 0x25c28f40, 0x00000000, 0x28000000, 0x00000000}
}; };
static const BIT_PE_SFAC S_Bits2PeTab22050[] = { static const BIT_PE_SFAC S_Bits2PeTab22050[] = {
@ -166,8 +166,8 @@ static const BIT_PE_SFAC S_Bits2PeTab22050[] = {
{ 48000, 0x23d70a3d, 0x014f8b59, 0x2199999a, 0x03eea20a, 0x23d70a3d, 0x14f8b59, 0x2199999a, 0x03eea20a}, { 48000, 0x23d70a3d, 0x014f8b59, 0x2199999a, 0x03eea20a, 0x23d70a3d, 0x14f8b59, 0x2199999a, 0x03eea20a},
{ 64000, 0x247ae148, 0x08d8ec96, 0x23851eb8, 0x00fba882, 0x247ae148, 0x88509c0, 0x23851eb8, 0x00fba882}, { 64000, 0x247ae148, 0x08d8ec96, 0x23851eb8, 0x00fba882, 0x247ae148, 0x88509c0, 0x23851eb8, 0x00fba882},
{ 96000, 0x2d1eb852, 0x3419e300, 0x247ae148, 0x00a7c5ac, 0x2ccccccd, 0x346dc5d6, 0x247ae148, 0x00fba882}, { 96000, 0x2d1eb852, 0x3419e300, 0x247ae148, 0x00a7c5ac, 0x2ccccccd, 0x346dc5d6, 0x247ae148, 0x00fba882},
{128000, 0x60000000, 0x00000000, 0x251eb852, 0x029f16b1, 0x60000000, 0x00000000, 0x2570a3d7, 0x009f16b1}, {128000, 0x25c28f40, 0x00000000, 0x251eb852, 0x029f16b1, 0x60000000, 0x25c28f40, 0x2570a3d7, 0x009f16b1},
{148000, 0x60000000, 0x00000000, 0x26b851ec, 0x00000000, 0x60000000, 0x00000000, 0x270a3d71, 0x00000000} {148000, 0x25c28f40, 0x00000000, 0x26b851ec, 0x00000000, 0x60000000, 0x25c28f40, 0x270a3d71, 0x00000000}
}; };
static const BIT_PE_SFAC S_Bits2PeTab24000[] = { static const BIT_PE_SFAC S_Bits2PeTab24000[] = {
@ -178,21 +178,21 @@ static const BIT_PE_SFAC S_Bits2PeTab24000[] = {
{ 64000, 0x24cccccd, 0x05e5f30e, 0x22e147ae, 0x01a36e2f, 0x24cccccd, 0x05e5f30e, 0x23333333, 0x014f8b59}, { 64000, 0x24cccccd, 0x05e5f30e, 0x22e147ae, 0x01a36e2f, 0x24cccccd, 0x05e5f30e, 0x23333333, 0x014f8b59},
{ 96000, 0x2a8f5c29, 0x24b33db0, 0x247ae148, 0x00fba882, 0x2a8f5c29, 0x26fe718b, 0x247ae148, 0x00fba882}, { 96000, 0x2a8f5c29, 0x24b33db0, 0x247ae148, 0x00fba882, 0x2a8f5c29, 0x26fe718b, 0x247ae148, 0x00fba882},
{128000, 0x4e666666, 0x1cd5f99c, 0x2570a3d7, 0x010c6f7a, 0x50a3d70a, 0x192a7371, 0x2570a3d7, 0x010c6f7a}, {128000, 0x4e666666, 0x1cd5f99c, 0x2570a3d7, 0x010c6f7a, 0x50a3d70a, 0x192a7371, 0x2570a3d7, 0x010c6f7a},
{148000, 0x60000000, 0x00000000, 0x26147ae1, 0x00000000, 0x60000000, 0x00000000, 0x26147ae1, 0x00000000} {148000, 0x25c28f40, 0x00000000, 0x26147ae1, 0x00000000, 0x25c28f40, 0x00000000, 0x26147ae1, 0x00000000}
}; };
static const BIT_PE_SFAC S_Bits2PeTab32000[] = { static const BIT_PE_SFAC S_Bits2PeTab32000[] = {
{ 16000, 0x1199999a, 0x20c49ba6, 0x00000000, 0x4577d955, 0x00000000, 0x60fe4799, 0x00000000, 0x00000000}, { 16000, 0x247ae140, 0xFFFFAC1E, 0x270a3d80, 0xFFFE9B7C, 0x14ccccc0, 0x000110A1, 0x15c28f60, 0xFFFEEF5F},
{ 24000, 0x1999999a, 0x0fba8827, 0x10f5c28f, 0x1b866e44, 0x17ae147b, 0x0fba8827, 0x00000000, 0x4d551d69}, { 24000, 0x23333340, 0x0fba8827, 0x21999980, 0x1b866e44, 0x18f5c280, 0x0fba8827, 0x119999a0, 0x4d551d69},
{ 32000, 0x1d70a3d7, 0x07357e67, 0x17ae147b, 0x09d49518, 0x1b851eb8, 0x0a7c5ac4, 0x12e147ae, 0x110a137f}, { 32000, 0x1d70a3d7, 0x07357e67, 0x17ae147b, 0x09d49518, 0x1b851eb8, 0x0a7c5ac4, 0x12e147ae, 0x110a137f},
{ 48000, 0x20f5c28f, 0x049667b6, 0x1c7ae148, 0x053e2d62, 0x20a3d70a, 0x053e2d62, 0x1b333333, 0x05e5f30e}, { 48000, 0x20f5c28f, 0x049667b6, 0x1c7ae148, 0x053e2d62, 0x20a3d70a, 0x053e2d62, 0x1b333333, 0x05e5f30e},
{ 64000, 0x23333333, 0x029f16b1, 0x1f0a3d71, 0x02f2f987, 0x23333333, 0x029f16b1, 0x1e147ae1, 0x03eea20a}, { 64000, 0x23333333, 0x029f16b1, 0x1f0a3d71, 0x02f2f987, 0x23333333, 0x029f16b1, 0x1e147ae1, 0x03eea20a},
{ 96000, 0x25c28f5c, 0x2c3c9eed, 0x21eb851f, 0x01f75105, 0x25c28f5c, 0x0a7c5ac4, 0x21eb851f, 0x01a36e2f}, { 96000, 0x25c28f5c, 0x2c3c9eed, 0x21eb851f, 0x01f75105, 0x25c28f5c, 0x0a7c5ac4, 0x21eb851f, 0x01a36e2f},
{128000, 0x50f5c28f, 0x18a43bb4, 0x23d70a3d, 0x010c6f7a, 0x30000000, 0x168b5cc0, 0x23851eb8, 0x0192a737}, {128000, 0x50f5c28f, 0x18a43bb4, 0x23d70a3d, 0x010c6f7a, 0x30000000, 0x168b5cc0, 0x23851eb8, 0x0192a737},
{148000, 0x60000000, 0x00000000, 0x247ae148, 0x00dfb23b, 0x3dc28f5c, 0x300f4aaf, 0x247ae148, 0x01bf6476}, {148000, 0x25c28f40, 0x00000000, 0x247ae148, 0x00dfb23b, 0x3dc28f5c, 0x300f4aaf, 0x247ae148, 0x01bf6476},
{160000, 0x60000000, 0xb15b5740, 0x24cccccd, 0x053e2d62, 0x4f5c28f6, 0xbefd0072, 0x251eb852, 0x04fb1184}, {160000, 0x25c28f40, 0xb15b5740, 0x24cccccd, 0x053e2d62, 0x4f5c28f6, 0xbefd0072, 0x251eb852, 0x04fb1184},
{200000, 0x00000000, 0x00000000, 0x2b333333, 0x0836be91, 0x00000000, 0x00000000, 0x2b333333, 0x0890390f}, {200000, 0x25c28f40, 0x00000000, 0x2b333333, 0x0836be91, 0x25c28f40, 0x00000000, 0x2b333333, 0x0890390f},
{320000, 0x00000000, 0x00000000, 0x4947ae14, 0x00000000, 0x00000000, 0x00000000, 0x4a8f5c29, 0x00000000} {320000, 0x25c28f40, 0x00000000, 0x4947ae14, 0x00000000, 0x25c28f40, 0x00000000, 0x4a8f5c29, 0x00000000}
}; };
static const BIT_PE_SFAC S_Bits2PeTab44100[] = { static const BIT_PE_SFAC S_Bits2PeTab44100[] = {
@ -205,8 +205,8 @@ static const BIT_PE_SFAC S_Bits2PeTab44100[] = {
{128000, 0x2ae147ae, 0x1b435265, 0x223d70a4, 0x0192a737, 0x2a3d70a4, 0x1040bfe4, 0x21eb851f, 0x0192a737}, {128000, 0x2ae147ae, 0x1b435265, 0x223d70a4, 0x0192a737, 0x2a3d70a4, 0x1040bfe4, 0x21eb851f, 0x0192a737},
{148000, 0x3b851eb8, 0x2832069c, 0x23333333, 0x00dfb23b, 0x3428f5c3, 0x2054c288, 0x22e147ae, 0x00dfb23b}, {148000, 0x3b851eb8, 0x2832069c, 0x23333333, 0x00dfb23b, 0x3428f5c3, 0x2054c288, 0x22e147ae, 0x00dfb23b},
{160000, 0x4a3d70a4, 0xc32ebe5a, 0x23851eb8, 0x01d5c316, 0x40000000, 0xcb923a2b, 0x23333333, 0x01d5c316}, {160000, 0x4a3d70a4, 0xc32ebe5a, 0x23851eb8, 0x01d5c316, 0x40000000, 0xcb923a2b, 0x23333333, 0x01d5c316},
{200000, 0x00000000, 0x00000000, 0x25c28f5c, 0x0713f078, 0x00000000, 0x00000000, 0x2570a3d7, 0x072a4f17}, {200000, 0x25c28f40, 0x00000000, 0x25c28f5c, 0x0713f078, 0x25c28f40, 0x00000000, 0x2570a3d7, 0x072a4f17},
{320000, 0x00000000, 0x00000000, 0x3fae147b, 0x00000000, 0x00000000, 0x00000000, 0x3fae147b, 0x00000000} {320000, 0x25c28f40, 0x00000000, 0x3fae147b, 0x00000000, 0x25c28f40, 0x00000000, 0x3fae147b, 0x00000000}
}; };
static const BIT_PE_SFAC S_Bits2PeTab48000[] = { static const BIT_PE_SFAC S_Bits2PeTab48000[] = {
@ -219,8 +219,8 @@ static const BIT_PE_SFAC S_Bits2PeTab48000[] = {
{128000, 0x28f5c28f, 0x14727dcc, 0x2147ae14, 0x0218def4, 0x2851eb85, 0x0e27e0f0, 0x20f5c28f, 0x0218def4}, {128000, 0x28f5c28f, 0x14727dcc, 0x2147ae14, 0x0218def4, 0x2851eb85, 0x0e27e0f0, 0x20f5c28f, 0x0218def4},
{148000, 0x3570a3d7, 0x1cd5f99c, 0x228f5c29, 0x01bf6476, 0x30f5c28f, 0x18777e75, 0x223d70a4, 0x01bf6476}, {148000, 0x3570a3d7, 0x1cd5f99c, 0x228f5c29, 0x01bf6476, 0x30f5c28f, 0x18777e75, 0x223d70a4, 0x01bf6476},
{160000, 0x40000000, 0xcb923a2b, 0x23333333, 0x0192a737, 0x39eb851f, 0xd08d4bae, 0x22e147ae, 0x0192a737}, {160000, 0x40000000, 0xcb923a2b, 0x23333333, 0x0192a737, 0x39eb851f, 0xd08d4bae, 0x22e147ae, 0x0192a737},
{200000, 0x00000000, 0x00000000, 0x251eb852, 0x06775a1b, 0x00000000, 0x00000000, 0x24cccccd, 0x06a4175a}, {200000, 0x25c28f40, 0x00000000, 0x251eb852, 0x06775a1b, 0x25c28f40, 0x00000000, 0x24cccccd, 0x06a4175a},
{320000, 0x00000000, 0x00000000, 0x3ccccccd, 0x00000000, 0x00000000, 0x00000000, 0x3d1eb852, 0x00000000} {320000, 0x25c28f40, 0x00000000, 0x3ccccccd, 0x00000000, 0x25c28f40, 0x00000000, 0x3d1eb852, 0x00000000}
}; };
static const BITS2PE_CFG_TAB bits2PeConfigTab[] = { static const BITS2PE_CFG_TAB bits2PeConfigTab[] = {
@ -258,6 +258,7 @@ static void FDKaacEnc_InitBits2PeFactor(
const INT nChannels, const INT nChannels,
const INT sampleRate, const INT sampleRate,
const INT advancedBitsToPe, const INT advancedBitsToPe,
const INT dZoneQuantEnable,
const INT invQuant const INT invQuant
) )
{ {
@ -329,7 +330,32 @@ static void FDKaacEnc_InitBits2PeFactor(
} /* advancedBitsToPe */ } /* advancedBitsToPe */
/* return bits2pe factor */ if (dZoneQuantEnable)
{
if(bit2PE_m >= (FL2FXCONST_DBL(0.6f))>>bit2PE_e)
{
/* Additional headroom for addition */
bit2PE_m >>= 1;
bit2PE_e += 1;
}
/* the quantTendencyCompensator compensates a lower bit consumption due to increasing the tendency to quantize low spectral values to the lower quantizer border for bitrates below a certain bitrate threshold --> see also function calcSfbDistLD in quantize.c */
if ((bitRate/nChannels > 32000) && (bitRate/nChannels <= 40000)) {
bit2PE_m += (FL2FXCONST_DBL(0.4f))>>bit2PE_e;
}
else if (bitRate/nChannels > 20000) {
bit2PE_m += (FL2FXCONST_DBL(0.3f))>>bit2PE_e;
}
else if (bitRate/nChannels >= 16000) {
bit2PE_m += (FL2FXCONST_DBL(0.3f))>>bit2PE_e;
}
else {
bit2PE_m += (FL2FXCONST_DBL(0.0f))>>bit2PE_e;
}
}
/***** 3.) Return bits2pe factor *****/
*bits2PeFactor_m = bit2PE_m; *bits2PeFactor_m = bit2PE_m;
*bits2PeFactor_e = bit2PE_e; *bits2PeFactor_e = bit2PE_e;
} }
@ -1649,6 +1675,7 @@ static void FDKaacEnc_adaptThresholdsToPe(CHANNEL_MAPPING* cm,
QC_OUT_ELEMENT* qcElement[(8)], QC_OUT_ELEMENT* qcElement[(8)],
PSY_OUT_ELEMENT* psyOutElement[(8)], PSY_OUT_ELEMENT* psyOutElement[(8)],
const INT desiredPe, const INT desiredPe,
const INT maxIter2ndGuess,
const INT processElements, const INT processElements,
const INT elementOffset) const INT elementOffset)
{ {
@ -1733,7 +1760,7 @@ static void FDKaacEnc_adaptThresholdsToPe(CHANNEL_MAPPING* cm,
/* Part III: Iterate until bit constraints are met */ /* Part III: Iterate until bit constraints are met */
/* -------------------------------------------------- */ /* -------------------------------------------------- */
iter = 0; iter = 0;
while ((fixp_abs(redPeGlobal - desiredPe) > fMultI(FL2FXCONST_DBL(0.05f),desiredPe)) && (iter < 1)) { while ((fixp_abs(redPeGlobal - desiredPe) > fMultI(FL2FXCONST_DBL(0.05f),desiredPe)) && (iter < maxIter2ndGuess)) {
INT desiredPeNoAHGlobal; INT desiredPeNoAHGlobal;
INT redPeNoAHGlobal = 0; INT redPeNoAHGlobal = 0;
@ -2225,7 +2252,8 @@ void FDKaacEnc_AdjThrInit(
INT nChannelsEff, INT nChannelsEff,
INT sampleRate, INT sampleRate,
INT advancedBitsToPe, INT advancedBitsToPe,
FIXP_DBL vbrQualFactor FIXP_DBL vbrQualFactor,
const INT dZoneQuantEnable
) )
{ {
INT i; INT i;
@ -2233,6 +2261,10 @@ void FDKaacEnc_AdjThrInit(
FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f); FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f);
FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f); FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f);
/* Max number of iterations in second guess is 3 for lowdelay aot and for configurations with
multiple audio elements in general, otherwise iteration value is always 1. */
hAdjThr->maxIter2ndGuess = (advancedBitsToPe!=0 || nElements>1) ? 3 : 1;
/* common for all elements: */ /* common for all elements: */
/* parameters for bitres control */ /* parameters for bitres control */
hAdjThr->bresParamLong.clipSaveLow = (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */ hAdjThr->bresParamLong.clipSaveLow = (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
@ -2313,10 +2345,11 @@ void FDKaacEnc_AdjThrInit(
FDKaacEnc_InitBits2PeFactor( FDKaacEnc_InitBits2PeFactor(
&atsElem->bits2PeFactor_m, &atsElem->bits2PeFactor_m,
&atsElem->bits2PeFactor_e, &atsElem->bits2PeFactor_e,
chBitrate, /* bitrate/channel*/ chBitrate*nChannelsEff, /* overall bitrate */
nChannelsEff, /* number of channels */ nChannelsEff, /* number of channels */
sampleRate, sampleRate,
advancedBitsToPe, advancedBitsToPe,
dZoneQuantEnable,
invQuant invQuant
); );
@ -2545,6 +2578,7 @@ void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(8)],
QC_OUT* qcOut, QC_OUT* qcOut,
PSY_OUT_ELEMENT* psyOutElement[(8)], PSY_OUT_ELEMENT* psyOutElement[(8)],
INT CBRbitrateMode, INT CBRbitrateMode,
INT maxIter2ndGuess,
CHANNEL_MAPPING* cm) CHANNEL_MAPPING* cm)
{ {
int i; int i;
@ -2570,6 +2604,7 @@ void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(8)],
qcElement, qcElement,
psyOutElement, psyOutElement,
qcElement[i]->grantedPeCorr, qcElement[i]->grantedPeCorr,
maxIter2ndGuess,
1, /* Process only 1 element */ 1, /* Process only 1 element */
i); /* Process exactly THIS element */ i); /* Process exactly THIS element */

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -118,7 +118,8 @@ void FDKaacEnc_AdjThrInit(ADJ_THR_STATE *hAdjThr,
INT nChannelsEff, INT nChannelsEff,
INT sampleRate, INT sampleRate,
INT advancedBitsToPe, INT advancedBitsToPe,
FIXP_DBL vbrQualFactor); FIXP_DBL vbrQualFactor,
const INT dZoneQuantEnable);
void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState, void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState,
@ -140,6 +141,7 @@ void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(8)],
QC_OUT* qcOut, QC_OUT* qcOut,
PSY_OUT_ELEMENT* psyOutElement[(8)], PSY_OUT_ELEMENT* psyOutElement[(8)],
INT CBRbitrateMode, INT CBRbitrateMode,
INT maxIter2ndGuess,
CHANNEL_MAPPING* cm); CHANNEL_MAPPING* cm);
void FDKaacEnc_AdjThrClose(ADJ_THR_STATE** hAdjThr); void FDKaacEnc_AdjThrClose(ADJ_THR_STATE** hAdjThr);

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -145,6 +145,7 @@ typedef struct {
typedef struct { typedef struct {
BRES_PARAM bresParamLong, bresParamShort; BRES_PARAM bresParamLong, bresParamShort;
ATS_ELEMENT* adjThrStateElem[(8)]; ATS_ELEMENT* adjThrStateElem[(8)];
INT maxIter2ndGuess;
} ADJ_THR_STATE; } ADJ_THR_STATE;
#endif #endif

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -127,7 +127,7 @@ static const BANDWIDTH_TAB bandWidthTable_LD_24000[] = {
{ 8000, 2000, 2000}, { 8000, 2000, 2000},
{12000, 2000, 2300}, {12000, 2000, 2300},
{16000, 2200, 2500}, {16000, 2200, 2500},
{24000, 5650, 6400}, {24000, 5650, 7200},
{32000, 11600, 12000}, {32000, 11600, 12000},
{40000, 12000, 16000}, {40000, 12000, 16000},
{48000, 16000, 16000}, {48000, 16000, 16000},
@ -138,10 +138,10 @@ static const BANDWIDTH_TAB bandWidthTable_LD_24000[] = {
static const BANDWIDTH_TAB bandWidthTable_LD_32000[] = { static const BANDWIDTH_TAB bandWidthTable_LD_32000[] = {
{ 8000, 2000, 2000}, { 8000, 2000, 2000},
{12000, 2000, 2000}, {12000, 2000, 2000},
{24000, 4250, 5200}, {24000, 4250, 7200},
{32000, 8400, 9000}, {32000, 8400, 9000},
{40000, 9400, 11300}, {40000, 9400, 11300},
{48000, 11900, 13700}, {48000, 11900, 14700},
{64000, 14800, 16000}, {64000, 14800, 16000},
{76000, 16000, 16000}, {76000, 16000, 16000},
{360001, 16000, 16000} {360001, 16000, 16000}

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -107,6 +107,7 @@ typedef struct {
typedef struct { typedef struct {
ULONG brFrom; ULONG brFrom;
ULONG brTo; ULONG brTo;
UCHAR S16000;
UCHAR S22050; UCHAR S22050;
UCHAR S24000; UCHAR S24000;
UCHAR S32000; UCHAR S32000;
@ -115,25 +116,26 @@ typedef struct {
} AUTO_PNS_TAB; } AUTO_PNS_TAB;
static const AUTO_PNS_TAB levelTable_mono[]= { static const AUTO_PNS_TAB levelTable_mono[]= {
{0, 11999, 1, 1, 1, 1, 1,}, {0, 11999, 0, 1, 1, 1, 1, 1,},
{12000, 19999, 1, 1, 1, 1, 1,}, {12000, 19999, 0, 1, 1, 1, 1, 1,},
{20000, 28999, 2, 1, 1, 1, 1,}, {20000, 28999, 0, 2, 1, 1, 1, 1,},
{29000, 40999, 4, 4, 4, 2, 2,}, {29000, 40999, 0, 4, 4, 4, 2, 2,},
{41000, 55999, 9, 9, 7, 7, 7,}, {41000, 55999, 0, 9, 9, 7, 7, 7,},
{56000, 79999, 0, 0, 0, 9, 9,}, {56000, 61999, 0, 0, 0, 0, 9, 9,},
{80000, 99999, 0, 0, 0, 0, 0,}, {62000, 75999, 0, 0, 0, 0, 0, 0,},
{100000,999999, 0, 0, 0, 0, 0,}, {76000, 92999, 0, 0, 0, 0, 0, 0,},
{93000, 999999, 0, 0, 0, 0, 0, 0,},
}; };
static const AUTO_PNS_TAB levelTable_stereo[]= { static const AUTO_PNS_TAB levelTable_stereo[]= {
{0, 11999, 1, 1, 1, 1, 1,}, {0, 11999, 0, 1, 1, 1, 1, 1,},
{12000, 19999, 3, 1, 1, 1, 1,}, {12000, 19999, 0, 3, 1, 1, 1, 1,},
{20000, 28999, 3, 3, 3, 2, 2,}, {20000, 28999, 0, 3, 3, 3, 2, 2,},
{29000, 40999, 7, 6, 6, 5, 5,}, {29000, 40999, 0, 7, 6, 6, 5, 5,},
{41000, 55999, 9, 9, 7, 7, 7,}, {41000, 55999, 0, 9, 9, 7, 7, 7,},
{56000, 79999, 0, 0, 0, 0, 0,}, {56000, 79999, 0, 0, 0, 0, 0, 0,},
{80000, 99999, 0, 0, 0, 0, 0,}, {80000, 99999, 0, 0, 0, 0, 0, 0,},
{100000,999999, 0, 0, 0, 0, 0,}, {100000,999999, 0, 0, 0, 0, 0, 0,},
}; };
@ -160,11 +162,11 @@ static const PNS_INFO_TAB pnsInfoTab[] = {
}; };
static const AUTO_PNS_TAB levelTable_lowComplexity[]= { static const AUTO_PNS_TAB levelTable_lowComplexity[]= {
{0, 27999, 0, 0, 0, 0, 0,}, {0, 27999, 0, 0, 0, 0, 0, 0,},
{28000, 31999, 2, 2, 2, 2, 2,}, {28000, 31999, 0, 2, 2, 2, 2, 2,},
{32000, 47999, 3, 3, 3, 3, 3,}, {32000, 47999, 0, 3, 3, 3, 3, 3,},
{48000, 48000, 4, 4, 4, 4, 4,}, {48000, 48000, 0, 4, 4, 4, 4, 4,},
{48001, 999999, 0, 0, 0, 0, 0,}, {48001, 999999, 0, 0, 0, 0, 0, 0,},
}; };
/* conversion of old LC tuning tables to new (LD enc) structure (only entries which are actually used were converted) */ /* conversion of old LC tuning tables to new (LD enc) structure (only entries which are actually used were converted) */
@ -211,6 +213,7 @@ int FDKaacEnc_lookUpPnsUse (int bitRate, int sampleRate, int numChan, const int
} }
switch (sampleRate) { switch (sampleRate) {
case 16000: hUsePns = levelTable[i].S16000; break;
case 22050: hUsePns = levelTable[i].S22050; break; case 22050: hUsePns = levelTable[i].S22050; break;
case 24000: hUsePns = levelTable[i].S24000; break; case 24000: hUsePns = levelTable[i].S24000; break;
case 32000: hUsePns = levelTable[i].S32000; break; case 32000: hUsePns = levelTable[i].S32000; break;

View File

@ -342,6 +342,7 @@ AAC_ENCODER_ERROR FDKaacEnc_psyMainInit(PSY_INTERNAL *hPsy,
tnsChannels, tnsChannels,
LONG_WINDOW, LONG_WINDOW,
hPsy->granuleLength, hPsy->granuleLength,
isLowDelay(audioObjectType),
(syntaxFlags&AC_SBR_PRESENT)?1:0, (syntaxFlags&AC_SBR_PRESENT)?1:0,
&(hPsy->psyConf[0].tnsConf), &(hPsy->psyConf[0].tnsConf),
&hPsy->psyConf[0], &hPsy->psyConf[0],
@ -362,6 +363,7 @@ AAC_ENCODER_ERROR FDKaacEnc_psyMainInit(PSY_INTERNAL *hPsy,
tnsChannels, tnsChannels,
SHORT_WINDOW, SHORT_WINDOW,
hPsy->granuleLength, hPsy->granuleLength,
isLowDelay(audioObjectType),
(syntaxFlags&AC_SBR_PRESENT)?1:0, (syntaxFlags&AC_SBR_PRESENT)?1:0,
&hPsy->psyConf[1].tnsConf, &hPsy->psyConf[1].tnsConf,
&hPsy->psyConf[1], &hPsy->psyConf[1],
@ -763,7 +765,8 @@ AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels,
/* Advance psychoacoustics: Tonality and TNS */ /* Advance psychoacoustics: Tonality and TNS */
if (psyStatic[0]->isLFE) { if (psyStatic[0]->isLFE) {
tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive = 0; tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] = 0;
tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT] = 0;
} }
else else
{ {
@ -819,11 +822,15 @@ AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels,
for(w = 0; w < nWindows[0]; w++) for(w = 0; w < nWindows[0]; w++)
{ {
if (isShortWindow[0]) if (isShortWindow[0])
tnsActive[w] = tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive || tnsActive[w] = tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive[HIFILT] ||
((channels == 2) ? tnsData[1]->dataRaw.Short.subBlockInfo[w].tnsActive : 0); tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive[LOFILT] ||
tnsData[channels-1]->dataRaw.Short.subBlockInfo[w].tnsActive[HIFILT] ||
tnsData[channels-1]->dataRaw.Short.subBlockInfo[w].tnsActive[LOFILT];
else else
tnsActive[w] = tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive || tnsActive[w] = tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] ||
((channels == 2) ? tnsData[1]->dataRaw.Long.subBlockInfo.tnsActive : 0); tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT] ||
tnsData[channels-1]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] ||
tnsData[channels-1]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT];
} }
for(ch = 0; ch < channels; ch++) { for(ch = 0; ch < channels; ch++) {
@ -1150,8 +1157,8 @@ AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels,
psyData[ch]->sfbMaxScaleSpec.Long, psyData[ch]->sfbMaxScaleSpec.Long,
sfbTonality[ch], sfbTonality[ch],
psyOutChannel[ch]->tnsInfo.order[0][0], psyOutChannel[ch]->tnsInfo.order[0][0],
tnsData[ch]->dataRaw.Long.subBlockInfo.predictionGain, tnsData[ch]->dataRaw.Long.subBlockInfo.predictionGain[HIFILT],
tnsData[ch]->dataRaw.Long.subBlockInfo.tnsActive, tnsData[ch]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT],
psyOutChannel[ch]->sfbEnergyLdData, psyOutChannel[ch]->sfbEnergyLdData,
psyOutChannel[ch]->noiseNrg ); psyOutChannel[ch]->noiseNrg );
} /* !isLFE */ } /* !isLFE */

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -269,6 +269,8 @@ typedef struct
BITCNTR_STATE *hBitCounter; BITCNTR_STATE *hBitCounter;
ADJ_THR_STATE *hAdjThr; ADJ_THR_STATE *hAdjThr;
INT dZoneQuantEnable; /* enable dead zone quantizer */
} QC_STATE; } QC_STATE;
#endif /* _QC_DATA_H */ #endif /* _QC_DATA_H */

View File

@ -380,7 +380,7 @@ AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC,
if ( isConstantBitrateMode(hQC->bitrateMode) ) { if ( isConstantBitrateMode(hQC->bitrateMode) ) {
INT bitresPerChannel = (hQC->bitResTotMax / init->channelMapping->nChannelsEff); INT bitresPerChannel = (hQC->bitResTotMax / init->channelMapping->nChannelsEff);
/* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir */ /* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir */
hQC->bitDistributionMode = (bitresPerChannel>100) ? 0 : (bitresPerChannel>0) ? 1 : 2; hQC->bitDistributionMode = (bitresPerChannel>BITRES_MIN_LD) ? 0 : (bitresPerChannel>0) ? 1 : 2;
} }
else { else {
hQC->bitDistributionMode = 0; /* full bitreservoir */ hQC->bitDistributionMode = 0; /* full bitreservoir */
@ -405,6 +405,16 @@ AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC,
} }
} }
if (init->channelMapping->nChannelsEff == 1 &&
(init->bitrate / init->channelMapping->nChannelsEff) < 32000 &&
init->advancedBitsToPe != 0
)
{
hQC->dZoneQuantEnable = 1;
} else {
hQC->dZoneQuantEnable = 0;
}
FDKaacEnc_AdjThrInit( FDKaacEnc_AdjThrInit(
hQC->hAdjThr, hQC->hAdjThr,
init->meanPe, init->meanPe,
@ -414,7 +424,8 @@ AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC,
init->channelMapping->nChannelsEff, init->channelMapping->nChannelsEff,
init->sampleRate, /* output sample rate */ init->sampleRate, /* output sample rate */
init->advancedBitsToPe, /* if set, calc bits2PE factor depending on samplerate */ init->advancedBitsToPe, /* if set, calc bits2PE factor depending on samplerate */
hQC->vbrQualFactor hQC->vbrQualFactor,
hQC->dZoneQuantEnable
); );
return AAC_ENC_OK; return AAC_ENC_OK;
@ -877,6 +888,7 @@ AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC,
qcOut[c], qcOut[c],
psyOut[c]->psyOutElement, psyOut[c]->psyOutElement,
isConstantBitrateMode(hQC->bitrateMode), isConstantBitrateMode(hQC->bitrateMode),
hQC->hAdjThr->maxIter2ndGuess,
cm); cm);
} /* -end- sub frame counter */ } /* -end- sub frame counter */
@ -904,6 +916,7 @@ AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC,
FDKaacEnc_EstimateScaleFactors(psyOut[c]->psyOutElement[i]->psyOutChannel, FDKaacEnc_EstimateScaleFactors(psyOut[c]->psyOutElement[i]->psyOutChannel,
qcElement[c][i]->qcOutChannel, qcElement[c][i]->qcOutChannel,
hQC->invQuant, hQC->invQuant,
hQC->dZoneQuantEnable,
cm->elInfo[i].nChannelsInEl); cm->elInfo[i].nChannelsInEl);
@ -998,7 +1011,8 @@ AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC,
qcOutCh->mdctSpectrum, qcOutCh->mdctSpectrum,
qcOutCh->globalGain, qcOutCh->globalGain,
qcOutCh->scf, qcOutCh->scf,
qcOutCh->quantSpec) ; qcOutCh->quantSpec,
hQC->dZoneQuantEnable);
/*-------------------------------------------- */ /*-------------------------------------------- */
if (FDKaacEnc_calcMaxValueInSfb(psyOutCh->sfbCnt, if (FDKaacEnc_calcMaxValueInSfb(psyOutCh->sfbCnt,

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -104,13 +104,19 @@ amm-info@iis.fraunhofer.de
static void FDKaacEnc_quantizeLines(INT gain, static void FDKaacEnc_quantizeLines(INT gain,
INT noOfLines, INT noOfLines,
FIXP_DBL *mdctSpectrum, FIXP_DBL *mdctSpectrum,
SHORT *quaSpectrum) SHORT *quaSpectrum,
INT dZoneQuantEnable)
{ {
int line; int line;
FIXP_DBL k = FL2FXCONST_DBL(-0.0946f + 0.5f)>>16; FIXP_DBL k = FL2FXCONST_DBL(0.0f);
FIXP_QTD quantizer = FDKaacEnc_quantTableQ[(-gain)&3]; FIXP_QTD quantizer = FDKaacEnc_quantTableQ[(-gain)&3];
INT quantizershift = ((-gain)>>2)+1; INT quantizershift = ((-gain)>>2)+1;
const INT kShift=16;
if (dZoneQuantEnable)
k = FL2FXCONST_DBL(0.23f)>>kShift;
else
k = FL2FXCONST_DBL(-0.0946f + 0.5f)>>kShift;
for (line = 0; line < noOfLines; line++) for (line = 0; line < noOfLines; line++)
{ {
@ -263,7 +269,8 @@ void FDKaacEnc_QuantizeSpectrum(INT sfbCnt,
FIXP_DBL *mdctSpectrum, FIXP_DBL *mdctSpectrum,
INT globalGain, INT globalGain,
INT *scalefactors, INT *scalefactors,
SHORT *quantizedSpectrum) SHORT *quantizedSpectrum,
INT dZoneQuantEnable)
{ {
INT sfbOffs,sfb; INT sfbOffs,sfb;
@ -280,7 +287,8 @@ void FDKaacEnc_QuantizeSpectrum(INT sfbCnt,
FDKaacEnc_quantizeLines(globalGain - scalefactor, /* QSS */ FDKaacEnc_quantizeLines(globalGain - scalefactor, /* QSS */
sfbOffset[sfbOffs+sfb+1] - sfbOffset[sfbOffs+sfb], sfbOffset[sfbOffs+sfb+1] - sfbOffset[sfbOffs+sfb],
mdctSpectrum + sfbOffset[sfbOffs+sfb], mdctSpectrum + sfbOffset[sfbOffs+sfb],
quantizedSpectrum + sfbOffset[sfbOffs+sfb]); quantizedSpectrum + sfbOffset[sfbOffs+sfb],
dZoneQuantEnable);
} }
} }
@ -296,7 +304,8 @@ void FDKaacEnc_QuantizeSpectrum(INT sfbCnt,
FIXP_DBL FDKaacEnc_calcSfbDist(FIXP_DBL *mdctSpectrum, FIXP_DBL FDKaacEnc_calcSfbDist(FIXP_DBL *mdctSpectrum,
SHORT *quantSpectrum, SHORT *quantSpectrum,
INT noOfLines, INT noOfLines,
INT gain INT gain,
INT dZoneQuantEnable
) )
{ {
INT i,scale; INT i,scale;
@ -311,7 +320,8 @@ FIXP_DBL FDKaacEnc_calcSfbDist(FIXP_DBL *mdctSpectrum,
FDKaacEnc_quantizeLines(gain, FDKaacEnc_quantizeLines(gain,
1, 1,
&mdctSpectrum[i], &mdctSpectrum[i],
&quantSpectrum[i]); &quantSpectrum[i],
dZoneQuantEnable);
if (fAbs(quantSpectrum[i])>MAX_QUANT) { if (fAbs(quantSpectrum[i])>MAX_QUANT) {
return FL2FXCONST_DBL(0.0f); return FL2FXCONST_DBL(0.0f);

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -102,12 +102,14 @@ void FDKaacEnc_QuantizeSpectrum(INT sfbCnt,
INT sfbPerGroup, INT sfbPerGroup,
INT *sfbOffset, FIXP_DBL *mdctSpectrum, INT *sfbOffset, FIXP_DBL *mdctSpectrum,
INT globalGain, INT *scalefactors, INT globalGain, INT *scalefactors,
SHORT *quantizedSpectrum); SHORT *quantizedSpectrum,
INT dZoneQuantEnable);
FIXP_DBL FDKaacEnc_calcSfbDist(FIXP_DBL *mdctSpectrum, FIXP_DBL FDKaacEnc_calcSfbDist(FIXP_DBL *mdctSpectrum,
SHORT *quantSpectrum, SHORT *quantSpectrum,
INT noOfLines, INT noOfLines,
INT gain); INT gain,
INT dZoneQuantEnable);
void FDKaacEnc_calcSfbQuantEnergyAndDist(FIXP_DBL *mdctSpectrum, void FDKaacEnc_calcSfbQuantEnergyAndDist(FIXP_DBL *mdctSpectrum,
SHORT *quantSpectrum, SHORT *quantSpectrum,

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -363,7 +363,8 @@ static INT FDKaacEnc_improveScf(FIXP_DBL *spec,
INT scf, INT scf,
INT minScf, INT minScf,
FIXP_DBL *distLdData, FIXP_DBL *distLdData,
INT *minScfCalculated INT *minScfCalculated,
INT dZoneQuantEnable
) )
{ {
FIXP_DBL sfbDistLdData; FIXP_DBL sfbDistLdData;
@ -375,7 +376,8 @@ static INT FDKaacEnc_improveScf(FIXP_DBL *spec,
sfbDistLdData = FDKaacEnc_calcSfbDist(spec, sfbDistLdData = FDKaacEnc_calcSfbDist(spec,
quantSpec, quantSpec,
sfbWidth, sfbWidth,
scf); scf,
dZoneQuantEnable);
*minScfCalculated = scf; *minScfCalculated = scf;
/* nmr > 1.25 -> try to improve nmr */ /* nmr > 1.25 -> try to improve nmr */
if (sfbDistLdData > (threshLdData-distFactorLdData)) { if (sfbDistLdData > (threshLdData-distFactorLdData)) {
@ -390,7 +392,8 @@ static INT FDKaacEnc_improveScf(FIXP_DBL *spec,
sfbDistLdData = FDKaacEnc_calcSfbDist(spec, sfbDistLdData = FDKaacEnc_calcSfbDist(spec,
quantSpecTmp, quantSpecTmp,
sfbWidth, sfbWidth,
scf); scf,
dZoneQuantEnable);
if (sfbDistLdData < sfbDistBestLdData) { if (sfbDistLdData < sfbDistBestLdData) {
scfBest = scf; scfBest = scf;
@ -408,7 +411,8 @@ static INT FDKaacEnc_improveScf(FIXP_DBL *spec,
sfbDistLdData = FDKaacEnc_calcSfbDist(spec, sfbDistLdData = FDKaacEnc_calcSfbDist(spec,
quantSpecTmp, quantSpecTmp,
sfbWidth, sfbWidth,
scf); scf,
dZoneQuantEnable);
if (sfbDistLdData < sfbDistBestLdData) { if (sfbDistLdData < sfbDistBestLdData) {
scfBest = scf; scfBest = scf;
@ -429,7 +433,8 @@ static INT FDKaacEnc_improveScf(FIXP_DBL *spec,
sfbDistLdData = FDKaacEnc_calcSfbDist(spec, sfbDistLdData = FDKaacEnc_calcSfbDist(spec,
quantSpecTmp, quantSpecTmp,
sfbWidth, sfbWidth,
scf); scf,
dZoneQuantEnable);
if (sfbDistLdData < sfbDistAllowedLdData) { if (sfbDistLdData < sfbDistAllowedLdData) {
*minScfCalculated = scfBest+1; *minScfCalculated = scfBest+1;
@ -454,6 +459,7 @@ static void FDKaacEnc_assimilateSingleScf(PSY_OUT_CHANNEL *psyOutChan,
QC_OUT_CHANNEL *qcOutChannel, QC_OUT_CHANNEL *qcOutChannel,
SHORT *quantSpec, SHORT *quantSpec,
SHORT *quantSpecTmp, SHORT *quantSpecTmp,
INT dZoneQuantEnable,
INT *scf, INT *scf,
INT *minScf, INT *minScf,
FIXP_DBL *sfbDist, FIXP_DBL *sfbDist,
@ -570,7 +576,8 @@ static void FDKaacEnc_assimilateSingleScf(PSY_OUT_CHANNEL *psyOutChan,
sfbDistNew = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs, sfbDistNew = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs,
quantSpecTmp+sfbOffs, quantSpecTmp+sfbOffs,
sfbWidth, sfbWidth,
scfAct); scfAct,
dZoneQuantEnable);
if (sfbDistNew < sfbDist[sfbAct]) { if (sfbDistNew < sfbDist[sfbAct]) {
/* success, replace scf by new one */ /* success, replace scf by new one */
@ -629,6 +636,7 @@ static void FDKaacEnc_assimilateMultipleScf(PSY_OUT_CHANNEL *psyOutChan,
QC_OUT_CHANNEL *qcOutChannel, QC_OUT_CHANNEL *qcOutChannel,
SHORT *quantSpec, SHORT *quantSpec,
SHORT *quantSpecTmp, SHORT *quantSpecTmp,
INT dZoneQuantEnable,
INT *scf, INT *scf,
INT *minScf, INT *minScf,
FIXP_DBL *sfbDist, FIXP_DBL *sfbDist,
@ -724,7 +732,8 @@ static void FDKaacEnc_assimilateMultipleScf(PSY_OUT_CHANNEL *psyOutChan,
sfbDistNew[sfb] = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs, sfbDistNew[sfb] = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs,
quantSpecTmp+sfbOffs, quantSpecTmp+sfbOffs,
sfbWidth, sfbWidth,
scfAct); scfAct,
dZoneQuantEnable);
if (sfbDistNew[sfb] >qcOutChannel->sfbThresholdLdData[sfb]) { if (sfbDistNew[sfb] >qcOutChannel->sfbThresholdLdData[sfb]) {
/* no improvement, skip further dist. calculations */ /* no improvement, skip further dist. calculations */
@ -768,6 +777,7 @@ static void FDKaacEnc_FDKaacEnc_assimilateMultipleScf2(PSY_OUT_CHANNEL *psyOutCh
QC_OUT_CHANNEL *qcOutChannel, QC_OUT_CHANNEL *qcOutChannel,
SHORT *quantSpec, SHORT *quantSpec,
SHORT *quantSpecTmp, SHORT *quantSpecTmp,
INT dZoneQuantEnable,
INT *scf, INT *scf,
INT *minScf, INT *minScf,
FIXP_DBL *sfbDist, FIXP_DBL *sfbDist,
@ -883,7 +893,8 @@ static void FDKaacEnc_FDKaacEnc_assimilateMultipleScf2(PSY_OUT_CHANNEL *psyOutCh
sfbDistNew[sfb] = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs[sfb], sfbDistNew[sfb] = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs[sfb],
quantSpecTmp+sfbOffs[sfb], quantSpecTmp+sfbOffs[sfb],
sfbOffs[sfb+1]-sfbOffs[sfb], sfbOffs[sfb+1]-sfbOffs[sfb],
scfNew); scfNew,
dZoneQuantEnable);
if (sfbDistNew[sfb] > sfbDistMax[sfb]) { if (sfbDistNew[sfb] > sfbDistMax[sfb]) {
/* no improvement, skip further dist. calculations */ /* no improvement, skip further dist. calculations */
@ -963,7 +974,8 @@ static void FDKaacEnc_FDKaacEnc_assimilateMultipleScf2(PSY_OUT_CHANNEL *psyOutCh
sfbDistNew[sfb] = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs[sfb], sfbDistNew[sfb] = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs[sfb],
quantSpecTmp+sfbOffs[sfb], quantSpecTmp+sfbOffs[sfb],
sfbOffs[sfb+1]-sfbOffs[sfb], sfbOffs[sfb+1]-sfbOffs[sfb],
scfNew); scfNew,
dZoneQuantEnable);
if (sfbDistNew[sfb] > qcOutChannel->sfbThresholdLdData[sfb]) { if (sfbDistNew[sfb] > qcOutChannel->sfbThresholdLdData[sfb]) {
/* no improvement, skip further dist. calculations */ /* no improvement, skip further dist. calculations */
@ -1058,7 +1070,8 @@ FDKaacEnc_FDKaacEnc_EstimateScaleFactorsChannel(QC_OUT_CHANNEL *qcOutChannel,
INT *RESTRICT globalGain, INT *RESTRICT globalGain,
FIXP_DBL *RESTRICT sfbFormFactorLdData FIXP_DBL *RESTRICT sfbFormFactorLdData
,const INT invQuant, ,const INT invQuant,
SHORT *RESTRICT quantSpec SHORT *RESTRICT quantSpec,
const INT dZoneQuantEnable
) )
{ {
INT i, j, sfb, sfbOffs; INT i, j, sfb, sfbOffs;
@ -1160,7 +1173,8 @@ FDKaacEnc_FDKaacEnc_EstimateScaleFactorsChannel(QC_OUT_CHANNEL *qcOutChannel,
quantSpecTmp+psyOutChannel->sfbOffsets[sfbOffs+sfb], quantSpecTmp+psyOutChannel->sfbOffsets[sfbOffs+sfb],
psyOutChannel->sfbOffsets[sfbOffs+sfb+1]-psyOutChannel->sfbOffsets[sfbOffs+sfb], psyOutChannel->sfbOffsets[sfbOffs+sfb+1]-psyOutChannel->sfbOffsets[sfbOffs+sfb],
threshLdData, scfInt, minSfMaxQuant[sfbOffs+sfb], threshLdData, scfInt, minSfMaxQuant[sfbOffs+sfb],
&sfbDistLdData[sfbOffs+sfb], &minScfCalculated[sfbOffs+sfb] &sfbDistLdData[sfbOffs+sfb], &minScfCalculated[sfbOffs+sfb],
dZoneQuantEnable
); );
} }
scf[sfbOffs+sfb] = scfInt; scf[sfbOffs+sfb] = scfInt;
@ -1187,20 +1201,32 @@ FDKaacEnc_FDKaacEnc_EstimateScaleFactorsChannel(QC_OUT_CHANNEL *qcOutChannel,
sfbNRelevantLines); sfbNRelevantLines);
FDKaacEnc_assimilateSingleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, scf, FDKaacEnc_assimilateSingleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp,
dZoneQuantEnable,
scf,
minSfMaxQuant, sfbDistLdData, sfbConstPePart, minSfMaxQuant, sfbDistLdData, sfbConstPePart,
sfbFormFactorLdData, sfbNRelevantLines, minScfCalculated, 1); sfbFormFactorLdData, sfbNRelevantLines, minScfCalculated, 1);
if(invQuant > 1) {
FDKaacEnc_assimilateMultipleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp,
dZoneQuantEnable,
scf,
minSfMaxQuant, sfbDistLdData, sfbConstPePart,
sfbFormFactorLdData, sfbNRelevantLines);
FDKaacEnc_assimilateMultipleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, scf, FDKaacEnc_assimilateMultipleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp,
dZoneQuantEnable,
scf,
minSfMaxQuant, sfbDistLdData, sfbConstPePart, minSfMaxQuant, sfbDistLdData, sfbConstPePart,
sfbFormFactorLdData, sfbNRelevantLines); sfbFormFactorLdData, sfbNRelevantLines);
FDKaacEnc_FDKaacEnc_assimilateMultipleScf2(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, scf, FDKaacEnc_FDKaacEnc_assimilateMultipleScf2(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp,
dZoneQuantEnable,
scf,
minSfMaxQuant, sfbDistLdData, sfbConstPePart, minSfMaxQuant, sfbDistLdData, sfbConstPePart,
sfbFormFactorLdData, sfbNRelevantLines); sfbFormFactorLdData, sfbNRelevantLines);
}
} }
@ -1223,7 +1249,8 @@ FDKaacEnc_FDKaacEnc_EstimateScaleFactorsChannel(QC_OUT_CHANNEL *qcOutChannel,
FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+psyOutChannel->sfbOffsets[sfbOffs+sfb], FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+psyOutChannel->sfbOffsets[sfbOffs+sfb],
quantSpec+psyOutChannel->sfbOffsets[sfbOffs+sfb], quantSpec+psyOutChannel->sfbOffsets[sfbOffs+sfb],
psyOutChannel->sfbOffsets[sfbOffs+sfb+1]-psyOutChannel->sfbOffsets[sfbOffs+sfb], psyOutChannel->sfbOffsets[sfbOffs+sfb+1]-psyOutChannel->sfbOffsets[sfbOffs+sfb],
scf[sfbOffs+sfb] scf[sfbOffs+sfb],
dZoneQuantEnable
); );
} }
} }
@ -1281,6 +1308,7 @@ void
FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[], FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[],
QC_OUT_CHANNEL* qcOutChannel[], QC_OUT_CHANNEL* qcOutChannel[],
const int invQuant, const int invQuant,
const INT dZoneQuantEnable,
const int nChannels) const int nChannels)
{ {
int ch; int ch;
@ -1293,7 +1321,8 @@ FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[],
&qcOutChannel[ch]->globalGain, &qcOutChannel[ch]->globalGain,
qcOutChannel[ch]->sfbFormFactorLdData qcOutChannel[ch]->sfbFormFactorLdData
,invQuant, ,invQuant,
qcOutChannel[ch]->quantSpec qcOutChannel[ch]->quantSpec,
dZoneQuantEnable
); );
} }

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -110,6 +110,7 @@ void
FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[], FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[],
QC_OUT_CHANNEL* qcOutChannel[], QC_OUT_CHANNEL* qcOutChannel[],
const int invQuant, const int invQuant,
const INT dZoneQuantEnable,
const int nChannels); const int nChannels);

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -100,6 +100,7 @@ AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitrate,
INT channels, INT channels,
INT blocktype, INT blocktype,
INT granuleLength, INT granuleLength,
INT isLowDelay,
INT ldSbrPresent, INT ldSbrPresent,
TNS_CONFIG *tnsConfig, TNS_CONFIG *tnsConfig,
PSY_CONFIGURATION *psyConfig, PSY_CONFIGURATION *psyConfig,

View File

@ -94,6 +94,35 @@ amm-info@iis.fraunhofer.de
#include "common_fix.h" #include "common_fix.h"
#if !defined(FUNCTION_fIsLessThan)
/**
* \brief Compares two fixpoint values incl. scaling.
* \param a_m mantissa of the first input value.
* \param a_e exponent of the first input value.
* \param b_m mantissa of the second input value.
* \param b_e exponent of the second input value.
* \return non-zero if (a_m*2^a_e) < (b_m*2^b_e), 0 otherwise
*/
FDK_INLINE INT fIsLessThan(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e)
{
if (a_e > b_e) {
return (b_m >> fMin(a_e-b_e, DFRACT_BITS-1) > a_m);
} else {
return (a_m >> fMin(b_e-a_e, DFRACT_BITS-1) < b_m);
}
}
FDK_INLINE INT fIsLessThan(FIXP_SGL a_m, INT a_e, FIXP_SGL b_m, INT b_e)
{
if (a_e > b_e) {
return (b_m >> fMin(a_e-b_e, FRACT_BITS-1) > a_m);
} else {
return (a_m >> fMin(b_e-a_e, FRACT_BITS-1) < b_m);
}
}
#endif
#define LD_DATA_SCALING (64.0f) #define LD_DATA_SCALING (64.0f)
#define LD_DATA_SHIFT 6 /* pow(2, LD_DATA_SHIFT) = LD_DATA_SCALING */ #define LD_DATA_SHIFT 6 /* pow(2, LD_DATA_SHIFT) = LD_DATA_SCALING */

View File

@ -93,7 +93,7 @@ amm-info@iis.fraunhofer.de
/* FDK tools library info */ /* FDK tools library info */
#define FDK_TOOLS_LIB_VL0 2 #define FDK_TOOLS_LIB_VL0 2
#define FDK_TOOLS_LIB_VL1 3 #define FDK_TOOLS_LIB_VL1 3
#define FDK_TOOLS_LIB_VL2 4 #define FDK_TOOLS_LIB_VL2 5
#define FDK_TOOLS_LIB_TITLE "FDK Tools" #define FDK_TOOLS_LIB_TITLE "FDK Tools"
#ifdef __ANDROID__ #ifdef __ANDROID__
#define FDK_TOOLS_LIB_BUILD_DATE "" #define FDK_TOOLS_LIB_BUILD_DATE ""

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -135,6 +135,12 @@ enum
SBR_SYNTAX_DRM_CRC = 0x0008 SBR_SYNTAX_DRM_CRC = 0x0008
}; };
typedef enum
{
FREQ_RES_LOW = 0,
FREQ_RES_HIGH
} FREQ_RES;
typedef struct typedef struct
{ {
CODEC_TYPE coreCoder; /*!< LC or ELD */ CODEC_TYPE coreCoder; /*!< LC or ELD */
@ -168,8 +174,9 @@ typedef struct sbrConfiguration
INT dynBwSupported; /*!< Flag: support for dynamic bandwidth in this combination. */ INT dynBwSupported; /*!< Flag: support for dynamic bandwidth in this combination. */
INT parametricCoding; /*!< Flag: usage of parametric coding tool. */ INT parametricCoding; /*!< Flag: usage of parametric coding tool. */
INT downSampleFactor; /*!< Sampling rate relation between the SBR and the core encoder. */ INT downSampleFactor; /*!< Sampling rate relation between the SBR and the core encoder. */
int freq_res_fixfix[3]; /*!< Frequency resolution of envelopes in frame class FIXFIX FREQ_RES freq_res_fixfix[2];/*!< Frequency resolution of envelopes in frame class FIXFIX, for non-split case and split case */
0=1 Env; 1=2 Env; 2=4 Env; */ UCHAR fResTransIsLow; /*!< Frequency resolution of envelopes in transient frames: low (0) or variable (1) */
/* /*
core coder dependent tuning parameters core coder dependent tuning parameters
*/ */
@ -221,6 +228,8 @@ typedef struct sbrConfiguration
INT sbr_interpol_freq; /*!< Flag: use interpolation in freq. direction. */ INT sbr_interpol_freq; /*!< Flag: use interpolation in freq. direction. */
INT sbr_smoothing_length; /*!< Flag: choose length 4 or 0 (=on, off). */ INT sbr_smoothing_length; /*!< Flag: choose length 4 or 0 (=on, off). */
UCHAR init_amp_res_FF; UCHAR init_amp_res_FF;
FIXP_DBL threshold_AmpRes_FF_m;
SCHAR threshold_AmpRes_FF_e;
} sbrConfiguration, *sbrConfigurationPtr ; } sbrConfiguration, *sbrConfigurationPtr ;
typedef struct SBR_CONFIG_DATA typedef struct SBR_CONFIG_DATA
@ -237,7 +246,7 @@ typedef struct SBR_CONFIG_DATA
INT noQmfBands; /**< Number of QMF frequency bands. */ INT noQmfBands; /**< Number of QMF frequency bands. */
INT noQmfSlots; /**< Number of QMF slots. */ INT noQmfSlots; /**< Number of QMF slots. */
UCHAR *freqBandTable[2]; /**< Frequency table for low and hires, only MAX_FREQ_COEFFS/2 +1 coeefs actually needed for lowres. */ UCHAR *freqBandTable[2]; /**< Frequency table for low and hires, only MAX_FREQ_COEFFS/2 +1 coeffs actually needed for lowres. */
UCHAR *v_k_master; /**< Master BandTable where freqBandTable is derived from. */ UCHAR *v_k_master; /**< Master BandTable where freqBandTable is derived from. */
@ -249,6 +258,8 @@ typedef struct SBR_CONFIG_DATA
INT xposCtrlSwitch; /**< Flag indicates whether to switch xpos ctrl on the fly. */ INT xposCtrlSwitch; /**< Flag indicates whether to switch xpos ctrl on the fly. */
INT switchTransposers; /**< Flag indicates whether to switch xpos on the fly . */ INT switchTransposers; /**< Flag indicates whether to switch xpos on the fly . */
UCHAR initAmpResFF; UCHAR initAmpResFF;
FIXP_DBL thresholdAmpResFF_m;
SCHAR thresholdAmpResFF_e;
} SBR_CONFIG_DATA, *HANDLE_SBR_CONFIG_DATA; } SBR_CONFIG_DATA, *HANDLE_SBR_CONFIG_DATA;
typedef struct { typedef struct {

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -141,8 +141,8 @@ struct SBR_ENV_DATA
{ {
INT sbr_xpos_ctrl; INT sbr_xpos_ctrl;
INT freq_res_fixfix; FREQ_RES freq_res_fixfix[2];
UCHAR fResTransIsLow;
INVF_MODE sbr_invf_mode; INVF_MODE sbr_invf_mode;
INVF_MODE sbr_invf_mode_vec[MAX_NUM_NOISE_VALUES]; INVF_MODE sbr_invf_mode_vec[MAX_NUM_NOISE_VALUES];
@ -205,6 +205,8 @@ struct SBR_ENV_DATA
INT balance; INT balance;
AMP_RES init_sbr_amp_res; AMP_RES init_sbr_amp_res;
AMP_RES currentAmpResFF; AMP_RES currentAmpResFF;
FIXP_DBL ton_HF[SBR_GLOBAL_TONALITY_VALUES]; /* tonality is scaled by 2^19/0.524288f (fract part of RELAXATION) */
FIXP_DBL global_tonality;
/* extended data */ /* extended data */
INT extended_data; INT extended_data;

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -103,6 +103,114 @@ static const UCHAR panTable[2][10] = { { 0, 2, 4, 6, 8,12,16,20,24},
static const UCHAR maxIndex[2] = {9, 5}; static const UCHAR maxIndex[2] = {9, 5};
/******************************************************************************
Functionname: FDKsbrEnc_GetTonality
******************************************************************************/
/***************************************************************************/
/*!
\brief Calculates complete energy per band from the energy values
of the QMF subsamples.
\brief quotaMatrix - calculated in FDKsbrEnc_CalculateTonalityQuotas()
\brief noEstPerFrame - number of estimations per frame
\brief startIndex - start index for the quota matrix
\brief Energies - energy matrix
\brief startBand - start band
\brief stopBand - number of QMF bands
\brief numberCols - number of QMF subsamples
\return mean tonality of the 5 bands with the highest energy
scaled by 2^(RELAXATION_SHIFT+2)*RELAXATION_FRACT
****************************************************************************/
static FIXP_DBL FDKsbrEnc_GetTonality(
const FIXP_DBL *const *quotaMatrix,
const INT noEstPerFrame,
const INT startIndex,
const FIXP_DBL *const *Energies,
const UCHAR startBand,
const INT stopBand,
const INT numberCols
)
{
UCHAR b, e, k;
INT no_enMaxBand[SBR_MAX_ENERGY_VALUES] = { -1, -1, -1, -1, -1 };
FIXP_DBL energyMax[SBR_MAX_ENERGY_VALUES] = { FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f) };
FIXP_DBL energyMaxMin = MAXVAL_DBL; /* min. energy in energyMax array */
UCHAR posEnergyMaxMin = 0; /* min. energy in energyMax array position */
FIXP_DBL tonalityBand[SBR_MAX_ENERGY_VALUES] = { FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f) };
FIXP_DBL globalTonality = FL2FXCONST_DBL(0.0f);
FIXP_DBL energyBand[QMF_CHANNELS];
INT maxNEnergyValues; /* max. number of max. energy values */
/*** Sum up energies for each band ***/
FDK_ASSERT(numberCols==15||numberCols==16);
/* numberCols is always 15 or 16 for ELD. In case of 16 bands, the
energyBands are initialized with the [15]th column.
The rest of the column energies are added in the next step. */
if (numberCols==15) {
for (b=startBand; b<stopBand; b++) {
energyBand[b]=FL2FXCONST_DBL(0.0f);
}
} else {
for (b=startBand; b<stopBand; b++) {
energyBand[b]=Energies[15][b]>>4;
}
}
for (k=0; k<15; k++) {
for (b=startBand; b<stopBand; b++) {
energyBand[b] += Energies[k][b]>>4;
}
}
/*** Determine 5 highest band-energies ***/
maxNEnergyValues = fMin(SBR_MAX_ENERGY_VALUES, stopBand-startBand);
/* Get min. value in energyMax array */
energyMaxMin = energyMax[0] = energyBand[startBand];
no_enMaxBand[0] = startBand;
posEnergyMaxMin = 0;
for (k=1; k<maxNEnergyValues; k++) {
energyMax[k] = energyBand[startBand+k];
no_enMaxBand[k] = startBand+k;
if (energyMaxMin > energyMax[k]) {
energyMaxMin = energyMax[k];
posEnergyMaxMin = k;
}
}
for (b=startBand+maxNEnergyValues; b<stopBand; b++) {
if (energyBand[b] > energyMaxMin) {
energyMax[posEnergyMaxMin] = energyBand[b];
no_enMaxBand[posEnergyMaxMin] = b;
/* Again, get min. value in energyMax array */
energyMaxMin = energyMax[0];
posEnergyMaxMin = 0;
for (k=1; k<maxNEnergyValues; k++) {
if (energyMaxMin > energyMax[k]) {
energyMaxMin = energyMax[k];
posEnergyMaxMin = k;
}
}
}
}
/*** End determine 5 highest band-energies ***/
/* Get tonality values for 5 highest energies */
for (e=0; e<maxNEnergyValues; e++) {
tonalityBand[e]=FL2FXCONST_DBL(0.0f);
for (k=0; k<noEstPerFrame; k++) {
tonalityBand[e] += quotaMatrix[startIndex + k][no_enMaxBand[e]] >> 1;
}
globalTonality += tonalityBand[e] >> 2; /* headroom of 2+1 (max. 5 additions) */
}
return globalTonality;
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -919,10 +1027,42 @@ FDKsbrEnc_extractSbrEnvelope1 (
hEnvChan->qmfScale); hEnvChan->qmfScale);
if(h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) {
FIXP_DBL tonality = FDKsbrEnc_GetTonality (
hEnvChan->TonCorr.quotaMatrix,
hEnvChan->TonCorr.numberOfEstimatesPerFrame,
hEnvChan->TonCorr.startIndexMatrix,
sbrExtrEnv->YBuffer + sbrExtrEnv->YBufferWriteOffset,
h_con->freqBandTable[HI][0]+1,
h_con->noQmfBands,
sbrExtrEnv->no_cols
);
hEnvChan->encEnvData.ton_HF[1] = hEnvChan->encEnvData.ton_HF[0];
hEnvChan->encEnvData.ton_HF[0] = tonality;
/* tonality is scaled by 2^19/0.524288f (fract part of RELAXATION) */
hEnvChan->encEnvData.global_tonality = (hEnvChan->encEnvData.ton_HF[0]>>1) + (hEnvChan->encEnvData.ton_HF[1]>>1);
}
/* /*
Transient detection COEFF Transform OK Transient detection COEFF Transform OK
*/ */
if(h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY)
{
FDKsbrEnc_fastTransientDetect(
&hEnvChan->sbrFastTransientDetector,
sbrExtrEnv->YBuffer,
sbrExtrEnv->YBufferScale,
sbrExtrEnv->YBufferWriteOffset,
eData->transient_info
);
}
else
{
FDKsbrEnc_transientDetect(&hEnvChan->sbrTransientDetector, FDKsbrEnc_transientDetect(&hEnvChan->sbrTransientDetector,
sbrExtrEnv->YBuffer, sbrExtrEnv->YBuffer,
sbrExtrEnv->YBufferScale, sbrExtrEnv->YBufferScale,
@ -931,6 +1071,7 @@ FDKsbrEnc_extractSbrEnvelope1 (
sbrExtrEnv->YBufferSzShift, sbrExtrEnv->YBufferSzShift,
sbrExtrEnv->time_step, sbrExtrEnv->time_step,
hEnvChan->SbrEnvFrame.frameMiddleSlot); hEnvChan->SbrEnvFrame.frameMiddleSlot);
}
@ -951,7 +1092,8 @@ FDKsbrEnc_extractSbrEnvelope1 (
sbrExtrEnv->YBufferSzShift, sbrExtrEnv->YBufferSzShift,
h_con->nSfb[1], h_con->nSfb[1],
sbrExtrEnv->time_step, sbrExtrEnv->time_step,
sbrExtrEnv->no_cols); sbrExtrEnv->no_cols,
&hEnvChan->encEnvData.global_tonality);
} }
@ -1128,10 +1270,24 @@ FDKsbrEnc_extractSbrEnvelope2 (
&& ( ed->nEnvelopes == 1 ) ) && ( ed->nEnvelopes == 1 ) )
{ {
if (hEnvChan->encEnvData.ldGrid) if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY)
hEnvChan->encEnvData.currentAmpResFF = (AMP_RES)h_con->initAmpResFF; {
else /* Note: global_tonaliy_float_value == ((float)hEnvChan->encEnvData.global_tonality/((INT64)(1)<<(31-(19+2)))/0.524288*(2.0/3.0)));
threshold_float_value == ((float)h_con->thresholdAmpResFF_m/((INT64)(1)<<(31-(h_con->thresholdAmpResFF_e)))/0.524288*(2.0/3.0))); */
/* decision of SBR_AMP_RES */
if (fIsLessThan( /* global_tonality > threshold ? */
h_con->thresholdAmpResFF_m, h_con->thresholdAmpResFF_e,
hEnvChan->encEnvData.global_tonality, RELAXATION_SHIFT+2 )
)
{
hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_1_5; hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_1_5;
}
else {
hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_3_0;
}
} else {
hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_1_5;
}
if ( hEnvChan->encEnvData.currentAmpResFF != hEnvChan->encEnvData.init_sbr_amp_res) { if ( hEnvChan->encEnvData.currentAmpResFF != hEnvChan->encEnvData.init_sbr_amp_res) {
@ -1172,7 +1328,12 @@ FDKsbrEnc_extractSbrEnvelope2 (
} }
/* Low energy in low band fix */ /* Low energy in low band fix */
if ( hEnvChan->sbrTransientDetector.prevLowBandEnergy < hEnvChan->sbrTransientDetector.prevHighBandEnergy && hEnvChan->sbrTransientDetector.prevHighBandEnergy > FL2FX_DBL(0.03)) if ( hEnvChan->sbrTransientDetector.prevLowBandEnergy < hEnvChan->sbrTransientDetector.prevHighBandEnergy
&& hEnvChan->sbrTransientDetector.prevHighBandEnergy > FL2FX_DBL(0.03)
/* The fix needs the non-fast transient detector running.
It sets prevLowBandEnergy and prevHighBandEnergy. */
&& !(h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY)
)
{ {
int i; int i;

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -127,6 +127,7 @@ typedef SBR_EXTRACT_ENVELOPE *HANDLE_SBR_EXTRACT_ENVELOPE;
struct ENV_CHANNEL struct ENV_CHANNEL
{ {
FAST_TRAN_DETECTOR sbrFastTransientDetector;
SBR_TRANSIENT_DETECTOR sbrTransientDetector; SBR_TRANSIENT_DETECTOR sbrTransientDetector;
SBR_CODE_ENVELOPE sbrCodeEnvelope; SBR_CODE_ENVELOPE sbrCodeEnvelope;
SBR_CODE_ENVELOPE sbrCodeNoiseFloor; SBR_CODE_ENVELOPE sbrCodeNoiseFloor;

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -266,7 +266,7 @@ static void calcCtrlSignal (HANDLE_SBR_GRID hSbrGrid, FRAME_CLASS frameClass,
static void ctrlSignal2FrameInfo (HANDLE_SBR_GRID hSbrGrid, static void ctrlSignal2FrameInfo (HANDLE_SBR_GRID hSbrGrid,
HANDLE_SBR_FRAME_INFO hFrameInfo, HANDLE_SBR_FRAME_INFO hFrameInfo,
INT freq_res_fixfix); FREQ_RES *freq_res_fixfix);
/* table for 8 time slot index */ /* table for 8 time slot index */
@ -341,7 +341,8 @@ static const FREQ_RES freqRes_table_16[16] = {
static void generateFixFixOnly ( HANDLE_SBR_FRAME_INFO hSbrFrameInfo, static void generateFixFixOnly ( HANDLE_SBR_FRAME_INFO hSbrFrameInfo,
HANDLE_SBR_GRID hSbrGrid, HANDLE_SBR_GRID hSbrGrid,
int tranPosInternal, int tranPosInternal,
int numberTimeSlots int numberTimeSlots,
UCHAR fResTransIsLow
); );
@ -402,11 +403,10 @@ FDKsbrEnc_frameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
const int *v_tuningFreq = v_tuning + 3; const int *v_tuningFreq = v_tuning + 3;
hSbrEnvFrame->v_tuningSegm = v_tuningSegm; hSbrEnvFrame->v_tuningSegm = v_tuningSegm;
INT freq_res_fixfix = hSbrEnvFrame->freq_res_fixfix;
if (ldGrid) { if (ldGrid) {
/* in case there was a transient at the very end of the previous frame, start with a transient envelope */ /* in case there was a transient at the very end of the previous frame, start with a transient envelope */
if(v_transient_info_pre[1] && (numberTimeSlots - v_transient_info_pre[0] < minFrameTranDistance)){ if ( !tranFlag && v_transient_info_pre[1] && (numberTimeSlots - v_transient_info_pre[0] < minFrameTranDistance) ){
tranFlag = 1; tranFlag = 1;
tranPos = 0; tranPos = 0;
} }
@ -529,7 +529,8 @@ FDKsbrEnc_frameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
generateFixFixOnly ( &(hSbrEnvFrame->SbrFrameInfo), generateFixFixOnly ( &(hSbrEnvFrame->SbrFrameInfo),
&(hSbrEnvFrame->SbrGrid), &(hSbrEnvFrame->SbrGrid),
tranPosInternal, tranPosInternal,
numberTimeSlots numberTimeSlots,
hSbrEnvFrame->fResTransIsLow
); );
return &(hSbrEnvFrame->SbrFrameInfo); return &(hSbrEnvFrame->SbrFrameInfo);
@ -677,7 +678,7 @@ FDKsbrEnc_frameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
ctrlSignal2FrameInfo (&hSbrEnvFrame->SbrGrid, ctrlSignal2FrameInfo (&hSbrEnvFrame->SbrGrid,
&hSbrEnvFrame->SbrFrameInfo, &hSbrEnvFrame->SbrFrameInfo,
freq_res_fixfix); hSbrEnvFrame->freq_res_fixfix);
return &hSbrEnvFrame->SbrFrameInfo; return &hSbrEnvFrame->SbrFrameInfo;
} }
@ -692,7 +693,8 @@ FDKsbrEnc_frameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
static void generateFixFixOnly ( HANDLE_SBR_FRAME_INFO hSbrFrameInfo, static void generateFixFixOnly ( HANDLE_SBR_FRAME_INFO hSbrFrameInfo,
HANDLE_SBR_GRID hSbrGrid, HANDLE_SBR_GRID hSbrGrid,
int tranPosInternal, int tranPosInternal,
int numberTimeSlots int numberTimeSlots,
UCHAR fResTransIsLow
) )
{ {
int nEnv, i, k=0, tranIdx; int nEnv, i, k=0, tranIdx;
@ -727,8 +729,12 @@ static void generateFixFixOnly ( HANDLE_SBR_FRAME_INFO hSbrFrameInfo,
/* adjust segment-frequency-resolution according to the segment-length */ /* adjust segment-frequency-resolution according to the segment-length */
for (i=0; i<nEnv; i++){ for (i=0; i<nEnv; i++){
k = hSbrFrameInfo->borders[i+1] - hSbrFrameInfo->borders[i]; k = hSbrFrameInfo->borders[i+1] - hSbrFrameInfo->borders[i];
if (!fResTransIsLow)
hSbrFrameInfo->freqRes[i] = freqResTable[k]; hSbrFrameInfo->freqRes[i] = freqResTable[k];
hSbrGrid->v_f[i] = freqResTable[k]; else
hSbrFrameInfo->freqRes[i] = FREQ_RES_LOW;
hSbrGrid->v_f[i] = hSbrFrameInfo->freqRes[i];
} }
hSbrFrameInfo->nEnvelopes = nEnv; hSbrFrameInfo->nEnvelopes = nEnv;
@ -765,15 +771,16 @@ static void generateFixFixOnly ( HANDLE_SBR_FRAME_INFO hSbrFrameInfo,
*******************************************************************************/ *******************************************************************************/
void void
FDKsbrEnc_initFrameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, FDKsbrEnc_initFrameInfoGenerator (
HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
INT allowSpread, INT allowSpread,
INT numEnvStatic, INT numEnvStatic,
INT staticFraming, INT staticFraming,
INT timeSlots, INT timeSlots,
INT freq_res_fixfix const FREQ_RES* freq_res_fixfix
,int ldGrid ,UCHAR fResTransIsLow,
INT ldGrid
) )
{ /* FH 00-06-26 */ { /* FH 00-06-26 */
FDKmemclear(hSbrEnvFrame,sizeof(SBR_ENVELOPE_FRAME )); FDKmemclear(hSbrEnvFrame,sizeof(SBR_ENVELOPE_FRAME ));
@ -786,7 +793,9 @@ FDKsbrEnc_initFrameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
hSbrEnvFrame->allowSpread = allowSpread; hSbrEnvFrame->allowSpread = allowSpread;
hSbrEnvFrame->numEnvStatic = numEnvStatic; hSbrEnvFrame->numEnvStatic = numEnvStatic;
hSbrEnvFrame->staticFraming = staticFraming; hSbrEnvFrame->staticFraming = staticFraming;
hSbrEnvFrame->freq_res_fixfix = freq_res_fixfix; hSbrEnvFrame->freq_res_fixfix[0] = freq_res_fixfix[0];
hSbrEnvFrame->freq_res_fixfix[1] = freq_res_fixfix[1];
hSbrEnvFrame->fResTransIsLow = fResTransIsLow;
hSbrEnvFrame->length_v_bord = 0; hSbrEnvFrame->length_v_bord = 0;
hSbrEnvFrame->length_v_bordFollow = 0; hSbrEnvFrame->length_v_bordFollow = 0;
@ -804,6 +813,7 @@ FDKsbrEnc_initFrameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
hSbrEnvFrame->dmin = 2; hSbrEnvFrame->dmin = 2;
hSbrEnvFrame->dmax = 16; hSbrEnvFrame->dmax = 16;
hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_512LD; hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_512LD;
hSbrEnvFrame->SbrGrid.bufferFrameStart = 0;
} else } else
switch(timeSlots){ switch(timeSlots){
case NUMBER_TIME_SLOTS_1920: case NUMBER_TIME_SLOTS_1920:
@ -1862,19 +1872,28 @@ createDefFrameInfo(HANDLE_SBR_FRAME_INFO hSbrFrameInfo, INT nEnv, INT nTimeSlots
Functionname: ctrlSignal2FrameInfo Functionname: ctrlSignal2FrameInfo
******************************************************************************* *******************************************************************************
Description: Calculates frame_info struct from control signal. Description: Convert "clear-text" sbr_grid() to "frame info" used by the
envelope and noise floor estimators.
This is basically (except for "low level" calculations) the
bitstream decoder defined in the MPEG-4 standard, sub clause
4.6.18.3.3, Time / Frequency Grid. See inline comments for
explanation of the shorten and noise border algorithms.
Arguments: hSbrGrid - source Arguments: hSbrGrid - source
hSbrFrameInfo - destination hSbrFrameInfo - destination
freq_res_fixfix - frequency resolution for FIXFIX frames
Return: void; hSbrFrameInfo contains the updated FRAME_INFO struct Return: void; hSbrFrameInfo contains the updated FRAME_INFO struct
*******************************************************************************/ *******************************************************************************/
static void static void
ctrlSignal2FrameInfo (HANDLE_SBR_GRID hSbrGrid, ctrlSignal2FrameInfo (
HANDLE_SBR_FRAME_INFO hSbrFrameInfo, HANDLE_SBR_GRID hSbrGrid, /* input : the grid handle */
INT freq_res_fixfix) HANDLE_SBR_FRAME_INFO hSbrFrameInfo, /* output: the frame info handle */
FREQ_RES *freq_res_fixfix /* in/out: frequency resolution for FIXFIX frames */
)
{ {
INT frameSplit = 0;
INT nEnv = 0, border = 0, i, k, p /*?*/; INT nEnv = 0, border = 0, i, k, p /*?*/;
INT *v_r = hSbrGrid->bs_rel_bord; INT *v_r = hSbrGrid->bs_rel_bord;
INT *v_f = hSbrGrid->v_f; INT *v_f = hSbrGrid->v_f;
@ -1887,17 +1906,10 @@ ctrlSignal2FrameInfo (HANDLE_SBR_GRID hSbrGrid,
case FIXFIX: case FIXFIX:
createDefFrameInfo(hSbrFrameInfo, hSbrGrid->bs_num_env, numberTimeSlots); createDefFrameInfo(hSbrFrameInfo, hSbrGrid->bs_num_env, numberTimeSlots);
/* At this point all frequency resolutions are set to FREQ_RES_HIGH, so frameSplit = (hSbrFrameInfo->nEnvelopes > 1);
* only if freq_res_fixfix is set to FREQ_RES_LOW, they all have to be
* changed.
* snd */
if (freq_res_fixfix == FREQ_RES_LOW) {
for (i = 0; i < hSbrFrameInfo->nEnvelopes; i++) { for (i = 0; i < hSbrFrameInfo->nEnvelopes; i++) {
hSbrFrameInfo->freqRes[i] = FREQ_RES_LOW; hSbrGrid->v_f[i] = hSbrFrameInfo->freqRes[i] = freq_res_fixfix[frameSplit];
} }
}
/* ELD: store current frequency resolution */
hSbrGrid->v_f[0] = hSbrFrameInfo->freqRes[0];
break; break;
case FIXVAR: case FIXVAR:

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -89,6 +89,7 @@ amm-info@iis.fraunhofer.de
#define _FRAM_GEN_H #define _FRAM_GEN_H
#include "sbr_def.h" /* for MAX_ENVELOPES and MAX_NOISE_ENVELOPES in struct FRAME_INFO and CODEC_TYPE */ #include "sbr_def.h" /* for MAX_ENVELOPES and MAX_NOISE_ENVELOPES in struct FRAME_INFO and CODEC_TYPE */
#include "sbr_encoder.h" /* for FREQ_RES */
#define MAX_ENVELOPES_VARVAR MAX_ENVELOPES /*!< worst case number of envelopes in a VARVAR frame */ #define MAX_ENVELOPES_VARVAR MAX_ENVELOPES /*!< worst case number of envelopes in a VARVAR frame */
#define MAX_ENVELOPES_FIXVAR_VARFIX 4 /*!< worst case number of envelopes in VARFIX and FIXVAR frames */ #define MAX_ENVELOPES_FIXVAR_VARFIX 4 /*!< worst case number of envelopes in VARFIX and FIXVAR frames */
@ -114,7 +115,7 @@ typedef enum {
#define NUMBER_TIME_SLOTS_1920 15 #define NUMBER_TIME_SLOTS_1920 15
#define LD_PRETRAN_OFF 3 #define LD_PRETRAN_OFF 3
#define FRAME_MIDDLE_SLOT_512LD 0 #define FRAME_MIDDLE_SLOT_512LD 4
#define NUMBER_TIME_SLOTS_512LD 8 #define NUMBER_TIME_SLOTS_512LD 8
#define TRANSIENT_OFFSET_LD 0 #define TRANSIENT_OFFSET_LD 0
@ -250,7 +251,8 @@ typedef struct
/* basic tuning parameters */ /* basic tuning parameters */
INT staticFraming; /*!< 1: run static framing in time, i.e. exclusive use of bs_frame_class = FIXFIX */ INT staticFraming; /*!< 1: run static framing in time, i.e. exclusive use of bs_frame_class = FIXFIX */
INT numEnvStatic; /*!< number of envelopes per frame for static framing */ INT numEnvStatic; /*!< number of envelopes per frame for static framing */
INT freq_res_fixfix; /*!< envelope frequency resolution to use for bs_frame_class = FIXFIX */ FREQ_RES freq_res_fixfix[2]; /*!< envelope frequency resolution to use for bs_frame_class = FIXFIX; single env and split */
UCHAR fResTransIsLow; /*!< frequency resolution for transient frames - always low (0) or according to table (1) */
/* expert tuning parameters */ /* expert tuning parameters */
const int *v_tuningSegm; /*!< segment lengths to use around transient */ const int *v_tuningSegm; /*!< segment lengths to use around transient */
@ -286,13 +288,15 @@ typedef SBR_ENVELOPE_FRAME *HANDLE_SBR_ENVELOPE_FRAME;
void void
FDKsbrEnc_initFrameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, FDKsbrEnc_initFrameInfoGenerator (
HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
INT allowSpread, INT allowSpread,
INT numEnvStatic, INT numEnvStatic,
INT staticFraming, INT staticFraming,
INT timeSlots, INT timeSlots,
INT freq_res_fixfix const FREQ_RES* freq_res_fixfix
,int ldGrid ,UCHAR fResTransIsLow,
INT ldGrid
); );
HANDLE_SBR_FRAME_INFO HANDLE_SBR_FRAME_INFO

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -663,10 +663,27 @@ static void transientCleanUp(FIXP_DBL **quotaBuffer,
} }
/**************************************************************************/ /*****************************************************************************/
/*! /*!
\brief Do detection for one tonality estimate. \brief Detection for one tonality estimate.
This is the actual missing harmonics detection, using information from the
previous detection.
If a missing harmonic was detected (in a previous frame) due to too high
tonality differences, but there was not enough tonality difference in the
current frame, the detection algorithm still continues to trace the strongest
tone in the scalefactor band (assuming that this is the tone that is going to
be replaced in the decoder). This is done to avoid abrupt endings of sines
fading out (e.g. in the glockenspiel).
The function also tries to estimate where one sine is going to be replaced
with multiple sines (due to the patching). This is done by comparing the
tonality flatness measure of the original and the SBR signal.
The function also tries to estimate (for the scalefactor bands only
containing one qmf subband) when a strong tone in the original will be
replaced by a strong tone in the adjacent QMF subband.
\return none. \return none.
@ -694,10 +711,10 @@ static void detection(FIXP_DBL *quotaBuffer,
for(i=0;i<nSfb;i++){ for(i=0;i<nSfb;i++){
thresTemp = (guideVectors.guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)) thresTemp = (guideVectors.guideVectorDiff[i] != FL2FXCONST_DBL(0.0f))
? fixMax(fMult(mhThresh.decayGuideDiff,guideVectors.guideVectorDiff[i]), mhThresh.thresHoldDiffGuide) ? fMax(fMult(mhThresh.decayGuideDiff,guideVectors.guideVectorDiff[i]), mhThresh.thresHoldDiffGuide)
: mhThresh.thresHoldDiff; : mhThresh.thresHoldDiff;
thresTemp = fixMin(thresTemp, mhThresh.thresHoldDiff); thresTemp = fMin(thresTemp, mhThresh.thresHoldDiff);
if(pDiffVecScfb[i] > thresTemp){ if(pDiffVecScfb[i] > thresTemp){
pHarmVec[i] = 1; pHarmVec[i] = 1;
@ -813,8 +830,11 @@ static void detectionWithPrediction(FIXP_DBL **quotaBuffer,
if(newDetectionAllowed){ if(newDetectionAllowed){
/* Since we don't want to use the transient region for detection (since the tonality values
tend to be a bit unreliable for this region) the guide-values are copied to the current
starting point. */
if(totNoEst > 1){ if(totNoEst > 1){
start = detectionStart; start = detectionStart+1;
if (start != 0) { if (start != 0) {
FDKmemcpy(guideVectors[start].guideVectorDiff,guideVectors[0].guideVectorDiff,nSfb*sizeof(FIXP_DBL)); FDKmemcpy(guideVectors[start].guideVectorDiff,guideVectors[0].guideVectorDiff,nSfb*sizeof(FIXP_DBL));

View File

@ -298,7 +298,7 @@ FDKsbrEnc_sbrNoiseFloorEstimateQmf(HANDLE_SBR_NOISE_FLOOR_ESTIMATE h_sbrNoiseFlo
SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ SCHAR *indexVector, /*!< Index vector to obtain the patched data. */
INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component will be missing. */ INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component will be missing. */
INT startIndex, /*!< Start index. */ INT startIndex, /*!< Start index. */
int numberOfEstimatesPerFrame, /*!< The number of tonality estimates per frame. */ UINT numberOfEstimatesPerFrame, /*!< The number of tonality estimates per frame. */
int transientFrame, /*!< A flag indicating if a transient is present. */ int transientFrame, /*!< A flag indicating if a transient is present. */
INVF_MODE* pInvFiltLevels, /*!< Pointer to the vector holding the inverse filtering levels. */ INVF_MODE* pInvFiltLevels, /*!< Pointer to the vector holding the inverse filtering levels. */
UINT sbrSyntaxFlags UINT sbrSyntaxFlags

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -119,7 +119,7 @@ FDKsbrEnc_sbrNoiseFloorEstimateQmf(HANDLE_SBR_NOISE_FLOOR_ESTIMATE h_sbrNoiseFlo
SCHAR* indexVector, /*!< Index vector to obtain the patched data. */ SCHAR* indexVector, /*!< Index vector to obtain the patched data. */
INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component will be missing. */ INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component will be missing. */
INT startIndex, /*!< Start index. */ INT startIndex, /*!< Start index. */
int numberOfEstimatesPerFrame, /*!< The number of tonality estimates per frame. */ UINT numberOfEstimatesPerFrame, /*!< The number of tonality estimates per frame. */
INT transientFrame, /*!< A flag indicating if a transient is present. */ INT transientFrame, /*!< A flag indicating if a transient is present. */
INVF_MODE* pInvFiltLevels, /*!< Pointer to the vector holding the inverse filtering levels. */ INVF_MODE* pInvFiltLevels, /*!< Pointer to the vector holding the inverse filtering levels. */
UINT sbrSyntaxFlags UINT sbrSyntaxFlags

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -122,6 +122,8 @@ amm-info@iis.fraunhofer.de
/************ Definitions ***************/ /************ Definitions ***************/
#define SBR_COMP_MODE_DELTA 0 #define SBR_COMP_MODE_DELTA 0
#define SBR_COMP_MODE_CTS 1 #define SBR_COMP_MODE_CTS 1
#define SBR_MAX_ENERGY_VALUES 5
#define SBR_GLOBAL_TONALITY_VALUES 2
#define MAX_NUM_CHANNELS 2 #define MAX_NUM_CHANNELS 2
@ -232,6 +234,8 @@ amm-info@iis.fraunhofer.de
#define FREQ 0 #define FREQ 0
#define TIME 1 #define TIME 1
/* qmf data scaling */
#define QMF_SCALE_OFFSET 7
/* huffman tables */ /* huffman tables */
#define CODE_BOOK_SCF_LAV00 60 #define CODE_BOOK_SCF_LAV00 60
@ -268,12 +272,4 @@ typedef enum
} }
INVF_MODE; INVF_MODE;
typedef enum
{
FREQ_RES_LOW = 0,
FREQ_RES_HIGH
}
FREQ_RES;
#endif #endif

View File

@ -103,7 +103,7 @@ amm-info@iis.fraunhofer.de
#define SBRENCODER_LIB_VL0 3 #define SBRENCODER_LIB_VL0 3
#define SBRENCODER_LIB_VL1 3 #define SBRENCODER_LIB_VL1 3
#define SBRENCODER_LIB_VL2 8 #define SBRENCODER_LIB_VL2 12
@ -412,6 +412,23 @@ FDKsbrEnc_AdjustSbrSettings (const sbrConfigurationPtr config, /*! output, modif
config->codecSettings.transFac = transFac; config->codecSettings.transFac = transFac;
config->codecSettings.standardBitrate = standardBitrate; config->codecSettings.standardBitrate = standardBitrate;
if (bitRate < 28000) {
config->threshold_AmpRes_FF_m = (FIXP_DBL)MAXVAL_DBL;
config->threshold_AmpRes_FF_e = 7;
}
else if (bitRate >= 28000 && bitRate <= 48000) {
/* The float threshold is 75
0.524288f is fractional part of RELAXATION, the quotaMatrix and therefore tonality are scaled by this
2/3 is because the original implementation divides the tonality values by 3, here it's divided by 2
128 compensates the necessary shiftfactor of 7 */
config->threshold_AmpRes_FF_m = FL2FXCONST_DBL(75.0f*0.524288f/(2.0f/3.0f)/128.0f);
config->threshold_AmpRes_FF_e = 7;
}
else if (bitRate > 48000) {
config->threshold_AmpRes_FF_m = FL2FXCONST_DBL(0);
config->threshold_AmpRes_FF_e = 0;
}
if (bitRate==0) { if (bitRate==0) {
/* map vbr quality to bitrate */ /* map vbr quality to bitrate */
if (vbrMode < 30) if (vbrMode < 30)
@ -467,6 +484,57 @@ FDKsbrEnc_AdjustSbrSettings (const sbrConfigurationPtr config, /*! output, modif
config->stereoMode = sbrTuningTable[idx].stereoMode ; config->stereoMode = sbrTuningTable[idx].stereoMode ;
config->freqScale = sbrTuningTable[idx].freqScale ; config->freqScale = sbrTuningTable[idx].freqScale ;
if (numChannels == 1) {
/* stereo case */
switch (core) {
case AOT_AAC_LC:
if (bitRate <= (useSpeechConfig?24000U:20000U)) {
config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency resolution for non-split frames */
config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency resolution for split frames */
}
break;
case AOT_ER_AAC_ELD:
if (bitRate < 36000)
config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency resolution for split frames */
if (bitRate < 26000) {
config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency resolution for non-split frames */
config->fResTransIsLow = 1; /* for transient frames, set low frequency resolution */
}
break;
default:
break;
}
}
else {
/* stereo case */
switch (core) {
case AOT_AAC_LC:
if (bitRate <= 28000) {
config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency resolution for non-split frames */
config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency resolution for split frames */
}
break;
case AOT_ER_AAC_ELD:
if (bitRate < 72000) {
config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency resolution for split frames */
}
if (bitRate < 52000) {
config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency resolution for non-split frames */
config->fResTransIsLow = 1; /* for transient frames, set low frequency resolution */
}
break;
default:
break;
}
if (bitRate <= 28000) {
/*
additionally restrict frequency resolution in FIXFIX frames
to further reduce SBR payload size */
config->freq_res_fixfix[0] = FREQ_RES_LOW;
config->freq_res_fixfix[1] = FREQ_RES_LOW;
}
}
/* adjust usage of parametric coding dependent on bitrate and speech config flag */ /* adjust usage of parametric coding dependent on bitrate and speech config flag */
if (useSpeechConfig) if (useSpeechConfig)
config->parametricCoding = 0; config->parametricCoding = 0;
@ -515,6 +583,7 @@ static UINT
FDKsbrEnc_InitializeSbrDefaults (sbrConfigurationPtr config, FDKsbrEnc_InitializeSbrDefaults (sbrConfigurationPtr config,
INT downSampleFactor, INT downSampleFactor,
UINT codecGranuleLen UINT codecGranuleLen
,const INT isLowDelay
) )
{ {
if ( (downSampleFactor < 1 || downSampleFactor > 2) || if ( (downSampleFactor < 1 || downSampleFactor > 2) ||
@ -525,7 +594,11 @@ FDKsbrEnc_InitializeSbrDefaults (sbrConfigurationPtr config,
config->useWaveCoding = 0; config->useWaveCoding = 0;
config->crcSbr = 0; config->crcSbr = 0;
config->dynBwSupported = 1; config->dynBwSupported = 1;
if (isLowDelay)
config->tran_thr = 6000;
else
config->tran_thr = 13000; config->tran_thr = 13000;
config->parametricCoding = 1; config->parametricCoding = 1;
config->sbrFrameSize = codecGranuleLen * downSampleFactor; config->sbrFrameSize = codecGranuleLen * downSampleFactor;
@ -558,7 +631,9 @@ FDKsbrEnc_InitializeSbrDefaults (sbrConfigurationPtr config,
config->noiseFloorOffset = 0; config->noiseFloorOffset = 0;
config->startFreq = 5; /* 5.9 respectively 6.0 kHz at fs = 44.1/48 kHz */ config->startFreq = 5; /* 5.9 respectively 6.0 kHz at fs = 44.1/48 kHz */
config->stopFreq = 9; /* 16.2 respectively 16.8 kHz at fs = 44.1/48 kHz */ config->stopFreq = 9; /* 16.2 respectively 16.8 kHz at fs = 44.1/48 kHz */
config->freq_res_fixfix[0] = FREQ_RES_HIGH; /* non-split case */
config->freq_res_fixfix[1] = FREQ_RES_HIGH; /* split case */
config->fResTransIsLow = 0; /* for transient frames, set variable frequency resolution according to freqResTable */
/* header_extra_1 */ /* header_extra_1 */
config->freqScale = SBR_FREQ_SCALE_DEFAULT; config->freqScale = SBR_FREQ_SCALE_DEFAULT;
@ -1206,7 +1281,10 @@ initEnvChannel ( HANDLE_SBR_CONFIG_DATA sbrConfigData,
FDK_ASSERT(params->e >= 0); FDK_ASSERT(params->e >= 0);
hEnv->encEnvData.freq_res_fixfix = 1; hEnv->encEnvData.freq_res_fixfix[0] = params->freq_res_fixfix[0];
hEnv->encEnvData.freq_res_fixfix[1] = params->freq_res_fixfix[1];
hEnv->encEnvData.fResTransIsLow = params->fResTransIsLow;
hEnv->fLevelProtect = 0; hEnv->fLevelProtect = 0;
hEnv->encEnvData.ldGrid = (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) ? 1 : 0; hEnv->encEnvData.ldGrid = (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) ? 1 : 0;
@ -1348,11 +1426,29 @@ initEnvChannel ( HANDLE_SBR_CONFIG_DATA sbrConfigData,
e, e,
params->stat, params->stat,
timeSlots, timeSlots,
hEnv->encEnvData.freq_res_fixfix hEnv->encEnvData.freq_res_fixfix,
,hEnv->encEnvData.ldGrid hEnv->encEnvData.fResTransIsLow,
hEnv->encEnvData.ldGrid
); );
if(sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY)
{
INT bandwidth_qmf_slot = (sbrConfigData->sampleFreq>>1) / (sbrConfigData->noQmfBands);
if(FDKsbrEnc_InitSbrFastTransientDetector(
&hEnv->sbrFastTransientDetector,
sbrConfigData->noQmfSlots,
bandwidth_qmf_slot,
sbrConfigData->noQmfBands,
sbrConfigData->freqBandTable[0][0]
))
return(1);
}
/* The transient detector has to be initialized also if the fast transient
detector was active, because the values from the transient detector
structure are used. */
if(FDKsbrEnc_InitSbrTransientDetector (&hEnv->sbrTransientDetector, if(FDKsbrEnc_InitSbrTransientDetector (&hEnv->sbrTransientDetector,
sbrConfigData->sbrSyntaxFlags,
sbrConfigData->frameSize, sbrConfigData->frameSize,
sbrConfigData->sampleFreq, sbrConfigData->sampleFreq,
params, params,
@ -1658,6 +1754,8 @@ INT FDKsbrEnc_EnvInit (
/* other switches */ /* other switches */
hSbrElement->sbrConfigData.useWaveCoding = params->useWaveCoding; hSbrElement->sbrConfigData.useWaveCoding = params->useWaveCoding;
hSbrElement->sbrConfigData.useParametricCoding = params->parametricCoding; hSbrElement->sbrConfigData.useParametricCoding = params->parametricCoding;
hSbrElement->sbrConfigData.thresholdAmpResFF_m = params->threshold_AmpRes_FF_m;
hSbrElement->sbrConfigData.thresholdAmpResFF_e = params->threshold_AmpRes_FF_e;
/* init freq band table */ /* init freq band table */
if(updateFreqBandTable(&hSbrElement->sbrConfigData, if(updateFreqBandTable(&hSbrElement->sbrConfigData,
@ -1999,7 +2097,8 @@ INT sbrEncoder_Init(
*/ */
if ( ! FDKsbrEnc_InitializeSbrDefaults ( &sbrConfig[el], if ( ! FDKsbrEnc_InitializeSbrDefaults ( &sbrConfig[el],
*downSampleFactor, *downSampleFactor,
coreFrameLength coreFrameLength,
IS_LOWDELAY(aot)
) ) ) )
{ {
error = 1; error = 1;

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -684,6 +684,9 @@ const sbrTuningTable_t sbrTuningTable[] =
/** AAC LOW DELAY SECTION **/ /** AAC LOW DELAY SECTION **/
/* 24 kHz dual rate - 12kHz singlerate is not allowed (deactivated in FDKsbrEnc_IsSbrSettingAvail()) */
{ CODEC_AACLD, 8000, 32000, 12000, 1, 1, 1, 0, 0, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 8 kbit/s */
/*** mono ***/ /*** mono ***/
/* 16/32 kHz dual rate not yet tuned ->alb copied from non LD tables*/ /* 16/32 kHz dual rate not yet tuned ->alb copied from non LD tables*/
{ CODEC_AACLD, 16000, 18000, 16000, 1, 4, 5, 9, 7, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s wrr: tuned */ { CODEC_AACLD, 16000, 18000, 16000, 1, 4, 5, 9, 7, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s wrr: tuned */
@ -702,10 +705,10 @@ const sbrTuningTable_t sbrTuningTable[] =
{ CODEC_AACLD, 52000, 64001, 22050, 1, 13,11,11,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 56 kbit/s */ { CODEC_AACLD, 52000, 64001, 22050, 1, 13,11,11,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 56 kbit/s */
/* 24/48 kHz dual rate */ /* 24/48 kHz dual rate */
{ CODEC_AACLD, 20000, 22000, 24000, 1, 4, 1, 8, 4, 2, 3, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */ { CODEC_AACLD, 20000, 22000, 24000, 1, 3, 4, 8, 8, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */
{ CODEC_AACLD, 22000, 28000, 24000, 1, 3, 8, 8, 7, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 24 kbit/s */ { CODEC_AACLD, 22000, 28000, 24000, 1, 3, 8, 8, 7, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 24 kbit/s */
{ CODEC_AACLD, 28000, 36000, 24000, 1, 4, 8, 8, 7, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 32 kbit/s */ { CODEC_AACLD, 28000, 36000, 24000, 1, 4, 8, 8, 7, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 32 kbit/s */
{ CODEC_AACLD, 36000, 56000, 24000, 1, 8, 9, 9, 9, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 40 kbit/s */ { CODEC_AACLD, 36000, 56000, 24000, 1, 8, 9, 9, 8, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 40 kbit/s */
{ CODEC_AACLD, 56000, 64001, 24000, 1, 13,11,11,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 64 kbit/s */ { CODEC_AACLD, 56000, 64001, 24000, 1, 13,11,11,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 64 kbit/s */
/* 32/64 kHz dual rate */ /* placebo settings */ /*jgr: new, copy from CODEC_AAC */ /* 32/64 kHz dual rate */ /* placebo settings */ /*jgr: new, copy from CODEC_AAC */
@ -722,7 +725,7 @@ const sbrTuningTable_t sbrTuningTable[] =
{ CODEC_AACLD, 100000,160001, 44100, 1, 13,13,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 128 */ { CODEC_AACLD, 100000,160001, 44100, 1, 13,13,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 128 */
/* 48/96 kHz dual rate */ /* 32 and 40kbps line tuned for dual-rate SBR */ /* 48/96 kHz dual rate */ /* 32 and 40kbps line tuned for dual-rate SBR */
{ CODEC_AACLD, 36000, 60000, 48000, 1, 8, 7, 6, 9, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 40 */ { CODEC_AACLD, 36000, 60000, 48000, 1, 4, 7, 4, 4, 2, 0, 3, SBR_MONO, 3 }, /* nominal: 40 */
{ CODEC_AACLD, 60000, 72000, 48000, 1, 9, 9,10,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 64 */ { CODEC_AACLD, 60000, 72000, 48000, 1, 9, 9,10,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 64 */
{ CODEC_AACLD, 72000,100000, 48000, 1, 11,11,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 80 */ { CODEC_AACLD, 72000,100000, 48000, 1, 11,11,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 80 */
{ CODEC_AACLD, 100000,160001, 48000, 1, 13,13,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 128 */ { CODEC_AACLD, 100000,160001, 48000, 1, 13,13,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 128 */

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -682,7 +682,7 @@ FDKsbrEnc_InitTonCorrParamExtr (INT frameSize, /*!< Current
/* /*
Reset the patching and allocate memory for the quota matrix. Reset the patching and allocate memory for the quota matrix.
Assing parameters for the LPC analysis. Assuming parameters for the LPC analysis.
*/ */
if (sbrCfg->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { if (sbrCfg->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) {
switch (timeSlots) { switch (timeSlots) {
@ -690,7 +690,7 @@ FDKsbrEnc_InitTonCorrParamExtr (INT frameSize, /*!< Current
hTonCorr->lpcLength[0] = 8 - LPC_ORDER; hTonCorr->lpcLength[0] = 8 - LPC_ORDER;
hTonCorr->lpcLength[1] = 7 - LPC_ORDER; hTonCorr->lpcLength[1] = 7 - LPC_ORDER;
hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD; hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD;
hTonCorr->numberOfEstimatesPerFrame = sbrCfg->noQmfSlots / 7; hTonCorr->numberOfEstimatesPerFrame = 2; /* sbrCfg->noQmfSlots / 7 */
hTonCorr->frameStartIndexInvfEst = 0; hTonCorr->frameStartIndexInvfEst = 0;
hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD;
break; break;
@ -698,7 +698,7 @@ FDKsbrEnc_InitTonCorrParamExtr (INT frameSize, /*!< Current
hTonCorr->lpcLength[0] = 8 - LPC_ORDER; hTonCorr->lpcLength[0] = 8 - LPC_ORDER;
hTonCorr->lpcLength[1] = 8 - LPC_ORDER; hTonCorr->lpcLength[1] = 8 - LPC_ORDER;
hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD; hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD;
hTonCorr->numberOfEstimatesPerFrame = sbrCfg->noQmfSlots / 8; hTonCorr->numberOfEstimatesPerFrame = 2; /* sbrCfg->noQmfSlots / 8 */
hTonCorr->frameStartIndexInvfEst = 0; hTonCorr->frameStartIndexInvfEst = 0;
hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD;
break; break;

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -118,7 +118,7 @@ typedef struct
INT bufferLength; /*!< Length of the r and i buffers. */ INT bufferLength; /*!< Length of the r and i buffers. */
INT stepSize; /*!< Stride for the lpc estimate. */ INT stepSize; /*!< Stride for the lpc estimate. */
INT numberOfEstimates; /*!< The total number of estiamtes, available in the quotaMatrix.*/ INT numberOfEstimates; /*!< The total number of estiamtes, available in the quotaMatrix.*/
INT numberOfEstimatesPerFrame; /*!< The number of estimates per frame available in the quotaMatrix.*/ UINT numberOfEstimatesPerFrame; /*!< The number of estimates per frame available in the quotaMatrix.*/
INT lpcLength[2]; /*!< Segment length used for second order LPC analysis.*/ INT lpcLength[2]; /*!< Segment length used for second order LPC analysis.*/
INT nextSample; /*!< Where to start the LPC analysis of the current frame.*/ INT nextSample; /*!< Where to start the LPC analysis of the current frame.*/
INT move; /*!< How many estimates to move in the quotaMatrix, when buffering. */ INT move; /*!< How many estimates to move in the quotaMatrix, when buffering. */

View File

@ -89,7 +89,7 @@ amm-info@iis.fraunhofer.de
#include "genericStds.h" #include "genericStds.h"
#define NORM_QMF_ENERGY 5.684341886080801486968994140625e-14 /* 2^-44 */ #define NORM_QMF_ENERGY 9.31322574615479E-10 /* 2^-30 */
/* static FIXP_DBL ABS_THRES = fixMax( FL2FXCONST_DBL(1.28e5 * NORM_QMF_ENERGY), (FIXP_DBL)1) Minimum threshold for detecting changes */ /* static FIXP_DBL ABS_THRES = fixMax( FL2FXCONST_DBL(1.28e5 * NORM_QMF_ENERGY), (FIXP_DBL)1) Minimum threshold for detecting changes */
#define ABS_THRES ((FIXP_DBL)16) #define ABS_THRES ((FIXP_DBL)16)
@ -106,22 +106,30 @@ amm-info@iis.fraunhofer.de
\return calculated value \return calculated value
*******************************************************************************/ *******************************************************************************/
#define NRG_SHIFT 3 /* for energy summation */
static FIXP_DBL spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS], static FIXP_DBL spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS],
INT *scaleEnergies, INT *scaleEnergies,
FIXP_DBL EnergyTotal, FIXP_DBL EnergyTotal,
INT nSfb, INT nSfb,
INT start, INT start,
INT border, INT border,
INT stop) INT YBufferWriteOffset,
INT stop,
INT *result_e)
{ {
INT i,j; INT i,j;
INT len1,len2; INT len1,len2;
FIXP_DBL delta,tmp0,tmp1,tmp2; SCHAR energies_e_diff[NUMBER_TIME_SLOTS_2304], energies_e, energyTotal_e=19, energies_e_add;
FIXP_DBL accu1,accu2,delta_sum,result; SCHAR prevEnergies_e_diff, newEnergies_e_diff;
FIXP_DBL tmp0,tmp1;
FIXP_DBL accu1,accu2,accu1_init,accu2_init;
FIXP_DBL delta, delta_sum;
INT accu_e, tmp_e;
FDK_ASSERT(scaleEnergies[0] >= 0); delta_sum = FL2FXCONST_DBL(0.0f);
*result_e = 0;
/* equal for aac (would be not equal for mp3) */
len1 = border-start; len1 = border-start;
len2 = stop-border; len2 = stop-border;
@ -130,43 +138,91 @@ static FIXP_DBL spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FRE
pos_weight = FL2FXCONST_DBL(0.5f) - (len1*GetInvInt(len1+len2)); pos_weight = FL2FXCONST_DBL(0.5f) - (len1*GetInvInt(len1+len2));
pos_weight = /*FL2FXCONST_DBL(1.0)*/ (FIXP_DBL)MAXVAL_DBL - (fMult(pos_weight, pos_weight)<<2); pos_weight = /*FL2FXCONST_DBL(1.0)*/ (FIXP_DBL)MAXVAL_DBL - (fMult(pos_weight, pos_weight)<<2);
delta_sum = FL2FXCONST_DBL(0.0f); /*** Calc scaling for energies ***/
FDK_ASSERT(scaleEnergies[0] >= 0);
FDK_ASSERT(scaleEnergies[1] >= 0);
energies_e = 19 - FDKmin(scaleEnergies[0], scaleEnergies[1]);
/* limit shift for energy accumulation, energies_e can be -10 min. */
if (energies_e < -10) {
energies_e_add = -10 - energies_e;
energies_e = -10;
} else if (energies_e > 17) {
energies_e_add = energies_e - 17;
energies_e = 17;
} else {
energies_e_add = 0;
}
/* compensate scaling differences between scaleEnergies[0] and scaleEnergies[1] */
prevEnergies_e_diff = scaleEnergies[0] - FDKmin(scaleEnergies[0], scaleEnergies[1]) + energies_e_add + NRG_SHIFT;
newEnergies_e_diff = scaleEnergies[1] - FDKmin(scaleEnergies[0], scaleEnergies[1]) + energies_e_add + NRG_SHIFT;
prevEnergies_e_diff = fMin(prevEnergies_e_diff, DFRACT_BITS-1);
newEnergies_e_diff = fMin(newEnergies_e_diff, DFRACT_BITS-1);
for (i=start; i<YBufferWriteOffset; i++) {
energies_e_diff[i] = prevEnergies_e_diff;
}
for (i=YBufferWriteOffset; i<stop; i++) {
energies_e_diff[i] = newEnergies_e_diff;
}
/* Sum up energies of all QMF-timeslots for both halfs */ /* Sum up energies of all QMF-timeslots for both halfs */
for (j=0; j<nSfb; j++) { FDK_ASSERT(len1<=8); /* otherwise an overflow is possible */
#define NRG_SCALE 3 FDK_ASSERT(len2<=8); /* otherwise an overflow is possible */
/* init with some energy to prevent division by zero /* init with some energy to prevent division by zero
and to prevent splitting for very low levels */ and to prevent splitting for very low levels */
accu1 = ((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY*8.0/32))) << fixMin(scaleEnergies[0],25))>>NRG_SCALE; /* complex init for compare with original version */ accu1_init = scaleValue((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY))),-energies_e);
accu2 = ((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY*8.0/32))) << fixMin(scaleEnergies[0],25))>>NRG_SCALE; /* can be simplified in dsp implementation */ accu2_init = scaleValue((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY))),-energies_e);
accu1_init = fMult(accu1_init, (FIXP_DBL)len1<<((DFRACT_BITS-1)-NRG_SHIFT-1))<<1;
accu2_init = fMult(accu2_init, (FIXP_DBL)len2<<((DFRACT_BITS-1)-NRG_SHIFT-1))<<1;
for (j=0; j<nSfb; j++) {
accu1 = accu1_init;
accu2 = accu2_init;
accu_e = energies_e+3;
/* Sum up energies in first half */ /* Sum up energies in first half */
for (i=start; i<border; i++) { for (i=start; i<border; i++) {
accu1 += (Energies[i][j]>>NRG_SCALE); accu1 += scaleValue(Energies[i][j], -energies_e_diff[i]);
} }
/* Sum up energies in second half */ /* Sum up energies in second half */
for (i=border; i<stop; i++) { for (i=border; i<stop; i++) {
accu2 += (Energies[i][j]>>NRG_SCALE); accu2 += scaleValue(Energies[i][j], -energies_e_diff[i]);
} }
/* Energy change in current band */ /* Energy change in current band */
tmp0 = CalcLdData(accu2); #define LN2 FL2FXCONST_DBL(0.6931471806f) /* ln(2) */
tmp1 = CalcLdData(accu1); tmp0 = fLog2(accu2, accu_e) - fLog2(accu1, accu_e);
tmp2 = (tmp0 - tmp1 + CalcLdData(len1)-CalcLdData(len2)); tmp1 = fLog2((FIXP_DBL)len1, 31) - fLog2((FIXP_DBL)len2, 31);
delta = fixp_abs(fMult(tmp2, FL2FXCONST_DBL(0.6931471806f))); delta = fMult(LN2, (tmp0 + tmp1));
delta = (FIXP_DBL)FDKabs( delta );
/* Weighting with amplitude ratio of this band */ /* Weighting with amplitude ratio of this band */
result = (EnergyTotal == FL2FXCONST_DBL(0.0f)) accu_e++;
? FL2FXCONST_DBL(0.f) accu1>>=1;
: FDKsbrEnc_LSI_divide_scale_fract( (accu1+accu2), accu2>>=1;
(EnergyTotal>>NRG_SCALE)+(FIXP_DBL)1, if (accu_e & 1) {
(FIXP_DBL)MAXVAL_DBL >> fixMin(scaleEnergies[0],(DFRACT_BITS-1)) ); accu_e++;
accu1>>=1;
delta_sum += (FIXP_DBL)(fMult(sqrtFixp(result), delta)); accu2>>=1;
} }
delta_sum += fMult(sqrtFixp(accu1+accu2), delta);
*result_e = ((accu_e>>1) + LD_DATA_SHIFT);
}
energyTotal_e+=1; /* for a defined square result exponent, the exponent has to be even */
EnergyTotal<<=1;
delta_sum = fMult(delta_sum, invSqrtNorm2(EnergyTotal, &tmp_e));
*result_e = *result_e + (tmp_e-(energyTotal_e>>1));
return fMult(delta_sum, pos_weight); return fMult(delta_sum, pos_weight);
} }
@ -175,9 +231,12 @@ static FIXP_DBL spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FRE
******************************************************************************* *******************************************************************************
\brief Calculates total lowband energy \brief Calculates total lowband energy
The return value nrgTotal is scaled by the factor (1/32.0) The input values Energies[0] (low-band) are scaled by the factor
2^(14-*scaleEnergies[0])
The input values Energies[1] (high-band) are scaled by the factor
2^(14-*scaleEnergies[1])
\return total energy in the lowband \return total energy in the lowband, scaled by the factor 2^19
*******************************************************************************/ *******************************************************************************/
static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies, static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies,
int *scaleEnergies, int *scaleEnergies,
@ -194,6 +253,7 @@ static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies,
int ts,k; int ts,k;
/* Sum up lowband energy from one frame at offset tran_off */ /* Sum up lowband energy from one frame at offset tran_off */
/* freqBandTable[LORES] has MAX_FREQ_COEFFS/2 +1 coeefs max. */
for (ts=tran_offdiv2; ts<YBufferWriteOffset; ts++) { for (ts=tran_offdiv2; ts<YBufferWriteOffset; ts++) {
for (k = 0; k < freqBandTable[0]; k++) { for (k = 0; k < freqBandTable[0]; k++) {
accu1 += Energies[ts][k] >> 6; accu1 += Energies[ts][k] >> 6;
@ -201,12 +261,12 @@ static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies,
} }
for (; ts<tran_offdiv2+(slots>>nrgSzShift); ts++) { for (; ts<tran_offdiv2+(slots>>nrgSzShift); ts++) {
for (k = 0; k < freqBandTable[0]; k++) { for (k = 0; k < freqBandTable[0]; k++) {
accu2 += Energies[ts][k] >> 6; accu2 += Energies[ts][k] >> 9;
} }
} }
nrgTotal = ( (accu1 >> fixMin(scaleEnergies[0],(DFRACT_BITS-1))) nrgTotal = ( scaleValueSaturate(accu1, 1-scaleEnergies[0]) )
+ (accu2 >> fixMin(scaleEnergies[1],(DFRACT_BITS-1))) ) << (2); + ( scaleValueSaturate(accu2, 4-scaleEnergies[1]) );
return(nrgTotal); return(nrgTotal);
} }
@ -222,21 +282,23 @@ static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies,
is 1 SBR-band. Therefore the data to be fed into the spectralChange is 1 SBR-band. Therefore the data to be fed into the spectralChange
function is reduced. function is reduced.
The values EnergiesM are scaled by the factor (1/32.0) and scaleEnergies[0] The values EnergiesM are scaled by the factor (2^19-scaleEnergies[0]) for
The return value nrgTotal is scaled by the factor (1/32.0) slots<YBufferWriteOffset and by the factor (2^19-scaleEnergies[1]) for
slots>=YBufferWriteOffset.
\return total energy in the highband \return total energy in the highband, scaled by factor 2^19
*******************************************************************************/ *******************************************************************************/
static FIXP_DBL addHighbandEnergies(FIXP_DBL **RESTRICT Energies, /*!< input */ static FIXP_DBL addHighbandEnergies(FIXP_DBL **RESTRICT Energies, /*!< input */
INT *scaleEnergies, INT *scaleEnergies,
INT YBufferWriteOffset,
FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS], /*!< Combined output */ FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS], /*!< Combined output */
UCHAR *RESTRICT freqBandTable, UCHAR *RESTRICT freqBandTable,
INT nSfb, INT nSfb,
INT sbrSlots, INT sbrSlots,
INT timeStep) INT timeStep)
{ {
INT i,j,k,slotIn,slotOut,scale; INT i,j,k,slotIn,slotOut,scale[2];
INT li,ui; INT li,ui;
FIXP_DBL nrgTotal; FIXP_DBL nrgTotal;
FIXP_DBL accu = FL2FXCONST_DBL(0.0f); FIXP_DBL accu = FL2FXCONST_DBL(0.0f);
@ -245,7 +307,7 @@ static FIXP_DBL addHighbandEnergies(FIXP_DBL **RESTRICT Energies, /*!< input */
combine QMF-bands to SBR-bands, combine QMF-bands to SBR-bands,
combine Left and Right channel */ combine Left and Right channel */
for (slotOut=0; slotOut<sbrSlots; slotOut++) { for (slotOut=0; slotOut<sbrSlots; slotOut++) {
slotIn = 2*slotOut; slotIn = timeStep*slotOut;
for (j=0; j<nSfb; j++) { for (j=0; j<nSfb; j++) {
accu = FL2FXCONST_DBL(0.0f); accu = FL2FXCONST_DBL(0.0f);
@ -262,19 +324,29 @@ static FIXP_DBL addHighbandEnergies(FIXP_DBL **RESTRICT Energies, /*!< input */
} }
} }
scale = fixMin(8,scaleEnergies[0]); /* scale energies down before add up */ /* scale energies down before add up */
scale[0] = fixMin(8,scaleEnergies[0]);
scale[1] = fixMin(8,scaleEnergies[1]);
if ((scaleEnergies[0]-1) > (DFRACT_BITS-1) ) if ((scaleEnergies[0]-scale[0]) > (DFRACT_BITS-1) || (scaleEnergies[1]-scale[0]) > (DFRACT_BITS-1))
nrgTotal = FL2FXCONST_DBL(0.0f); nrgTotal = FL2FXCONST_DBL(0.0f);
else { else {
/* Now add all energies */ /* Now add all energies */
accu = FL2FXCONST_DBL(0.0f); accu = FL2FXCONST_DBL(0.0f);
for (slotOut=0; slotOut<sbrSlots; slotOut++) {
for (slotOut=0; slotOut<YBufferWriteOffset; slotOut++) {
for (j=0; j<nSfb; j++) { for (j=0; j<nSfb; j++) {
accu += (EnergiesM[slotOut][j] >> scale); accu += (EnergiesM[slotOut][j] >> scale[0]);
} }
} }
nrgTotal = accu >> (scaleEnergies[0]-scale); nrgTotal = accu >> (scaleEnergies[0]-scale[0]);
for (slotOut=YBufferWriteOffset; slotOut<sbrSlots; slotOut++) {
for (j=0; j<nSfb; j++) {
accu += (EnergiesM[slotOut][j] >> scale[0]);
}
}
nrgTotal = accu >> (scaleEnergies[1]-scale[1]);
} }
return(nrgTotal); return(nrgTotal);
@ -299,18 +371,23 @@ FDKsbrEnc_frameSplitter(FIXP_DBL **Energies,
int YBufferSzShift, int YBufferSzShift,
int nSfb, int nSfb,
int timeStep, int timeStep,
int no_cols) int no_cols,
FIXP_DBL* tonality)
{ {
if (tran_vector[1]==0) /* no transient was detected */ if (tran_vector[1]==0) /* no transient was detected */
{ {
FIXP_DBL delta; FIXP_DBL delta;
FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS]; INT delta_e;
FIXP_DBL (*EnergiesM)[MAX_FREQ_COEFFS];
FIXP_DBL EnergyTotal,newLowbandEnergy,newHighbandEnergy; FIXP_DBL EnergyTotal,newLowbandEnergy,newHighbandEnergy;
INT border; INT border;
INT sbrSlots = fMultI(GetInvInt(timeStep),no_cols); INT sbrSlots = fMultI(GetInvInt(timeStep),no_cols);
C_ALLOC_SCRATCH_START(_EnergiesM, FIXP_DBL, NUMBER_TIME_SLOTS_2304*MAX_FREQ_COEFFS)
FDK_ASSERT( sbrSlots * timeStep == no_cols ); FDK_ASSERT( sbrSlots * timeStep == no_cols );
EnergiesM = (FIXP_DBL(*)[MAX_FREQ_COEFFS])_EnergiesM;
/* /*
Get Lowband-energy over a range of 2 frames (Look half a frame back and ahead). Get Lowband-energy over a range of 2 frames (Look half a frame back and ahead).
*/ */
@ -324,16 +401,13 @@ FDKsbrEnc_frameSplitter(FIXP_DBL **Energies,
newHighbandEnergy = addHighbandEnergies(Energies, newHighbandEnergy = addHighbandEnergies(Energies,
scaleEnergies, scaleEnergies,
YBufferWriteOffset,
EnergiesM, EnergiesM,
freqBandTable, freqBandTable,
nSfb, nSfb,
sbrSlots, sbrSlots,
timeStep); timeStep);
if ( h_sbrTransientDetector->frameShift != 0 ) {
if (tran_vector[1]==0)
tran_vector[0] = 0;
} else
{ {
/* prevLowBandEnergy: Corresponds to 1 frame, starting with half a frame look-behind /* prevLowBandEnergy: Corresponds to 1 frame, starting with half a frame look-behind
newLowbandEnergy: Corresponds to 1 frame, starting in the middle of the current frame */ newLowbandEnergy: Corresponds to 1 frame, starting in the middle of the current frame */
@ -343,23 +417,39 @@ FDKsbrEnc_frameSplitter(FIXP_DBL **Energies,
of a FIXFIX-frame with 2 envelopes. */ of a FIXFIX-frame with 2 envelopes. */
border = (sbrSlots+1) >> 1; border = (sbrSlots+1) >> 1;
if ( (INT)EnergyTotal&0xffffffe0 && (scaleEnergies[0]<32 || scaleEnergies[1]<32) ) /* i.e. > 31 */ {
delta = spectralChange(EnergiesM, delta = spectralChange(EnergiesM,
scaleEnergies, scaleEnergies,
EnergyTotal, EnergyTotal,
nSfb, nSfb,
0, 0,
border, border,
sbrSlots); YBufferWriteOffset,
sbrSlots,
&delta_e
);
} else {
delta = FL2FXCONST_DBL(0.0f);
delta_e = 0;
if (delta > (h_sbrTransientDetector->split_thr >> LD_DATA_SHIFT)) /* delta scaled by 1/64 */ /* set tonality to 0 when energy is very low, since the amplitude
resolution should then be low as well */
*tonality = FL2FXCONST_DBL(0.0f);
}
if ( fIsLessThan(h_sbrTransientDetector->split_thr_m, h_sbrTransientDetector->split_thr_e, delta, delta_e) ) {
tran_vector[0] = 1; /* Set flag for splitting */ tran_vector[0] = 1; /* Set flag for splitting */
else } else {
tran_vector[0] = 0; tran_vector[0] = 0;
} }
}
/* Update prevLowBandEnergy */ /* Update prevLowBandEnergy */
h_sbrTransientDetector->prevLowBandEnergy = newLowbandEnergy; h_sbrTransientDetector->prevLowBandEnergy = newLowbandEnergy;
h_sbrTransientDetector->prevHighBandEnergy = newHighbandEnergy; h_sbrTransientDetector->prevHighBandEnergy = newHighbandEnergy;
C_ALLOC_SCRATCH_END(_EnergiesM, FIXP_DBL, NUMBER_TIME_SLOTS_2304*MAX_FREQ_COEFFS)
} }
} }
@ -636,6 +726,7 @@ FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTran,
int int
FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
UINT sbrSyntaxFlags, /* SBR syntax flags derived from AOT. */
INT frameSize, INT frameSize,
INT sampleFreq, INT sampleFreq,
sbrConfigurationPtr params, sbrConfigurationPtr params,
@ -649,8 +740,8 @@ FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientD
{ {
INT totalBitrate = params->codecSettings.standardBitrate * params->codecSettings.nChannels; INT totalBitrate = params->codecSettings.standardBitrate * params->codecSettings.nChannels;
INT codecBitrate = params->codecSettings.bitRate; INT codecBitrate = params->codecSettings.bitRate;
FIXP_DBL bitrateFactor_fix, framedur_fix; FIXP_DBL bitrateFactor_m, framedur_fix;
INT scale_0, scale_1; INT bitrateFactor_e, tmp_e;
FDKmemclear(h_sbrTransientDetector,sizeof(SBR_TRANSIENT_DETECTOR)); FDKmemclear(h_sbrTransientDetector,sizeof(SBR_TRANSIENT_DETECTOR));
@ -658,11 +749,12 @@ FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientD
h_sbrTransientDetector->tran_off = tran_off; h_sbrTransientDetector->tran_off = tran_off;
if(codecBitrate) { if(codecBitrate) {
bitrateFactor_fix = fDivNorm((FIXP_DBL)totalBitrate, (FIXP_DBL)(codecBitrate<<2),&scale_0); bitrateFactor_m = fDivNorm((FIXP_DBL)totalBitrate, (FIXP_DBL)(codecBitrate<<2),&bitrateFactor_e);
bitrateFactor_e += 2;
} }
else { else {
bitrateFactor_fix = FL2FXCONST_DBL(1.0/4.0); bitrateFactor_m = FL2FXCONST_DBL(1.0/4.0);
scale_0 = 0; bitrateFactor_e = 2;
} }
framedur_fix = fDivNorm(frameSize, sampleFreq); framedur_fix = fDivNorm(frameSize, sampleFreq);
@ -674,9 +766,13 @@ FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientD
FIXP_DBL tmp = framedur_fix - FL2FXCONST_DBL(0.010); FIXP_DBL tmp = framedur_fix - FL2FXCONST_DBL(0.010);
tmp = fixMax(tmp, FL2FXCONST_DBL(0.0001)); tmp = fixMax(tmp, FL2FXCONST_DBL(0.0001));
tmp = fDivNorm(FL2FXCONST_DBL(0.000075), fPow2(tmp), &scale_1); tmp = fDivNorm(FL2FXCONST_DBL(0.000075), fPow2(tmp), &tmp_e);
scale_1 = (scale_1 + scale_0 + 2); bitrateFactor_e = (tmp_e + bitrateFactor_e);
if(sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) {
bitrateFactor_e--; /* divide by 2 */
}
FDK_ASSERT(no_cols <= QMF_MAX_TIME_SLOTS); FDK_ASSERT(no_cols <= QMF_MAX_TIME_SLOTS);
FDK_ASSERT(no_rows <= QMF_CHANNELS); FDK_ASSERT(no_rows <= QMF_CHANNELS);
@ -684,7 +780,8 @@ FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientD
h_sbrTransientDetector->no_cols = no_cols; h_sbrTransientDetector->no_cols = no_cols;
h_sbrTransientDetector->tran_thr = (FIXP_DBL)((params->tran_thr << (32-24-1)) / no_rows); h_sbrTransientDetector->tran_thr = (FIXP_DBL)((params->tran_thr << (32-24-1)) / no_rows);
h_sbrTransientDetector->tran_fc = tran_fc; h_sbrTransientDetector->tran_fc = tran_fc;
h_sbrTransientDetector->split_thr = scaleValueSaturate(fMult(tmp, bitrateFactor_fix), scale_1); h_sbrTransientDetector->split_thr_m = fMult(tmp, bitrateFactor_m);
h_sbrTransientDetector->split_thr_e = bitrateFactor_e;
h_sbrTransientDetector->no_rows = no_rows; h_sbrTransientDetector->no_rows = no_rows;
h_sbrTransientDetector->mode = params->tran_det_mode; h_sbrTransientDetector->mode = params->tran_det_mode;
h_sbrTransientDetector->prevLowBandEnergy = FL2FXCONST_DBL(0.0f); h_sbrTransientDetector->prevLowBandEnergy = FL2FXCONST_DBL(0.0f);
@ -692,3 +789,281 @@ FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientD
return (0); return (0);
} }
#define ENERGY_SCALING_SIZE 32
INT FDKsbrEnc_InitSbrFastTransientDetector(
HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector,
const INT time_slots_per_frame,
const INT bandwidth_qmf_slot,
const INT no_qmf_channels,
const INT sbr_qmf_1st_band
)
{
int i, e;
int buff_size;
FIXP_DBL myExp;
FIXP_DBL myExpSlot;
h_sbrFastTransientDetector->lookahead = TRAN_DET_LOOKAHEAD;
h_sbrFastTransientDetector->nTimeSlots = time_slots_per_frame;
buff_size = h_sbrFastTransientDetector->nTimeSlots + h_sbrFastTransientDetector->lookahead;
for(i=0; i< buff_size; i++) {
h_sbrFastTransientDetector->delta_energy[i] = FL2FXCONST_DBL(0.0f);
h_sbrFastTransientDetector->energy_timeSlots[i] = FL2FXCONST_DBL(0.0f);
h_sbrFastTransientDetector->lowpass_energy[i] = FL2FXCONST_DBL(0.0f);
h_sbrFastTransientDetector->transientCandidates[i] = 0;
}
FDK_ASSERT(bandwidth_qmf_slot > 0.f);
h_sbrFastTransientDetector->stopBand = fMin(TRAN_DET_STOP_FREQ/bandwidth_qmf_slot, no_qmf_channels);
h_sbrFastTransientDetector->startBand = fMin(sbr_qmf_1st_band, h_sbrFastTransientDetector->stopBand - TRAN_DET_MIN_QMFBANDS);
FDK_ASSERT(h_sbrFastTransientDetector->startBand < no_qmf_channels);
FDK_ASSERT(h_sbrFastTransientDetector->startBand < h_sbrFastTransientDetector->stopBand);
FDK_ASSERT(h_sbrFastTransientDetector->startBand > 1);
FDK_ASSERT(h_sbrFastTransientDetector->stopBand > 1);
/* the energy weighting and adding up has a headroom of 6 Bits,
so up to 64 bands can be added without potential overflow. */
FDK_ASSERT(h_sbrFastTransientDetector->stopBand - h_sbrFastTransientDetector->startBand <= 64);
/* QMF_HP_dB_SLOPE_FIX says that we want a 20 dB per 16 kHz HP filter.
The following lines map this to the QMF bandwidth. */
#define EXP_E 7 /* QMF_CHANNELS (=64) multiplications max, max. allowed sum is 0.5 */
myExp = fMultNorm(QMF_HP_dBd_SLOPE_FIX, (FIXP_DBL)bandwidth_qmf_slot, &e);
myExp = scaleValueSaturate(myExp, e+0+DFRACT_BITS-1-EXP_E);
myExpSlot = myExp;
for(i=0; i<QMF_CHANNELS; i++){
/* Calculate dBf over all qmf bands:
dBf = (10^(0.002266f/10*bw(slot)))^(band) =
= 2^(log2(10)*0.002266f/10*bw(slot)*band) =
= 2^(0.00075275f*bw(slot)*band) */
FIXP_DBL dBf_m; /* dBf mantissa */
INT dBf_e; /* dBf exponent */
INT tmp;
INT dBf_int; /* dBf integer part */
FIXP_DBL dBf_fract; /* dBf fractional part */
/* myExp*(i+1) = myExp_int - myExp_fract
myExp*(i+1) is split up here for better accuracy of CalcInvLdData(),
for its result can be split up into an integer and a fractional part */
/* Round up to next integer */
FIXP_DBL myExp_int = (myExpSlot & (FIXP_DBL)0xfe000000) + (FIXP_DBL)0x02000000;
/* This is the fractional part that needs to be substracted */
FIXP_DBL myExp_fract = myExp_int - myExpSlot;
/* Calc integer part */
dBf_int = CalcInvLdData(myExp_int);
/* The result needs to be re-scaled. The ld(myExp_int) had been scaled by EXP_E,
the CalcInvLdData expects the operand to be scaled by LD_DATA_SHIFT.
Therefore, the correctly scaled result is dBf_int^(2^(EXP_E-LD_DATA_SHIFT)),
which is dBf_int^2 */
dBf_int *= dBf_int;
/* Calc fractional part */
dBf_fract = CalcInvLdData(-myExp_fract);
/* The result needs to be re-scaled. The ld(myExp_fract) had been scaled by EXP_E,
the CalcInvLdData expects the operand to be scaled by LD_DATA_SHIFT.
Therefore, the correctly scaled result is dBf_fract^(2^(EXP_E-LD_DATA_SHIFT)),
which is dBf_fract^2 */
dBf_fract = fMultNorm(dBf_fract, dBf_fract, &tmp);
/* Get worst case scaling of multiplication result */
dBf_e = (DFRACT_BITS-1 - tmp) - CountLeadingBits(dBf_int);
/* Now multiply integer with fractional part of the result, thus resulting
in the overall accurate fractional result */
dBf_m = fMultNorm(dBf_int, dBf_fract, &e);
dBf_m = scaleValueSaturate(dBf_m, e+DFRACT_BITS-1+tmp-dBf_e);
myExpSlot += myExp;
/* Keep the results */
h_sbrFastTransientDetector->dBf_m[i] = dBf_m;
h_sbrFastTransientDetector->dBf_e[i] = dBf_e;
}
/* Make sure that dBf is greater than 1.0 (because it should be a highpass) */
/* ... */
return 0;
}
void FDKsbrEnc_fastTransientDetect(
const HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector,
const FIXP_DBL *const *Energies,
const int *const scaleEnergies,
const INT YBufferWriteOffset,
UCHAR *const tran_vector
)
{
int timeSlot, band;
FIXP_DBL max_delta_energy; /* helper to store maximum energy ratio */
int max_delta_energy_scale; /* helper to store scale of maximum energy ratio */
int ind_max = 0; /* helper to store index of maximum energy ratio */
int isTransientInFrame = 0;
const int nTimeSlots = h_sbrFastTransientDetector->nTimeSlots;
const int lookahead = h_sbrFastTransientDetector->lookahead;
const int startBand = h_sbrFastTransientDetector->startBand;
const int stopBand = h_sbrFastTransientDetector->stopBand;
int * transientCandidates = h_sbrFastTransientDetector->transientCandidates;
FIXP_DBL * energy_timeSlots = h_sbrFastTransientDetector->energy_timeSlots;
int * energy_timeSlots_scale = h_sbrFastTransientDetector->energy_timeSlots_scale;
FIXP_DBL * delta_energy = h_sbrFastTransientDetector->delta_energy;
int * delta_energy_scale = h_sbrFastTransientDetector->delta_energy_scale;
const FIXP_DBL thr = TRAN_DET_THRSHLD;
const INT thr_scale = TRAN_DET_THRSHLD_SCALE;
/*reset transient info*/
tran_vector[2] = 0;
/* reset transient candidates */
FDKmemclear(transientCandidates+lookahead, nTimeSlots*sizeof(int));
for(timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) {
int i, norm;
FIXP_DBL tmpE = FL2FXCONST_DBL(0.0f);
int headroomEnSlot = DFRACT_BITS-1;
FIXP_DBL smallNRG = FL2FXCONST_DBL(1e-2f);
FIXP_DBL denominator;
INT denominator_scale;
/* determine minimum headroom of energy values for this timeslot */
for(band = startBand; band < stopBand; band++) {
int tmp_headroom = fNormz(Energies[timeSlot][band])-1;
if(tmp_headroom < headroomEnSlot){
headroomEnSlot = tmp_headroom;
}
}
for(i = 0, band = startBand; band < stopBand; band++, i++) {
/* energy is weighted by weightingfactor stored in dBf_m array */
/* dBf_m index runs from 0 to stopBand-startband */
/* energy shifted by calculated headroom for maximum precision */
FIXP_DBL weightedEnergy = fMult(Energies[timeSlot][band]<<headroomEnSlot, h_sbrFastTransientDetector->dBf_m[i]);
/* energy is added up */
/* shift by 6 to have a headroom for maximum 64 additions */
/* shift by dBf_e to handle weighting factor dependent scale factors */
tmpE += weightedEnergy >> (6 + (10 - h_sbrFastTransientDetector->dBf_e[i]));
}
/* store calculated energy for timeslot */
energy_timeSlots[timeSlot] = tmpE;
/* calculate overall scale factor for energy of this timeslot */
/* = original scale factor of energies (-scaleEnergies[0]+2*QMF_SCALE_OFFSET or -scaleEnergies[1]+2*QMF_SCALE_OFFSET */
/* depending on YBufferWriteOffset) */
/* + weighting factor scale (10) */
/* + adding up scale factor ( 6) */
/* - headroom of energy value (headroomEnSlot) */
if(timeSlot < YBufferWriteOffset){
energy_timeSlots_scale[timeSlot] = (-scaleEnergies[0]+2*QMF_SCALE_OFFSET) + (10+6) - headroomEnSlot;
} else {
energy_timeSlots_scale[timeSlot] = (-scaleEnergies[1]+2*QMF_SCALE_OFFSET) + (10+6) - headroomEnSlot;
}
/* Add a small energy to the denominator, thus making the transient
detection energy-dependent. Loud transients are being detected,
silent ones not. */
/* make sure that smallNRG does not overflow */
if ( -energy_timeSlots_scale[timeSlot-1] + 1 > 5 )
{
denominator = smallNRG;
denominator_scale = 0;
} else {
/* Leave an additional headroom of 1 bit for this addition. */
smallNRG = scaleValue(smallNRG, -(energy_timeSlots_scale[timeSlot-1] + 1));
denominator = (energy_timeSlots[timeSlot-1]>>1) + smallNRG;
denominator_scale = energy_timeSlots_scale[timeSlot-1]+1;
}
delta_energy[timeSlot] = fDivNorm(energy_timeSlots[timeSlot], denominator, &norm);
delta_energy_scale[timeSlot] = energy_timeSlots_scale[timeSlot] - denominator_scale + norm;
}
/*get transient candidates*/
/* For every timeslot, check if delta(E) exceeds the threshold. If it did,
it could potentially be marked as a transient candidate. However, the 2
slots before the current one must not be transients with an energy higher
than 1.4*E(current). If both aren't transients or if the energy of the
current timesolot is more than 1.4 times higher than the energy in the
last or the one before the last slot, it is marked as a transient.*/
FDK_ASSERT(lookahead >= 2);
for(timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) {
FIXP_DBL energy_cur_slot_weighted = fMult(energy_timeSlots[timeSlot],FL2FXCONST_DBL(1.0f/1.4f));
if( !fIsLessThan(delta_energy[timeSlot], delta_energy_scale[timeSlot], thr, thr_scale) &&
( ((transientCandidates[timeSlot-2]==0) && (transientCandidates[timeSlot-1]==0)) ||
!fIsLessThan(energy_cur_slot_weighted, energy_timeSlots_scale[timeSlot], energy_timeSlots[timeSlot-1], energy_timeSlots_scale[timeSlot-1] ) ||
!fIsLessThan(energy_cur_slot_weighted, energy_timeSlots_scale[timeSlot], energy_timeSlots[timeSlot-2], energy_timeSlots_scale[timeSlot-2] )
)
)
{
/* in case of strong transients, subsequent
* qmf slots might be recognized as transients. */
transientCandidates[timeSlot] = 1;
}
}
/*get transient with max energy*/
max_delta_energy = FL2FXCONST_DBL(0.0f);
max_delta_energy_scale = 0;
ind_max = 0;
isTransientInFrame = 0;
for(timeSlot = 0; timeSlot < nTimeSlots; timeSlot++) {
int scale = fMax(delta_energy_scale[timeSlot], max_delta_energy_scale);
if(transientCandidates[timeSlot] && ( (delta_energy[timeSlot] >> (scale - delta_energy_scale[timeSlot])) > (max_delta_energy >> (scale - max_delta_energy_scale)) ) ) {
max_delta_energy = delta_energy[timeSlot];
max_delta_energy_scale = scale;
ind_max = timeSlot;
isTransientInFrame = 1;
}
}
/*from all transient candidates take the one with the biggest energy*/
if(isTransientInFrame) {
tran_vector[0] = ind_max;
tran_vector[1] = 1;
} else {
/*reset transient info*/
tran_vector[0] = tran_vector[1] = 0;
}
/*check for transients in lookahead*/
for(timeSlot = nTimeSlots; timeSlot < nTimeSlots + lookahead; timeSlot++) {
if(transientCandidates[timeSlot]) {
tran_vector[2] = 1;
}
}
/*update buffers*/
for(timeSlot = 0; timeSlot < lookahead; timeSlot++) {
transientCandidates[timeSlot] = transientCandidates[nTimeSlots + timeSlot];
/* fixpoint stuff */
energy_timeSlots[timeSlot] = energy_timeSlots[nTimeSlots + timeSlot];
energy_timeSlots_scale[timeSlot] = energy_timeSlots_scale[nTimeSlots + timeSlot];
delta_energy[timeSlot] = delta_energy[nTimeSlots + timeSlot];
delta_energy_scale[timeSlot] = delta_energy_scale[nTimeSlots + timeSlot];
}
}

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -96,7 +96,8 @@ typedef struct
FIXP_DBL transients[QMF_MAX_TIME_SLOTS+(QMF_MAX_TIME_SLOTS/2)]; FIXP_DBL transients[QMF_MAX_TIME_SLOTS+(QMF_MAX_TIME_SLOTS/2)];
FIXP_DBL thresholds[QMF_CHANNELS]; FIXP_DBL thresholds[QMF_CHANNELS];
FIXP_DBL tran_thr; /* Master threshold for transient signals */ FIXP_DBL tran_thr; /* Master threshold for transient signals */
FIXP_DBL split_thr; /* Threshold for splitting FIXFIX-frames into 2 env */ FIXP_DBL split_thr_m; /* Threshold for splitting FIXFIX-frames into 2 env */
INT split_thr_e; /* Scale for splitting threshold */
FIXP_DBL prevLowBandEnergy; /* Energy of low band */ FIXP_DBL prevLowBandEnergy; /* Energy of low band */
FIXP_DBL prevHighBandEnergy; /* Energy of high band */ FIXP_DBL prevHighBandEnergy; /* Energy of high band */
INT tran_fc; /* Number of lowband subbands to discard */ INT tran_fc; /* Number of lowband subbands to discard */
@ -112,6 +113,57 @@ SBR_TRANSIENT_DETECTOR;
typedef SBR_TRANSIENT_DETECTOR *HANDLE_SBR_TRANSIENT_DETECTOR; typedef SBR_TRANSIENT_DETECTOR *HANDLE_SBR_TRANSIENT_DETECTOR;
#define TRAN_DET_LOOKAHEAD 2
#define TRAN_DET_START_FREQ 4500 /*start frequency for transient detection*/
#define TRAN_DET_STOP_FREQ 13500 /*stop frequency for transient detection*/
#define TRAN_DET_MIN_QMFBANDS 4 /* minimum qmf bands for transient detection */
#define QMF_HP_dBd_SLOPE_FIX FL2FXCONST_DBL(0.00075275f) /* 0.002266f/10 * log2(10) */
#define TRAN_DET_THRSHLD FL2FXCONST_DBL(3.2f/4.f)
#define TRAN_DET_THRSHLD_SCALE (2)
typedef struct
{
INT transientCandidates[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD];
INT nTimeSlots;
INT lookahead;
INT startBand;
INT stopBand;
FIXP_DBL dBf_m[QMF_CHANNELS];
INT dBf_e[QMF_CHANNELS];
FIXP_DBL energy_timeSlots[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD];
INT energy_timeSlots_scale[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD];
FIXP_DBL delta_energy[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD];
INT delta_energy_scale[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD];
FIXP_DBL lowpass_energy[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD];
INT lowpass_energy_scale[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD];
#if defined (FTD_LOG)
FDKFILE *ftd_log;
#endif
}
FAST_TRAN_DETECTOR;
typedef FAST_TRAN_DETECTOR *HANDLE_FAST_TRAN_DET;
INT FDKsbrEnc_InitSbrFastTransientDetector(
HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector,
const INT time_slots_per_frame,
const INT bandwidth_qmf_slot,
const INT no_qmf_channels,
const INT sbr_qmf_1st_band
);
void FDKsbrEnc_fastTransientDetect(
const HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector,
const FIXP_DBL *const *Energies,
const int *const scaleEnergies,
const INT YBufferWriteOffset,
UCHAR *const tran_vector
);
void void
FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
FIXP_DBL **Energies, FIXP_DBL **Energies,
@ -124,6 +176,7 @@ FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
int int
FDKsbrEnc_InitSbrTransientDetector (HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, FDKsbrEnc_InitSbrTransientDetector (HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
UINT sbrSyntaxFlags, /* SBR syntax flags derived from AOT. */
INT frameSize, INT frameSize,
INT sampleFreq, INT sampleFreq,
sbrConfigurationPtr params, sbrConfigurationPtr params,
@ -145,6 +198,6 @@ FDKsbrEnc_frameSplitter(FIXP_DBL **Energies,
int YBufferSzShift, int YBufferSzShift,
int nSfb, int nSfb,
int timeStep, int timeStep,
int no_cols); int no_cols,
FIXP_DBL* tonality);
#endif #endif