From 7ad97579f8ccb843afdb5b184c4b209253839fe3 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Wed, 28 Aug 2013 17:54:51 -0700 Subject: 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 --- libAACenc/src/aacEnc_ram.cpp | 6 +- libAACenc/src/aacenc.cpp | 2 + libAACenc/src/aacenc_lib.cpp | 4 +- libAACenc/src/aacenc_tns.cpp | 2 +- libAACenc/src/adj_thr.cpp | 565 +++++++++++++++++++++++++++++++---------- libAACenc/src/adj_thr.h | 23 +- libAACenc/src/block_switch.cpp | 34 +-- libAACenc/src/block_switch.h | 3 +- libAACenc/src/interface.h | 6 + libAACenc/src/psy_main.cpp | 19 +- libAACenc/src/qc_data.h | 4 +- libAACenc/src/qc_main.cpp | 22 +- 12 files changed, 500 insertions(+), 190 deletions(-) (limited to 'libAACenc') diff --git a/libAACenc/src/aacEnc_ram.cpp b/libAACenc/src/aacEnc_ram.cpp index 2268726..1844331 100644 --- a/libAACenc/src/aacEnc_ram.cpp +++ b/libAACenc/src/aacEnc_ram.cpp @@ -89,13 +89,13 @@ amm-info@iis.fraunhofer.de ******************************************************************************/ /*! \file - \brief Memory layout + \brief Memory layout \author Markus Lohwasser */ #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 ! @@ -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_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) { FDK_ASSERT(dynamic_RAM!=0); return ((QC_OUT_CHANNEL*) (dynamic_RAM + P_BUF_0 + n*sizeof(QC_OUT_CHANNEL))); diff --git a/libAACenc/src/aacenc.cpp b/libAACenc/src/aacenc.cpp index 29e588f..6ce7b22 100644 --- a/libAACenc/src/aacenc.cpp +++ b/libAACenc/src/aacenc.cpp @@ -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.sampleRate = config->sampleRate; + qcInit.advancedBitsToPe = isLowDelay(config->audioObjectType) ? 1 : 0 ; qcInit.nSubFrames = config->nSubFrames; qcInit.padding.paddingRest = config->sampleRate; diff --git a/libAACenc/src/aacenc_lib.cpp b/libAACenc/src/aacenc_lib.cpp index a256f05..4d5984d 100644 --- a/libAACenc/src/aacenc_lib.cpp +++ b/libAACenc/src/aacenc_lib.cpp @@ -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 7 +#define AACENCODER_LIB_VL2 8 #define AACENCODER_LIB_TITLE "AAC Encoder" #define AACENCODER_LIB_BUILD_DATE __DATE__ #define AACENCODER_LIB_BUILD_TIME __TIME__ @@ -689,7 +689,7 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder, hAacConfig->bitrateMode = 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) { return AACENC_INVALID_CONFIG; diff --git a/libAACenc/src/aacenc_tns.cpp b/libAACenc/src/aacenc_tns.cpp index 9a0edd4..85aea65 100644 --- a/libAACenc/src/aacenc_tns.cpp +++ b/libAACenc/src/aacenc_tns.cpp @@ -83,7 +83,7 @@ amm-info@iis.fraunhofer.de /******************************** MPEG Audio Encoder ************************** - Initial author: Alex Groeschel + Initial author: Alex Groeschel, Tobias Chalupka contents/description: Temporal noise shaping ******************************************************************************/ diff --git a/libAACenc/src/adj_thr.cpp b/libAACenc/src/adj_thr.cpp index 3fcb0be..0bd5827 100644 --- a/libAACenc/src/adj_thr.cpp +++ b/libAACenc/src/adj_thr.cpp @@ -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);*/ +/* +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 */ enum _avoid_hole_state { NO_AH =0, @@ -135,6 +246,99 @@ enum _avoid_hole_state { #define Q_BITFAC (24) /* Q scaling used in FDKaacEnc_bitresCalcBitFac() calculation */ #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; ibitRate) || ((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( const INT bits, const FIXP_DBL factor_m, @@ -450,22 +654,23 @@ void FDKaacEnc_calcWeighting(PE_DATA *peData, FIXP_DBL nrgSum14, nrgSum12, nrgSum34, nrgTotal; FIXP_DBL nrgFacLd_14, nrgFacLd_12, nrgFacLd_34; INT usePatch, exePatch; - int sfb, nLinesSum = 0; + int sfb, sfbGrp, nLinesSum = 0; nrgSum14 = nrgSum12 = nrgSum34 = nrgTotal = FL2FXCONST_DBL(0.f); /* calculate flatness of audible spectrum, i.e. spectrum above masking threshold. */ - for (sfb = 0; sfb < psyOutChan->sfbCnt; sfb++) { - - FIXP_DBL nrgFac12 = CalcInvLdData(psyOutChan->sfbEnergyLdData[sfb]>>1); /* nrg^(1/2) */ - FIXP_DBL nrgFac14 = CalcInvLdData(psyOutChan->sfbEnergyLdData[sfb]>>2); /* nrg^(1/4) */ + for (sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + FIXP_DBL nrgFac12 = CalcInvLdData(psyOutChan->sfbEnergyLdData[sfbGrp+sfb]>>1); /* nrg^(1/2) */ + FIXP_DBL nrgFac14 = CalcInvLdData(psyOutChan->sfbEnergyLdData[sfbGrp+sfb]>>2); /* nrg^(1/4) */ /* maximal number of bands is 64, results scaling factor 6 */ - nLinesSum += peData->peChannelData[ch].sfbNLines[sfb]; /* relevant lines */ - nrgTotal += ( psyOutChan->sfbEnergy[sfb] >> 6 ); /* sum up nrg */ + nLinesSum += peData->peChannelData[ch].sfbNLines[sfbGrp+sfb]; /* relevant lines */ + nrgTotal += ( psyOutChan->sfbEnergy[sfbGrp+sfb] >> 6 ); /* sum up nrg */ nrgSum12 += ( nrgFac12 >> 6 ); /* sum up nrg^(2/4) */ nrgSum14 += ( nrgFac14 >> 6 ); /* sum up nrg^(1/4) */ nrgSum34 += ( fMult(nrgFac14, nrgFac12) >> 6 ); /* sum up nrg^(3/4) */ + } } 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)); 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; sfbmaxSfbPerGroup; sfb++) { + INT sfbExePatch; /* 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; } else { 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 */ 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)) { - 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 { - 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 */ adjThrStateElement->lastEnFacPatch[ch] = usePatch; @@ -735,7 +943,6 @@ static FIXP_DBL FDKaacEnc_calcChaosMeasure(PSY_OUT_CHANNEL *psyOutChannel, return chaosMeasure; } - /* apply reduction formula for VBR-mode */ static void FDKaacEnc_reduceThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)], PSY_OUT_CHANNEL* psyOutChannel[(2)], @@ -923,7 +1130,6 @@ static void FDKaacEnc_reduceThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)], } } - /***************************************************************************** functionname: FDKaacEnc_correctThresh 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 sfbEnLdData, sfbThrLdData, sfbThrReducedLdData; FIXP_DBL *sfbPeFactorsLdData[(6)][(2)]; - FIXP_DBL sfbNActiveLinesLdData[(2)][MAX_GROUPED_SFB]; + FIXP_DBL sfbNActiveLinesLdData[(6)][(2)][MAX_GROUPED_SFB]; INT normFactorInt; FIXP_DBL normFactorLdData; @@ -979,13 +1185,13 @@ static void FDKaacEnc_correctThresh(CHANNEL_MAPPING* cm, for (sfb=0; sfbmaxSfbPerGroup; sfb++) { if ( peChanData->sfbNActiveLines[sfbGrp+sfb] == 0 ) { - sfbNActiveLinesLdData[ch][sfbGrp+sfb] = FL2FXCONST_DBL(-1.0f); + sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] = FL2FXCONST_DBL(-1.0f); } else { /* Both CalcLdInt and CalcLdData can be used! * No offset has to be subtracted, because sfbNActiveLinesLdData * 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)) && 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)); 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 { - if ( sfbNActiveLinesLdData[ch][sfbGrp+sfb] > (FL2FXCONST_DBL(-1.f) + sumLd) ) { - sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = sfbNActiveLinesLdData[ch][sfbGrp+sfb] - sumLd; + if ( sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] > (FL2FXCONST_DBL(-1.f) + sumLd) ) { + sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] - sumLd; } 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 { /* 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 */ tmp = (deltaPe<0) ? tmp : (-tmp); @@ -1683,7 +1889,6 @@ static void FDKaacEnc_adaptThresholdsToPe(CHANNEL_MAPPING* cm, } - /* similar to FDKaacEnc_adaptThresholdsToPe(), for VBR-mode */ void FDKaacEnc_AdaptThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)], PSY_OUT_CHANNEL* psyOutChannel[(2)], @@ -1692,8 +1897,14 @@ void FDKaacEnc_AdaptThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)], PE_DATA *peData, const INT nChannels) { - UCHAR pAhFlag[(2)][MAX_GROUPED_SFB]; - FIXP_DBL pThrExp[(2)][MAX_GROUPED_SFB]; + UCHAR (*pAhFlag)[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 */ FDKaacEnc_calcThreshExp(pThrExp, qcOutChannel, psyOutChannel, nChannels); @@ -1711,6 +1922,9 @@ void FDKaacEnc_AdaptThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)], AdjThrStateElement->vbrQualFactor, &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 description: initialize ADJ_THR_STATE *****************************************************************************/ -void FDKaacEnc_AdjThrInit(ADJ_THR_STATE *hAdjThr, - const INT meanPe, - ELEMENT_BITS *elBits[(6)], - INT nElements, - FIXP_DBL vbrQualFactor) +void FDKaacEnc_AdjThrInit( + ADJ_THR_STATE *hAdjThr, + const INT meanPe, + ELEMENT_BITS *elBits[(6)], + INT invQuant, + INT nElements, + INT nChannelsEff, + INT sampleRate, + INT advancedBitsToPe, + FIXP_DBL vbrQualFactor + ) { - INT i; - - FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f); - FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f); + INT i; + + FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f); + 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; iadjThrStateElem[i]; + MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam; + INT chBitrate = elBits[i]->chBitrateEl; - /* 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; iadjThrStateElem[i]; - MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam; - INT chBitrate = elBits[i]->chBitrateEl; + atsElem->peMin = fMultI(POINT8, meanPe) >> 1; + atsElem->peMax = fMultI(POINT6, meanPe); - /* parameters for bitres control */ - atsElem->peMin = fMultI(POINT8, meanPe) >> 1; - atsElem->peMax = fMultI(POINT6, meanPe); + /* for use in FDKaacEnc_reduceThresholdsVBR */ + atsElem->chaosMeasureOld = FL2FXCONST_DBL(0.3f); - /* for use in FDKaacEnc_reduceThresholdsVBR */ - atsElem->chaosMeasureOld = FL2FXCONST_DBL(0.3f); + /* additional pe offset to correct pe2bits for low bitrates */ + atsElem->peOffset = 0; - /* 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)); + } - /* 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; + } - /* 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 */ - /* 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; - } } @@ -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, ATS_ELEMENT *AdjThrStateElement, PSY_OUT_CHANNEL *psyOutChannel[(2)], @@ -2166,7 +2458,7 @@ void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState, const INT bitresBits, const INT maxBitresBits, const FIXP_DBL maxBitFac, - const INT bitDistributenMode) + const INT bitDistributionMode) { FIXP_DBL bitFactor; INT noRedPe = peData->pe; @@ -2184,7 +2476,7 @@ void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState, } if (grantedDynBits >= 1) { - if (bitDistributenMode!=0) { + if (bitDistributionMode!=0) { *grantedPe = FDKaacEnc_bits2pe2(grantedDynBits, AdjThrStateElement->bits2PeFactor_m, AdjThrStateElement->bits2PeFactor_e); } else @@ -2208,16 +2500,32 @@ void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState, } /* correction of pe value */ - { - FDKaacEnc_FDKaacEnc_calcPeCorrection( - &AdjThrStateElement->peCorrectionFactor_m, - &AdjThrStateElement->peCorrectionFactor_e, - fixMin(*grantedPe, noRedPe), - AdjThrStateElement->peLast, - AdjThrStateElement->dynBitsLast, - AdjThrStateElement->bits2PeFactor_m, - AdjThrStateElement->bits2PeFactor_e + switch (bitDistributionMode) { + case 2: + case 1: + FDKaacEnc_calcPeCorrectionLowBitRes( + &AdjThrStateElement->peCorrectionFactor_m, + &AdjThrStateElement->peCorrectionFactor_e, + AdjThrStateElement->peLast, + AdjThrStateElement->dynBitsLast, + 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<peCorrectionFactor_m) >> (Q_AVGBITS-AdjThrStateElement->peCorrectionFactor_e)); @@ -2291,20 +2599,19 @@ void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(6)], } /* -end- element loop */ } - for (i=0; inElements; i++) { - int ch,sfb,sfbGrp; - /* no weighting of threholds and energies for mlout */ - /* weight energies and thresholds */ - for (ch=0; chelInfo[i].nChannelsInEl; 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 (sfb=0; sfbpsyOutChannel[ch]->maxSfbPerGroup; sfb++) { - pQcOutCh->sfbThresholdLdData[sfb+sfbGrp] += pQcOutCh->sfbEnFacLd[sfb+sfbGrp]; - } + for (i=0; inElements; i++) { + int ch,sfb,sfbGrp; + /* no weighting of threholds and energies for mlout */ + /* weight energies and thresholds */ + for (ch=0; chelInfo[i].nChannelsInEl; 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 (sfb=0; sfbpsyOutChannel[ch]->maxSfbPerGroup; sfb++) { + pQcOutCh->sfbThresholdLdData[sfb+sfbGrp] += pQcOutCh->sfbEnFacLd[sfb+sfbGrp]; } } } - + } } void FDKaacEnc_AdjThrClose(ADJ_THR_STATE** phAdjThr) diff --git a/libAACenc/src/adj_thr.h b/libAACenc/src/adj_thr.h index d03375c..a429dff 100644 --- a/libAACenc/src/adj_thr.h +++ b/libAACenc/src/adj_thr.h @@ -98,13 +98,14 @@ amm-info@iis.fraunhofer.de #include "interface.h" - -void FDKaacEnc_peCalculation(PE_DATA *peData, - PSY_OUT_CHANNEL* psyOutChannel[(2)], - QC_OUT_CHANNEL* qcOutChannel[(2)], - struct TOOLSINFO *toolsInfo, - ATS_ELEMENT* adjThrStateElement, - const INT nChannels); +void FDKaacEnc_peCalculation( + PE_DATA *peData, + PSY_OUT_CHANNEL* psyOutChannel[(2)], + QC_OUT_CHANNEL* qcOutChannel[(2)], + struct TOOLSINFO *toolsInfo, + ATS_ELEMENT* adjThrStateElement, + const INT nChannels + ); INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE** phAdjThr, INT nElements); @@ -112,9 +113,13 @@ INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE** phAdjThr, void FDKaacEnc_AdjThrInit(ADJ_THR_STATE *hAdjThr, const INT peMean, ELEMENT_BITS* elBits[(6)], + INT invQuant, INT nElements, + INT nChannelsEff, + INT sampleRate, + INT advancedBitsToPe, FIXP_DBL vbrQualFactor); - + void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState, ATS_ELEMENT *AdjThrStateElement, @@ -128,7 +133,7 @@ void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState, const INT bitresBits, const INT maxBitresBits, const FIXP_DBL maxBitFac, - const INT bitDistributenMode); + const INT bitDistributionMode); void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(6)], QC_OUT_ELEMENT* qcElement[(6)], diff --git a/libAACenc/src/block_switch.cpp b/libAACenc/src/block_switch.cpp index 948c89f..7b3e275 100644 --- a/libAACenc/src/block_switch.cpp +++ b/libAACenc/src/block_switch.cpp @@ -83,7 +83,7 @@ amm-info@iis.fraunhofer.de /***************************** MPEG-4 AAC Encoder ************************** - Author(s): M. Werner + Author(s): M. Werner, Tobias Chalupka 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 void FDKaacEnc_CalcWindowEnergy( BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, - INT windowLen); - +static void FDKaacEnc_CalcWindowEnergy( + BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, + INT windowLen, + const INT_PCM *pTimeSignal + ); /****************** Constants *****************************/ /* 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 ***********/ -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 ****************************/ 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)); 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 */ }; -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; 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 */ - FDKaacEnc_CalcWindowEnergy(blockSwitchingControl, granuleLength>>(nBlockSwitchWindows==4? 2:3 )); + FDKaacEnc_CalcWindowEnergy(blockSwitchingControl, granuleLength>>(nBlockSwitchWindows==4? 2:3 ), pTimeSignal); /* 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) +static void FDKaacEnc_CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, INT windowLen, const INT_PCM *pTimeSignal) { INT i; UINT w; @@ -344,8 +334,6 @@ static void FDKaacEnc_CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *RESTRICT blockSw FIXP_SGL hiPassCoeff0 = hiPassCoeff[0]; FIXP_SGL hiPassCoeff1 = hiPassCoeff[1]; - INT_PCM *timeSignal = blockSwitchingControl->timeSignal; - /* sum up scalarproduct of timesignal as windowed Energies */ 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; /* tempUnfiltered is scaled with 1 to prevent overflows during calculation of tempFiltred */ #if SAMPLE_BITS == DFRACT_BITS - tempUnfiltered = (FIXP_DBL) *timeSignal++ >> 1; + tempUnfiltered = (FIXP_DBL) *pTimeSignal++ >> 1; #else - tempUnfiltered = (FIXP_DBL) *timeSignal++ << (DFRACT_BITS-SAMPLE_BITS-1); + tempUnfiltered = (FIXP_DBL) *pTimeSignal++ << (DFRACT_BITS-SAMPLE_BITS-1); #endif t1 = fMultDiv2(hiPassCoeff1, tempUnfiltered-temp_iirState0); t2 = fMultDiv2(hiPassCoeff0, temp_iirState1); diff --git a/libAACenc/src/block_switch.h b/libAACenc/src/block_switch.h index 174f05f..e94b6f5 100644 --- a/libAACenc/src/block_switch.h +++ b/libAACenc/src/block_switch.h @@ -107,7 +107,6 @@ amm-info@iis.fraunhofer.de /****************** Structures ***************************/ typedef struct{ - INT_PCM *timeSignal; INT lastWindowSequence; INT windowShape; INT lastWindowShape; @@ -136,7 +135,7 @@ typedef struct{ 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( BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft, diff --git a/libAACenc/src/interface.h b/libAACenc/src/interface.h index 177ddbf..2ec1852 100644 --- a/libAACenc/src/interface.h +++ b/libAACenc/src/interface.h @@ -92,6 +92,7 @@ amm-info@iis.fraunhofer.de #define _INTERFACE_H #include "common_fix.h" +#include "FDK_audio.h" #include "psy_data.h" #include "aacenc_tns.h" @@ -160,4 +161,9 @@ typedef struct { }PSY_OUT; +inline int isLowDelay( AUDIO_OBJECT_TYPE aot ) +{ + return (aot==AOT_ER_AAC_LD || aot==AOT_ER_AAC_ELD); +} + #endif /* _INTERFACE_H */ diff --git a/libAACenc/src/psy_main.cpp b/libAACenc/src/psy_main.cpp index 8649a7e..0949b6d 100644 --- a/libAACenc/src/psy_main.cpp +++ b/libAACenc/src/psy_main.cpp @@ -116,11 +116,6 @@ static const FIXP_DBL fadeOutFactor[FADE_OUT_LEN] = {1840644096, 1533870080, 122 /* forward definitions */ -static inline int isLowDelay( AUDIO_OBJECT_TYPE aot ) -{ - return (aot==AOT_ER_AAC_LD || aot==AOT_ER_AAC_ELD); -} - /***************************************************************************** functionname: FDKaacEnc_PsyNew @@ -513,28 +508,28 @@ AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels, for(ch = 0; ch < channels; ch++) { - C_ALLOC_SCRATCH_START(timeSignal, INT_PCM, (1024)); - psyStatic[ch]->blockSwitchingControl.timeSignal = timeSignal; + C_ALLOC_SCRATCH_START(pTimeSignal, INT_PCM, (1024)) /* deinterleave input data and use for block switching */ - FDKaacEnc_deinterleaveInputBuffer( psyStatic[ch]->blockSwitchingControl.timeSignal, + FDKaacEnc_deinterleaveInputBuffer( pTimeSignal, &pInput[chIdx[ch]], psyConf->granuleLength, totalChannels); FDKaacEnc_BlockSwitching (&psyStatic[ch]->blockSwitchingControl, - psyConf->granuleLength - ,psyStatic[ch]->isLFE + psyConf->granuleLength, + psyStatic[ch]->isLFE, + pTimeSignal ); /* fill up internal input buffer, to 2xframelength samples */ FDKmemcpy(psyStatic[ch]->psyInputBuffer+blockSwitchingOffset, - psyStatic[ch]->blockSwitchingControl.timeSignal, + pTimeSignal, (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 */ diff --git a/libAACenc/src/qc_data.h b/libAACenc/src/qc_data.h index be6d158..51e66c6 100644 --- a/libAACenc/src/qc_data.h +++ b/libAACenc/src/qc_data.h @@ -143,6 +143,8 @@ struct QC_INIT{ INT maxBits; /* maximum number of bits in reservoir */ INT averageBits; /* average number of bits we should use */ 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. */ QCDATA_BR_MODE bitrateMode; INT meanPe; @@ -252,7 +254,7 @@ typedef struct INT minBitsPerFrame; /* minimal allowd bits per fram, superframing - DRM */ INT nElements; 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 bitResTotMax; INT maxIterations; /* Maximum number of allowed iterations before FDKaacEnc_crashRecovery() is applied. */ diff --git a/libAACenc/src/qc_main.cpp b/libAACenc/src/qc_main.cpp index 0a4bcbc..15646e9 100644 --- a/libAACenc/src/qc_main.cpp +++ b/libAACenc/src/qc_main.cpp @@ -382,10 +382,10 @@ 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->bitDistributenMode = (bitresPerChannel>50) ? 0 : (bitresPerChannel>0) ? 1 : 2; + hQC->bitDistributionMode = (bitresPerChannel>100) ? 0 : (bitresPerChannel>0) ? 1 : 2; } else { - hQC->bitDistributenMode = 0; /* full bitreservoir */ + hQC->bitDistributionMode = 0; /* full bitreservoir */ } @@ -420,11 +420,17 @@ AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC, break; } - FDKaacEnc_AdjThrInit(hQC->hAdjThr, - init->meanPe, - hQC->elementBits, /* or channelBitrates, was: channelBitrate */ - init->channelMapping->nElements, - hQC->vbrQualFactor); + FDKaacEnc_AdjThrInit( + hQC->hAdjThr, + init->meanPe, + hQC->elementBits, /* or channelBitrates, was: channelBitrate */ + 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; } @@ -655,7 +661,7 @@ static AAC_ENCODER_ERROR FDKaacEnc_prepareBitDistribution(QC_STATE* h hQC->elementBits[i]->bitResLevelEl, hQC->elementBits[i]->maxBitResBitsEl, hQC->maxBitFac, - hQC->bitDistributenMode); + hQC->bitDistributionMode); *totalAvailableBits += hQC->elementBits[i]->bitResLevelEl; /* get total corrected granted PE */ -- cgit v1.2.3