AAC Encoder low delay quality

* AAC-Encoder

   - Revise bit distribution for lowdelay configuration to improve encoder
     audio quality.
   - Adjust lowdelay bitreservoir for low bitreservoir configuration.
     Modified file(s):
        libAACenc\src\aacEnc_ram.cpp
        libAACenc\src\aacenc.cpp
        libAACenc\src\aacenc_lib.cpp
        libAACenc\src\aacenc_tns.cpp
        libAACenc\src\adj_thr.cpp
        libAACenc\src\adj_thr.h
        libAACenc\src\block_switch.cpp
        libAACenc\src\block_switch.h
        libAACenc\src\interface.h
        libAACenc\src\psy_main.cpp
        libAACenc\src\qc_data.h
        libAACenc\src\qc_main.cpp

* FDK-Library

   - Increase the accuracy in CalcInvLdData() calculation which improves the
     encoder audio quality.
     Modified file(s):
        libFDK\src\fixpoint_math.cpp

Bug 9428126

Change-Id: I302d7f4c3aeccf79e1b85f20e18a31e6e2b10544
This commit is contained in:
Jean-Michel Trivi 2013-08-28 17:54:51 -07:00
parent 206a397c70
commit 7ad97579f8
14 changed files with 564 additions and 212 deletions

View File

@ -89,13 +89,13 @@ amm-info@iis.fraunhofer.de
******************************************************************************/ ******************************************************************************/
/*! /*!
\file \file
\brief Memory layout \brief Memory layout
\author Markus Lohwasser \author Markus Lohwasser
*/ */
#include "aacEnc_ram.h" #include "aacEnc_ram.h"
C_ALLOC_MEM (AACdynamic_RAM, FIXP_DBL, AAC_ENC_DYN_RAM_SIZE/sizeof(FIXP_DBL)) C_AALLOC_MEM (AACdynamic_RAM, FIXP_DBL, AAC_ENC_DYN_RAM_SIZE/sizeof(FIXP_DBL))
/* /*
Static memory areas, must not be overwritten in other sections of the decoder ! Static memory areas, must not be overwritten in other sections of the decoder !
@ -175,7 +175,7 @@ C_ALLOC_MEM (Ram_aacEnc_BitCntrState, BITCNTR_STATE, 1)
*/ */
C_ALLOC_MEM2 (Ram_aacEnc_QCout, QC_OUT, 1, (1)) C_ALLOC_MEM2 (Ram_aacEnc_QCout, QC_OUT, 1, (1))
C_ALLOC_MEM2 (Ram_aacEnc_QCelement, QC_OUT_ELEMENT, 1, (1)*(6)) C_ALLOC_MEM2 (Ram_aacEnc_QCelement, QC_OUT_ELEMENT, (1), (6))
QC_OUT_CHANNEL *GetRam_aacEnc_QCchannel (int n, UCHAR* dynamic_RAM) { QC_OUT_CHANNEL *GetRam_aacEnc_QCchannel (int n, UCHAR* dynamic_RAM) {
FDK_ASSERT(dynamic_RAM!=0); FDK_ASSERT(dynamic_RAM!=0);
return ((QC_OUT_CHANNEL*) (dynamic_RAM + P_BUF_0 + n*sizeof(QC_OUT_CHANNEL))); return ((QC_OUT_CHANNEL*) (dynamic_RAM + P_BUF_0 + n*sizeof(QC_OUT_CHANNEL)));

View File

@ -578,6 +578,8 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize(HANDLE_AAC_ENC hAacEnc,
qcInit.minBits = (config->minBitsPerFrame!=-1) ? fixMax(qcInit.minBits, config->minBitsPerFrame) : qcInit.minBits; qcInit.minBits = (config->minBitsPerFrame!=-1) ? fixMax(qcInit.minBits, config->minBitsPerFrame) : qcInit.minBits;
} }
qcInit.sampleRate = config->sampleRate;
qcInit.advancedBitsToPe = isLowDelay(config->audioObjectType) ? 1 : 0 ;
qcInit.nSubFrames = config->nSubFrames; qcInit.nSubFrames = config->nSubFrames;
qcInit.padding.paddingRest = config->sampleRate; qcInit.padding.paddingRest = config->sampleRate;

View File

@ -98,7 +98,7 @@ amm-info@iis.fraunhofer.de
/* Encoder library info */ /* Encoder library info */
#define AACENCODER_LIB_VL0 3 #define AACENCODER_LIB_VL0 3
#define AACENCODER_LIB_VL1 4 #define AACENCODER_LIB_VL1 4
#define AACENCODER_LIB_VL2 7 #define AACENCODER_LIB_VL2 8
#define AACENCODER_LIB_TITLE "AAC Encoder" #define AACENCODER_LIB_TITLE "AAC Encoder"
#define AACENCODER_LIB_BUILD_DATE __DATE__ #define AACENCODER_LIB_BUILD_DATE __DATE__
#define AACENCODER_LIB_BUILD_TIME __TIME__ #define AACENCODER_LIB_BUILD_TIME __TIME__
@ -689,7 +689,7 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder,
hAacConfig->bitrateMode = 0; hAacConfig->bitrateMode = 0;
} }
if (config->userBitrateMode==0) { if (config->userBitrateMode==0) {
hAacConfig->bitreservoir = 50*config->nChannels; /* default, reduced bitreservoir */ hAacConfig->bitreservoir = 100*config->nChannels; /* default, reduced bitreservoir */
} }
if (hAacConfig->bitrateMode!=0) { if (hAacConfig->bitrateMode!=0) {
return AACENC_INVALID_CONFIG; return AACENC_INVALID_CONFIG;

View File

@ -83,7 +83,7 @@ amm-info@iis.fraunhofer.de
/******************************** MPEG Audio Encoder ************************** /******************************** MPEG Audio Encoder **************************
Initial author: Alex Groeschel Initial author: Alex Groeschel, Tobias Chalupka
contents/description: Temporal noise shaping contents/description: Temporal noise shaping
******************************************************************************/ ******************************************************************************/

View File

@ -123,6 +123,117 @@ static const FIXP_DBL SnrLdMin4 = (FIXP_DBL)0x02000000; /*FL2FXCONST_DBL(FDKlog
static const FIXP_DBL SnrLdMin5 = (FIXP_DBL)0xfc000000; /*FL2FXCONST_DBL(FDKlog(0.25) /FDKlog(2.0)/LD_DATA_SCALING);*/ static const FIXP_DBL SnrLdMin5 = (FIXP_DBL)0xfc000000; /*FL2FXCONST_DBL(FDKlog(0.25) /FDKlog(2.0)/LD_DATA_SCALING);*/
/*
The bits2Pe factors are choosen for the case that some times
the crash recovery strategy will be activated once.
*/
typedef struct {
INT bitrate;
LONG bits2PeFactor_mono;
LONG bits2PeFactor_mono_slope;
LONG bits2PeFactor_stereo;
LONG bits2PeFactor_stereo_slope;
LONG bits2PeFactor_mono_scfOpt;
LONG bits2PeFactor_mono_scfOpt_slope;
LONG bits2PeFactor_stereo_scfOpt;
LONG bits2PeFactor_stereo_scfOpt_slope;
} BIT_PE_SFAC;
typedef struct {
const INT sampleRate;
const BIT_PE_SFAC * pPeTab;
const INT nEntries;
} BITS2PE_CFG_TAB;
static const BIT_PE_SFAC S_Bits2PeTab16000[] = {
{ 10000, 0x228F5C29, 0x02FEF55D, 0x1D70A3D7, 0x09BC9D6D, 0x228F5C29, 0x02FEF55D, 0x1C28F5C3, 0x0CBB92CA},
{ 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}
};
static const BIT_PE_SFAC S_Bits2PeTab22050[] = {
{ 16000, 0x1a8f5c29, 0x1797cc3a, 0x128f5c29, 0x18e75793, 0x175c28f6, 0x221426fe, 0x00000000, 0x5a708ede},
{ 24000, 0x2051eb85, 0x092ccf6c, 0x18a3d70a, 0x13a92a30, 0x1fae147b, 0xbcbe61d, 0x16147ae1, 0x18e75793},
{ 32000, 0x228f5c29, 0x029f16b1, 0x1d70a3d7, 0x088509c0, 0x228f5c29, 0x29f16b1, 0x1c28f5c3, 0x0b242071},
{ 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}
};
static const BIT_PE_SFAC S_Bits2PeTab24000[] = {
{ 16000, 0x19eb851f, 0x13a92a30, 0x1147ae14, 0x164840e1, 0x1999999a, 0x12599ed8, 0x00000000, 0x46c764ae},
{ 24000, 0x1eb851ec, 0x0d1b7176, 0x16b851ec, 0x18e75793, 0x1e147ae1, 0x0fba8827, 0x1147ae14, 0x2c9081c3},
{ 32000, 0x21eb851f, 0x049667b6, 0x1ccccccd, 0x07357e67, 0x21eb851f, 0x03eea20a, 0x1c28f5c3, 0x07357e67},
{ 48000, 0x2428f5c3, 0x014f8b59, 0x2051eb85, 0x053e2d62, 0x23d70a3d, 0x01f75105, 0x1fae147b, 0x07357e67},
{ 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}
};
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},
{ 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}
};
static const BIT_PE_SFAC S_Bits2PeTab44100[] = {
{ 16000, 0x10a3d70a, 0x1797cc3a, 0x00000000, 0x00000000, 0x00000000, 0x59210386, 0x00000000, 0x00000000},
{ 24000, 0x16666666, 0x1797cc3a, 0x00000000, 0x639d5e4a, 0x15c28f5c, 0x12599ed8, 0x00000000, 0x5bc01a37},
{ 32000, 0x1c28f5c3, 0x049667b6, 0x1851eb85, 0x049667b6, 0x1a3d70a4, 0x088509c0, 0x16666666, 0x053e2d62},
{ 48000, 0x1e666666, 0x05e5f30e, 0x1a8f5c29, 0x049667b6, 0x1e666666, 0x05e5f30e, 0x18f5c28f, 0x05e5f30e},
{ 64000, 0x2147ae14, 0x0346dc5d, 0x1ccccccd, 0x02f2f987, 0x2147ae14, 0x02f2f987, 0x1bd70a3d, 0x039abf34},
{ 96000, 0x247ae148, 0x068db8bb, 0x1fae147b, 0x029f16b1, 0x2428f5c3, 0x0639d5e5, 0x1f5c28f6, 0x029f16b1},
{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}
};
static const BIT_PE_SFAC S_Bits2PeTab48000[] = {
{ 16000, 0x0f5c28f6, 0x31ceaf25, 0x00000000, 0x00000000, 0x00000000, 0x74a771c9, 0x00000000, 0x00000000},
{ 24000, 0x1b851eb8, 0x029f16b1, 0x00000000, 0x663c74fb, 0x1c7ae148, 0xe47991bd, 0x00000000, 0x49667b5f},
{ 32000, 0x1c28f5c3, 0x029f16b1, 0x18f5c28f, 0x07357e67, 0x15c28f5c, 0x0f12c27a, 0x11eb851f, 0x13016484},
{ 48000, 0x1d70a3d7, 0x053e2d62, 0x1c7ae148, 0xfe08aefc, 0x1d1eb852, 0x068db8bb, 0x1b333333, 0xfeb074a8},
{ 64000, 0x20000000, 0x03eea20a, 0x1b851eb8, 0x0346dc5d, 0x2051eb85, 0x0346dc5d, 0x1a8f5c29, 0x039abf34},
{ 96000, 0x23d70a3d, 0x053e2d62, 0x1eb851ec, 0x029f16b1, 0x23851eb8, 0x04ea4a8c, 0x1e147ae1, 0x02f2f987},
{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}
};
static const BITS2PE_CFG_TAB bits2PeConfigTab[] = {
{ 16000, S_Bits2PeTab16000, sizeof(S_Bits2PeTab16000)/sizeof(BIT_PE_SFAC) },
{ 22050, S_Bits2PeTab22050, sizeof(S_Bits2PeTab22050)/sizeof(BIT_PE_SFAC) },
{ 24000, S_Bits2PeTab24000, sizeof(S_Bits2PeTab24000)/sizeof(BIT_PE_SFAC) },
{ 32000, S_Bits2PeTab32000, sizeof(S_Bits2PeTab32000)/sizeof(BIT_PE_SFAC) },
{ 44100, S_Bits2PeTab44100, sizeof(S_Bits2PeTab44100)/sizeof(BIT_PE_SFAC) },
{ 48000, S_Bits2PeTab48000, sizeof(S_Bits2PeTab48000)/sizeof(BIT_PE_SFAC) }
};
/* values for avoid hole flag */ /* values for avoid hole flag */
enum _avoid_hole_state { enum _avoid_hole_state {
NO_AH =0, NO_AH =0,
@ -135,6 +246,99 @@ enum _avoid_hole_state {
#define Q_BITFAC (24) /* Q scaling used in FDKaacEnc_bitresCalcBitFac() calculation */ #define Q_BITFAC (24) /* Q scaling used in FDKaacEnc_bitresCalcBitFac() calculation */
#define Q_AVGBITS (17) /* scale bit values */ #define Q_AVGBITS (17) /* scale bit values */
/*****************************************************************************
functionname: FDKaacEnc_InitBits2PeFactor
description: retrieve bits2PeFactor from table
*****************************************************************************/
static void FDKaacEnc_InitBits2PeFactor(
FIXP_DBL *bits2PeFactor_m,
INT *bits2PeFactor_e,
const INT bitRate,
const INT nChannels,
const INT sampleRate,
const INT advancedBitsToPe,
const INT invQuant
)
{
/* default bits2pe factor */
FIXP_DBL bit2PE_m = FL2FXCONST_DBL(1.18f/(1<<(1)));
INT bit2PE_e = 1;
/* make use of advanced bits to pe factor table */
if (advancedBitsToPe) {
int i;
const BIT_PE_SFAC *peTab = NULL;
INT size = 0;
/* Get correct table entry */
for (i=0; i<(INT)(sizeof(bits2PeConfigTab)/sizeof(BITS2PE_CFG_TAB)); i++) {
if (sampleRate >= bits2PeConfigTab[i].sampleRate) {
peTab = bits2PeConfigTab[i].pPeTab;
size = bits2PeConfigTab[i].nEntries;
}
}
if ( (peTab!=NULL) && (size!=0) ) {
INT startB = -1;
LONG startPF = 0;
LONG peSlope = 0;
/* stereo or mono mode and invQuant used or not */
for (i=0; i<size-1; i++)
{
if ((peTab[i].bitrate<=bitRate) && ((peTab[i+1].bitrate>bitRate) || ((i==size-2)) ))
{
if (nChannels==1)
{
startPF = (!invQuant) ? peTab[i].bits2PeFactor_mono : peTab[i].bits2PeFactor_mono_scfOpt;
peSlope = (!invQuant) ? peTab[i].bits2PeFactor_mono_slope : peTab[i].bits2PeFactor_mono_scfOpt_slope;
/*endPF = (!invQuant) ? peTab[i+1].bits2PeFactor_mono : peTab[i+1].bits2PeFactor_mono_scfOpt;
endB=peTab[i+1].bitrate;*/
startB=peTab[i].bitrate;
break;
}
else
{
startPF = (!invQuant) ? peTab[i].bits2PeFactor_stereo : peTab[i].bits2PeFactor_stereo_scfOpt;
peSlope = (!invQuant) ? peTab[i].bits2PeFactor_stereo_slope : peTab[i].bits2PeFactor_stereo_scfOpt_slope;
/*endPF = (!invQuant) ? peTab[i+1].bits2PeFactor_stereo : peTab[i+1].bits2PeFactor_stereo_scfOpt;
endB=peTab[i+1].bitrate;*/
startB=peTab[i].bitrate;
break;
}
}
} /* for i */
/* if a configuration is available */
if (startB!=-1) {
/* linear interpolate to actual PEfactor */
FIXP_DBL peFac = fMult((FIXP_DBL)(bitRate-startB)<<14, (FIXP_DBL)peSlope) << 2;
FIXP_DBL bit2PE = peFac + (FIXP_DBL)startPF; /* startPF_float = startPF << 2 */
/* sanity check if bits2pe value is high enough */
if ( bit2PE >= (FL2FXCONST_DBL(0.35f) >> 2) ) {
bit2PE_m = bit2PE;
bit2PE_e = 2; /* table is fixed scaled */
}
} /* br */
} /* sr */
} /* advancedBitsToPe */
/* return bits2pe factor */
*bits2PeFactor_m = bit2PE_m;
*bits2PeFactor_e = bit2PE_e;
}
/*****************************************************************************
functionname: FDKaacEnc_bits2pe2
description: convert from bits to pe
*****************************************************************************/
static INT FDKaacEnc_bits2pe2( static INT FDKaacEnc_bits2pe2(
const INT bits, const INT bits,
const FIXP_DBL factor_m, const FIXP_DBL factor_m,
@ -450,22 +654,23 @@ void FDKaacEnc_calcWeighting(PE_DATA *peData,
FIXP_DBL nrgSum14, nrgSum12, nrgSum34, nrgTotal; FIXP_DBL nrgSum14, nrgSum12, nrgSum34, nrgTotal;
FIXP_DBL nrgFacLd_14, nrgFacLd_12, nrgFacLd_34; FIXP_DBL nrgFacLd_14, nrgFacLd_12, nrgFacLd_34;
INT usePatch, exePatch; INT usePatch, exePatch;
int sfb, nLinesSum = 0; int sfb, sfbGrp, nLinesSum = 0;
nrgSum14 = nrgSum12 = nrgSum34 = nrgTotal = FL2FXCONST_DBL(0.f); nrgSum14 = nrgSum12 = nrgSum34 = nrgTotal = FL2FXCONST_DBL(0.f);
/* calculate flatness of audible spectrum, i.e. spectrum above masking threshold. */ /* calculate flatness of audible spectrum, i.e. spectrum above masking threshold. */
for (sfb = 0; sfb < psyOutChan->sfbCnt; sfb++) { for (sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) {
for (sfb=0; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
FIXP_DBL nrgFac12 = CalcInvLdData(psyOutChan->sfbEnergyLdData[sfb]>>1); /* nrg^(1/2) */ FIXP_DBL nrgFac12 = CalcInvLdData(psyOutChan->sfbEnergyLdData[sfbGrp+sfb]>>1); /* nrg^(1/2) */
FIXP_DBL nrgFac14 = CalcInvLdData(psyOutChan->sfbEnergyLdData[sfb]>>2); /* nrg^(1/4) */ FIXP_DBL nrgFac14 = CalcInvLdData(psyOutChan->sfbEnergyLdData[sfbGrp+sfb]>>2); /* nrg^(1/4) */
/* maximal number of bands is 64, results scaling factor 6 */ /* maximal number of bands is 64, results scaling factor 6 */
nLinesSum += peData->peChannelData[ch].sfbNLines[sfb]; /* relevant lines */ nLinesSum += peData->peChannelData[ch].sfbNLines[sfbGrp+sfb]; /* relevant lines */
nrgTotal += ( psyOutChan->sfbEnergy[sfb] >> 6 ); /* sum up nrg */ nrgTotal += ( psyOutChan->sfbEnergy[sfbGrp+sfb] >> 6 ); /* sum up nrg */
nrgSum12 += ( nrgFac12 >> 6 ); /* sum up nrg^(2/4) */ nrgSum12 += ( nrgFac12 >> 6 ); /* sum up nrg^(2/4) */
nrgSum14 += ( nrgFac14 >> 6 ); /* sum up nrg^(1/4) */ nrgSum14 += ( nrgFac14 >> 6 ); /* sum up nrg^(1/4) */
nrgSum34 += ( fMult(nrgFac14, nrgFac12) >> 6 ); /* sum up nrg^(3/4) */ nrgSum34 += ( fMult(nrgFac14, nrgFac12) >> 6 ); /* sum up nrg^(3/4) */
}
} }
nrgTotal = CalcLdData(nrgTotal); /* get ld64 of total nrg */ nrgTotal = CalcLdData(nrgTotal); /* get ld64 of total nrg */
@ -479,32 +684,35 @@ void FDKaacEnc_calcWeighting(PE_DATA *peData,
usePatch = (adjThrStateElement->chaosMeasureEnFac[ch] > FL2FXCONST_DBL(0.78125f)); usePatch = (adjThrStateElement->chaosMeasureEnFac[ch] > FL2FXCONST_DBL(0.78125f));
exePatch = ((usePatch) && (adjThrStateElement->lastEnFacPatch[ch])); exePatch = ((usePatch) && (adjThrStateElement->lastEnFacPatch[ch]));
for (sfb = 0; sfb < psyOutChan->sfbCnt; sfb++) { for (sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) {
for (sfb=0; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
INT sfbExePatch; INT sfbExePatch;
/* for MS coupled SFBs, also execute patch in side channel if done in mid channel */ /* for MS coupled SFBs, also execute patch in side channel if done in mid channel */
if ((ch == 1) && (toolsInfo->msMask[sfb])) { if ((ch == 1) && (toolsInfo->msMask[sfbGrp+sfb])) {
sfbExePatch = exePatchM; sfbExePatch = exePatchM;
} }
else { else {
sfbExePatch = exePatch; sfbExePatch = exePatch;
} }
if ( (sfbExePatch) && (psyOutChan->sfbEnergy[sfb]>FL2FXCONST_DBL(0.f)) ) if ( (sfbExePatch) && (psyOutChan->sfbEnergy[sfbGrp+sfb]>FL2FXCONST_DBL(0.f)) )
{ {
/* execute patch based on spectral flatness calculated above */ /* execute patch based on spectral flatness calculated above */
if (adjThrStateElement->chaosMeasureEnFac[ch] > FL2FXCONST_DBL(0.8125f)) { if (adjThrStateElement->chaosMeasureEnFac[ch] > FL2FXCONST_DBL(0.8125f)) {
qcOutChannel[ch]->sfbEnFacLd[sfb] = ( (nrgFacLd_14 + (psyOutChan->sfbEnergyLdData[sfb]+(psyOutChan->sfbEnergyLdData[sfb]>>1)))>>1 ); /* sfbEnergy^(3/4) */ qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb] = ( (nrgFacLd_14 + (psyOutChan->sfbEnergyLdData[sfbGrp+sfb]+(psyOutChan->sfbEnergyLdData[sfbGrp+sfb]>>1)))>>1 ); /* sfbEnergy^(3/4) */
} }
else if (adjThrStateElement->chaosMeasureEnFac[ch] > FL2FXCONST_DBL(0.796875f)) { else if (adjThrStateElement->chaosMeasureEnFac[ch] > FL2FXCONST_DBL(0.796875f)) {
qcOutChannel[ch]->sfbEnFacLd[sfb] = ( (nrgFacLd_12 + psyOutChan->sfbEnergyLdData[sfb])>>1 ); /* sfbEnergy^(2/4) */ qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb] = ( (nrgFacLd_12 + psyOutChan->sfbEnergyLdData[sfbGrp+sfb])>>1 ); /* sfbEnergy^(2/4) */
} }
else { else {
qcOutChannel[ch]->sfbEnFacLd[sfb] = ( (nrgFacLd_34 + (psyOutChan->sfbEnergyLdData[sfb]>>1))>>1 ); /* sfbEnergy^(1/4) */ qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb] = ( (nrgFacLd_34 + (psyOutChan->sfbEnergyLdData[sfbGrp+sfb]>>1))>>1 ); /* sfbEnergy^(1/4) */
} }
qcOutChannel[ch]->sfbEnFacLd[sfb] = fixMin(qcOutChannel[ch]->sfbEnFacLd[sfb],(FIXP_DBL)0); qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb] = fixMin(qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb],(FIXP_DBL)0);
} }
}
} /* sfb loop */ } /* sfb loop */
adjThrStateElement->lastEnFacPatch[ch] = usePatch; adjThrStateElement->lastEnFacPatch[ch] = usePatch;
@ -735,7 +943,6 @@ static FIXP_DBL FDKaacEnc_calcChaosMeasure(PSY_OUT_CHANNEL *psyOutChannel,
return chaosMeasure; return chaosMeasure;
} }
/* apply reduction formula for VBR-mode */ /* apply reduction formula for VBR-mode */
static void FDKaacEnc_reduceThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)], static void FDKaacEnc_reduceThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)],
PSY_OUT_CHANNEL* psyOutChannel[(2)], PSY_OUT_CHANNEL* psyOutChannel[(2)],
@ -923,7 +1130,6 @@ static void FDKaacEnc_reduceThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)],
} }
} }
/***************************************************************************** /*****************************************************************************
functionname: FDKaacEnc_correctThresh functionname: FDKaacEnc_correctThresh
description: if pe difference deltaPe between desired pe and real pe is small enough, description: if pe difference deltaPe between desired pe and real pe is small enough,
@ -948,7 +1154,7 @@ static void FDKaacEnc_correctThresh(CHANNEL_MAPPING* cm,
FIXP_DBL thrFactorLdData; FIXP_DBL thrFactorLdData;
FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData; FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData;
FIXP_DBL *sfbPeFactorsLdData[(6)][(2)]; FIXP_DBL *sfbPeFactorsLdData[(6)][(2)];
FIXP_DBL sfbNActiveLinesLdData[(2)][MAX_GROUPED_SFB]; FIXP_DBL sfbNActiveLinesLdData[(6)][(2)][MAX_GROUPED_SFB];
INT normFactorInt; INT normFactorInt;
FIXP_DBL normFactorLdData; FIXP_DBL normFactorLdData;
@ -979,13 +1185,13 @@ static void FDKaacEnc_correctThresh(CHANNEL_MAPPING* cm,
for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
if ( peChanData->sfbNActiveLines[sfbGrp+sfb] == 0 ) { if ( peChanData->sfbNActiveLines[sfbGrp+sfb] == 0 ) {
sfbNActiveLinesLdData[ch][sfbGrp+sfb] = FL2FXCONST_DBL(-1.0f); sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] = FL2FXCONST_DBL(-1.0f);
} }
else { else {
/* Both CalcLdInt and CalcLdData can be used! /* Both CalcLdInt and CalcLdData can be used!
* No offset has to be subtracted, because sfbNActiveLinesLdData * No offset has to be subtracted, because sfbNActiveLinesLdData
* is shorted while thrFactor calculation */ * is shorted while thrFactor calculation */
sfbNActiveLinesLdData[ch][sfbGrp+sfb] = CalcLdInt(peChanData->sfbNActiveLines[sfbGrp+sfb]); sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] = CalcLdInt(peChanData->sfbNActiveLines[sfbGrp+sfb]);
} }
if ( ((ahFlag[elementId][ch][sfbGrp+sfb] < AH_ACTIVE) || (deltaPe > 0)) && if ( ((ahFlag[elementId][ch][sfbGrp+sfb] < AH_ACTIVE) || (deltaPe > 0)) &&
peChanData->sfbNActiveLines[sfbGrp+sfb] != 0 ) peChanData->sfbNActiveLines[sfbGrp+sfb] != 0 )
@ -1002,14 +1208,14 @@ static void FDKaacEnc_correctThresh(CHANNEL_MAPPING* cm,
- (FIXP_DBL)(minScale<<(DFRACT_BITS-1-LD_DATA_SHIFT)); - (FIXP_DBL)(minScale<<(DFRACT_BITS-1-LD_DATA_SHIFT));
if (sumLd < FL2FXCONST_DBL(0.f)) { if (sumLd < FL2FXCONST_DBL(0.f)) {
sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = sfbNActiveLinesLdData[ch][sfbGrp+sfb] - sumLd; sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] - sumLd;
} }
else { else {
if ( sfbNActiveLinesLdData[ch][sfbGrp+sfb] > (FL2FXCONST_DBL(-1.f) + sumLd) ) { if ( sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] > (FL2FXCONST_DBL(-1.f) + sumLd) ) {
sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = sfbNActiveLinesLdData[ch][sfbGrp+sfb] - sumLd; sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] - sumLd;
} }
else { else {
sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = sfbNActiveLinesLdData[ch][sfbGrp+sfb]; sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb];
} }
} }
@ -1050,7 +1256,7 @@ static void FDKaacEnc_correctThresh(CHANNEL_MAPPING* cm,
} }
else { else {
/* new threshold */ /* new threshold */
FIXP_DBL tmp = CalcInvLdData(sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] + normFactorLdData - sfbNActiveLinesLdData[ch][sfbGrp+sfb] - FL2FXCONST_DBL((float)LD_DATA_SHIFT/LD_DATA_SCALING)); FIXP_DBL tmp = CalcInvLdData(sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] + normFactorLdData - sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] - FL2FXCONST_DBL((float)LD_DATA_SHIFT/LD_DATA_SCALING));
/* limit thrFactor to 60dB */ /* limit thrFactor to 60dB */
tmp = (deltaPe<0) ? tmp : (-tmp); tmp = (deltaPe<0) ? tmp : (-tmp);
@ -1683,7 +1889,6 @@ static void FDKaacEnc_adaptThresholdsToPe(CHANNEL_MAPPING* cm,
} }
/* similar to FDKaacEnc_adaptThresholdsToPe(), for VBR-mode */ /* similar to FDKaacEnc_adaptThresholdsToPe(), for VBR-mode */
void FDKaacEnc_AdaptThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)], void FDKaacEnc_AdaptThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)],
PSY_OUT_CHANNEL* psyOutChannel[(2)], PSY_OUT_CHANNEL* psyOutChannel[(2)],
@ -1692,8 +1897,14 @@ void FDKaacEnc_AdaptThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)],
PE_DATA *peData, PE_DATA *peData,
const INT nChannels) const INT nChannels)
{ {
UCHAR pAhFlag[(2)][MAX_GROUPED_SFB]; UCHAR (*pAhFlag)[MAX_GROUPED_SFB];
FIXP_DBL pThrExp[(2)][MAX_GROUPED_SFB]; FIXP_DBL (*pThrExp)[MAX_GROUPED_SFB];
/* allocate scratch memory */
C_ALLOC_SCRATCH_START(_pAhFlag, UCHAR, (2)*MAX_GROUPED_SFB)
C_ALLOC_SCRATCH_START(_pThrExp, FIXP_DBL, (2)*MAX_GROUPED_SFB)
pAhFlag = (UCHAR(*)[MAX_GROUPED_SFB])_pAhFlag;
pThrExp = (FIXP_DBL(*)[MAX_GROUPED_SFB])_pThrExp;
/* thresholds to the power of redExp */ /* thresholds to the power of redExp */
FDKaacEnc_calcThreshExp(pThrExp, qcOutChannel, psyOutChannel, nChannels); FDKaacEnc_calcThreshExp(pThrExp, qcOutChannel, psyOutChannel, nChannels);
@ -1711,6 +1922,9 @@ void FDKaacEnc_AdaptThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)],
AdjThrStateElement->vbrQualFactor, AdjThrStateElement->vbrQualFactor,
&AdjThrStateElement->chaosMeasureOld); &AdjThrStateElement->chaosMeasureOld);
/* free scratch memory */
C_ALLOC_SCRATCH_END(_pThrExp, FIXP_DBL, (2)*MAX_GROUPED_SFB)
C_ALLOC_SCRATCH_END(_pAhFlag, UCHAR, (2)*MAX_GROUPED_SFB)
} }
@ -2002,95 +2216,112 @@ bail:
functionname: FDKaacEnc_AdjThrInit functionname: FDKaacEnc_AdjThrInit
description: initialize ADJ_THR_STATE description: initialize ADJ_THR_STATE
*****************************************************************************/ *****************************************************************************/
void FDKaacEnc_AdjThrInit(ADJ_THR_STATE *hAdjThr, void FDKaacEnc_AdjThrInit(
const INT meanPe, ADJ_THR_STATE *hAdjThr,
ELEMENT_BITS *elBits[(6)], const INT meanPe,
INT nElements, ELEMENT_BITS *elBits[(6)],
FIXP_DBL vbrQualFactor) INT invQuant,
INT nElements,
INT nChannelsEff,
INT sampleRate,
INT advancedBitsToPe,
FIXP_DBL vbrQualFactor
)
{ {
INT i; INT i;
FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f); FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f);
FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f); FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f);
/* common for all elements: */
/* parameters for bitres control */
hAdjThr->bresParamLong.clipSaveLow = (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
hAdjThr->bresParamLong.clipSaveHigh = (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
hAdjThr->bresParamLong.minBitSave = (FIXP_DBL)0xf999999a; /* FL2FXCONST_DBL(-0.05f); */
hAdjThr->bresParamLong.maxBitSave = (FIXP_DBL)0x26666666; /* FL2FXCONST_DBL(0.3f); */
hAdjThr->bresParamLong.clipSpendLow = (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
hAdjThr->bresParamLong.clipSpendHigh = (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
hAdjThr->bresParamLong.minBitSpend = (FIXP_DBL)0xf3333333; /* FL2FXCONST_DBL(-0.10f); */
hAdjThr->bresParamLong.maxBitSpend = (FIXP_DBL)0x33333333; /* FL2FXCONST_DBL(0.4f); */
hAdjThr->bresParamShort.clipSaveLow = (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
hAdjThr->bresParamShort.clipSaveHigh = (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
hAdjThr->bresParamShort.minBitSave = (FIXP_DBL)0x00000000; /* FL2FXCONST_DBL(0.0f); */
hAdjThr->bresParamShort.maxBitSave = (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
hAdjThr->bresParamShort.clipSpendLow = (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
hAdjThr->bresParamShort.clipSpendHigh = (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
hAdjThr->bresParamShort.minBitSpend = (FIXP_DBL)0xf9999998; /* FL2FXCONST_DBL(-0.05f); */
hAdjThr->bresParamShort.maxBitSpend = (FIXP_DBL)0x40000000; /* FL2FXCONST_DBL(0.5f); */
/* specific for each element: */
for (i=0; i<nElements; i++) {
ATS_ELEMENT* atsElem = hAdjThr->adjThrStateElem[i];
MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam;
INT chBitrate = elBits[i]->chBitrateEl;
/* common for all elements: */
/* parameters for bitres control */ /* parameters for bitres control */
hAdjThr->bresParamLong.clipSaveLow = (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */ atsElem->peMin = fMultI(POINT8, meanPe) >> 1;
hAdjThr->bresParamLong.clipSaveHigh = (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */ atsElem->peMax = fMultI(POINT6, meanPe);
hAdjThr->bresParamLong.minBitSave = (FIXP_DBL)0xf999999a; /* FL2FXCONST_DBL(-0.05f); */
hAdjThr->bresParamLong.maxBitSave = (FIXP_DBL)0x26666666; /* FL2FXCONST_DBL(0.3f); */
hAdjThr->bresParamLong.clipSpendLow = (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
hAdjThr->bresParamLong.clipSpendHigh = (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
hAdjThr->bresParamLong.minBitSpend = (FIXP_DBL)0xf3333333; /* FL2FXCONST_DBL(-0.10f); */
hAdjThr->bresParamLong.maxBitSpend = (FIXP_DBL)0x33333333; /* FL2FXCONST_DBL(0.4f); */
hAdjThr->bresParamShort.clipSaveLow = (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */ /* for use in FDKaacEnc_reduceThresholdsVBR */
hAdjThr->bresParamShort.clipSaveHigh = (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */ atsElem->chaosMeasureOld = FL2FXCONST_DBL(0.3f);
hAdjThr->bresParamShort.minBitSave = (FIXP_DBL)0x00000000; /* FL2FXCONST_DBL(0.0f); */
hAdjThr->bresParamShort.maxBitSave = (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
hAdjThr->bresParamShort.clipSpendLow = (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
hAdjThr->bresParamShort.clipSpendHigh = (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
hAdjThr->bresParamShort.minBitSpend = (FIXP_DBL)0xf9999998; /* FL2FXCONST_DBL(-0.05f); */
hAdjThr->bresParamShort.maxBitSpend = (FIXP_DBL)0x40000000; /* FL2FXCONST_DBL(0.5f); */
/* specific for each element: */ /* additional pe offset to correct pe2bits for low bitrates */
for (i=0; i<nElements; i++) { atsElem->peOffset = 0;
ATS_ELEMENT* atsElem = hAdjThr->adjThrStateElem[i];
MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam;
INT chBitrate = elBits[i]->chBitrateEl;
/* parameters for bitres control */ /* vbr initialisation */
atsElem->peMin = fMultI(POINT8, meanPe) >> 1; atsElem->vbrQualFactor = vbrQualFactor;
atsElem->peMax = fMultI(POINT6, meanPe); if (chBitrate < 32000)
{
/* for use in FDKaacEnc_reduceThresholdsVBR */ atsElem->peOffset = fixMax(50, 100-fMultI((FIXP_DBL)0x666667, chBitrate));
atsElem->chaosMeasureOld = FL2FXCONST_DBL(0.3f);
/* additional pe offset to correct pe2bits for low bitrates */
atsElem->peOffset = 0;
/* vbr initialisation */
atsElem->vbrQualFactor = vbrQualFactor;
if (chBitrate < 32000)
{
atsElem->peOffset = fixMax(50, 100-fMultI((FIXP_DBL)0x666667, chBitrate));
}
/* avoid hole parameters */
if (chBitrate > 20000) {
atsElem->ahParam.modifyMinSnr = TRUE;
atsElem->ahParam.startSfbL = 15;
atsElem->ahParam.startSfbS = 3;
}
else {
atsElem->ahParam.modifyMinSnr = FALSE;
atsElem->ahParam.startSfbL = 0;
atsElem->ahParam.startSfbS = 0;
}
/* minSnr adaptation */
msaParam->maxRed = FL2FXCONST_DBL(0.00390625f); /* 0.25f/64.0f */
/* start adaptation of minSnr for avgEn/sfbEn > startRatio */
msaParam->startRatio = FL2FXCONST_DBL(0.05190512648f); /* ld64(10.0f) */
/* maximum minSnr reduction to minSnr^maxRed is reached for
avgEn/sfbEn >= maxRatio */
/* msaParam->maxRatio = 1000.0f; */
/*msaParam->redRatioFac = ((float)1.0f - msaParam->maxRed) / ((float)10.0f*log10(msaParam->startRatio/msaParam->maxRatio)/log10(2.0f)*(float)0.3010299956f);*/
msaParam->redRatioFac = FL2FXCONST_DBL(-0.375f); /* -0.0375f * 10.0f */
/*msaParam->redOffs = (float)1.0f - msaParam->redRatioFac * (float)10.0f * log10(msaParam->startRatio)/log10(2.0f) * (float)0.3010299956f;*/
msaParam->redOffs = FL2FXCONST_DBL(0.021484375); /* 1.375f/64.0f */
/* init pe correction */
atsElem->peCorrectionFactor_m = FL2FXCONST_DBL(0.5f); /* 1.0 */
atsElem->peCorrectionFactor_e = 1;
atsElem->dynBitsLast = -1;
atsElem->peLast = 0;
/* init bits to pe factor */
atsElem->bits2PeFactor_m = FL2FXCONST_DBL(1.18f/(1<<(1)));
atsElem->bits2PeFactor_e = 1;
} }
/* avoid hole parameters */
if (chBitrate > 20000) {
atsElem->ahParam.modifyMinSnr = TRUE;
atsElem->ahParam.startSfbL = 15;
atsElem->ahParam.startSfbS = 3;
}
else {
atsElem->ahParam.modifyMinSnr = FALSE;
atsElem->ahParam.startSfbL = 0;
atsElem->ahParam.startSfbS = 0;
}
/* minSnr adaptation */
msaParam->maxRed = FL2FXCONST_DBL(0.00390625f); /* 0.25f/64.0f */
/* start adaptation of minSnr for avgEn/sfbEn > startRatio */
msaParam->startRatio = FL2FXCONST_DBL(0.05190512648f); /* ld64(10.0f) */
/* maximum minSnr reduction to minSnr^maxRed is reached for
avgEn/sfbEn >= maxRatio */
/* msaParam->maxRatio = 1000.0f; */
/*msaParam->redRatioFac = ((float)1.0f - msaParam->maxRed) / ((float)10.0f*log10(msaParam->startRatio/msaParam->maxRatio)/log10(2.0f)*(float)0.3010299956f);*/
msaParam->redRatioFac = FL2FXCONST_DBL(-0.375f); /* -0.0375f * 10.0f */
/*msaParam->redOffs = (float)1.0f - msaParam->redRatioFac * (float)10.0f * log10(msaParam->startRatio)/log10(2.0f) * (float)0.3010299956f;*/
msaParam->redOffs = FL2FXCONST_DBL(0.021484375); /* 1.375f/64.0f */
/* init pe correction */
atsElem->peCorrectionFactor_m = FL2FXCONST_DBL(0.5f); /* 1.0 */
atsElem->peCorrectionFactor_e = 1;
atsElem->dynBitsLast = -1;
atsElem->peLast = 0;
/* init bits to pe factor */
/* init bits2PeFactor */
FDKaacEnc_InitBits2PeFactor(
&atsElem->bits2PeFactor_m,
&atsElem->bits2PeFactor_e,
chBitrate, /* bitrate/channel*/
nChannelsEff, /* number of channels */
sampleRate,
advancedBitsToPe,
invQuant
);
} /* for nElements */
} }
@ -2154,6 +2385,67 @@ static void FDKaacEnc_FDKaacEnc_calcPeCorrection(
} }
static void FDKaacEnc_calcPeCorrectionLowBitRes(
FIXP_DBL *const correctionFac_m,
INT *const correctionFac_e,
const INT peLast,
const INT bitsLast,
const INT bitresLevel,
const INT nChannels,
const FIXP_DBL bits2PeFactor_m,
const INT bits2PeFactor_e
)
{
/* tuning params */
const FIXP_DBL amp = FL2FXCONST_DBL(0.005);
const FIXP_DBL maxDiff = FL2FXCONST_DBL(0.25f);
if (bitsLast > 0) {
/* Estimate deviation of granted and used dynamic bits in previous frame, in PE units */
const int bitsBalLast = peLast - FDKaacEnc_bits2pe2(
bitsLast,
bits2PeFactor_m,
bits2PeFactor_e);
/* reserve n bits per channel */
int headroom = (bitresLevel>=50*nChannels) ? 0 : (100*nChannels);
/* in PE units */
headroom = FDKaacEnc_bits2pe2(
headroom,
bits2PeFactor_m,
bits2PeFactor_e);
/*
* diff = amp * ((bitsBalLast - headroom) / (bitresLevel + headroom)
* diff = max ( min ( diff, maxDiff, -maxDiff)) / 2
*/
FIXP_DBL denominator = (FIXP_DBL)FDKaacEnc_bits2pe2(bitresLevel, bits2PeFactor_m, bits2PeFactor_e) + (FIXP_DBL)headroom;
int scaling = 0;
FIXP_DBL diff = (bitsBalLast>=headroom)
? fMult(amp, fDivNorm( (FIXP_DBL)(bitsBalLast - headroom), denominator, &scaling))
: -fMult(amp, fDivNorm(-(FIXP_DBL)(bitsBalLast - headroom), denominator, &scaling)) ;
scaling -= 1; /* divide by 2 */
diff = (scaling<=0) ? FDKmax( FDKmin (diff>>(-scaling), maxDiff>>1), -maxDiff>>1)
: FDKmax( FDKmin (diff, maxDiff>>(1+scaling)), -maxDiff>>(1+scaling)) << scaling;
/*
* corrFac += diff
* corrFac = max ( min ( corrFac/2.f, 1.f/2.f, 0.75f/2.f ) )
*/
*correctionFac_m = FDKmax(FDKmin((*correctionFac_m)+diff, FL2FXCONST_DBL(1.0f/2.f)), FL2FXCONST_DBL(0.75f/2.f)) ;
*correctionFac_e = 1;
}
else {
*correctionFac_m = FL2FXCONST_DBL(0.75/2.f);
*correctionFac_e = 1;
}
}
void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState, void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState,
ATS_ELEMENT *AdjThrStateElement, ATS_ELEMENT *AdjThrStateElement,
PSY_OUT_CHANNEL *psyOutChannel[(2)], PSY_OUT_CHANNEL *psyOutChannel[(2)],
@ -2166,7 +2458,7 @@ void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState,
const INT bitresBits, const INT bitresBits,
const INT maxBitresBits, const INT maxBitresBits,
const FIXP_DBL maxBitFac, const FIXP_DBL maxBitFac,
const INT bitDistributenMode) const INT bitDistributionMode)
{ {
FIXP_DBL bitFactor; FIXP_DBL bitFactor;
INT noRedPe = peData->pe; INT noRedPe = peData->pe;
@ -2184,7 +2476,7 @@ void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState,
} }
if (grantedDynBits >= 1) { if (grantedDynBits >= 1) {
if (bitDistributenMode!=0) { if (bitDistributionMode!=0) {
*grantedPe = FDKaacEnc_bits2pe2(grantedDynBits, AdjThrStateElement->bits2PeFactor_m, AdjThrStateElement->bits2PeFactor_e); *grantedPe = FDKaacEnc_bits2pe2(grantedDynBits, AdjThrStateElement->bits2PeFactor_m, AdjThrStateElement->bits2PeFactor_e);
} }
else else
@ -2208,16 +2500,32 @@ void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState,
} }
/* correction of pe value */ /* correction of pe value */
{ switch (bitDistributionMode) {
FDKaacEnc_FDKaacEnc_calcPeCorrection( case 2:
&AdjThrStateElement->peCorrectionFactor_m, case 1:
&AdjThrStateElement->peCorrectionFactor_e, FDKaacEnc_calcPeCorrectionLowBitRes(
fixMin(*grantedPe, noRedPe), &AdjThrStateElement->peCorrectionFactor_m,
AdjThrStateElement->peLast, &AdjThrStateElement->peCorrectionFactor_e,
AdjThrStateElement->dynBitsLast, AdjThrStateElement->peLast,
AdjThrStateElement->bits2PeFactor_m, AdjThrStateElement->dynBitsLast,
AdjThrStateElement->bits2PeFactor_e bitresBits,
nChannels,
AdjThrStateElement->bits2PeFactor_m,
AdjThrStateElement->bits2PeFactor_e
); );
break;
case 0:
default:
FDKaacEnc_FDKaacEnc_calcPeCorrection(
&AdjThrStateElement->peCorrectionFactor_m,
&AdjThrStateElement->peCorrectionFactor_e,
fixMin(*grantedPe, noRedPe),
AdjThrStateElement->peLast,
AdjThrStateElement->dynBitsLast,
AdjThrStateElement->bits2PeFactor_m,
AdjThrStateElement->bits2PeFactor_e
);
break;
} }
*grantedPeCorr = (INT)(fMult((FIXP_DBL)(*grantedPe<<Q_AVGBITS), AdjThrStateElement->peCorrectionFactor_m) >> (Q_AVGBITS-AdjThrStateElement->peCorrectionFactor_e)); *grantedPeCorr = (INT)(fMult((FIXP_DBL)(*grantedPe<<Q_AVGBITS), AdjThrStateElement->peCorrectionFactor_m) >> (Q_AVGBITS-AdjThrStateElement->peCorrectionFactor_e));
@ -2291,20 +2599,19 @@ void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(6)],
} /* -end- element loop */ } /* -end- element loop */
} }
for (i=0; i<cm->nElements; i++) { for (i=0; i<cm->nElements; i++) {
int ch,sfb,sfbGrp; int ch,sfb,sfbGrp;
/* no weighting of threholds and energies for mlout */ /* no weighting of threholds and energies for mlout */
/* weight energies and thresholds */ /* weight energies and thresholds */
for (ch=0; ch<cm->elInfo[i].nChannelsInEl; ch++) { for (ch=0; ch<cm->elInfo[i].nChannelsInEl; ch++) {
QC_OUT_CHANNEL* pQcOutCh = qcElement[i]->qcOutChannel[ch]; QC_OUT_CHANNEL* pQcOutCh = qcElement[i]->qcOutChannel[ch];
for (sfbGrp = 0;sfbGrp < psyOutElement[i]->psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutElement[i]->psyOutChannel[ch]->sfbPerGroup) { for (sfbGrp = 0;sfbGrp < psyOutElement[i]->psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutElement[i]->psyOutChannel[ch]->sfbPerGroup) {
for (sfb=0; sfb<psyOutElement[i]->psyOutChannel[ch]->maxSfbPerGroup; sfb++) { for (sfb=0; sfb<psyOutElement[i]->psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
pQcOutCh->sfbThresholdLdData[sfb+sfbGrp] += pQcOutCh->sfbEnFacLd[sfb+sfbGrp]; pQcOutCh->sfbThresholdLdData[sfb+sfbGrp] += pQcOutCh->sfbEnFacLd[sfb+sfbGrp];
}
} }
} }
} }
}
} }
void FDKaacEnc_AdjThrClose(ADJ_THR_STATE** phAdjThr) void FDKaacEnc_AdjThrClose(ADJ_THR_STATE** phAdjThr)

View File

@ -98,13 +98,14 @@ amm-info@iis.fraunhofer.de
#include "interface.h" #include "interface.h"
void FDKaacEnc_peCalculation(
void FDKaacEnc_peCalculation(PE_DATA *peData, PE_DATA *peData,
PSY_OUT_CHANNEL* psyOutChannel[(2)], PSY_OUT_CHANNEL* psyOutChannel[(2)],
QC_OUT_CHANNEL* qcOutChannel[(2)], QC_OUT_CHANNEL* qcOutChannel[(2)],
struct TOOLSINFO *toolsInfo, struct TOOLSINFO *toolsInfo,
ATS_ELEMENT* adjThrStateElement, ATS_ELEMENT* adjThrStateElement,
const INT nChannels); const INT nChannels
);
INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE** phAdjThr, INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE** phAdjThr,
INT nElements); INT nElements);
@ -112,9 +113,13 @@ INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE** phAdjThr,
void FDKaacEnc_AdjThrInit(ADJ_THR_STATE *hAdjThr, void FDKaacEnc_AdjThrInit(ADJ_THR_STATE *hAdjThr,
const INT peMean, const INT peMean,
ELEMENT_BITS* elBits[(6)], ELEMENT_BITS* elBits[(6)],
INT invQuant,
INT nElements, INT nElements,
INT nChannelsEff,
INT sampleRate,
INT advancedBitsToPe,
FIXP_DBL vbrQualFactor); FIXP_DBL vbrQualFactor);
void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState, void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState,
ATS_ELEMENT *AdjThrStateElement, ATS_ELEMENT *AdjThrStateElement,
@ -128,7 +133,7 @@ void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState,
const INT bitresBits, const INT bitresBits,
const INT maxBitresBits, const INT maxBitresBits,
const FIXP_DBL maxBitFac, const FIXP_DBL maxBitFac,
const INT bitDistributenMode); const INT bitDistributionMode);
void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(6)], void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(6)],
QC_OUT_ELEMENT* qcElement[(6)], QC_OUT_ELEMENT* qcElement[(6)],

View File

@ -83,7 +83,7 @@ amm-info@iis.fraunhofer.de
/***************************** MPEG-4 AAC Encoder ************************** /***************************** MPEG-4 AAC Encoder **************************
Author(s): M. Werner Author(s): M. Werner, Tobias Chalupka
Description: Block switching Description: Block switching
******************************************************************************/ ******************************************************************************/
@ -100,9 +100,11 @@ amm-info@iis.fraunhofer.de
static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], const INT blSwWndIdx); static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], const INT blSwWndIdx);
static void FDKaacEnc_CalcWindowEnergy( BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, static void FDKaacEnc_CalcWindowEnergy(
INT windowLen); BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl,
INT windowLen,
const INT_PCM *pTimeSignal
);
/****************** Constants *****************************/ /****************** Constants *****************************/
/* LONG START SHORT STOP LOWOV */ /* LONG START SHORT STOP LOWOV */
@ -145,20 +147,9 @@ static const FIXP_DBL minAttackNrg = (FL2FXCONST_DBL(1e+6f*NORM_PCM_ENERGY)>>BLO
/**************** internal function prototypes ***********/ /**************** internal function prototypes ***********/
static INT FDKaacEnc_GetWindowIndex(INT blockSwWindowIndex);
static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], const INT shortWndIdx);
static void FDKaacEnc_CalcWindowEnergy( BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl,
INT windowLen);
/****************** Routines ****************************/ /****************** Routines ****************************/
void FDKaacEnc_InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay) void FDKaacEnc_InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay)
{ {
/* note: the pointer to timeSignal can be zeroed here, because it is initialized for every call
to FDKaacEnc_BlockSwitching anew */
FDKmemclear (blockSwitchingControl, sizeof(BLOCK_SWITCHING_CONTROL)); FDKmemclear (blockSwitchingControl, sizeof(BLOCK_SWITCHING_CONTROL));
if (isLowDelay) if (isLowDelay)
@ -214,7 +205,7 @@ static const INT chgWndSqLkAhd[2][2][N_BLOCKTYPES] =
/*attack */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, START_WINDOW, WRONG_WINDOW, WRONG_WINDOW} } /* attack */ /*attack */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, START_WINDOW, WRONG_WINDOW, WRONG_WINDOW} } /* attack */
}; };
int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, const INT granuleLength, const int isLFE) int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, const INT granuleLength, const int isLFE, const INT_PCM *pTimeSignal)
{ {
UINT i; UINT i;
FIXP_DBL enM1, enMax; FIXP_DBL enM1, enMax;
@ -263,7 +254,7 @@ int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, con
/* Calculate unfiltered and filtered energies in subwindows and combine to segments */ /* Calculate unfiltered and filtered energies in subwindows and combine to segments */
FDKaacEnc_CalcWindowEnergy(blockSwitchingControl, granuleLength>>(nBlockSwitchWindows==4? 2:3 )); FDKaacEnc_CalcWindowEnergy(blockSwitchingControl, granuleLength>>(nBlockSwitchWindows==4? 2:3 ), pTimeSignal);
/* now calculate if there is an attack */ /* now calculate if there is an attack */
@ -335,8 +326,7 @@ static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], const INT blSwWnd
} }
static void FDKaacEnc_CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, INT windowLen, const INT_PCM *pTimeSignal)
static void FDKaacEnc_CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, INT windowLen)
{ {
INT i; INT i;
UINT w; UINT w;
@ -344,8 +334,6 @@ static void FDKaacEnc_CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *RESTRICT blockSw
FIXP_SGL hiPassCoeff0 = hiPassCoeff[0]; FIXP_SGL hiPassCoeff0 = hiPassCoeff[0];
FIXP_SGL hiPassCoeff1 = hiPassCoeff[1]; FIXP_SGL hiPassCoeff1 = hiPassCoeff[1];
INT_PCM *timeSignal = blockSwitchingControl->timeSignal;
/* sum up scalarproduct of timesignal as windowed Energies */ /* sum up scalarproduct of timesignal as windowed Energies */
for (w=0; w < blockSwitchingControl->nBlockSwitchWindows; w++) { for (w=0; w < blockSwitchingControl->nBlockSwitchWindows; w++) {
@ -361,9 +349,9 @@ static void FDKaacEnc_CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *RESTRICT blockSw
FIXP_DBL tempUnfiltered, tempFiltred, t1, t2; FIXP_DBL tempUnfiltered, tempFiltred, t1, t2;
/* tempUnfiltered is scaled with 1 to prevent overflows during calculation of tempFiltred */ /* tempUnfiltered is scaled with 1 to prevent overflows during calculation of tempFiltred */
#if SAMPLE_BITS == DFRACT_BITS #if SAMPLE_BITS == DFRACT_BITS
tempUnfiltered = (FIXP_DBL) *timeSignal++ >> 1; tempUnfiltered = (FIXP_DBL) *pTimeSignal++ >> 1;
#else #else
tempUnfiltered = (FIXP_DBL) *timeSignal++ << (DFRACT_BITS-SAMPLE_BITS-1); tempUnfiltered = (FIXP_DBL) *pTimeSignal++ << (DFRACT_BITS-SAMPLE_BITS-1);
#endif #endif
t1 = fMultDiv2(hiPassCoeff1, tempUnfiltered-temp_iirState0); t1 = fMultDiv2(hiPassCoeff1, tempUnfiltered-temp_iirState0);
t2 = fMultDiv2(hiPassCoeff0, temp_iirState1); t2 = fMultDiv2(hiPassCoeff0, temp_iirState1);

View File

@ -107,7 +107,6 @@ amm-info@iis.fraunhofer.de
/****************** Structures ***************************/ /****************** Structures ***************************/
typedef struct{ typedef struct{
INT_PCM *timeSignal;
INT lastWindowSequence; INT lastWindowSequence;
INT windowShape; INT windowShape;
INT lastWindowShape; INT lastWindowShape;
@ -136,7 +135,7 @@ typedef struct{
void FDKaacEnc_InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay); void FDKaacEnc_InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay);
int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, const INT granuleLength, const int isLFE); int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, const INT granuleLength, const int isLFE, const INT_PCM *pTimeSignal);
int FDKaacEnc_SyncBlockSwitching( int FDKaacEnc_SyncBlockSwitching(
BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft, BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft,

View File

@ -92,6 +92,7 @@ amm-info@iis.fraunhofer.de
#define _INTERFACE_H #define _INTERFACE_H
#include "common_fix.h" #include "common_fix.h"
#include "FDK_audio.h"
#include "psy_data.h" #include "psy_data.h"
#include "aacenc_tns.h" #include "aacenc_tns.h"
@ -160,4 +161,9 @@ typedef struct {
}PSY_OUT; }PSY_OUT;
inline int isLowDelay( AUDIO_OBJECT_TYPE aot )
{
return (aot==AOT_ER_AAC_LD || aot==AOT_ER_AAC_ELD);
}
#endif /* _INTERFACE_H */ #endif /* _INTERFACE_H */

View File

@ -116,11 +116,6 @@ static const FIXP_DBL fadeOutFactor[FADE_OUT_LEN] = {1840644096, 1533870080, 122
/* forward definitions */ /* forward definitions */
static inline int isLowDelay( AUDIO_OBJECT_TYPE aot )
{
return (aot==AOT_ER_AAC_LD || aot==AOT_ER_AAC_ELD);
}
/***************************************************************************** /*****************************************************************************
functionname: FDKaacEnc_PsyNew functionname: FDKaacEnc_PsyNew
@ -513,28 +508,28 @@ AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels,
for(ch = 0; ch < channels; ch++) for(ch = 0; ch < channels; ch++)
{ {
C_ALLOC_SCRATCH_START(timeSignal, INT_PCM, (1024)); C_ALLOC_SCRATCH_START(pTimeSignal, INT_PCM, (1024))
psyStatic[ch]->blockSwitchingControl.timeSignal = timeSignal;
/* deinterleave input data and use for block switching */ /* deinterleave input data and use for block switching */
FDKaacEnc_deinterleaveInputBuffer( psyStatic[ch]->blockSwitchingControl.timeSignal, FDKaacEnc_deinterleaveInputBuffer( pTimeSignal,
&pInput[chIdx[ch]], &pInput[chIdx[ch]],
psyConf->granuleLength, psyConf->granuleLength,
totalChannels); totalChannels);
FDKaacEnc_BlockSwitching (&psyStatic[ch]->blockSwitchingControl, FDKaacEnc_BlockSwitching (&psyStatic[ch]->blockSwitchingControl,
psyConf->granuleLength psyConf->granuleLength,
,psyStatic[ch]->isLFE psyStatic[ch]->isLFE,
pTimeSignal
); );
/* fill up internal input buffer, to 2xframelength samples */ /* fill up internal input buffer, to 2xframelength samples */
FDKmemcpy(psyStatic[ch]->psyInputBuffer+blockSwitchingOffset, FDKmemcpy(psyStatic[ch]->psyInputBuffer+blockSwitchingOffset,
psyStatic[ch]->blockSwitchingControl.timeSignal, pTimeSignal,
(2*psyConf->granuleLength-blockSwitchingOffset)*sizeof(INT_PCM)); (2*psyConf->granuleLength-blockSwitchingOffset)*sizeof(INT_PCM));
C_ALLOC_SCRATCH_END(timeSignal, INT_PCM, (1024)); C_ALLOC_SCRATCH_END(pTimeSignal, INT_PCM, (1024))
} }
/* synch left and right block type */ /* synch left and right block type */

View File

@ -143,6 +143,8 @@ struct QC_INIT{
INT maxBits; /* maximum number of bits in reservoir */ INT maxBits; /* maximum number of bits in reservoir */
INT averageBits; /* average number of bits we should use */ INT averageBits; /* average number of bits we should use */
INT bitRes; INT bitRes;
INT sampleRate; /* output sample rate */
INT advancedBitsToPe; /* if set, calc bits2PE factor depending on samplerate */
INT staticBits; /* Bits per frame consumed by transport layers. */ INT staticBits; /* Bits per frame consumed by transport layers. */
QCDATA_BR_MODE bitrateMode; QCDATA_BR_MODE bitrateMode;
INT meanPe; INT meanPe;
@ -252,7 +254,7 @@ typedef struct
INT minBitsPerFrame; /* minimal allowd bits per fram, superframing - DRM */ INT minBitsPerFrame; /* minimal allowd bits per fram, superframing - DRM */
INT nElements; INT nElements;
QCDATA_BR_MODE bitrateMode; QCDATA_BR_MODE bitrateMode;
INT bitDistributenMode; /* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir */ INT bitDistributionMode; /* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir */
INT bitResTot; INT bitResTot;
INT bitResTotMax; INT bitResTotMax;
INT maxIterations; /* Maximum number of allowed iterations before FDKaacEnc_crashRecovery() is applied. */ INT maxIterations; /* Maximum number of allowed iterations before FDKaacEnc_crashRecovery() is applied. */

View File

@ -382,10 +382,10 @@ AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC,
if ( isConstantBitrateMode(hQC->bitrateMode) ) { if ( isConstantBitrateMode(hQC->bitrateMode) ) {
INT bitresPerChannel = (hQC->bitResTotMax / init->channelMapping->nChannelsEff); INT bitresPerChannel = (hQC->bitResTotMax / init->channelMapping->nChannelsEff);
/* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir */ /* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir */
hQC->bitDistributenMode = (bitresPerChannel>50) ? 0 : (bitresPerChannel>0) ? 1 : 2; hQC->bitDistributionMode = (bitresPerChannel>100) ? 0 : (bitresPerChannel>0) ? 1 : 2;
} }
else { else {
hQC->bitDistributenMode = 0; /* full bitreservoir */ hQC->bitDistributionMode = 0; /* full bitreservoir */
} }
@ -420,11 +420,17 @@ AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC,
break; break;
} }
FDKaacEnc_AdjThrInit(hQC->hAdjThr, FDKaacEnc_AdjThrInit(
init->meanPe, hQC->hAdjThr,
hQC->elementBits, /* or channelBitrates, was: channelBitrate */ init->meanPe,
init->channelMapping->nElements, hQC->elementBits, /* or channelBitrates, was: channelBitrate */
hQC->vbrQualFactor); hQC->invQuant,
init->channelMapping->nElements,
init->channelMapping->nChannelsEff,
init->sampleRate, /* output sample rate */
init->advancedBitsToPe, /* if set, calc bits2PE factor depending on samplerate */
hQC->vbrQualFactor
);
return AAC_ENC_OK; return AAC_ENC_OK;
} }
@ -655,7 +661,7 @@ static AAC_ENCODER_ERROR FDKaacEnc_prepareBitDistribution(QC_STATE* h
hQC->elementBits[i]->bitResLevelEl, hQC->elementBits[i]->bitResLevelEl,
hQC->elementBits[i]->maxBitResBitsEl, hQC->elementBits[i]->maxBitResBitsEl,
hQC->maxBitFac, hQC->maxBitFac,
hQC->bitDistributenMode); hQC->bitDistributionMode);
*totalAvailableBits += hQC->elementBits[i]->bitResLevelEl; *totalAvailableBits += hQC->elementBits[i]->bitResLevelEl;
/* get total corrected granted PE */ /* get total corrected granted PE */

View File

@ -93,7 +93,7 @@ amm-info@iis.fraunhofer.de
/* FDK tools library info */ /* FDK tools library info */
#define FDK_TOOLS_LIB_VL0 2 #define FDK_TOOLS_LIB_VL0 2
#define FDK_TOOLS_LIB_VL1 3 #define FDK_TOOLS_LIB_VL1 3
#define FDK_TOOLS_LIB_VL2 1 #define FDK_TOOLS_LIB_VL2 2
#define FDK_TOOLS_LIB_TITLE "FDK Tools" #define FDK_TOOLS_LIB_TITLE "FDK Tools"
#define FDK_TOOLS_LIB_BUILD_DATE __DATE__ #define FDK_TOOLS_LIB_BUILD_DATE __DATE__
#define FDK_TOOLS_LIB_BUILD_TIME __TIME__ #define FDK_TOOLS_LIB_BUILD_TIME __TIME__

View File

@ -242,30 +242,72 @@ FIXP_DBL mul_dbl_sgl_rnd (const FIXP_DBL op1, const FIXP_SGL op2)
*****************************************************************************/ *****************************************************************************/
LNK_SECTION_CODE_L1 LNK_SECTION_CODE_L1
FIXP_DBL CalcInvLdData(FIXP_DBL op) /* This table is used for lookup 2^x with */
/* x in range [0...1.0[ in steps of 1/32 */
LNK_SECTION_DATA_L1 static const UINT exp2_tab_long[32]={
0x40000000,0x4166C34C,0x42D561B4,0x444C0740,
0x45CAE0F2,0x47521CC6,0x48E1E9BA,0x4A7A77D4,
0x4C1BF829,0x4DC69CDD,0x4F7A9930,0x51382182,
0x52FF6B55,0x54D0AD5A,0x56AC1F75,0x5891FAC1,
0x5A82799A,0x5C7DD7A4,0x5E8451D0,0x60962665,
0x62B39509,0x64DCDEC3,0x6712460B,0x69540EC9,
0x6BA27E65,0x6DFDDBCC,0x70666F76,0x72DC8374,
0x75606374,0x77F25CCE,0x7A92BE8B,0x7D41D96E
// 0x80000000
};
/* This table is used for lookup 2^x with */
/* x in range [0...1/32[ in steps of 1/1024 */
LNK_SECTION_DATA_L1 static const UINT exp2w_tab_long[32]={
0x40000000,0x400B1818,0x4016321B,0x40214E0C,
0x402C6BE9,0x40378BB4,0x4042AD6D,0x404DD113,
0x4058F6A8,0x40641E2B,0x406F479E,0x407A7300,
0x4085A051,0x4090CF92,0x409C00C4,0x40A733E6,
0x40B268FA,0x40BD9FFF,0x40C8D8F5,0x40D413DD,
0x40DF50B8,0x40EA8F86,0x40F5D046,0x410112FA,
0x410C57A2,0x41179E3D,0x4122E6CD,0x412E3152,
0x41397DCC,0x4144CC3B,0x41501CA0,0x415B6EFB,
// 0x4166C34C,
};
/* This table is used for lookup 2^x with */
/* x in range [0...1/1024[ in steps of 1/32768 */
LNK_SECTION_DATA_L1 static const UINT exp2x_tab_long[32]={
0x40000000,0x400058B9,0x4000B173,0x40010A2D,
0x400162E8,0x4001BBA3,0x4002145F,0x40026D1B,
0x4002C5D8,0x40031E95,0x40037752,0x4003D011,
0x400428CF,0x4004818E,0x4004DA4E,0x4005330E,
0x40058BCE,0x4005E48F,0x40063D51,0x40069613,
0x4006EED5,0x40074798,0x4007A05B,0x4007F91F,
0x400851E4,0x4008AAA8,0x4009036E,0x40095C33,
0x4009B4FA,0x400A0DC0,0x400A6688,0x400ABF4F,
//0x400B1818
};
LNK_SECTION_CODE_L1 FIXP_DBL CalcInvLdData(FIXP_DBL x)
{ {
FIXP_DBL result_m; int set_zero = (x < FL2FXCONST_DBL(-31.0/64.0))? 0 : 1;
int set_max = (x >= FL2FXCONST_DBL( 31.0/64.0)) | (x == FL2FXCONST_DBL(0.0));
if ( op == FL2FXCONST_DBL(0.0f) ) { FIXP_SGL frac = (FIXP_SGL)(LONG)(x & 0x3FF);
result_m = (FIXP_DBL)MAXVAL_DBL; UINT index3 = (UINT)(LONG)(x >> 10) & 0x1F;
} UINT index2 = (UINT)(LONG)(x >> 15) & 0x1F;
else if ( op < FL2FXCONST_DBL(0.0f) ) { UINT index1 = (UINT)(LONG)(x >> 20) & 0x1F;
result_m = f2Pow(op, LD_DATA_SHIFT); int exp = (x > FL2FXCONST_DBL(0.0f)) ? (31 - (int)(x>>25)) : (int)(-(x>>25));
}
else {
int result_e;
result_m = f2Pow(op, LD_DATA_SHIFT, &result_e); UINT lookup1 = exp2_tab_long[index1]*set_zero;
result_e = fixMin(fixMax(result_e+1-(DFRACT_BITS-1), -(DFRACT_BITS-1)), (DFRACT_BITS-1)); /* rounding and saturation */ UINT lookup2 = exp2w_tab_long[index2];
UINT lookup3 = exp2x_tab_long[index3];
UINT lookup3f = lookup3 + (UINT)(LONG)fMultDiv2((FIXP_DBL)(0x0016302F),(FIXP_SGL)frac);
UINT lookup12 = (UINT)(LONG)fMult((FIXP_DBL)lookup1, (FIXP_DBL) lookup2);
UINT lookup = (UINT)(LONG)fMult((FIXP_DBL)lookup12, (FIXP_DBL) lookup3f);
if ( (result_e>0) && ( result_m > (((FIXP_DBL)MAXVAL_DBL)>>result_e) ) ) { FIXP_DBL retVal = (lookup<<3) >> exp;
result_m = (FIXP_DBL)MAXVAL_DBL; /* saturate to max representable value */
} if (set_max)
else { retVal=FL2FXCONST_DBL(1.0f);
result_m = (scaleValue(result_m, result_e)+(FIXP_DBL)1)>>1; /* descale result + rounding */
} return retVal;
}
return result_m;
} }