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"
#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
extern "C" {
#endif

View File

@ -98,7 +98,7 @@ amm-info@iis.fraunhofer.de
/* Encoder library info */
#define AACENCODER_LIB_VL0 3
#define AACENCODER_LIB_VL1 4
#define AACENCODER_LIB_VL2 19
#define AACENCODER_LIB_VL2 22
#define AACENCODER_LIB_TITLE "AAC Encoder"
#ifdef __ANDROID__
#define AACENCODER_LIB_BUILD_DATE ""
@ -813,11 +813,16 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder,
switch ( hAacConfig->audioObjectType ) {
case AOT_ER_AAC_LD:
case AOT_ER_AAC_ELD:
if (config->userBitrateMode==8) {
hAacConfig->bitrateMode = 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) {
return AACENC_INVALID_CONFIG;

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -95,13 +95,7 @@ amm-info@iis.fraunhofer.de
#include "aacEnc_rom.h"
#include "aacenc_tns.h"
enum {
HIFILT = 0, /* index of higher filter */
LOFILT = 1 /* index of lower filter */
};
#define FILTER_DIRECTION 0
#define FILTER_DIRECTION 0 /* 0 = up, 1 = down */
static const FIXP_DBL acfWindowLong[12+3+1] = {
0x7fffffff,0x7fb80000,0x7ee00000,0x7d780000,0x7b800000,0x78f80000,0x75e00000,0x72380000,
@ -112,20 +106,6 @@ static const FIXP_DBL acfWindowShort[4+3+1] = {
0x7fffffff,0x7e000000,0x78000000,0x6e000000,0x60000000,0x4e000000,0x38000000,0x1e000000
};
typedef struct {
INT filterEnabled[MAX_NUM_OF_FILTERS];
INT threshOn[MAX_NUM_OF_FILTERS]; /* min. prediction gain for using tns TABUL*/
INT filterStartFreq[MAX_NUM_OF_FILTERS]; /* lowest freq for lpc TABUL*/
INT tnsLimitOrder[MAX_NUM_OF_FILTERS]; /* Limit for TNS order TABUL*/
INT tnsFilterDirection[MAX_NUM_OF_FILTERS]; /* Filtering direction, 0=up, 1=down TABUL */
INT acfSplit[MAX_NUM_OF_FILTERS];
FIXP_DBL tnsTimeResolution[MAX_NUM_OF_FILTERS]; /* TNS max. time resolution TABUL. Should be fract but MSVC won't compile then */
INT seperateFiltersAllowed;
} TNS_PARAMETER_TABULATED;
typedef struct{
INT bitRateFrom[2]; /* noneSbr=0, useSbr=1 */
INT bitRateTo[2]; /* noneSbr=0, useSbr=1 */
@ -373,6 +353,7 @@ AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitRate,
INT channels,
INT blockType,
INT granuleLength,
INT isLowDelay,
INT ldSbrPresent,
TNS_CONFIG *tC,
PSY_CONFIGURATION *pC,
@ -385,6 +366,8 @@ AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitRate,
if (channels <= 0)
return (AAC_ENCODER_ERROR)1;
tC->isLowDelay = isLowDelay;
/* initialize TNS filter flag, order, and coefficient resolution (in bits per coeff) */
tC->tnsActive = (active) ? TRUE : FALSE;
tC->maxOrder = (blockType == SHORT_WINDOW) ? 5 : 12; /* maximum: 7, 20 */
@ -450,27 +433,14 @@ AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitRate,
const TNS_PARAMETER_TABULATED* pCfg = FDKaacEnc_GetTnsParam(bitRate, channels, ldSbrPresent);
if ( pCfg != NULL ) {
FDKmemcpy(&(tC->confTab), pCfg, sizeof(tC->confTab));
tC->lpcStartBand[HIFILT] = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[HIFILT], sampleRate, pC->sfbCnt, pC->sfbOffset);
tC->lpcStartLine[HIFILT] = pC->sfbOffset[tC->lpcStartBand[HIFILT]];
tC->lpcStartBand[LOFILT] = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[LOFILT], sampleRate, pC->sfbCnt, pC->sfbOffset);
tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]];
tC->confTab.threshOn[HIFILT] = pCfg->threshOn[HIFILT];
tC->confTab.threshOn[LOFILT] = pCfg->threshOn[LOFILT];
tC->confTab.tnsLimitOrder[HIFILT] = pCfg->tnsLimitOrder[HIFILT];
tC->confTab.tnsLimitOrder[LOFILT] = pCfg->tnsLimitOrder[LOFILT];
tC->confTab.tnsFilterDirection[HIFILT] = pCfg->tnsFilterDirection[HIFILT];
tC->confTab.tnsFilterDirection[LOFILT] = pCfg->tnsFilterDirection[LOFILT];
tC->confTab.acfSplit[HIFILT] = pCfg->acfSplit[HIFILT];
tC->confTab.acfSplit[LOFILT] = pCfg->acfSplit[LOFILT];
tC->confTab.filterEnabled[HIFILT] = pCfg->filterEnabled[HIFILT];
tC->confTab.filterEnabled[LOFILT] = pCfg->filterEnabled[LOFILT];
tC->confTab.seperateFiltersAllowed = pCfg->seperateFiltersAllowed;
FDKaacEnc_CalcGaussWindow(tC->acfWindow[HIFILT], tC->maxOrder+1, sampleRate, granuleLength, pCfg->tnsTimeResolution[HIFILT], TNS_TIMERES_SCALE);
FDKaacEnc_CalcGaussWindow(tC->acfWindow[LOFILT], tC->maxOrder+1, sampleRate, granuleLength, pCfg->tnsTimeResolution[LOFILT], TNS_TIMERES_SCALE);
}
@ -614,6 +584,7 @@ static inline FIXP_DBL FDKaacEnc_AutoCorrNormFac(
static void FDKaacEnc_MergedAutoCorrelation(
const FIXP_DBL *spectrum,
const INT isLowDelay,
const FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER+3+1],
const INT lpcStartLine[MAX_NUM_OF_FILTERS],
const INT lpcStopLine,
@ -633,6 +604,8 @@ static void FDKaacEnc_MergedAutoCorrelation(
FDKmemclear(&_rxx1[0], sizeof(FIXP_DBL)*(maxOrder+1));
FDKmemclear(&_rxx2[0], sizeof(FIXP_DBL)*(maxOrder+1));
idx0 = idx1 = idx2 = idx3 = idx4 = 0;
/* MDCT line indices separating the 1st, 2nd, 3rd, and 4th analysis quarters */
if ( (acfSplit[LOFILT]==-1) || (acfSplit[HIFILT]==-1) ) {
/* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the spectrum */
@ -680,14 +653,24 @@ static void FDKaacEnc_MergedAutoCorrelation(
FIXP_DBL fac1 = FDKaacEnc_AutoCorrNormFac(rxx1_0, ((-2*sc1)+nsc1), &sc_fac1);
_rxx1[0] = scaleValue(fMult(rxx1_0,fac1),sc_fac1);
if (isLowDelay)
{
for (lag = 1; lag <= maxOrder; lag++) {
/* compute energy-normalized and windowed autocorrelation values at this lag */
FIXP_DBL x1 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1);
_rxx1[lag] = fMult(scaleValue(fMult(x1,fac1),sc_fac1), acfWindow[LOFILT][lag]);
}
}
else
{
for (lag = 1; lag <= maxOrder; lag++) {
if ((3 * lag) <= maxOrder + 3) {
FIXP_DBL x1 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1);
_rxx1[lag] = fMult(scaleValue(fMult(x1,fac1),sc_fac1), acfWindow[LOFILT][3*lag]);
}
}
}
}
/* auto corr over upper 3/4 of spectrum */
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->filtersMerged = FALSE;
tsbi->tnsActive = FALSE;
tsbi->predictionGain = 1000;
tsbi->tnsActive[HIFILT] = FALSE;
tsbi->predictionGain[HIFILT] = 1000;
tsbi->tnsActive[LOFILT] = FALSE;
tsbi->predictionGain[LOFILT] = 1000;
tnsInfo->numOfFilters[subBlockNumber] = 0;
tnsInfo->coefRes[subBlockNumber] = tC->coefRes;
for (i = 0; i < tC->maxOrder; i++) {
@ -779,6 +766,7 @@ INT FDKaacEnc_TnsDetect(
FDKaacEnc_MergedAutoCorrelation(
spectrum,
tC->isLowDelay,
tC->acfWindow,
tC->lpcStartLine,
tC->lpcStopLine,
@ -788,7 +776,7 @@ INT FDKaacEnc_TnsDetect(
rxx2);
/* compute higher TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */
tsbi->predictionGain = FDKaacEnc_AutoToParcor(rxx2, parcor_tmp, tC->confTab.tnsLimitOrder[HIFILT]);
tsbi->predictionGain[HIFILT] = FDKaacEnc_AutoToParcor(rxx2, parcor_tmp, tC->confTab.tnsLimitOrder[HIFILT]);
/* non-linear quantization of TNS lattice coefficients with given resolution */
FDKaacEnc_Parcor2Index(
@ -815,9 +803,9 @@ INT FDKaacEnc_TnsDetect(
tnsInfo->length[subBlockNumber][HIFILT] = sfbCnt - tC->lpcStartBand[HIFILT];
/* disable TNS if predictionGain is less than 3dB or sumSqrCoef is too small */
if ((tsbi->predictionGain > tC->confTab.threshOn[HIFILT]) || (sumSqrCoef > (tC->confTab.tnsLimitOrder[HIFILT]/2 + 2)))
if ((tsbi->predictionGain[HIFILT] > tC->confTab.threshOn[HIFILT]) || (sumSqrCoef > (tC->confTab.tnsLimitOrder[HIFILT]/2 + 2)))
{
tsbi->tnsActive = TRUE;
tsbi->tnsActive[HIFILT] = TRUE;
tnsInfo->numOfFilters[subBlockNumber]++;
/* compute second filter for lower quarter; only allowed for long windows! */
@ -857,6 +845,7 @@ INT FDKaacEnc_TnsDetect(
|| ( (sumSqrCoef > 9) && (sumSqrCoef < 22 * tC->confTab.tnsLimitOrder[LOFILT]) ) )
{
/* compare lower to upper filter; if they are very similar, merge them */
tsbi->tnsActive[LOFILT] = TRUE;
sumSqrCoef = 0;
for (i = 0; i < tC->confTab.tnsLimitOrder[LOFILT]; i++) {
sumSqrCoef += FDKabs(tnsInfo->coef[subBlockNumber][HIFILT][i] - tnsInfo->coef[subBlockNumber][LOFILT][i]);
@ -884,6 +873,8 @@ INT FDKaacEnc_TnsDetect(
tnsInfo->numOfFilters[subBlockNumber]++;
}
} /* filter lower part */
tsbi->predictionGain[LOFILT]=predGain;
} /* second filter allowed */
} /* if predictionGain > 1437 ... */
} /* maxOrder > 0 && tnsActive */
@ -944,7 +935,7 @@ void FDKaacEnc_TnsSync(
INT doSync = 1, absDiffSum = 0;
/* if TNS is active in at least one channel, check if ParCor coefficients of higher filter are similar */
if (pSbInfoDestW->tnsActive || pSbInfoSrcW->tnsActive) {
if (pSbInfoDestW->tnsActive[HIFILT] || pSbInfoSrcW->tnsActive[HIFILT]) {
for (i = 0; i < tC->maxOrder; i++) {
absDiff = FDKabs(tnsInfoDest->coef[w][HIFILT][i] - tnsInfoSrc->coef[w][HIFILT][i]);
absDiffSum += absDiff;
@ -957,12 +948,12 @@ void FDKaacEnc_TnsSync(
if (doSync) {
/* if no significant difference was detected, synchronize coefficient sets */
if (pSbInfoSrcW->tnsActive) {
if (pSbInfoSrcW->tnsActive[HIFILT]) {
/* no dest filter, or more dest than source filters: use one dest filter */
if ((!pSbInfoDestW->tnsActive) ||
((pSbInfoDestW->tnsActive) && (tnsInfoDest->numOfFilters[w] > tnsInfoSrc->numOfFilters[w])))
if ((!pSbInfoDestW->tnsActive[HIFILT]) ||
((pSbInfoDestW->tnsActive[HIFILT]) && (tnsInfoDest->numOfFilters[w] > tnsInfoSrc->numOfFilters[w])))
{
pSbInfoDestW->tnsActive = tnsInfoDest->numOfFilters[w] = 1;
pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 1;
}
tnsDataDest->filtersMerged = tnsDataSrc->filtersMerged;
tnsInfoDest->order [w][HIFILT] = tnsInfoSrc->order [w][HIFILT];
@ -975,7 +966,7 @@ void FDKaacEnc_TnsSync(
}
}
else
pSbInfoDestW->tnsActive = tnsInfoDest->numOfFilters[w] = 0;
pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 0;
}
}
@ -1012,8 +1003,8 @@ INT FDKaacEnc_TnsEncode(
{
INT i, startLine, stopLine;
if ( ( (blockType == SHORT_WINDOW) && (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber].tnsActive) )
|| ( (blockType != SHORT_WINDOW) && (!tnsData->dataRaw.Long.subBlockInfo.tnsActive) ) )
if ( ( (blockType == SHORT_WINDOW) && (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber].tnsActive[HIFILT]) )
|| ( (blockType != SHORT_WINDOW) && (!tnsData->dataRaw.Long.subBlockInfo.tnsActive[HIFILT]) ) )
{
return 1;
}
@ -1129,8 +1120,9 @@ static INT FDKaacEnc_AutoToParcor(
FIXP_DBL *RESTRICT workBuffer = parcorWorkBuffer;
const FIXP_DBL autoCorr_0 = input[0];
if((FIXP_DBL)input[0] == FL2FXCONST_DBL(0.0)) {
FDKmemclear(reflCoeff,numOfCoeff*sizeof(FIXP_DBL));
if((FIXP_DBL)input[0] == FL2FXCONST_DBL(0.0)) {
return(predictionGain);
}

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -117,21 +117,25 @@ amm-info@iis.fraunhofer.de
#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. */
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_CONFIG_TABULATED;
} TNS_PARAMETER_TABULATED;
typedef struct { /*assigned at InitTime*/
TNS_CONFIG_TABULATED confTab;
TNS_PARAMETER_TABULATED confTab;
INT isLowDelay;
INT tnsActive;
INT maxOrder; /* max. order of tns filter */
INT coefRes;
@ -148,8 +152,8 @@ typedef struct { /*assigned at InitTime*/
typedef struct {
INT tnsActive;
INT predictionGain;
INT tnsActive[MAX_NUM_OF_FILTERS];
INT predictionGain[MAX_NUM_OF_FILTERS];
} TNS_SUBBLOCK_INFO;
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},
{ 32000, 0x247AE148, 0x11B1D92B, 0x23851EB8, 0x01F75105, 0x247AE148, 0x110A137F, 0x23851EB8, 0x01F75105},
{ 48000, 0x2D1EB852, 0x6833C600, 0x247AE148, 0x014F8B59, 0x2CCCCCCD, 0x68DB8BAC, 0x247AE148, 0x01F75105},
{ 64000, 0x60000000, 0x00000000, 0x251EB852, 0x154C985F, 0x60000000, 0x00000000, 0x2570A3D7, 0x154C985F},
{ 96000, 0x60000000, 0x00000000, 0x39EB851F, 0x088509C0, 0x60000000, 0x00000000, 0x3A3D70A4, 0x088509C0},
{128000, 0x60000000, 0x00000000, 0x423D70A4, 0x18A43BB4, 0x60000000, 0x00000000, 0x428F5C29, 0x181E03F7},
{148000, 0x60000000, 0x00000000, 0x5147AE14, 0x00000000, 0x60000000, 0x00000000, 0x5147AE14, 0x00000000}
{ 64000, 0x25c28f40, 0x00000000, 0x251EB852, 0x01480000, 0x25c28f40, 0x00000000, 0x2570A3D7, 0x01480000},
{ 96000, 0x25c28f40, 0x00000000, 0x26000000, 0x01000000, 0x25c28f40, 0x00000000, 0x26000000, 0x01000000},
{128000, 0x25c28f40, 0x00000000, 0x270a3d80, 0x01000000, 0x25c28f40, 0x00000000, 0x270a3d80, 0x01000000},
{148000, 0x25c28f40, 0x00000000, 0x28000000, 0x00000000, 0x25c28f40, 0x00000000, 0x28000000, 0x00000000}
};
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},
{ 64000, 0x247ae148, 0x08d8ec96, 0x23851eb8, 0x00fba882, 0x247ae148, 0x88509c0, 0x23851eb8, 0x00fba882},
{ 96000, 0x2d1eb852, 0x3419e300, 0x247ae148, 0x00a7c5ac, 0x2ccccccd, 0x346dc5d6, 0x247ae148, 0x00fba882},
{128000, 0x60000000, 0x00000000, 0x251eb852, 0x029f16b1, 0x60000000, 0x00000000, 0x2570a3d7, 0x009f16b1},
{148000, 0x60000000, 0x00000000, 0x26b851ec, 0x00000000, 0x60000000, 0x00000000, 0x270a3d71, 0x00000000}
{128000, 0x25c28f40, 0x00000000, 0x251eb852, 0x029f16b1, 0x60000000, 0x25c28f40, 0x2570a3d7, 0x009f16b1},
{148000, 0x25c28f40, 0x00000000, 0x26b851ec, 0x00000000, 0x60000000, 0x25c28f40, 0x270a3d71, 0x00000000}
};
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},
{ 96000, 0x2a8f5c29, 0x24b33db0, 0x247ae148, 0x00fba882, 0x2a8f5c29, 0x26fe718b, 0x247ae148, 0x00fba882},
{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[] = {
{ 16000, 0x1199999a, 0x20c49ba6, 0x00000000, 0x4577d955, 0x00000000, 0x60fe4799, 0x00000000, 0x00000000},
{ 24000, 0x1999999a, 0x0fba8827, 0x10f5c28f, 0x1b866e44, 0x17ae147b, 0x0fba8827, 0x00000000, 0x4d551d69},
{ 16000, 0x247ae140, 0xFFFFAC1E, 0x270a3d80, 0xFFFE9B7C, 0x14ccccc0, 0x000110A1, 0x15c28f60, 0xFFFEEF5F},
{ 24000, 0x23333340, 0x0fba8827, 0x21999980, 0x1b866e44, 0x18f5c280, 0x0fba8827, 0x119999a0, 0x4d551d69},
{ 32000, 0x1d70a3d7, 0x07357e67, 0x17ae147b, 0x09d49518, 0x1b851eb8, 0x0a7c5ac4, 0x12e147ae, 0x110a137f},
{ 48000, 0x20f5c28f, 0x049667b6, 0x1c7ae148, 0x053e2d62, 0x20a3d70a, 0x053e2d62, 0x1b333333, 0x05e5f30e},
{ 64000, 0x23333333, 0x029f16b1, 0x1f0a3d71, 0x02f2f987, 0x23333333, 0x029f16b1, 0x1e147ae1, 0x03eea20a},
{ 96000, 0x25c28f5c, 0x2c3c9eed, 0x21eb851f, 0x01f75105, 0x25c28f5c, 0x0a7c5ac4, 0x21eb851f, 0x01a36e2f},
{128000, 0x50f5c28f, 0x18a43bb4, 0x23d70a3d, 0x010c6f7a, 0x30000000, 0x168b5cc0, 0x23851eb8, 0x0192a737},
{148000, 0x60000000, 0x00000000, 0x247ae148, 0x00dfb23b, 0x3dc28f5c, 0x300f4aaf, 0x247ae148, 0x01bf6476},
{160000, 0x60000000, 0xb15b5740, 0x24cccccd, 0x053e2d62, 0x4f5c28f6, 0xbefd0072, 0x251eb852, 0x04fb1184},
{200000, 0x00000000, 0x00000000, 0x2b333333, 0x0836be91, 0x00000000, 0x00000000, 0x2b333333, 0x0890390f},
{320000, 0x00000000, 0x00000000, 0x4947ae14, 0x00000000, 0x00000000, 0x00000000, 0x4a8f5c29, 0x00000000}
{148000, 0x25c28f40, 0x00000000, 0x247ae148, 0x00dfb23b, 0x3dc28f5c, 0x300f4aaf, 0x247ae148, 0x01bf6476},
{160000, 0x25c28f40, 0xb15b5740, 0x24cccccd, 0x053e2d62, 0x4f5c28f6, 0xbefd0072, 0x251eb852, 0x04fb1184},
{200000, 0x25c28f40, 0x00000000, 0x2b333333, 0x0836be91, 0x25c28f40, 0x00000000, 0x2b333333, 0x0890390f},
{320000, 0x25c28f40, 0x00000000, 0x4947ae14, 0x00000000, 0x25c28f40, 0x00000000, 0x4a8f5c29, 0x00000000}
};
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},
{148000, 0x3b851eb8, 0x2832069c, 0x23333333, 0x00dfb23b, 0x3428f5c3, 0x2054c288, 0x22e147ae, 0x00dfb23b},
{160000, 0x4a3d70a4, 0xc32ebe5a, 0x23851eb8, 0x01d5c316, 0x40000000, 0xcb923a2b, 0x23333333, 0x01d5c316},
{200000, 0x00000000, 0x00000000, 0x25c28f5c, 0x0713f078, 0x00000000, 0x00000000, 0x2570a3d7, 0x072a4f17},
{320000, 0x00000000, 0x00000000, 0x3fae147b, 0x00000000, 0x00000000, 0x00000000, 0x3fae147b, 0x00000000}
{200000, 0x25c28f40, 0x00000000, 0x25c28f5c, 0x0713f078, 0x25c28f40, 0x00000000, 0x2570a3d7, 0x072a4f17},
{320000, 0x25c28f40, 0x00000000, 0x3fae147b, 0x00000000, 0x25c28f40, 0x00000000, 0x3fae147b, 0x00000000}
};
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},
{148000, 0x3570a3d7, 0x1cd5f99c, 0x228f5c29, 0x01bf6476, 0x30f5c28f, 0x18777e75, 0x223d70a4, 0x01bf6476},
{160000, 0x40000000, 0xcb923a2b, 0x23333333, 0x0192a737, 0x39eb851f, 0xd08d4bae, 0x22e147ae, 0x0192a737},
{200000, 0x00000000, 0x00000000, 0x251eb852, 0x06775a1b, 0x00000000, 0x00000000, 0x24cccccd, 0x06a4175a},
{320000, 0x00000000, 0x00000000, 0x3ccccccd, 0x00000000, 0x00000000, 0x00000000, 0x3d1eb852, 0x00000000}
{200000, 0x25c28f40, 0x00000000, 0x251eb852, 0x06775a1b, 0x25c28f40, 0x00000000, 0x24cccccd, 0x06a4175a},
{320000, 0x25c28f40, 0x00000000, 0x3ccccccd, 0x00000000, 0x25c28f40, 0x00000000, 0x3d1eb852, 0x00000000}
};
static const BITS2PE_CFG_TAB bits2PeConfigTab[] = {
@ -258,6 +258,7 @@ static void FDKaacEnc_InitBits2PeFactor(
const INT nChannels,
const INT sampleRate,
const INT advancedBitsToPe,
const INT dZoneQuantEnable,
const INT invQuant
)
{
@ -329,7 +330,32 @@ static void FDKaacEnc_InitBits2PeFactor(
} /* 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_e = bit2PE_e;
}
@ -1649,6 +1675,7 @@ static void FDKaacEnc_adaptThresholdsToPe(CHANNEL_MAPPING* cm,
QC_OUT_ELEMENT* qcElement[(8)],
PSY_OUT_ELEMENT* psyOutElement[(8)],
const INT desiredPe,
const INT maxIter2ndGuess,
const INT processElements,
const INT elementOffset)
{
@ -1733,7 +1760,7 @@ static void FDKaacEnc_adaptThresholdsToPe(CHANNEL_MAPPING* cm,
/* Part III: Iterate until bit constraints are met */
/* -------------------------------------------------- */
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 redPeNoAHGlobal = 0;
@ -2225,7 +2252,8 @@ void FDKaacEnc_AdjThrInit(
INT nChannelsEff,
INT sampleRate,
INT advancedBitsToPe,
FIXP_DBL vbrQualFactor
FIXP_DBL vbrQualFactor,
const INT dZoneQuantEnable
)
{
INT i;
@ -2233,6 +2261,10 @@ void FDKaacEnc_AdjThrInit(
FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f);
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: */
/* parameters for bitres control */
hAdjThr->bresParamLong.clipSaveLow = (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
@ -2313,10 +2345,11 @@ void FDKaacEnc_AdjThrInit(
FDKaacEnc_InitBits2PeFactor(
&atsElem->bits2PeFactor_m,
&atsElem->bits2PeFactor_e,
chBitrate, /* bitrate/channel*/
chBitrate*nChannelsEff, /* overall bitrate */
nChannelsEff, /* number of channels */
sampleRate,
advancedBitsToPe,
dZoneQuantEnable,
invQuant
);
@ -2545,6 +2578,7 @@ void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(8)],
QC_OUT* qcOut,
PSY_OUT_ELEMENT* psyOutElement[(8)],
INT CBRbitrateMode,
INT maxIter2ndGuess,
CHANNEL_MAPPING* cm)
{
int i;
@ -2570,6 +2604,7 @@ void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(8)],
qcElement,
psyOutElement,
qcElement[i]->grantedPeCorr,
maxIter2ndGuess,
1, /* Process only 1 element */
i); /* Process exactly THIS element */

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -118,7 +118,8 @@ void FDKaacEnc_AdjThrInit(ADJ_THR_STATE *hAdjThr,
INT nChannelsEff,
INT sampleRate,
INT advancedBitsToPe,
FIXP_DBL vbrQualFactor);
FIXP_DBL vbrQualFactor,
const INT dZoneQuantEnable);
void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState,
@ -140,6 +141,7 @@ void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(8)],
QC_OUT* qcOut,
PSY_OUT_ELEMENT* psyOutElement[(8)],
INT CBRbitrateMode,
INT maxIter2ndGuess,
CHANNEL_MAPPING* cm);
void FDKaacEnc_AdjThrClose(ADJ_THR_STATE** hAdjThr);

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -145,6 +145,7 @@ typedef struct {
typedef struct {
BRES_PARAM bresParamLong, bresParamShort;
ATS_ELEMENT* adjThrStateElem[(8)];
INT maxIter2ndGuess;
} ADJ_THR_STATE;
#endif

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -127,7 +127,7 @@ static const BANDWIDTH_TAB bandWidthTable_LD_24000[] = {
{ 8000, 2000, 2000},
{12000, 2000, 2300},
{16000, 2200, 2500},
{24000, 5650, 6400},
{24000, 5650, 7200},
{32000, 11600, 12000},
{40000, 12000, 16000},
{48000, 16000, 16000},
@ -138,10 +138,10 @@ static const BANDWIDTH_TAB bandWidthTable_LD_24000[] = {
static const BANDWIDTH_TAB bandWidthTable_LD_32000[] = {
{ 8000, 2000, 2000},
{12000, 2000, 2000},
{24000, 4250, 5200},
{24000, 4250, 7200},
{32000, 8400, 9000},
{40000, 9400, 11300},
{48000, 11900, 13700},
{48000, 11900, 14700},
{64000, 14800, 16000},
{76000, 16000, 16000},
{360001, 16000, 16000}

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -107,6 +107,7 @@ typedef struct {
typedef struct {
ULONG brFrom;
ULONG brTo;
UCHAR S16000;
UCHAR S22050;
UCHAR S24000;
UCHAR S32000;
@ -115,25 +116,26 @@ typedef struct {
} AUTO_PNS_TAB;
static const AUTO_PNS_TAB levelTable_mono[]= {
{0, 11999, 1, 1, 1, 1, 1,},
{12000, 19999, 1, 1, 1, 1, 1,},
{20000, 28999, 2, 1, 1, 1, 1,},
{29000, 40999, 4, 4, 4, 2, 2,},
{41000, 55999, 9, 9, 7, 7, 7,},
{56000, 79999, 0, 0, 0, 9, 9,},
{80000, 99999, 0, 0, 0, 0, 0,},
{100000,999999, 0, 0, 0, 0, 0,},
{0, 11999, 0, 1, 1, 1, 1, 1,},
{12000, 19999, 0, 1, 1, 1, 1, 1,},
{20000, 28999, 0, 2, 1, 1, 1, 1,},
{29000, 40999, 0, 4, 4, 4, 2, 2,},
{41000, 55999, 0, 9, 9, 7, 7, 7,},
{56000, 61999, 0, 0, 0, 0, 9, 9,},
{62000, 75999, 0, 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[]= {
{0, 11999, 1, 1, 1, 1, 1,},
{12000, 19999, 3, 1, 1, 1, 1,},
{20000, 28999, 3, 3, 3, 2, 2,},
{29000, 40999, 7, 6, 6, 5, 5,},
{41000, 55999, 9, 9, 7, 7, 7,},
{56000, 79999, 0, 0, 0, 0, 0,},
{80000, 99999, 0, 0, 0, 0, 0,},
{100000,999999, 0, 0, 0, 0, 0,},
{0, 11999, 0, 1, 1, 1, 1, 1,},
{12000, 19999, 0, 3, 1, 1, 1, 1,},
{20000, 28999, 0, 3, 3, 3, 2, 2,},
{29000, 40999, 0, 7, 6, 6, 5, 5,},
{41000, 55999, 0, 9, 9, 7, 7, 7,},
{56000, 79999, 0, 0, 0, 0, 0, 0,},
{80000, 99999, 0, 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[]= {
{0, 27999, 0, 0, 0, 0, 0,},
{28000, 31999, 2, 2, 2, 2, 2,},
{32000, 47999, 3, 3, 3, 3, 3,},
{48000, 48000, 4, 4, 4, 4, 4,},
{48001, 999999, 0, 0, 0, 0, 0,},
{0, 27999, 0, 0, 0, 0, 0, 0,},
{28000, 31999, 0, 2, 2, 2, 2, 2,},
{32000, 47999, 0, 3, 3, 3, 3, 3,},
{48000, 48000, 0, 4, 4, 4, 4, 4,},
{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) */
@ -211,6 +213,7 @@ int FDKaacEnc_lookUpPnsUse (int bitRate, int sampleRate, int numChan, const int
}
switch (sampleRate) {
case 16000: hUsePns = levelTable[i].S16000; break;
case 22050: hUsePns = levelTable[i].S22050; break;
case 24000: hUsePns = levelTable[i].S24000; break;
case 32000: hUsePns = levelTable[i].S32000; break;

View File

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

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -269,6 +269,8 @@ typedef struct
BITCNTR_STATE *hBitCounter;
ADJ_THR_STATE *hAdjThr;
INT dZoneQuantEnable; /* enable dead zone quantizer */
} QC_STATE;
#endif /* _QC_DATA_H */

View File

@ -380,7 +380,7 @@ AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC,
if ( isConstantBitrateMode(hQC->bitrateMode) ) {
INT bitresPerChannel = (hQC->bitResTotMax / init->channelMapping->nChannelsEff);
/* 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 {
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(
hQC->hAdjThr,
init->meanPe,
@ -414,7 +424,8 @@ AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC,
init->channelMapping->nChannelsEff,
init->sampleRate, /* output sample rate */
init->advancedBitsToPe, /* if set, calc bits2PE factor depending on samplerate */
hQC->vbrQualFactor
hQC->vbrQualFactor,
hQC->dZoneQuantEnable
);
return AAC_ENC_OK;
@ -877,6 +888,7 @@ AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC,
qcOut[c],
psyOut[c]->psyOutElement,
isConstantBitrateMode(hQC->bitrateMode),
hQC->hAdjThr->maxIter2ndGuess,
cm);
} /* -end- sub frame counter */
@ -904,6 +916,7 @@ AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC,
FDKaacEnc_EstimateScaleFactors(psyOut[c]->psyOutElement[i]->psyOutChannel,
qcElement[c][i]->qcOutChannel,
hQC->invQuant,
hQC->dZoneQuantEnable,
cm->elInfo[i].nChannelsInEl);
@ -998,7 +1011,8 @@ AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC,
qcOutCh->mdctSpectrum,
qcOutCh->globalGain,
qcOutCh->scf,
qcOutCh->quantSpec) ;
qcOutCh->quantSpec,
hQC->dZoneQuantEnable);
/*-------------------------------------------- */
if (FDKaacEnc_calcMaxValueInSfb(psyOutCh->sfbCnt,

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -104,13 +104,19 @@ amm-info@iis.fraunhofer.de
static void FDKaacEnc_quantizeLines(INT gain,
INT noOfLines,
FIXP_DBL *mdctSpectrum,
SHORT *quaSpectrum)
SHORT *quaSpectrum,
INT dZoneQuantEnable)
{
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];
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++)
{
@ -263,7 +269,8 @@ void FDKaacEnc_QuantizeSpectrum(INT sfbCnt,
FIXP_DBL *mdctSpectrum,
INT globalGain,
INT *scalefactors,
SHORT *quantizedSpectrum)
SHORT *quantizedSpectrum,
INT dZoneQuantEnable)
{
INT sfbOffs,sfb;
@ -280,7 +287,8 @@ void FDKaacEnc_QuantizeSpectrum(INT sfbCnt,
FDKaacEnc_quantizeLines(globalGain - scalefactor, /* QSS */
sfbOffset[sfbOffs+sfb+1] - 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,
SHORT *quantSpectrum,
INT noOfLines,
INT gain
INT gain,
INT dZoneQuantEnable
)
{
INT i,scale;
@ -311,7 +320,8 @@ FIXP_DBL FDKaacEnc_calcSfbDist(FIXP_DBL *mdctSpectrum,
FDKaacEnc_quantizeLines(gain,
1,
&mdctSpectrum[i],
&quantSpectrum[i]);
&quantSpectrum[i],
dZoneQuantEnable);
if (fAbs(quantSpectrum[i])>MAX_QUANT) {
return FL2FXCONST_DBL(0.0f);

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -102,12 +102,14 @@ void FDKaacEnc_QuantizeSpectrum(INT sfbCnt,
INT sfbPerGroup,
INT *sfbOffset, FIXP_DBL *mdctSpectrum,
INT globalGain, INT *scalefactors,
SHORT *quantizedSpectrum);
SHORT *quantizedSpectrum,
INT dZoneQuantEnable);
FIXP_DBL FDKaacEnc_calcSfbDist(FIXP_DBL *mdctSpectrum,
SHORT *quantSpectrum,
INT noOfLines,
INT gain);
INT gain,
INT dZoneQuantEnable);
void FDKaacEnc_calcSfbQuantEnergyAndDist(FIXP_DBL *mdctSpectrum,
SHORT *quantSpectrum,

View File

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

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -100,6 +100,7 @@ AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitrate,
INT channels,
INT blocktype,
INT granuleLength,
INT isLowDelay,
INT ldSbrPresent,
TNS_CONFIG *tnsConfig,
PSY_CONFIGURATION *psyConfig,

View File

@ -94,6 +94,35 @@ amm-info@iis.fraunhofer.de
#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_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 */
#define FDK_TOOLS_LIB_VL0 2
#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"
#ifdef __ANDROID__
#define FDK_TOOLS_LIB_BUILD_DATE ""

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -135,6 +135,12 @@ enum
SBR_SYNTAX_DRM_CRC = 0x0008
};
typedef enum
{
FREQ_RES_LOW = 0,
FREQ_RES_HIGH
} FREQ_RES;
typedef struct
{
CODEC_TYPE coreCoder; /*!< LC or ELD */
@ -168,8 +174,9 @@ typedef struct sbrConfiguration
INT dynBwSupported; /*!< Flag: support for dynamic bandwidth in this combination. */
INT parametricCoding; /*!< Flag: usage of parametric coding tool. */
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
0=1 Env; 1=2 Env; 2=4 Env; */
FREQ_RES freq_res_fixfix[2];/*!< Frequency resolution of envelopes in frame class FIXFIX, for non-split case and split case */
UCHAR fResTransIsLow; /*!< Frequency resolution of envelopes in transient frames: low (0) or variable (1) */
/*
core coder dependent tuning parameters
*/
@ -221,6 +228,8 @@ typedef struct sbrConfiguration
INT sbr_interpol_freq; /*!< Flag: use interpolation in freq. direction. */
INT sbr_smoothing_length; /*!< Flag: choose length 4 or 0 (=on, off). */
UCHAR init_amp_res_FF;
FIXP_DBL threshold_AmpRes_FF_m;
SCHAR threshold_AmpRes_FF_e;
} sbrConfiguration, *sbrConfigurationPtr ;
typedef struct SBR_CONFIG_DATA
@ -237,7 +246,7 @@ typedef struct SBR_CONFIG_DATA
INT noQmfBands; /**< Number of QMF frequency bands. */
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. */
@ -249,6 +258,8 @@ typedef struct SBR_CONFIG_DATA
INT xposCtrlSwitch; /**< Flag indicates whether to switch xpos ctrl on the fly. */
INT switchTransposers; /**< Flag indicates whether to switch xpos on the fly . */
UCHAR initAmpResFF;
FIXP_DBL thresholdAmpResFF_m;
SCHAR thresholdAmpResFF_e;
} SBR_CONFIG_DATA, *HANDLE_SBR_CONFIG_DATA;
typedef struct {

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -141,8 +141,8 @@ struct SBR_ENV_DATA
{
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_vec[MAX_NUM_NOISE_VALUES];
@ -205,6 +205,8 @@ struct SBR_ENV_DATA
INT balance;
AMP_RES init_sbr_amp_res;
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 */
INT extended_data;

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -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};
/******************************************************************************
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);
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
*/
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,
sbrExtrEnv->YBuffer,
sbrExtrEnv->YBufferScale,
@ -931,6 +1071,7 @@ FDKsbrEnc_extractSbrEnvelope1 (
sbrExtrEnv->YBufferSzShift,
sbrExtrEnv->time_step,
hEnvChan->SbrEnvFrame.frameMiddleSlot);
}
@ -951,7 +1092,8 @@ FDKsbrEnc_extractSbrEnvelope1 (
sbrExtrEnv->YBufferSzShift,
h_con->nSfb[1],
sbrExtrEnv->time_step,
sbrExtrEnv->no_cols);
sbrExtrEnv->no_cols,
&hEnvChan->encEnvData.global_tonality);
}
@ -1128,10 +1270,24 @@ FDKsbrEnc_extractSbrEnvelope2 (
&& ( ed->nEnvelopes == 1 ) )
{
if (hEnvChan->encEnvData.ldGrid)
hEnvChan->encEnvData.currentAmpResFF = (AMP_RES)h_con->initAmpResFF;
else
if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY)
{
/* 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;
}
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) {
@ -1172,7 +1328,12 @@ FDKsbrEnc_extractSbrEnvelope2 (
}
/* 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;

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -127,6 +127,7 @@ typedef SBR_EXTRACT_ENVELOPE *HANDLE_SBR_EXTRACT_ENVELOPE;
struct ENV_CHANNEL
{
FAST_TRAN_DETECTOR sbrFastTransientDetector;
SBR_TRANSIENT_DETECTOR sbrTransientDetector;
SBR_CODE_ENVELOPE sbrCodeEnvelope;
SBR_CODE_ENVELOPE sbrCodeNoiseFloor;

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -266,7 +266,7 @@ static void calcCtrlSignal (HANDLE_SBR_GRID hSbrGrid, FRAME_CLASS frameClass,
static void ctrlSignal2FrameInfo (HANDLE_SBR_GRID hSbrGrid,
HANDLE_SBR_FRAME_INFO hFrameInfo,
INT freq_res_fixfix);
FREQ_RES *freq_res_fixfix);
/* 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,
HANDLE_SBR_GRID hSbrGrid,
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;
hSbrEnvFrame->v_tuningSegm = v_tuningSegm;
INT freq_res_fixfix = hSbrEnvFrame->freq_res_fixfix;
if (ldGrid) {
/* 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;
tranPos = 0;
}
@ -529,7 +529,8 @@ FDKsbrEnc_frameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
generateFixFixOnly ( &(hSbrEnvFrame->SbrFrameInfo),
&(hSbrEnvFrame->SbrGrid),
tranPosInternal,
numberTimeSlots
numberTimeSlots,
hSbrEnvFrame->fResTransIsLow
);
return &(hSbrEnvFrame->SbrFrameInfo);
@ -677,7 +678,7 @@ FDKsbrEnc_frameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
---------------------------------------------------------------------------*/
ctrlSignal2FrameInfo (&hSbrEnvFrame->SbrGrid,
&hSbrEnvFrame->SbrFrameInfo,
freq_res_fixfix);
hSbrEnvFrame->freq_res_fixfix);
return &hSbrEnvFrame->SbrFrameInfo;
}
@ -692,7 +693,8 @@ FDKsbrEnc_frameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
static void generateFixFixOnly ( HANDLE_SBR_FRAME_INFO hSbrFrameInfo,
HANDLE_SBR_GRID hSbrGrid,
int tranPosInternal,
int numberTimeSlots
int numberTimeSlots,
UCHAR fResTransIsLow
)
{
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 */
for (i=0; i<nEnv; i++){
k = hSbrFrameInfo->borders[i+1] - hSbrFrameInfo->borders[i];
if (!fResTransIsLow)
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;
@ -765,15 +771,16 @@ static void generateFixFixOnly ( HANDLE_SBR_FRAME_INFO hSbrFrameInfo,
*******************************************************************************/
void
FDKsbrEnc_initFrameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
FDKsbrEnc_initFrameInfoGenerator (
HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
INT allowSpread,
INT numEnvStatic,
INT staticFraming,
INT timeSlots,
INT freq_res_fixfix
,int ldGrid
const FREQ_RES* freq_res_fixfix
,UCHAR fResTransIsLow,
INT ldGrid
)
{ /* FH 00-06-26 */
FDKmemclear(hSbrEnvFrame,sizeof(SBR_ENVELOPE_FRAME ));
@ -786,7 +793,9 @@ FDKsbrEnc_initFrameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
hSbrEnvFrame->allowSpread = allowSpread;
hSbrEnvFrame->numEnvStatic = numEnvStatic;
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_bordFollow = 0;
@ -804,6 +813,7 @@ FDKsbrEnc_initFrameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
hSbrEnvFrame->dmin = 2;
hSbrEnvFrame->dmax = 16;
hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_512LD;
hSbrEnvFrame->SbrGrid.bufferFrameStart = 0;
} else
switch(timeSlots){
case NUMBER_TIME_SLOTS_1920:
@ -1862,19 +1872,28 @@ createDefFrameInfo(HANDLE_SBR_FRAME_INFO hSbrFrameInfo, INT nEnv, INT nTimeSlots
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
hSbrFrameInfo - destination
freq_res_fixfix - frequency resolution for FIXFIX frames
Return: void; hSbrFrameInfo contains the updated FRAME_INFO struct
*******************************************************************************/
static void
ctrlSignal2FrameInfo (HANDLE_SBR_GRID hSbrGrid,
HANDLE_SBR_FRAME_INFO hSbrFrameInfo,
INT freq_res_fixfix)
ctrlSignal2FrameInfo (
HANDLE_SBR_GRID hSbrGrid, /* input : the grid handle */
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 *v_r = hSbrGrid->bs_rel_bord;
INT *v_f = hSbrGrid->v_f;
@ -1887,17 +1906,10 @@ ctrlSignal2FrameInfo (HANDLE_SBR_GRID hSbrGrid,
case FIXFIX:
createDefFrameInfo(hSbrFrameInfo, hSbrGrid->bs_num_env, numberTimeSlots);
/* At this point all frequency resolutions are set to FREQ_RES_HIGH, so
* 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) {
frameSplit = (hSbrFrameInfo->nEnvelopes > 1);
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;
case FIXVAR:

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -89,6 +89,7 @@ amm-info@iis.fraunhofer.de
#define _FRAM_GEN_H
#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_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 LD_PRETRAN_OFF 3
#define FRAME_MIDDLE_SLOT_512LD 0
#define FRAME_MIDDLE_SLOT_512LD 4
#define NUMBER_TIME_SLOTS_512LD 8
#define TRANSIENT_OFFSET_LD 0
@ -250,7 +251,8 @@ typedef struct
/* basic tuning parameters */
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 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 */
const int *v_tuningSegm; /*!< segment lengths to use around transient */
@ -286,13 +288,15 @@ typedef SBR_ENVELOPE_FRAME *HANDLE_SBR_ENVELOPE_FRAME;
void
FDKsbrEnc_initFrameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
FDKsbrEnc_initFrameInfoGenerator (
HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
INT allowSpread,
INT numEnvStatic,
INT staticFraming,
INT timeSlots,
INT freq_res_fixfix
,int ldGrid
const FREQ_RES* freq_res_fixfix
,UCHAR fResTransIsLow,
INT ldGrid
);
HANDLE_SBR_FRAME_INFO

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -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.
@ -694,10 +711,10 @@ static void detection(FIXP_DBL *quotaBuffer,
for(i=0;i<nSfb;i++){
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;
thresTemp = fixMin(thresTemp, mhThresh.thresHoldDiff);
thresTemp = fMin(thresTemp, mhThresh.thresHoldDiff);
if(pDiffVecScfb[i] > thresTemp){
pHarmVec[i] = 1;
@ -813,8 +830,11 @@ static void detectionWithPrediction(FIXP_DBL **quotaBuffer,
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){
start = detectionStart;
start = detectionStart+1;
if (start != 0) {
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. */
INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component will be missing. */
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. */
INVF_MODE* pInvFiltLevels, /*!< Pointer to the vector holding the inverse filtering levels. */
UINT sbrSyntaxFlags

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -119,7 +119,7 @@ FDKsbrEnc_sbrNoiseFloorEstimateQmf(HANDLE_SBR_NOISE_FLOOR_ESTIMATE h_sbrNoiseFlo
SCHAR* indexVector, /*!< Index vector to obtain the patched data. */
INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component will be missing. */
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. */
INVF_MODE* pInvFiltLevels, /*!< Pointer to the vector holding the inverse filtering levels. */
UINT sbrSyntaxFlags

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -122,6 +122,8 @@ amm-info@iis.fraunhofer.de
/************ Definitions ***************/
#define SBR_COMP_MODE_DELTA 0
#define SBR_COMP_MODE_CTS 1
#define SBR_MAX_ENERGY_VALUES 5
#define SBR_GLOBAL_TONALITY_VALUES 2
#define MAX_NUM_CHANNELS 2
@ -232,6 +234,8 @@ amm-info@iis.fraunhofer.de
#define FREQ 0
#define TIME 1
/* qmf data scaling */
#define QMF_SCALE_OFFSET 7
/* huffman tables */
#define CODE_BOOK_SCF_LAV00 60
@ -268,12 +272,4 @@ typedef enum
}
INVF_MODE;
typedef enum
{
FREQ_RES_LOW = 0,
FREQ_RES_HIGH
}
FREQ_RES;
#endif

View File

@ -103,7 +103,7 @@ amm-info@iis.fraunhofer.de
#define SBRENCODER_LIB_VL0 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.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) {
/* map vbr quality to bitrate */
if (vbrMode < 30)
@ -467,6 +484,57 @@ FDKsbrEnc_AdjustSbrSettings (const sbrConfigurationPtr config, /*! output, modif
config->stereoMode = sbrTuningTable[idx].stereoMode ;
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 */
if (useSpeechConfig)
config->parametricCoding = 0;
@ -515,6 +583,7 @@ static UINT
FDKsbrEnc_InitializeSbrDefaults (sbrConfigurationPtr config,
INT downSampleFactor,
UINT codecGranuleLen
,const INT isLowDelay
)
{
if ( (downSampleFactor < 1 || downSampleFactor > 2) ||
@ -525,7 +594,11 @@ FDKsbrEnc_InitializeSbrDefaults (sbrConfigurationPtr config,
config->useWaveCoding = 0;
config->crcSbr = 0;
config->dynBwSupported = 1;
if (isLowDelay)
config->tran_thr = 6000;
else
config->tran_thr = 13000;
config->parametricCoding = 1;
config->sbrFrameSize = codecGranuleLen * downSampleFactor;
@ -558,7 +631,9 @@ FDKsbrEnc_InitializeSbrDefaults (sbrConfigurationPtr config,
config->noiseFloorOffset = 0;
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->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 */
config->freqScale = SBR_FREQ_SCALE_DEFAULT;
@ -1206,7 +1281,10 @@ initEnvChannel ( HANDLE_SBR_CONFIG_DATA sbrConfigData,
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->encEnvData.ldGrid = (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) ? 1 : 0;
@ -1348,11 +1426,29 @@ initEnvChannel ( HANDLE_SBR_CONFIG_DATA sbrConfigData,
e,
params->stat,
timeSlots,
hEnv->encEnvData.freq_res_fixfix
,hEnv->encEnvData.ldGrid
hEnv->encEnvData.freq_res_fixfix,
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,
sbrConfigData->sbrSyntaxFlags,
sbrConfigData->frameSize,
sbrConfigData->sampleFreq,
params,
@ -1658,6 +1754,8 @@ INT FDKsbrEnc_EnvInit (
/* other switches */
hSbrElement->sbrConfigData.useWaveCoding = params->useWaveCoding;
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 */
if(updateFreqBandTable(&hSbrElement->sbrConfigData,
@ -1999,7 +2097,8 @@ INT sbrEncoder_Init(
*/
if ( ! FDKsbrEnc_InitializeSbrDefaults ( &sbrConfig[el],
*downSampleFactor,
coreFrameLength
coreFrameLength,
IS_LOWDELAY(aot)
) )
{
error = 1;

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -684,6 +684,9 @@ const sbrTuningTable_t sbrTuningTable[] =
/** 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 ***/
/* 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 */
@ -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 */
/* 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, 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 */
/* 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 */
/* 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, 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 */

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -682,7 +682,7 @@ FDKsbrEnc_InitTonCorrParamExtr (INT frameSize, /*!< Current
/*
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) {
switch (timeSlots) {
@ -690,7 +690,7 @@ FDKsbrEnc_InitTonCorrParamExtr (INT frameSize, /*!< Current
hTonCorr->lpcLength[0] = 8 - LPC_ORDER;
hTonCorr->lpcLength[1] = 7 - LPC_ORDER;
hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD;
hTonCorr->numberOfEstimatesPerFrame = sbrCfg->noQmfSlots / 7;
hTonCorr->numberOfEstimatesPerFrame = 2; /* sbrCfg->noQmfSlots / 7 */
hTonCorr->frameStartIndexInvfEst = 0;
hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD;
break;
@ -698,7 +698,7 @@ FDKsbrEnc_InitTonCorrParamExtr (INT frameSize, /*!< Current
hTonCorr->lpcLength[0] = 8 - LPC_ORDER;
hTonCorr->lpcLength[1] = 8 - LPC_ORDER;
hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD;
hTonCorr->numberOfEstimatesPerFrame = sbrCfg->noQmfSlots / 8;
hTonCorr->numberOfEstimatesPerFrame = 2; /* sbrCfg->noQmfSlots / 8 */
hTonCorr->frameStartIndexInvfEst = 0;
hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD;
break;

View File

@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -118,7 +118,7 @@ typedef struct
INT bufferLength; /*!< Length of the r and i buffers. */
INT stepSize; /*!< Stride for the lpc estimate. */
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 nextSample; /*!< Where to start the LPC analysis of the current frame.*/
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"
#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 */
#define ABS_THRES ((FIXP_DBL)16)
@ -106,22 +106,30 @@ amm-info@iis.fraunhofer.de
\return calculated value
*******************************************************************************/
#define NRG_SHIFT 3 /* for energy summation */
static FIXP_DBL spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS],
INT *scaleEnergies,
FIXP_DBL EnergyTotal,
INT nSfb,
INT start,
INT border,
INT stop)
INT YBufferWriteOffset,
INT stop,
INT *result_e)
{
INT i,j;
INT len1,len2;
FIXP_DBL delta,tmp0,tmp1,tmp2;
FIXP_DBL accu1,accu2,delta_sum,result;
SCHAR energies_e_diff[NUMBER_TIME_SLOTS_2304], energies_e, energyTotal_e=19, energies_e_add;
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;
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(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 */
for (j=0; j<nSfb; j++) {
#define NRG_SCALE 3
FDK_ASSERT(len1<=8); /* otherwise an overflow is possible */
FDK_ASSERT(len2<=8); /* otherwise an overflow is possible */
/* init with some energy to prevent division by zero
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 */
accu2 = ((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY*8.0/32))) << fixMin(scaleEnergies[0],25))>>NRG_SCALE; /* can be simplified in dsp implementation */
accu1_init = scaleValue((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY))),-energies_e);
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 */
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 */
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 */
tmp0 = CalcLdData(accu2);
tmp1 = CalcLdData(accu1);
tmp2 = (tmp0 - tmp1 + CalcLdData(len1)-CalcLdData(len2));
delta = fixp_abs(fMult(tmp2, FL2FXCONST_DBL(0.6931471806f)));
#define LN2 FL2FXCONST_DBL(0.6931471806f) /* ln(2) */
tmp0 = fLog2(accu2, accu_e) - fLog2(accu1, accu_e);
tmp1 = fLog2((FIXP_DBL)len1, 31) - fLog2((FIXP_DBL)len2, 31);
delta = fMult(LN2, (tmp0 + tmp1));
delta = (FIXP_DBL)FDKabs( delta );
/* Weighting with amplitude ratio of this band */
result = (EnergyTotal == FL2FXCONST_DBL(0.0f))
? FL2FXCONST_DBL(0.f)
: FDKsbrEnc_LSI_divide_scale_fract( (accu1+accu2),
(EnergyTotal>>NRG_SCALE)+(FIXP_DBL)1,
(FIXP_DBL)MAXVAL_DBL >> fixMin(scaleEnergies[0],(DFRACT_BITS-1)) );
delta_sum += (FIXP_DBL)(fMult(sqrtFixp(result), delta));
accu_e++;
accu1>>=1;
accu2>>=1;
if (accu_e & 1) {
accu_e++;
accu1>>=1;
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);
}
@ -175,9 +231,12 @@ static FIXP_DBL spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FRE
*******************************************************************************
\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,
int *scaleEnergies,
@ -194,6 +253,7 @@ static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies,
int ts,k;
/* 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 (k = 0; k < freqBandTable[0]; k++) {
accu1 += Energies[ts][k] >> 6;
@ -201,12 +261,12 @@ static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies,
}
for (; ts<tran_offdiv2+(slots>>nrgSzShift); ts++) {
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)))
+ (accu2 >> fixMin(scaleEnergies[1],(DFRACT_BITS-1))) ) << (2);
nrgTotal = ( scaleValueSaturate(accu1, 1-scaleEnergies[0]) )
+ ( scaleValueSaturate(accu2, 4-scaleEnergies[1]) );
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
function is reduced.
The values EnergiesM are scaled by the factor (1/32.0) and scaleEnergies[0]
The return value nrgTotal is scaled by the factor (1/32.0)
The values EnergiesM are scaled by the factor (2^19-scaleEnergies[0]) for
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 */
INT *scaleEnergies,
INT YBufferWriteOffset,
FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS], /*!< Combined output */
UCHAR *RESTRICT freqBandTable,
INT nSfb,
INT sbrSlots,
INT timeStep)
{
INT i,j,k,slotIn,slotOut,scale;
INT i,j,k,slotIn,slotOut,scale[2];
INT li,ui;
FIXP_DBL nrgTotal;
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 Left and Right channel */
for (slotOut=0; slotOut<sbrSlots; slotOut++) {
slotIn = 2*slotOut;
slotIn = timeStep*slotOut;
for (j=0; j<nSfb; j++) {
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);
else {
/* Now add all energies */
accu = FL2FXCONST_DBL(0.0f);
for (slotOut=0; slotOut<sbrSlots; slotOut++) {
for (slotOut=0; slotOut<YBufferWriteOffset; slotOut++) {
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);
@ -299,18 +371,23 @@ FDKsbrEnc_frameSplitter(FIXP_DBL **Energies,
int YBufferSzShift,
int nSfb,
int timeStep,
int no_cols)
int no_cols,
FIXP_DBL* tonality)
{
if (tran_vector[1]==0) /* no transient was detected */
{
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;
INT border;
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 );
EnergiesM = (FIXP_DBL(*)[MAX_FREQ_COEFFS])_EnergiesM;
/*
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,
scaleEnergies,
YBufferWriteOffset,
EnergiesM,
freqBandTable,
nSfb,
sbrSlots,
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
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. */
border = (sbrSlots+1) >> 1;
if ( (INT)EnergyTotal&0xffffffe0 && (scaleEnergies[0]<32 || scaleEnergies[1]<32) ) /* i.e. > 31 */ {
delta = spectralChange(EnergiesM,
scaleEnergies,
EnergyTotal,
nSfb,
0,
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 */
else
} else {
tran_vector[0] = 0;
}
}
/* Update prevLowBandEnergy */
h_sbrTransientDetector->prevLowBandEnergy = newLowbandEnergy;
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
FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
UINT sbrSyntaxFlags, /* SBR syntax flags derived from AOT. */
INT frameSize,
INT sampleFreq,
sbrConfigurationPtr params,
@ -649,8 +740,8 @@ FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientD
{
INT totalBitrate = params->codecSettings.standardBitrate * params->codecSettings.nChannels;
INT codecBitrate = params->codecSettings.bitRate;
FIXP_DBL bitrateFactor_fix, framedur_fix;
INT scale_0, scale_1;
FIXP_DBL bitrateFactor_m, framedur_fix;
INT bitrateFactor_e, tmp_e;
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;
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 {
bitrateFactor_fix = FL2FXCONST_DBL(1.0/4.0);
scale_0 = 0;
bitrateFactor_m = FL2FXCONST_DBL(1.0/4.0);
bitrateFactor_e = 2;
}
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);
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_rows <= QMF_CHANNELS);
@ -684,7 +780,8 @@ FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientD
h_sbrTransientDetector->no_cols = no_cols;
h_sbrTransientDetector->tran_thr = (FIXP_DBL)((params->tran_thr << (32-24-1)) / no_rows);
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->mode = params->tran_det_mode;
h_sbrTransientDetector->prevLowBandEnergy = FL2FXCONST_DBL(0.0f);
@ -692,3 +789,281 @@ FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientD
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
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@ -96,7 +96,8 @@ typedef struct
FIXP_DBL transients[QMF_MAX_TIME_SLOTS+(QMF_MAX_TIME_SLOTS/2)];
FIXP_DBL thresholds[QMF_CHANNELS];
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 prevHighBandEnergy; /* Energy of high band */
INT tran_fc; /* Number of lowband subbands to discard */
@ -112,6 +113,57 @@ 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
FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
FIXP_DBL **Energies,
@ -124,6 +176,7 @@ FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
int
FDKsbrEnc_InitSbrTransientDetector (HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector,
UINT sbrSyntaxFlags, /* SBR syntax flags derived from AOT. */
INT frameSize,
INT sampleFreq,
sbrConfigurationPtr params,
@ -145,6 +198,6 @@ FDKsbrEnc_frameSplitter(FIXP_DBL **Energies,
int YBufferSzShift,
int nSfb,
int timeStep,
int no_cols);
int no_cols,
FIXP_DBL* tonality);
#endif