diff options
75 files changed, 2606 insertions, 823 deletions
diff --git a/documentation/aacDecoder.pdf b/documentation/aacDecoder.pdf Binary files differindex d388576..458fda1 100644 --- a/documentation/aacDecoder.pdf +++ b/documentation/aacDecoder.pdf diff --git a/documentation/aacEncoder.pdf b/documentation/aacEncoder.pdf Binary files differindex e8420b1..efb1858 100644 --- a/documentation/aacEncoder.pdf +++ b/documentation/aacEncoder.pdf diff --git a/libAACdec/include/aacdecoder_lib.h b/libAACdec/include/aacdecoder_lib.h index a0c0854..7ab60f1 100644 --- a/libAACdec/include/aacdecoder_lib.h +++ b/libAACdec/include/aacdecoder_lib.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -378,6 +378,7 @@ typedef enum { not exist. */ AAC_DEC_NEED_TO_RESTART = 0x200B, /*!< The decoder needs to be restarted, since the requiered configuration change cannot be performed. */ + AAC_DEC_OUTPUT_BUFFER_TOO_SMALL = 0x200C, /*!< The provided output buffer is too small. */ aac_dec_init_error_end = 0x2FFF, /* Decode errors. Output buffer is valid but concealed. */ diff --git a/libAACdec/src/aac_rom.cpp b/libAACdec/src/aac_rom.cpp index 607cb3b..f3c9b5a 100644 --- a/libAACdec/src/aac_rom.cpp +++ b/libAACdec/src/aac_rom.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -167,6 +167,36 @@ const SCHAR ExponentTable [4][14] = } ; +/* 41 scfbands */ +static const SHORT sfb_96_1024[42] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, + 48, 52, 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, + 156, 172, 188, 212, 240, 276, 320, 384, 448, 512, 576, 640, + 704, 768, 832, 896, 960, 1024 +}; +/* 12 scfbands */ +static const SHORT sfb_96_128[13] = +{ + 0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 92, + 128 +}; + +/* 47 scfbands*/ +static const SHORT sfb_64_1024[48] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, + 56, 64, 72, 80, 88, 100, 112, 124, 140, 156, 172, 192, 216, 240, + 268, 304, 344, 384, 424, 464, 504, 544, 584, 624, 664, 704, 744, 784, + 824, 864, 904, 944, 984,1024 +}; + +/* 12 scfbands */ +static const SHORT sfb_64_128[13] = +{ + 0, 4, 8, 12, 16, 20, 24, + 32, 40, 48, 64, 92, 128 +}; /* 49 scfbands */ static const SHORT sfb_48_1024[50] = { @@ -239,6 +269,35 @@ static const SHORT sfb_8_128[16] = }; +static const SHORT sfb_96_960[42] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, + 108, 120, 132, 144, 156, 172, 188, 212, 240, 276, + 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, + 960 +}; /* 40 scfbands */ + +static const SHORT sfb_96_120[13] = +{ + 0, 4, 8, 12, 16, 20, 24, 32, 40, 48, + 64, 92, 120 +}; /* 12 scfbands */ + +static const SHORT sfb_64_960[47] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 64, 72, 80, 88, 100, + 112, 124, 140, 156, 172, 192, 216, 240, 268, 304, + 344, 384, 424, 464, 504, 544, 584, 624, 664, 704, + 744, 784, 824, 864, 904, 944, 960 +}; /* 46 scfbands */ + +static const SHORT sfb_64_120[13] = +{ + 0, 4, 8, 12, 16, 20, 24, 32, 40, 48, + 64, 92, 120 +}; /* 12 scfbands */ static const SHORT sfb_48_960[50] = { @@ -358,9 +417,9 @@ static const SHORT sfb_24_480[31] = const SFB_INFO sfbOffsetTables[5][16] = { { - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, + { sfb_96_1024, sfb_96_128, 41, 12 }, + { sfb_96_1024, sfb_96_128, 41, 12 }, + { sfb_64_1024, sfb_64_128, 47, 12 }, { sfb_48_1024, sfb_48_128, 49, 14 }, { sfb_48_1024, sfb_48_128, 49, 14 }, { sfb_32_1024, sfb_48_128, 51, 14 }, @@ -372,9 +431,9 @@ const SFB_INFO sfbOffsetTables[5][16] = { sfb_8_1024, sfb_8_128, 40, 15 }, { sfb_8_1024, sfb_8_128, 40, 15 }, }, { - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, + { sfb_96_960, sfb_96_120, 40, 12 }, + { sfb_96_960, sfb_96_120, 40, 12 }, + { sfb_64_960, sfb_64_120, 46, 12 }, { sfb_48_960, sfb_48_120, 49, 14 }, { sfb_48_960, sfb_48_120, 49, 14 }, { sfb_32_960, sfb_48_120, 49, 14 }, @@ -388,9 +447,9 @@ const SFB_INFO sfbOffsetTables[5][16] = }, { { NULL, NULL, 0, 0 }, }, { - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, + { sfb_48_512, NULL, 36, 0 }, + { sfb_48_512, NULL, 36, 0 }, + { sfb_48_512, NULL, 36, 0 }, { sfb_48_512, NULL, 36, 0 }, { sfb_48_512, NULL, 36, 0}, { sfb_32_512, NULL, 37, 0 }, @@ -402,9 +461,9 @@ const SFB_INFO sfbOffsetTables[5][16] = { sfb_24_512, NULL, 31, 0 }, { sfb_24_512, NULL, 31, 0 }, }, { - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, + { sfb_48_480, NULL, 35, 0 }, + { sfb_48_480, NULL, 35, 0 }, + { sfb_48_480, NULL, 35, 0 }, { sfb_48_480, NULL, 35, 0 }, { sfb_48_480, NULL, 35, 0 }, { sfb_32_480, NULL, 37, 0 }, diff --git a/libAACdec/src/aacdec_drc.cpp b/libAACdec/src/aacdec_drc.cpp index 0c33a2b..eb8e410 100644 --- a/libAACdec/src/aacdec_drc.cpp +++ b/libAACdec/src/aacdec_drc.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -705,7 +705,7 @@ static int aacDecoder_drcExtractAndMap ( } self->numPayloads = 0; - if (self->dvbAncDataAvailable) + if (self->dvbAncDataAvailable && self->numThreads < MAX_DRC_THREADS) { /* Append a DVB heavy compression payload thread if available. */ int bitsParsed; diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp index e19c501..579e470 100644 --- a/libAACdec/src/aacdecoder.cpp +++ b/libAACdec/src/aacdecoder.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -157,23 +157,9 @@ amm-info@iis.fraunhofer.de #include "conceal.h" + #include "FDK_crc.h" -#define CAN_DO_PS(aot) \ - ((aot) == AOT_AAC_LC \ -|| (aot) == AOT_SBR \ -|| (aot) == AOT_PS \ -|| (aot) == AOT_ER_BSAC \ -|| (aot) == AOT_DRM_AAC) - -#define IS_USAC(aot) \ - ((aot) == AOT_USAC \ -|| (aot) == AOT_RSVD50) - -#define IS_LOWDELAY(aot) \ - ((aot) == AOT_ER_AAC_LD \ -|| (aot) == AOT_ER_AAC_ELD) - void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self) { @@ -552,8 +538,9 @@ AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self, previous_element, elIndex, self->flags & AC_INDEP ); - /* Enable SBR for implicit SBR signalling. */ - if (sbrError == SBRDEC_OK) { + /* Enable SBR for implicit SBR signalling but only if no severe error happend. */ + if ( (sbrError == SBRDEC_OK) + || (sbrError == SBRDEC_PARSE_ERROR) ) { self->sbrEnabled = 1; } } else { @@ -568,7 +555,7 @@ AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self, FDKpushBiDirectional(hBs, *count); *count = 0; } else { - /* If this is not a fill element with a known length, we are screwed an no further parsing makes sense. */ + /* If this is not a fill element with a known length, we are screwed and further parsing makes no sense. */ if (sbrError != SBRDEC_OK) { self->frameOK = 0; } @@ -847,12 +834,18 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS switch (asc->m_aot) { case AOT_AAC_LC: self->streamInfo.profile = 1; - break; + + case AOT_ER_AAC_SCAL: + if (asc->m_sc.m_gaSpecificConfig.m_layer > 0) { + /* aac_scalable_extension_element() currently not supported. */ + return AAC_DEC_UNSUPPORTED_FORMAT; + } case AOT_SBR: case AOT_PS: case AOT_ER_AAC_LD: case AOT_ER_AAC_ELD: + case AOT_DRM_AAC: break; default: @@ -972,11 +965,20 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS if (asc->m_aot == AOT_ER_AAC_ELD) { self->flags |= AC_ELD; + self->flags |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0; /* Need to set the SBR flag for backward-compatibility + reasons. Even if SBR is not supported. */ self->flags |= (asc->m_sc.m_eldSpecificConfig.m_sbrCrcFlag) ? AC_SBRCRC : 0; self->flags |= (asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) ? AC_LD_MPS : 0; } self->flags |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0; self->flags |= (asc->m_epConfig >= 0) ? AC_ER : 0; + if ( asc->m_aot == AOT_DRM_AAC ) { + self->flags |= AC_DRM|AC_SBRCRC|AC_SCALABLE; + } + if ( (asc->m_aot == AOT_AAC_SCAL) + || (asc->m_aot == AOT_ER_AAC_SCAL) ) { + self->flags |= AC_SCALABLE; + } if (asc->m_sbrPresentFlag) { @@ -1162,6 +1164,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( /* Check sampling frequency */ switch ( self->streamInfo.aacSampleRate ) { + case 96000: + case 88200: + case 64000: case 16000: case 12000: case 11025: @@ -1490,7 +1495,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( /* get the remaining bits of this frame */ bitCnt = transportDec_GetAuBitsRemaining(self->hInput, 0); - if ( (bitCnt > 0) && (self->flags & AC_SBR_PRESENT) && (self->flags & (AC_USAC|AC_RSVD50|AC_ELD)) ) + if ( (bitCnt > 0) && (self->flags & AC_SBR_PRESENT) && (self->flags & (AC_USAC|AC_RSVD50|AC_ELD|AC_DRM)) ) { SBR_ERROR err = SBRDEC_OK; int elIdx, numChElements = el_cnt[ID_SCE] + el_cnt[ID_CPE]; @@ -1528,6 +1533,13 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( } + if (self->flags & AC_DRM) + { + if ((bitCnt = (INT)FDKgetValidBits(bs)) != 0) { + FDKpushBiDirectional(bs, bitCnt); + } + } + if ( ! (self->flags & (AC_USAC|AC_RSVD50|AC_DRM)) ) { while ( bitCnt > 7 ) { diff --git a/libAACdec/src/aacdecoder.h b/libAACdec/src/aacdecoder.h index 3541773..25bc35d 100644 --- a/libAACdec/src/aacdecoder.h +++ b/libAACdec/src/aacdecoder.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -226,6 +226,8 @@ struct AAC_DECODER_INSTANCE { FIXP_DBL extGain[1]; /*!< Gain that must be applied to the output signal. */ UINT extGainDelay; /*!< Delay that must be accounted for extGain. */ + INT_PCM pcmOutputBuffer[(8)*(2048)]; + }; diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp index 94eb3c0..8863da5 100644 --- a/libAACdec/src/aacdecoder_lib.cpp +++ b/libAACdec/src/aacdecoder_lib.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -110,7 +110,7 @@ amm-info@iis.fraunhofer.de /* Decoder library info */ #define AACDECODER_LIB_VL0 2 #define AACDECODER_LIB_VL1 5 -#define AACDECODER_LIB_VL2 10 +#define AACDECODER_LIB_VL2 17 #define AACDECODER_LIB_TITLE "AAC Decoder Lib" #ifdef __ANDROID__ #define AACDECODER_LIB_BUILD_DATE "" @@ -181,8 +181,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_ConfigRaw ( break; } /* if baselayer is OK we continue decoding */ - if(layer >= 1){ + if(layer >= 1){ self->nrOfLayers = layer; + err = AAC_DEC_OK; } break; } @@ -785,8 +786,8 @@ static INT aacDecoder_EstimateNumberOfLostFrames(HANDLE_AACDECODER self) LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( HANDLE_AACDECODER self, - INT_PCM *pTimeData, - const INT timeDataSize, + INT_PCM *pTimeData_extern, + const INT timeDataSize_extern, const UINT flags) { AAC_DECODER_ERROR ErrorStatus; @@ -796,12 +797,17 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( HANDLE_FDK_BITSTREAM hBs; int fTpInterruption = 0; /* Transport originated interruption detection. */ int fTpConceal = 0; /* Transport originated concealment. */ + INT_PCM *pTimeData = NULL; + INT timeDataSize = 0; if (self == NULL) { return AAC_DEC_INVALID_HANDLE; } + pTimeData = self->pcmOutputBuffer; + timeDataSize = sizeof(self->pcmOutputBuffer)/sizeof(*self->pcmOutputBuffer); + if (flags & AACDEC_INTR) { self->streamInfo.numLostAccessUnits = 0; } @@ -918,7 +924,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( if (self->sbrEnabled) { SBR_ERROR sbrError = SBRDEC_OK; - int chOutMapIdx = ((self->chMapIndex==0) && (self->streamInfo.numChannels<7)) ? self->streamInfo.numChannels : self->chMapIndex; + int chIdx, numCoreChannel = self->streamInfo.numChannels; + int chOutMapIdx = ((self->chMapIndex==0) && (numCoreChannel<7)) ? numCoreChannel : self->chMapIndex; /* set params */ sbrDecoder_SetParam ( self->hSbrDecoder, @@ -978,10 +985,10 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( if (self->psPossible) { self->flags |= AC_PS_PRESENT; - self->channelType[0] = ACT_FRONT; - self->channelType[1] = ACT_FRONT; - self->channelIndices[0] = 0; - self->channelIndices[1] = 1; + } + for (chIdx = numCoreChannel; chIdx < self->streamInfo.numChannels; chIdx+=1) { + self->channelType[chIdx] = ACT_FRONT; + self->channelIndices[chIdx] = chIdx; } } } @@ -1006,7 +1013,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( self->channelOutputMapping, (self->limiterEnableCurr) ? &pcmLimiterScale : NULL ); - if (dmxErr == PCMDMX_INVALID_MODE) { + if ( (ErrorStatus == AAC_DEC_OK) + && (dmxErr == PCMDMX_INVALID_MODE) ) { /* Announce the framework that the current combination of channel configuration and downmix * settings are not know to produce a predictable behavior and thus maybe produce strange output. */ ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; @@ -1051,6 +1059,19 @@ bail: /* Update Statistics */ aacDecoder_UpdateBitStreamCounters(&self->streamInfo, hBs, nBits, ErrorStatus); + /* Check whether external output buffer is large enough. */ + if (timeDataSize_extern < self->streamInfo.numChannels*self->streamInfo.frameSize) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + } + + /* Update external output buffer. */ + if ( IS_OUTPUT_VALID(ErrorStatus) ) { + FDKmemcpy(pTimeData_extern, pTimeData, self->streamInfo.numChannels*self->streamInfo.frameSize*sizeof(*pTimeData)); + } + else { + FDKmemclear(pTimeData_extern, timeDataSize_extern*sizeof(*pTimeData_extern)); + } + return ErrorStatus; } @@ -1120,6 +1141,7 @@ LINKSPEC_CPP INT aacDecoder_GetLibInfo ( LIB_INFO *info ) /* Set flags */ info->flags = 0 | CAPF_AAC_LC + | CAPF_ER_AAC_SCAL | CAPF_AAC_VCB11 | CAPF_AAC_HCR | CAPF_AAC_RVLC @@ -1130,6 +1152,7 @@ LINKSPEC_CPP INT aacDecoder_GetLibInfo ( LIB_INFO *info ) | CAPF_AAC_MPEG4 + | CAPF_AAC_DRM_BSFORMAT | CAPF_AAC_1024 | CAPF_AAC_960 diff --git a/libAACdec/src/block.cpp b/libAACdec/src/block.cpp index 526accb..a19284e 100644 --- a/libAACdec/src/block.cpp +++ b/libAACdec/src/block.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -324,11 +324,11 @@ AAC_DECODER_ERROR CBlock_ReadSectionData(HANDLE_FDK_BITSTREAM bs, if (flags & AC_ER_HCR) { /* HCR input (long) -- collecting sideinfo (for HCR-_long_ only) */ - pNumLinesInSec[numLinesInSecIdx] = BandOffsets[top] - BandOffsets[band]; - numLinesInSecIdx++; if (numLinesInSecIdx >= MAX_SFB_HCR) { return AAC_DEC_PARSE_ERROR; } + pNumLinesInSec[numLinesInSecIdx] = BandOffsets[top] - BandOffsets[band]; + numLinesInSecIdx++; if (sect_cb == BOOKSCL) { return AAC_DEC_INVALID_CODE_BOOK; diff --git a/libAACenc/include/aacenc_lib.h b/libAACenc/include/aacenc_lib.h index 8c0e1cd..828a917 100644 --- a/libAACenc/include/aacenc_lib.h +++ b/libAACenc/include/aacenc_lib.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -897,11 +897,7 @@ typedef enum This configuration can be used only with stereo input audio data. - 23: MPEG-4 AAC Low-Delay. - 39: MPEG-4 AAC Enhanced Low-Delay. Since there is no ::AUDIO_OBJECT_TYPE for ELD in - combination with SBR defined, enable SBR explicitely by ::AACENC_SBR_MODE parameter. - - 129: MPEG-2 AAC Low Complexity. - - 132: MPEG-2 AAC Low Complexity with Spectral Band Replication (HE-AAC). - - 156: MPEG-2 AAC Low Complexity with Spectral Band Replication and Parametric Stereo (HE-AAC v2). - This configuration can be used only with stereo input audio data. */ + combination with SBR defined, enable SBR explicitely by ::AACENC_SBR_MODE parameter. */ AACENC_BITRATE = 0x0101, /*!< Total encoder bitrate. This parameter is mandatory and interacts with ::AACENC_BITRATEMODE. - CBR: Bitrate in bits/second. @@ -958,6 +954,16 @@ typedef enum - 1 to fs/2: Frequency bandwidth in Hertz. (Experts only, better do not touch this value to avoid degraded audio quality) */ + AACENC_PEAK_BITRATE = 0x0207, /*!< Peak bitrate configuration parameter to adjust maximum bits per audio frame. Bitrate is in bits/second. + The peak bitrate will internally be limited to the chosen bitrate ::AACENC_BITRATE as lower limit + and the number_of_effective_channels*6144 bit as upper limit. + + Setting the peak bitrate equal to ::AACENC_BITRATE does not necessarily mean that the audio frames + will be of constant size. Since the peak bitate is in bits/second, the frame sizes can vary by + one byte in one or the other direction over various frames. However, it is not recommended to reduce + the peak pitrate to ::AACENC_BITRATE - it would disable the bitreservoir, which would affect the + audio quality by a large amount. */ + AACENC_TRANSMUX = 0x0300, /*!< Transport type to be used. See ::TRANSPORT_TYPE in FDK_audio.h. Following types can be configured in encoder library: - 0: raw access units @@ -1023,6 +1029,11 @@ typedef enum - ADTS: Maximum number of sub frames restricted to 4. - LOAS/LATM: Maximum number of sub frames restricted to 2.*/ + AACENC_AUDIOMUXVER = 0x0304, /*!< AudioMuxVersion to be used for LATM. (AudioMuxVersionA, currently not implemented): + - 0: Default, no transmission of tara Buffer fullness, no ASC length and including actual latm Buffer fullnes. + - 1: Transmission of tara Buffer fullness, ASC length and actual latm Buffer fullness. + - 2: Transmission of tara Buffer fullness, ASC length and maximum level of latm Buffer fullness. */ + AACENC_PROTECTION = 0x0306, /*!< Configure protection in tranpsort layer: - 0: No protection. (default) - 1: CRC active for ADTS bitstream format. */ diff --git a/libAACenc/src/aacEnc_rom.cpp b/libAACenc/src/aacEnc_rom.cpp index 0cdf5fe..c6477e3 100644 --- a/libAACenc/src/aacEnc_rom.cpp +++ b/libAACenc/src/aacEnc_rom.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -93,7 +93,7 @@ amm-info@iis.fraunhofer.de /* Huffman Tables */ -const INT FDKaacEnc_huff_ltab1_2[3][3][3][3]= +const ULONG FDKaacEnc_huff_ltab1_2[3][3][3][3]= { { { {0x000b0009,0x00090007,0x000b0009}, {0x000a0008,0x00070006,0x000a0008}, {0x000b0009,0x00090008,0x000b0009} }, @@ -113,7 +113,7 @@ const INT FDKaacEnc_huff_ltab1_2[3][3][3][3]= }; -const INT FDKaacEnc_huff_ltab3_4[3][3][3][3]= +const ULONG FDKaacEnc_huff_ltab3_4[3][3][3][3]= { { { {0x00010004,0x00040005,0x00080008}, {0x00040005,0x00050004,0x00080008}, {0x00090009,0x00090008,0x000a000b} }, @@ -132,7 +132,7 @@ const INT FDKaacEnc_huff_ltab3_4[3][3][3][3]= } }; -const INT FDKaacEnc_huff_ltab5_6[9][9]= +const ULONG FDKaacEnc_huff_ltab5_6[9][9]= { {0x000d000b, 0x000c000a, 0x000b0009, 0x000b0009, 0x000a0009, 0x000b0009, 0x000b0009, 0x000c000a, 0x000d000b}, {0x000c000a, 0x000b0009, 0x000a0008, 0x00090007, 0x00080007, 0x00090007, 0x000a0008, 0x000b0009, 0x000c000a}, @@ -145,7 +145,7 @@ const INT FDKaacEnc_huff_ltab5_6[9][9]= {0x000d000b, 0x000c000a, 0x000c0009, 0x000b0009, 0x000a0009, 0x000a0009, 0x000b0009, 0x000c000a, 0x000d000b} }; -const INT FDKaacEnc_huff_ltab7_8[8][8]= +const ULONG FDKaacEnc_huff_ltab7_8[8][8]= { {0x00010005, 0x00030004, 0x00060005, 0x00070006, 0x00080007, 0x00090008, 0x000a0009, 0x000b000a}, {0x00030004, 0x00040003, 0x00060004, 0x00070005, 0x00080006, 0x00080007, 0x00090007, 0x00090008}, @@ -157,7 +157,7 @@ const INT FDKaacEnc_huff_ltab7_8[8][8]= {0x000b000a, 0x000a0008, 0x000a0008, 0x000a0008, 0x000b0009, 0x000b0009, 0x000c0009, 0x000c000a} }; -const INT FDKaacEnc_huff_ltab9_10[13][13]= +const ULONG FDKaacEnc_huff_ltab9_10[13][13]= { {0x00010006, 0x00030005, 0x00060006, 0x00080006, 0x00090007, 0x000a0008, 0x000a0009, 0x000b000a, 0x000b000a, 0x000c000a, 0x000c000b, 0x000d000b, 0x000d000c}, {0x00030005, 0x00040004, 0x00060004, 0x00070005, 0x00080006, 0x00080007, 0x00090007, 0x000a0008, 0x000a0008, 0x000a0009, 0x000b000a, 0x000c000a, 0x000c000b}, @@ -392,7 +392,7 @@ const USHORT FDKaacEnc_huff_ctab11[21][17]= {0x0046, 0x00ea, 0x0034, 0x00ea, 0x0011, 0x001b, 0x00a9, 0x0094, 0x00e2, 0x0031, 0x00d0, 0x00e5, 0x0007, 0x0070, 0x0069, 0x003e, 0x0021} }; -const INT FDKaacEnc_huff_ctabscf[121]= +const ULONG FDKaacEnc_huff_ctabscf[121]= { 0x0003ffe8, 0x0003ffe6, 0x0003ffe7, 0x0003ffe5, 0x0007fff5, 0x0007fff1, 0x0007ffed, 0x0007fff6, 0x0007ffee, 0x0007ffef, 0x0007fff0, 0x0007fffc, 0x0007fffd, 0x0007ffff, 0x0007fffe, 0x0007fff7, @@ -657,11 +657,11 @@ const SFB_PARAM_SHORT p_FDKaacEnc_96000_short_128 = { */ const FIXP_DBL FDKaacEnc_tnsEncCoeff3[8]= { - 0x81f1d201, 0x91261481, 0xadb92301, 0xd438af00, 0x00000000, 0x37898080, 0x64130dff, 0x7cca6fff + (FIXP_DBL)0x81f1d201, (FIXP_DBL)0x91261481, (FIXP_DBL)0xadb92301, (FIXP_DBL)0xd438af00, (FIXP_DBL)0x00000000, (FIXP_DBL)0x37898080, (FIXP_DBL)0x64130dff, (FIXP_DBL)0x7cca6fff }; const FIXP_DBL FDKaacEnc_tnsCoeff3Borders[8]={ - 0x80000001 /*-4*/, 0x87b826df /*-3*/, 0x9df24154 /*-2*/, 0xbfffffe5 /*-1*/, - 0xe9c5e578 /* 0*/, 0x1c7b90f0 /* 1*/, 0x4fce83a9 /* 2*/, 0x7352f2c3 /* 3*/ + (FIXP_DBL)0x80000001 /*-4*/, (FIXP_DBL)0x87b826df /*-3*/, (FIXP_DBL)0x9df24154 /*-2*/, (FIXP_DBL)0xbfffffe5 /*-1*/, + (FIXP_DBL)0xe9c5e578 /* 0*/, (FIXP_DBL)0x1c7b90f0 /* 1*/, (FIXP_DBL)0x4fce83a9 /* 2*/, (FIXP_DBL)0x7352f2c3 /* 3*/ }; /* @@ -669,15 +669,15 @@ const FIXP_DBL FDKaacEnc_tnsCoeff3Borders[8]={ */ const FIXP_DBL FDKaacEnc_tnsEncCoeff4[16]= { - 0x808bc881, 0x84e2e581, 0x8d6b4a01, 0x99da9201, 0xa9c45701, 0xbc9dde81, 0xd1c2d500, 0xe87ae540, - 0x00000000, 0x1a9cd9c0, 0x340ff240, 0x4b3c8bff, 0x5f1f5e7f, 0x6ed9eb7f, 0x79bc387f, 0x7f4c7e7f + (FIXP_DBL)0x808bc881, (FIXP_DBL)0x84e2e581, (FIXP_DBL)0x8d6b4a01, (FIXP_DBL)0x99da9201, (FIXP_DBL)0xa9c45701, (FIXP_DBL)0xbc9dde81, (FIXP_DBL)0xd1c2d500, (FIXP_DBL)0xe87ae540, + (FIXP_DBL)0x00000000, (FIXP_DBL)0x1a9cd9c0, (FIXP_DBL)0x340ff240, (FIXP_DBL)0x4b3c8bff, (FIXP_DBL)0x5f1f5e7f, (FIXP_DBL)0x6ed9eb7f, (FIXP_DBL)0x79bc387f, (FIXP_DBL)0x7f4c7e7f }; const FIXP_DBL FDKaacEnc_tnsCoeff4Borders[16]= { - 0x80000001 /*-8*/, 0x822deff0 /*-7*/, 0x88a4bfe6 /*-6*/, 0x932c159d /*-5*/, - 0xa16827c2 /*-4*/, 0xb2dcde27 /*-3*/, 0xc6f20b91 /*-2*/, 0xdcf89c64 /*-1*/, - 0xf4308ce1 /* 0*/, 0x0d613054 /* 1*/, 0x278dde80 /* 2*/, 0x4000001b /* 3*/, - 0x55a6127b /* 4*/, 0x678dde8f /* 5*/, 0x74ef0ed7 /* 6*/, 0x7d33f0da /* 7*/ + (FIXP_DBL)0x80000001 /*-8*/, (FIXP_DBL)0x822deff0 /*-7*/, (FIXP_DBL)0x88a4bfe6 /*-6*/, (FIXP_DBL)0x932c159d /*-5*/, + (FIXP_DBL)0xa16827c2 /*-4*/, (FIXP_DBL)0xb2dcde27 /*-3*/, (FIXP_DBL)0xc6f20b91 /*-2*/, (FIXP_DBL)0xdcf89c64 /*-1*/, + (FIXP_DBL)0xf4308ce1 /* 0*/, (FIXP_DBL)0x0d613054 /* 1*/, (FIXP_DBL)0x278dde80 /* 2*/, (FIXP_DBL)0x4000001b /* 3*/, + (FIXP_DBL)0x55a6127b /* 4*/, (FIXP_DBL)0x678dde8f /* 5*/, (FIXP_DBL)0x74ef0ed7 /* 6*/, (FIXP_DBL)0x7d33f0da /* 7*/ }; const FIXP_DBL FDKaacEnc_mTab_4_3Elc[512]={ FL2FXCONST_DBL(0.3968502629920499),FL2FXCONST_DBL(0.3978840634868335),FL2FXCONST_DBL(0.3989185359354711),FL2FXCONST_DBL(0.3999536794661432), diff --git a/libAACenc/src/aacEnc_rom.h b/libAACenc/src/aacEnc_rom.h index 37e5012..862417f 100644 --- a/libAACenc/src/aacEnc_rom.h +++ b/libAACenc/src/aacEnc_rom.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -105,11 +105,11 @@ amm-info@iis.fraunhofer.de /* Huffman Tables */ -extern const INT FDKaacEnc_huff_ltab1_2[3][3][3][3]; -extern const INT FDKaacEnc_huff_ltab3_4[3][3][3][3]; -extern const INT FDKaacEnc_huff_ltab5_6[9][9]; -extern const INT FDKaacEnc_huff_ltab7_8[8][8]; -extern const INT FDKaacEnc_huff_ltab9_10[13][13]; +extern const ULONG FDKaacEnc_huff_ltab1_2[3][3][3][3]; +extern const ULONG FDKaacEnc_huff_ltab3_4[3][3][3][3]; +extern const ULONG FDKaacEnc_huff_ltab5_6[9][9]; +extern const ULONG FDKaacEnc_huff_ltab7_8[8][8]; +extern const ULONG FDKaacEnc_huff_ltab9_10[13][13]; extern const UCHAR FDKaacEnc_huff_ltab11[17][17]; extern const UCHAR FDKaacEnc_huff_ltabscf[121]; extern const USHORT FDKaacEnc_huff_ctab1[3][3][3][3]; @@ -123,7 +123,7 @@ extern const USHORT FDKaacEnc_huff_ctab8[8][8]; extern const USHORT FDKaacEnc_huff_ctab9[13][13]; extern const USHORT FDKaacEnc_huff_ctab10[13][13]; extern const USHORT FDKaacEnc_huff_ctab11[21][17]; -extern const INT FDKaacEnc_huff_ctabscf[121]; +extern const ULONG FDKaacEnc_huff_ctabscf[121]; /* quantizer diff --git a/libAACenc/src/aacenc.cpp b/libAACenc/src/aacenc.cpp index 569662b..5e8c08d 100644 --- a/libAACenc/src/aacenc.cpp +++ b/libAACenc/src/aacenc.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -107,6 +107,39 @@ amm-info@iis.fraunhofer.de #define MIN_BUFSIZE_PER_EFF_CHAN 6144 +INT FDKaacEnc_CalcBitsPerFrame( + const INT bitRate, + const INT frameLength, + const INT samplingRate + ) +{ + int shift = 0; + while ((frameLength & ~((1 << (shift + 1)) - 1)) == frameLength + && (samplingRate & ~((1 << (shift + 1)) - 1)) == samplingRate) + { + shift++; + } + + return (bitRate*(frameLength>>shift)) / (samplingRate>>shift); +} + +INT FDKaacEnc_CalcBitrate( + const INT bitsPerFrame, + const INT frameLength, + const INT samplingRate + ) +{ + int shift = 0; + while ((frameLength & ~((1 << (shift + 1)) - 1)) == frameLength + && (samplingRate & ~((1 << (shift + 1)) - 1)) == samplingRate) + { + shift++; + } + + return (bitsPerFrame * (samplingRate>>shift)) / ( frameLength>>shift) ; + +} + static AAC_ENCODER_ERROR FDKaacEnc_InitCheckAncillary(INT bitRate, INT framelength, INT ancillaryRate, @@ -220,21 +253,19 @@ INT FDKaacEnc_GetVBRBitrate(INT bitrateMode, CHANNEL_MODE channelMode) /** * \brief Convert encoder bitreservoir value for transport library. * - * \param bitrateMode Bitratemode used in current encoder instance. Se ::AACENC_BITRATE_MODE - * \param bitresTotal Encoder bitreservoir level in bits. + * \param hAacEnc Encoder handle * * \return Corrected bitreservoir level used in transport library. */ static INT FDKaacEnc_EncBitresToTpBitres( - const AACENC_BITRATE_MODE bitrateMode, - const INT bitresTotal + const HANDLE_AAC_ENC hAacEnc ) { INT transporBitreservoir = 0; - switch (bitrateMode) { + switch (hAacEnc->bitrateMode) { case AACENC_BR_MODE_CBR: - transporBitreservoir = bitresTotal; /* encoder bitreservoir level */ + transporBitreservoir = hAacEnc->qcKernel->bitResTot; /* encoder bitreservoir level */ break; case AACENC_BR_MODE_VBR_1: case AACENC_BR_MODE_VBR_2: @@ -253,6 +284,10 @@ static INT FDKaacEnc_EncBitresToTpBitres( FDK_ASSERT(0); } + if (hAacEnc->config->audioMuxVersion==2) { + transporBitreservoir = MIN_BUFSIZE_PER_EFF_CHAN * hAacEnc->channelMapping.nChannelsEff; + } + return transporBitreservoir; } @@ -289,6 +324,7 @@ void FDKaacEnc_AacInitDefaultConfig(AACENC_CONFIG *config) config->minBitsPerFrame = -1; /* minum number of bits in each AU */ config->maxBitsPerFrame = -1; /* minum number of bits in each AU */ config->bitreservoir = -1; /* default, uninitialized value */ + config->audioMuxVersion = -1; /* audio mux version not configured */ /* init tabs in fixpoint_math */ InitLdInt(); @@ -435,7 +471,9 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize(HANDLE_AAC_ENC hAacEnc, &averageBitsPerFrame, config->bitrateMode, config->nSubFrames - ) != config->bitRate ) + ) != config->bitRate + && !((config->bitrateMode>=1) && (config->bitrateMode<=5)) + ) { return AAC_ENC_UNSUPPORTED_BITRATE; } @@ -562,7 +600,10 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize(HANDLE_AAC_ENC hAacEnc, qcInit.averageBits = (averageBitsPerFrame+7)&~7; qcInit.bitRes = MIN_BUFSIZE_PER_EFF_CHAN*cm->nChannelsEff; qcInit.maxBits = MIN_BUFSIZE_PER_EFF_CHAN*cm->nChannelsEff; - qcInit.minBits = 0; + qcInit.maxBits = (config->maxBitsPerFrame!=-1) ? fixMin(qcInit.maxBits, config->maxBitsPerFrame) : qcInit.maxBits; + qcInit.maxBits = fixMax(qcInit.maxBits, (averageBitsPerFrame+7)&~7); + qcInit.minBits = (config->minBitsPerFrame!=-1) ? config->minBitsPerFrame : 0; + qcInit.minBits = fixMin(qcInit.minBits, averageBitsPerFrame&~7); } else { @@ -573,9 +614,11 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize(HANDLE_AAC_ENC hAacEnc, qcInit.maxBits = fixMin(MIN_BUFSIZE_PER_EFF_CHAN*cm->nChannelsEff, ((averageBitsPerFrame+7)&~7)+qcInit.bitRes); qcInit.maxBits = (config->maxBitsPerFrame!=-1) ? fixMin(qcInit.maxBits, config->maxBitsPerFrame) : qcInit.maxBits; + qcInit.maxBits = fixMin(MIN_BUFSIZE_PER_EFF_CHAN*cm->nChannelsEff, fixMax(qcInit.maxBits, (averageBitsPerFrame+7+8)&~7)); qcInit.minBits = fixMax(0, ((averageBitsPerFrame-1)&~7)-qcInit.bitRes-transportEnc_GetStaticBits(hTpEnc, ((averageBitsPerFrame+7)&~7)+qcInit.bitRes)); qcInit.minBits = (config->minBitsPerFrame!=-1) ? fixMax(qcInit.minBits, config->minBitsPerFrame) : qcInit.minBits; + qcInit.minBits = fixMin(qcInit.minBits, (averageBitsPerFrame - transportEnc_GetStaticBits(hTpEnc, qcInit.maxBits))&~7); } qcInit.sampleRate = config->sampleRate; @@ -583,11 +626,9 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize(HANDLE_AAC_ENC hAacEnc, qcInit.nSubFrames = config->nSubFrames; qcInit.padding.paddingRest = config->sampleRate; - /* Calc meanPe */ - bw_ratio = fDivNorm((FIXP_DBL)hAacEnc->bandwidth90dB, (FIXP_DBL)(config->sampleRate>>1), &qbw); - qbw = DFRACT_BITS-1-qbw; - /* qcInit.meanPe = 10.0f * FRAME_LEN_LONG * hAacEnc->bandwidth90dB/(config->sampleRate/2.0f); */ - qcInit.meanPe = fMult(bw_ratio, (FIXP_DBL)((10*config->framelength)<<16)) >> (qbw-15); + /* Calc meanPe: qcInit.meanPe = 10.0f * FRAME_LEN_LONG * hAacEnc->bandwidth90dB/(config->sampleRate/2.0f); */ + bw_ratio = fDivNorm((FIXP_DBL)(10*config->framelength*hAacEnc->bandwidth90dB), (FIXP_DBL)(config->sampleRate), &qbw); + qcInit.meanPe = FDKmax((INT)scaleValue(bw_ratio, qbw+1-(DFRACT_BITS-1)), 1); /* Calc maxBitFac */ mbfac = fDivNorm((MIN_BUFSIZE_PER_EFF_CHAN-744)*cm->nChannelsEff, qcInit.averageBits/qcInit.nSubFrames, &qmbfac); @@ -649,23 +690,7 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize(HANDLE_AAC_ENC hAacEnc, if (ErrorStatus != AAC_ENC_OK) goto bail; - /* Map virtual aot's to intern aot used in bitstream writer. */ - switch (hAacEnc->config->audioObjectType) { - case AOT_MP2_AAC_LC: - case AOT_DABPLUS_AAC_LC: - hAacEnc->aot = AOT_AAC_LC; - break; - case AOT_MP2_SBR: - case AOT_DABPLUS_SBR: - hAacEnc->aot = AOT_SBR; - break; - case AOT_MP2_PS: - case AOT_DABPLUS_PS: - hAacEnc->aot = AOT_PS; - break; - default: - hAacEnc->aot = hAacEnc->config->audioObjectType; - } + hAacEnc->aot = hAacEnc->config->audioObjectType; /* common things */ @@ -930,7 +955,7 @@ AAC_ENCODER_ERROR FDKaacEnc_EncodeFrame( HANDLE_AAC_ENC hAacEnc, transportEnc_WriteAccessUnit( hTpEnc, totalBits, - FDKaacEnc_EncBitresToTpBitres(hAacEnc->bitrateMode, hAacEnc->qcKernel->bitResTot), + FDKaacEnc_EncBitresToTpBitres(hAacEnc), cm->nChannelsEff); /* write bitstream */ diff --git a/libAACenc/src/aacenc.h b/libAACenc/src/aacenc.h index 87fc3e8..79524b5 100644 --- a/libAACenc/src/aacenc.h +++ b/libAACenc/src/aacenc.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -98,6 +98,11 @@ amm-info@iis.fraunhofer.de #include "sbr_encoder.h" +#define BITRES_MAX_LD 4000 +#define BITRES_MIN_LD 500 +#define BITRATE_MAX_LD 70000 /* Max assumed bitrate for bitres calculation */ +#define BITRATE_MIN_LD 12000 /* Min assumed bitrate for bitres calculation */ + #ifdef __cplusplus extern "C" { #endif @@ -204,6 +209,8 @@ struct AACENC_CONFIG { INT maxBitsPerFrame; /* maximum number of bits in AU */ INT bitreservoir; /* size of bitreservoir */ + INT audioMuxVersion; /* audio mux version in loas/latm transport format */ + UINT sbrRatio; /* sbr sampling rate ratio: dual- or single-rate */ UCHAR useTns; /* flag: use temporal noise shaping */ @@ -223,6 +230,36 @@ typedef struct { typedef struct AAC_ENC *HANDLE_AAC_ENC; /** + * \brief Calculate framesize in bits for given bit rate, frame length and sampling rate. + * + * \param bitRate Ttarget bitrate in bits per second. + * \param frameLength Number of audio samples in one frame. + * \param samplingRate Sampling rate in Hz. + * + * \return Framesize in bits per frame. +*/ +INT FDKaacEnc_CalcBitsPerFrame( + const INT bitRate, + const INT frameLength, + const INT samplingRate + ); + +/** + * \brief Calculate bitrate in bits per second for given framesize, frame length and sampling rate. + * + * \param bitsPerFrame Framesize in bits per frame. + * \param frameLength Number of audio samples in one frame. + * \param samplingRate Sampling rate in Hz. + * + * \return Bitrate in bits per second. +*/ +INT FDKaacEnc_CalcBitrate( + const INT bitsPerFrame, + const INT frameLength, + const INT samplingRate + ); + +/** * \brief Limit given bit rate to a valid value * \param hTpEnc transport encoder handle * \param coreSamplingRate the sample rate to be used for the AAC encoder diff --git a/libAACenc/src/aacenc_lib.cpp b/libAACenc/src/aacenc_lib.cpp index e24df65..64445b9 100644 --- a/libAACenc/src/aacenc_lib.cpp +++ b/libAACenc/src/aacenc_lib.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -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 12 +#define AACENCODER_LIB_VL2 22 #define AACENCODER_LIB_TITLE "AAC Encoder" #ifdef __ANDROID__ #define AACENCODER_LIB_BUILD_DATE "" @@ -153,6 +153,7 @@ typedef struct { UINT userAfterburner; UINT userFramelength; UINT userAncDataRate; + UINT userPeakBitrate; UCHAR userTns; /*!< Use TNS coding. */ UCHAR userPns; /*!< Use PNS coding. */ @@ -303,7 +304,7 @@ static AACENC_ERROR eldSbrConfigurator( int i, cfgIdx = -1; const ULONG channelBitrate = totalBitrate / FDKaacEnc_GetChannelModeConfiguration(channelMode)->nChannelsEff; - for (i=0; i<(sizeof(eldSbrAutoConfigTab)/sizeof(ELD_SBR_CONFIGURATOR)); i++) { + for (i=0; i<(int)(sizeof(eldSbrAutoConfigTab)/sizeof(ELD_SBR_CONFIGURATOR)); i++) { if ( (samplingRate <= eldSbrAutoConfigTab[i].samplingRate) && (channelBitrate >= eldSbrAutoConfigTab[i].bitrateRange) ) { @@ -326,10 +327,7 @@ static inline INT isSbrActive(const HANDLE_AACENC_CONFIG hAacConfig) { INT sbrUsed = 0; - if ( (hAacConfig->audioObjectType==AOT_SBR) || (hAacConfig->audioObjectType==AOT_PS) - || (hAacConfig->audioObjectType==AOT_MP2_SBR) || (hAacConfig->audioObjectType==AOT_MP2_PS) - || (hAacConfig->audioObjectType==AOT_DABPLUS_SBR) || (hAacConfig->audioObjectType==AOT_DABPLUS_PS) - || (hAacConfig->audioObjectType==AOT_DRM_SBR) || (hAacConfig->audioObjectType==AOT_DRM_MPEG_PS) ) + if ( (hAacConfig->audioObjectType==AOT_SBR) || (hAacConfig->audioObjectType==AOT_PS) ) { sbrUsed = 1; } @@ -345,10 +343,7 @@ static inline INT isPsActive(const AUDIO_OBJECT_TYPE audioObjectType) { INT psUsed = 0; - if ( (audioObjectType==AOT_PS) - || (audioObjectType==AOT_MP2_PS) - || (audioObjectType==AOT_DABPLUS_PS) - || (audioObjectType==AOT_DRM_MPEG_PS) ) + if ( (audioObjectType==AOT_PS) ) { psUsed = 1; } @@ -373,8 +368,7 @@ static SBR_PS_SIGNALING getSbrSignalingMode( sbrSignaling = SIG_IMPLICIT; /* default: implicit signaling */ } - if ((audioObjectType==AOT_AAC_LC) || (audioObjectType==AOT_SBR) || (audioObjectType==AOT_PS) || - (audioObjectType==AOT_MP2_AAC_LC) || (audioObjectType==AOT_MP2_SBR) || (audioObjectType==AOT_MP2_PS) ) { + if ( (audioObjectType==AOT_AAC_LC) || (audioObjectType==AOT_SBR) || (audioObjectType==AOT_PS) ) { switch (transportType) { case TT_MP4_ADIF: case TT_MP4_ADTS: @@ -430,22 +424,7 @@ static void FDKaacEnc_MapConfig( cc->flags = 0; - /* Map virtual aot to transport aot. */ - switch (hAacConfig->audioObjectType) { - case AOT_MP2_AAC_LC: - transport_AOT = AOT_AAC_LC; - break; - case AOT_MP2_SBR: - transport_AOT = AOT_SBR; - cc->flags |= CC_SBR; - break; - case AOT_MP2_PS: - transport_AOT = AOT_PS; - cc->flags |= CC_SBR; - break; - default: - transport_AOT = hAacConfig->audioObjectType; - } + transport_AOT = hAacConfig->audioObjectType; if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) { cc->flags |= (hAacConfig->syntaxFlags & AC_SBR_PRESENT) ? CC_SBR : 0; @@ -511,16 +490,7 @@ static void FDKaacEnc_MapConfig( cc->samplingRate = hAacConfig->sampleRate; /* Mpeg-4 signaling for transport library. */ - switch ( hAacConfig->audioObjectType ) { - case AOT_MP2_AAC_LC: - case AOT_MP2_SBR: - case AOT_MP2_PS: - cc->flags &= ~CC_MPEG_ID; /* Required for ADTS. */ - cc->extAOT = AOT_NULL_OBJECT; - break; - default: - cc->flags |= CC_MPEG_ID; - } + cc->flags |= CC_MPEG_ID; /* ER-tools signaling. */ cc->flags |= (hAacConfig->syntaxFlags & AC_ER_VCB11) ? CC_VCB11 : 0; @@ -585,6 +555,7 @@ AAC_ENCODER_ERROR aacEncDefaultConfig(HANDLE_AACENC_CONFIG hAacConfig, config->userChannelMode = hAacConfig->channelMode; config->userBitrate = hAacConfig->bitRate; config->userBitrateMode = hAacConfig->bitrateMode; + config->userPeakBitrate = (UINT)-1; config->userBandwidth = hAacConfig->bandWidth; config->userTns = hAacConfig->useTns; config->userPns = hAacConfig->usePns; @@ -792,12 +763,15 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder, hAacConfig->syntaxFlags = 0; hAacConfig->epConfig = -1; + if (config->userTpType==TT_MP4_LATM_MCP1 || config->userTpType==TT_MP4_LATM_MCP0 || config->userTpType==TT_MP4_LOAS) { + hAacConfig->audioMuxVersion = config->userTpAmxv; + } + else { + hAacConfig->audioMuxVersion = -1; + } + /* Adapt internal AOT when necessary. */ switch ( hAacConfig->audioObjectType ) { - case AOT_MP2_AAC_LC: - case AOT_MP2_SBR: - case AOT_MP2_PS: - hAacConfig->usePns = 0; case AOT_AAC_LC: case AOT_SBR: case AOT_PS: @@ -839,11 +813,16 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder, switch ( hAacConfig->audioObjectType ) { case AOT_ER_AAC_LD: case AOT_ER_AAC_ELD: - if (config->userBitrateMode==8) { - hAacConfig->bitrateMode = 0; - } if (config->userBitrateMode==0) { - hAacConfig->bitreservoir = 100*config->nChannels; /* default, reduced bitreservoir */ + /* bitreservoir = (maxBitRes-minBitRes)/(maxBitRate-minBitrate)*(bitRate-minBitrate)+minBitRes; */ + if ( isLowDelay(hAacConfig->audioObjectType) ) { + INT bitreservoir; + INT brPerChannel = hAacConfig->bitRate/hAacConfig->nChannels; + brPerChannel = fMin(BITRATE_MAX_LD, fMax(BITRATE_MIN_LD, brPerChannel)); + FIXP_DBL slope = fDivNorm((brPerChannel-BITRATE_MIN_LD), BITRATE_MAX_LD-BITRATE_MIN_LD); /* calc slope for interpolation */ + bitreservoir = fMultI(slope, (INT)(BITRES_MAX_LD-BITRES_MIN_LD)) + BITRES_MIN_LD; /* interpolate */ + hAacConfig->bitreservoir = bitreservoir & ~7; /* align to bytes */ + } } if (hAacConfig->bitrateMode!=0) { return AACENC_INVALID_CONFIG; @@ -884,6 +863,18 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder, } } + if ((hAacConfig->bitrateMode >= 0) && (hAacConfig->bitrateMode <= 5)) { + if ((INT)config->userPeakBitrate != -1) { + hAacConfig->maxBitsPerFrame = (FDKaacEnc_CalcBitsPerFrame(fMax(hAacConfig->bitRate, (INT)config->userPeakBitrate), hAacConfig->framelength, hAacConfig->sampleRate) + 7)&~7; + } + else { + hAacConfig->maxBitsPerFrame = -1; + } + if (hAacConfig->audioMuxVersion==2) { + hAacConfig->minBitsPerFrame = fMin(32*8, FDKaacEnc_CalcBitsPerFrame(hAacConfig->bitRate, hAacConfig->framelength, hAacConfig->sampleRate))&~7; + } + } + /* Initialize SBR parameters */ if ( (hAacConfig->audioObjectType==AOT_ER_AAC_ELD) && (config->userSbrEnabled == (UCHAR)-1) && (config->userSbrRatio==0) ) @@ -914,7 +905,7 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder, } else { /* SBR ratio has been set by the user, so use it. */ - hAacConfig->sbrRatio = config->userSbrRatio; + hAacConfig->sbrRatio = isSbrActive(hAacConfig) ? config->userSbrRatio : 0; } { @@ -1139,7 +1130,7 @@ static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder, hAacConfig); /* create flags for transport encoder */ - if (config->userTpAmxv == 1) { + if (config->userTpAmxv != 0) { flags |= TP_FLAG_LATM_AMV; } /* Clear output buffer */ @@ -1569,7 +1560,7 @@ AACENC_ERROR aacEncEncode( && ((hAacEncoder->extParam.userChannelMode==MODE_1_2_2)||(hAacEncoder->extParam.userChannelMode==MODE_1_2_2_1)) ) { /* Set matrix mixdown coefficient. */ - UINT pceValue = (UINT)( (1<<3) | ((matrix_mixdown_idx&0x3)<<1) | 1 ); + UINT pceValue = (UINT)( (0<<3) | ((matrix_mixdown_idx&0x3)<<1) | 1 ); if (hAacEncoder->extParam.userPceAdditions != pceValue) { hAacEncoder->extParam.userPceAdditions = pceValue; hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; @@ -1785,19 +1776,16 @@ AACENC_ERROR aacEncoder_SetParam( /* check if AOT matches the allocated modules */ switch ( value ) { case AOT_PS: - case AOT_MP2_PS: if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_PS))) { err = AACENC_INVALID_CONFIG; goto bail; } case AOT_SBR: - case AOT_MP2_SBR: if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_SBR))) { err = AACENC_INVALID_CONFIG; goto bail; } case AOT_AAC_LC: - case AOT_MP2_AAC_LC: case AOT_ER_AAC_LD: case AOT_ER_AAC_ELD: if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_AAC))) { @@ -1823,6 +1811,7 @@ AACENC_ERROR aacEncoder_SetParam( if (settings->userBitrateMode != value) { switch ( value ) { case 0: + case 1: case 2: case 3: case 4: case 5: case 8: settings->userBitrateMode = value; hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; @@ -1973,6 +1962,16 @@ AACENC_ERROR aacEncoder_SetParam( hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; } break; + case AACENC_AUDIOMUXVER: + if (settings->userTpAmxv != value) { + if ( !((value==0) || (value==1) || (value==2)) ) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpAmxv = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; case AACENC_TPSUBFRAMES: if (settings->userTpNsubFrames != value) { if (! ( (value>=1) && (value<=4) ) ) { @@ -1998,7 +1997,7 @@ AACENC_ERROR aacEncoder_SetParam( break; case AACENC_METADATA_MODE: if ((UINT)settings->userMetaDataMode != value) { - if ( !((value>=0) && (value<=2)) ) { + if ( !(((INT)value>=0) && ((INT)value<=2)) ) { err = AACENC_INVALID_CONFIG; break; } @@ -2006,6 +2005,12 @@ AACENC_ERROR aacEncoder_SetParam( hAacEncoder->InitFlags |= AACENC_INIT_CONFIG; } break; + case AACENC_PEAK_BITRATE: + if (settings->userPeakBitrate != value) { + settings->userPeakBitrate = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + } + break; default: err = AACENC_UNSUPPORTED_PARAMETER; break; @@ -2076,6 +2081,9 @@ UINT aacEncoder_GetParam( case AACENC_HEADER_PERIOD: value = (UINT)hAacEncoder->coderConfig.headerPeriod; break; + case AACENC_AUDIOMUXVER: + value = (UINT)hAacEncoder->aacConfig.audioMuxVersion; + break; case AACENC_TPSUBFRAMES: value = (UINT)settings->userTpNsubFrames; break; @@ -2088,6 +2096,12 @@ UINT aacEncoder_GetParam( case AACENC_METADATA_MODE: value = (hAacEncoder->metaDataAllowed==0) ? 0 : (UINT)settings->userMetaDataMode; break; + case AACENC_PEAK_BITRATE: + value = (UINT)-1; /* peak bitrate parameter is meaningless */ + if ( ((INT)hAacEncoder->extParam.userPeakBitrate!=-1) ) { + value = (UINT)(fMax((INT)hAacEncoder->extParam.userPeakBitrate, hAacEncoder->aacConfig.bitRate)); /* peak bitrate parameter is in use */ + } + break; default: //err = MPS_INVALID_PARAMETER; break; diff --git a/libAACenc/src/aacenc_tns.cpp b/libAACenc/src/aacenc_tns.cpp index 85aea65..9a07e8f 100644 --- a/libAACenc/src/aacenc_tns.cpp +++ b/libAACenc/src/aacenc_tns.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -95,13 +95,7 @@ amm-info@iis.fraunhofer.de #include "aacEnc_rom.h" #include "aacenc_tns.h" -enum { - HIFILT = 0, /* index of higher filter */ - LOFILT = 1 /* index of lower filter */ -}; - - -#define FILTER_DIRECTION 0 +#define FILTER_DIRECTION 0 /* 0 = up, 1 = down */ static const FIXP_DBL acfWindowLong[12+3+1] = { 0x7fffffff,0x7fb80000,0x7ee00000,0x7d780000,0x7b800000,0x78f80000,0x75e00000,0x72380000, @@ -112,20 +106,6 @@ static const FIXP_DBL acfWindowShort[4+3+1] = { 0x7fffffff,0x7e000000,0x78000000,0x6e000000,0x60000000,0x4e000000,0x38000000,0x1e000000 }; - -typedef struct { - INT filterEnabled[MAX_NUM_OF_FILTERS]; - INT threshOn[MAX_NUM_OF_FILTERS]; /* min. prediction gain for using tns TABUL*/ - INT filterStartFreq[MAX_NUM_OF_FILTERS]; /* lowest freq for lpc TABUL*/ - INT tnsLimitOrder[MAX_NUM_OF_FILTERS]; /* Limit for TNS order TABUL*/ - INT tnsFilterDirection[MAX_NUM_OF_FILTERS]; /* Filtering direction, 0=up, 1=down TABUL */ - INT acfSplit[MAX_NUM_OF_FILTERS]; - FIXP_DBL tnsTimeResolution[MAX_NUM_OF_FILTERS]; /* TNS max. time resolution TABUL. Should be fract but MSVC won't compile then */ - INT seperateFiltersAllowed; - -} TNS_PARAMETER_TABULATED; - - typedef struct{ INT bitRateFrom[2]; /* noneSbr=0, useSbr=1 */ INT bitRateTo[2]; /* noneSbr=0, useSbr=1 */ @@ -373,6 +353,7 @@ AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitRate, INT channels, INT blockType, INT granuleLength, + INT isLowDelay, INT ldSbrPresent, TNS_CONFIG *tC, PSY_CONFIGURATION *pC, @@ -385,6 +366,8 @@ AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitRate, if (channels <= 0) return (AAC_ENCODER_ERROR)1; + tC->isLowDelay = isLowDelay; + /* initialize TNS filter flag, order, and coefficient resolution (in bits per coeff) */ tC->tnsActive = (active) ? TRUE : FALSE; tC->maxOrder = (blockType == SHORT_WINDOW) ? 5 : 12; /* maximum: 7, 20 */ @@ -450,27 +433,14 @@ AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitRate, const TNS_PARAMETER_TABULATED* pCfg = FDKaacEnc_GetTnsParam(bitRate, channels, ldSbrPresent); if ( pCfg != NULL ) { + + FDKmemcpy(&(tC->confTab), pCfg, sizeof(tC->confTab)); + tC->lpcStartBand[HIFILT] = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[HIFILT], sampleRate, pC->sfbCnt, pC->sfbOffset); tC->lpcStartLine[HIFILT] = pC->sfbOffset[tC->lpcStartBand[HIFILT]]; tC->lpcStartBand[LOFILT] = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[LOFILT], sampleRate, pC->sfbCnt, pC->sfbOffset); tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]]; - tC->confTab.threshOn[HIFILT] = pCfg->threshOn[HIFILT]; - tC->confTab.threshOn[LOFILT] = pCfg->threshOn[LOFILT]; - - tC->confTab.tnsLimitOrder[HIFILT] = pCfg->tnsLimitOrder[HIFILT]; - tC->confTab.tnsLimitOrder[LOFILT] = pCfg->tnsLimitOrder[LOFILT]; - - tC->confTab.tnsFilterDirection[HIFILT] = pCfg->tnsFilterDirection[HIFILT]; - tC->confTab.tnsFilterDirection[LOFILT] = pCfg->tnsFilterDirection[LOFILT]; - - tC->confTab.acfSplit[HIFILT] = pCfg->acfSplit[HIFILT]; - tC->confTab.acfSplit[LOFILT] = pCfg->acfSplit[LOFILT]; - - tC->confTab.filterEnabled[HIFILT] = pCfg->filterEnabled[HIFILT]; - tC->confTab.filterEnabled[LOFILT] = pCfg->filterEnabled[LOFILT]; - tC->confTab.seperateFiltersAllowed = pCfg->seperateFiltersAllowed; - FDKaacEnc_CalcGaussWindow(tC->acfWindow[HIFILT], tC->maxOrder+1, sampleRate, granuleLength, pCfg->tnsTimeResolution[HIFILT], TNS_TIMERES_SCALE); FDKaacEnc_CalcGaussWindow(tC->acfWindow[LOFILT], tC->maxOrder+1, sampleRate, granuleLength, pCfg->tnsTimeResolution[LOFILT], TNS_TIMERES_SCALE); } @@ -614,6 +584,7 @@ static inline FIXP_DBL FDKaacEnc_AutoCorrNormFac( static void FDKaacEnc_MergedAutoCorrelation( const FIXP_DBL *spectrum, + const INT isLowDelay, const FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER+3+1], const INT lpcStartLine[MAX_NUM_OF_FILTERS], const INT lpcStopLine, @@ -633,6 +604,8 @@ static void FDKaacEnc_MergedAutoCorrelation( FDKmemclear(&_rxx1[0], sizeof(FIXP_DBL)*(maxOrder+1)); FDKmemclear(&_rxx2[0], sizeof(FIXP_DBL)*(maxOrder+1)); + idx0 = idx1 = idx2 = idx3 = idx4 = 0; + /* MDCT line indices separating the 1st, 2nd, 3rd, and 4th analysis quarters */ if ( (acfSplit[LOFILT]==-1) || (acfSplit[HIFILT]==-1) ) { /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the spectrum */ @@ -676,17 +649,27 @@ static void FDKaacEnc_MergedAutoCorrelation( /* compute energy normalization factors, i. e. 1/energy (saves some divisions) */ if (rxx1_0 != FL2FXCONST_DBL(0.f)) { - INT sc_fac1 = -1; - FIXP_DBL fac1 = FDKaacEnc_AutoCorrNormFac(rxx1_0, ((-2*sc1)+nsc1), &sc_fac1); - _rxx1[0] = scaleValue(fMult(rxx1_0,fac1),sc_fac1); + INT sc_fac1 = -1; + FIXP_DBL fac1 = FDKaacEnc_AutoCorrNormFac(rxx1_0, ((-2*sc1)+nsc1), &sc_fac1); + _rxx1[0] = scaleValue(fMult(rxx1_0,fac1),sc_fac1); + if (isLowDelay) + { for (lag = 1; lag <= maxOrder; lag++) { /* compute energy-normalized and windowed autocorrelation values at this lag */ + FIXP_DBL x1 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1); + _rxx1[lag] = fMult(scaleValue(fMult(x1,fac1),sc_fac1), acfWindow[LOFILT][lag]); + } + } + else + { + for (lag = 1; lag <= maxOrder; lag++) { if ((3 * lag) <= maxOrder + 3) { FIXP_DBL x1 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1); _rxx1[lag] = fMult(scaleValue(fMult(x1,fac1),sc_fac1), acfWindow[LOFILT][3*lag]); } } + } } /* auto corr over upper 3/4 of spectrum */ @@ -762,8 +745,12 @@ INT FDKaacEnc_TnsDetect( : &tnsData->dataRaw.Long.subBlockInfo; tnsData->filtersMerged = FALSE; - tsbi->tnsActive = FALSE; - tsbi->predictionGain = 1000; + + tsbi->tnsActive[HIFILT] = FALSE; + tsbi->predictionGain[HIFILT] = 1000; + tsbi->tnsActive[LOFILT] = FALSE; + tsbi->predictionGain[LOFILT] = 1000; + tnsInfo->numOfFilters[subBlockNumber] = 0; tnsInfo->coefRes[subBlockNumber] = tC->coefRes; for (i = 0; i < tC->maxOrder; i++) { @@ -779,6 +766,7 @@ INT FDKaacEnc_TnsDetect( FDKaacEnc_MergedAutoCorrelation( spectrum, + tC->isLowDelay, tC->acfWindow, tC->lpcStartLine, tC->lpcStopLine, @@ -788,7 +776,7 @@ INT FDKaacEnc_TnsDetect( rxx2); /* compute higher TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */ - tsbi->predictionGain = FDKaacEnc_AutoToParcor(rxx2, parcor_tmp, tC->confTab.tnsLimitOrder[HIFILT]); + tsbi->predictionGain[HIFILT] = FDKaacEnc_AutoToParcor(rxx2, parcor_tmp, tC->confTab.tnsLimitOrder[HIFILT]); /* non-linear quantization of TNS lattice coefficients with given resolution */ FDKaacEnc_Parcor2Index( @@ -815,9 +803,9 @@ INT FDKaacEnc_TnsDetect( tnsInfo->length[subBlockNumber][HIFILT] = sfbCnt - tC->lpcStartBand[HIFILT]; /* disable TNS if predictionGain is less than 3dB or sumSqrCoef is too small */ - if ((tsbi->predictionGain > tC->confTab.threshOn[HIFILT]) || (sumSqrCoef > (tC->confTab.tnsLimitOrder[HIFILT]/2 + 2))) + if ((tsbi->predictionGain[HIFILT] > tC->confTab.threshOn[HIFILT]) || (sumSqrCoef > (tC->confTab.tnsLimitOrder[HIFILT]/2 + 2))) { - tsbi->tnsActive = TRUE; + tsbi->tnsActive[HIFILT] = TRUE; tnsInfo->numOfFilters[subBlockNumber]++; /* compute second filter for lower quarter; only allowed for long windows! */ @@ -857,6 +845,7 @@ INT FDKaacEnc_TnsDetect( || ( (sumSqrCoef > 9) && (sumSqrCoef < 22 * tC->confTab.tnsLimitOrder[LOFILT]) ) ) { /* compare lower to upper filter; if they are very similar, merge them */ + tsbi->tnsActive[LOFILT] = TRUE; sumSqrCoef = 0; for (i = 0; i < tC->confTab.tnsLimitOrder[LOFILT]; i++) { sumSqrCoef += FDKabs(tnsInfo->coef[subBlockNumber][HIFILT][i] - tnsInfo->coef[subBlockNumber][LOFILT][i]); @@ -884,6 +873,8 @@ INT FDKaacEnc_TnsDetect( tnsInfo->numOfFilters[subBlockNumber]++; } } /* filter lower part */ + tsbi->predictionGain[LOFILT]=predGain; + } /* second filter allowed */ } /* if predictionGain > 1437 ... */ } /* maxOrder > 0 && tnsActive */ @@ -944,7 +935,7 @@ void FDKaacEnc_TnsSync( INT doSync = 1, absDiffSum = 0; /* if TNS is active in at least one channel, check if ParCor coefficients of higher filter are similar */ - if (pSbInfoDestW->tnsActive || pSbInfoSrcW->tnsActive) { + if (pSbInfoDestW->tnsActive[HIFILT] || pSbInfoSrcW->tnsActive[HIFILT]) { for (i = 0; i < tC->maxOrder; i++) { absDiff = FDKabs(tnsInfoDest->coef[w][HIFILT][i] - tnsInfoSrc->coef[w][HIFILT][i]); absDiffSum += absDiff; @@ -957,12 +948,12 @@ void FDKaacEnc_TnsSync( if (doSync) { /* if no significant difference was detected, synchronize coefficient sets */ - if (pSbInfoSrcW->tnsActive) { + if (pSbInfoSrcW->tnsActive[HIFILT]) { /* no dest filter, or more dest than source filters: use one dest filter */ - if ((!pSbInfoDestW->tnsActive) || - ((pSbInfoDestW->tnsActive) && (tnsInfoDest->numOfFilters[w] > tnsInfoSrc->numOfFilters[w]))) + if ((!pSbInfoDestW->tnsActive[HIFILT]) || + ((pSbInfoDestW->tnsActive[HIFILT]) && (tnsInfoDest->numOfFilters[w] > tnsInfoSrc->numOfFilters[w]))) { - pSbInfoDestW->tnsActive = tnsInfoDest->numOfFilters[w] = 1; + pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 1; } tnsDataDest->filtersMerged = tnsDataSrc->filtersMerged; tnsInfoDest->order [w][HIFILT] = tnsInfoSrc->order [w][HIFILT]; @@ -975,7 +966,7 @@ void FDKaacEnc_TnsSync( } } else - pSbInfoDestW->tnsActive = tnsInfoDest->numOfFilters[w] = 0; + pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 0; } } @@ -1012,8 +1003,8 @@ INT FDKaacEnc_TnsEncode( { INT i, startLine, stopLine; - if ( ( (blockType == SHORT_WINDOW) && (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber].tnsActive) ) - || ( (blockType != SHORT_WINDOW) && (!tnsData->dataRaw.Long.subBlockInfo.tnsActive) ) ) + if ( ( (blockType == SHORT_WINDOW) && (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber].tnsActive[HIFILT]) ) + || ( (blockType != SHORT_WINDOW) && (!tnsData->dataRaw.Long.subBlockInfo.tnsActive[HIFILT]) ) ) { return 1; } @@ -1129,8 +1120,9 @@ static INT FDKaacEnc_AutoToParcor( FIXP_DBL *RESTRICT workBuffer = parcorWorkBuffer; const FIXP_DBL autoCorr_0 = input[0]; + FDKmemclear(reflCoeff,numOfCoeff*sizeof(FIXP_DBL)); + if((FIXP_DBL)input[0] == FL2FXCONST_DBL(0.0)) { - FDKmemclear(reflCoeff,numOfCoeff*sizeof(FIXP_DBL)); return(predictionGain); } diff --git a/libAACenc/src/aacenc_tns.h b/libAACenc/src/aacenc_tns.h index f2b731f..2824cbc 100644 --- a/libAACenc/src/aacenc_tns.h +++ b/libAACenc/src/aacenc_tns.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -117,21 +117,25 @@ amm-info@iis.fraunhofer.de #define MAX_NUM_OF_FILTERS 2 +#define HIFILT 0 /* index of higher filter */ +#define LOFILT 1 /* index of lower filter */ -typedef struct{ /*stuff that is tabulated dependent on bitrate etc. */ - INT filterEnabled[MAX_NUM_OF_FILTERS]; - INT threshOn[MAX_NUM_OF_FILTERS]; /* min. prediction gain for using tns TABUL*/ - INT tnsLimitOrder[MAX_NUM_OF_FILTERS]; /* Limit for TNS order TABUL*/ - INT tnsFilterDirection[MAX_NUM_OF_FILTERS]; /* Filtering direction, 0=up, 1=down TABUL */ - INT acfSplit[MAX_NUM_OF_FILTERS]; - INT seperateFiltersAllowed; - -}TNS_CONFIG_TABULATED; +typedef struct{ /* stuff that is tabulated dependent on bitrate etc. */ + INT filterEnabled[MAX_NUM_OF_FILTERS]; + INT threshOn[MAX_NUM_OF_FILTERS]; /* min. prediction gain for using tns TABUL*/ + INT filterStartFreq[MAX_NUM_OF_FILTERS]; /* lowest freq for lpc TABUL*/ + INT tnsLimitOrder[MAX_NUM_OF_FILTERS]; /* Limit for TNS order TABUL*/ + INT tnsFilterDirection[MAX_NUM_OF_FILTERS]; /* Filtering direction, 0=up, 1=down TABUL */ + INT acfSplit[MAX_NUM_OF_FILTERS]; + FIXP_DBL tnsTimeResolution[MAX_NUM_OF_FILTERS]; /* TNS max. time resolution TABUL. Should be fract but MSVC won't compile then */ + INT seperateFiltersAllowed; +} TNS_PARAMETER_TABULATED; typedef struct { /*assigned at InitTime*/ - TNS_CONFIG_TABULATED confTab; + TNS_PARAMETER_TABULATED confTab; + INT isLowDelay; INT tnsActive; INT maxOrder; /* max. order of tns filter */ INT coefRes; @@ -148,8 +152,8 @@ typedef struct { /*assigned at InitTime*/ typedef struct { - INT tnsActive; - INT predictionGain; + INT tnsActive[MAX_NUM_OF_FILTERS]; + INT predictionGain[MAX_NUM_OF_FILTERS]; } TNS_SUBBLOCK_INFO; typedef struct{ /*changed at runTime*/ diff --git a/libAACenc/src/adj_thr.cpp b/libAACenc/src/adj_thr.cpp index 6433633..a79a9ae 100644 --- a/libAACenc/src/adj_thr.cpp +++ b/libAACenc/src/adj_thr.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -130,14 +130,14 @@ 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; + ULONG bits2PeFactor_mono; + ULONG bits2PeFactor_mono_slope; + ULONG bits2PeFactor_stereo; + ULONG bits2PeFactor_stereo_slope; + ULONG bits2PeFactor_mono_scfOpt; + ULONG bits2PeFactor_mono_scfOpt_slope; + ULONG bits2PeFactor_stereo_scfOpt; + ULONG bits2PeFactor_stereo_scfOpt_slope; } BIT_PE_SFAC; @@ -153,10 +153,10 @@ static const BIT_PE_SFAC S_Bits2PeTab16000[] = { { 24000, 0x23D70A3D, 0x029F16B1, 0x2199999A, 0x07DD4413, 0x23D70A3D, 0x029F16B1, 0x2199999A, 0x07DD4413}, { 32000, 0x247AE148, 0x11B1D92B, 0x23851EB8, 0x01F75105, 0x247AE148, 0x110A137F, 0x23851EB8, 0x01F75105}, { 48000, 0x2D1EB852, 0x6833C600, 0x247AE148, 0x014F8B59, 0x2CCCCCCD, 0x68DB8BAC, 0x247AE148, 0x01F75105}, - { 64000, 0x60000000, 0x00000000, 0x251EB852, 0x154C985F, 0x60000000, 0x00000000, 0x2570A3D7, 0x154C985F}, - { 96000, 0x60000000, 0x00000000, 0x39EB851F, 0x088509C0, 0x60000000, 0x00000000, 0x3A3D70A4, 0x088509C0}, - {128000, 0x60000000, 0x00000000, 0x423D70A4, 0x18A43BB4, 0x60000000, 0x00000000, 0x428F5C29, 0x181E03F7}, - {148000, 0x60000000, 0x00000000, 0x5147AE14, 0x00000000, 0x60000000, 0x00000000, 0x5147AE14, 0x00000000} + { 64000, 0x25c28f40, 0x00000000, 0x251EB852, 0x01480000, 0x25c28f40, 0x00000000, 0x2570A3D7, 0x01480000}, + { 96000, 0x25c28f40, 0x00000000, 0x26000000, 0x01000000, 0x25c28f40, 0x00000000, 0x26000000, 0x01000000}, + {128000, 0x25c28f40, 0x00000000, 0x270a3d80, 0x01000000, 0x25c28f40, 0x00000000, 0x270a3d80, 0x01000000}, + {148000, 0x25c28f40, 0x00000000, 0x28000000, 0x00000000, 0x25c28f40, 0x00000000, 0x28000000, 0x00000000} }; static const BIT_PE_SFAC S_Bits2PeTab22050[] = { @@ -166,8 +166,8 @@ static const BIT_PE_SFAC S_Bits2PeTab22050[] = { { 48000, 0x23d70a3d, 0x014f8b59, 0x2199999a, 0x03eea20a, 0x23d70a3d, 0x14f8b59, 0x2199999a, 0x03eea20a}, { 64000, 0x247ae148, 0x08d8ec96, 0x23851eb8, 0x00fba882, 0x247ae148, 0x88509c0, 0x23851eb8, 0x00fba882}, { 96000, 0x2d1eb852, 0x3419e300, 0x247ae148, 0x00a7c5ac, 0x2ccccccd, 0x346dc5d6, 0x247ae148, 0x00fba882}, - {128000, 0x60000000, 0x00000000, 0x251eb852, 0x029f16b1, 0x60000000, 0x00000000, 0x2570a3d7, 0x009f16b1}, - {148000, 0x60000000, 0x00000000, 0x26b851ec, 0x00000000, 0x60000000, 0x00000000, 0x270a3d71, 0x00000000} + {128000, 0x25c28f40, 0x00000000, 0x251eb852, 0x029f16b1, 0x60000000, 0x25c28f40, 0x2570a3d7, 0x009f16b1}, + {148000, 0x25c28f40, 0x00000000, 0x26b851ec, 0x00000000, 0x60000000, 0x25c28f40, 0x270a3d71, 0x00000000} }; static const BIT_PE_SFAC S_Bits2PeTab24000[] = { @@ -178,21 +178,21 @@ static const BIT_PE_SFAC S_Bits2PeTab24000[] = { { 64000, 0x24cccccd, 0x05e5f30e, 0x22e147ae, 0x01a36e2f, 0x24cccccd, 0x05e5f30e, 0x23333333, 0x014f8b59}, { 96000, 0x2a8f5c29, 0x24b33db0, 0x247ae148, 0x00fba882, 0x2a8f5c29, 0x26fe718b, 0x247ae148, 0x00fba882}, {128000, 0x4e666666, 0x1cd5f99c, 0x2570a3d7, 0x010c6f7a, 0x50a3d70a, 0x192a7371, 0x2570a3d7, 0x010c6f7a}, - {148000, 0x60000000, 0x00000000, 0x26147ae1, 0x00000000, 0x60000000, 0x00000000, 0x26147ae1, 0x00000000} + {148000, 0x25c28f40, 0x00000000, 0x26147ae1, 0x00000000, 0x25c28f40, 0x00000000, 0x26147ae1, 0x00000000} }; static const BIT_PE_SFAC S_Bits2PeTab32000[] = { - { 16000, 0x1199999a, 0x20c49ba6, 0x00000000, 0x4577d955, 0x00000000, 0x60fe4799, 0x00000000, 0x00000000}, - { 24000, 0x1999999a, 0x0fba8827, 0x10f5c28f, 0x1b866e44, 0x17ae147b, 0x0fba8827, 0x00000000, 0x4d551d69}, + { 16000, 0x247ae140, 0xFFFFAC1E, 0x270a3d80, 0xFFFE9B7C, 0x14ccccc0, 0x000110A1, 0x15c28f60, 0xFFFEEF5F}, + { 24000, 0x23333340, 0x0fba8827, 0x21999980, 0x1b866e44, 0x18f5c280, 0x0fba8827, 0x119999a0, 0x4d551d69}, { 32000, 0x1d70a3d7, 0x07357e67, 0x17ae147b, 0x09d49518, 0x1b851eb8, 0x0a7c5ac4, 0x12e147ae, 0x110a137f}, { 48000, 0x20f5c28f, 0x049667b6, 0x1c7ae148, 0x053e2d62, 0x20a3d70a, 0x053e2d62, 0x1b333333, 0x05e5f30e}, { 64000, 0x23333333, 0x029f16b1, 0x1f0a3d71, 0x02f2f987, 0x23333333, 0x029f16b1, 0x1e147ae1, 0x03eea20a}, { 96000, 0x25c28f5c, 0x2c3c9eed, 0x21eb851f, 0x01f75105, 0x25c28f5c, 0x0a7c5ac4, 0x21eb851f, 0x01a36e2f}, {128000, 0x50f5c28f, 0x18a43bb4, 0x23d70a3d, 0x010c6f7a, 0x30000000, 0x168b5cc0, 0x23851eb8, 0x0192a737}, - {148000, 0x60000000, 0x00000000, 0x247ae148, 0x00dfb23b, 0x3dc28f5c, 0x300f4aaf, 0x247ae148, 0x01bf6476}, - {160000, 0x60000000, 0xb15b5740, 0x24cccccd, 0x053e2d62, 0x4f5c28f6, 0xbefd0072, 0x251eb852, 0x04fb1184}, - {200000, 0x00000000, 0x00000000, 0x2b333333, 0x0836be91, 0x00000000, 0x00000000, 0x2b333333, 0x0890390f}, - {320000, 0x00000000, 0x00000000, 0x4947ae14, 0x00000000, 0x00000000, 0x00000000, 0x4a8f5c29, 0x00000000} + {148000, 0x25c28f40, 0x00000000, 0x247ae148, 0x00dfb23b, 0x3dc28f5c, 0x300f4aaf, 0x247ae148, 0x01bf6476}, + {160000, 0x25c28f40, 0xb15b5740, 0x24cccccd, 0x053e2d62, 0x4f5c28f6, 0xbefd0072, 0x251eb852, 0x04fb1184}, + {200000, 0x25c28f40, 0x00000000, 0x2b333333, 0x0836be91, 0x25c28f40, 0x00000000, 0x2b333333, 0x0890390f}, + {320000, 0x25c28f40, 0x00000000, 0x4947ae14, 0x00000000, 0x25c28f40, 0x00000000, 0x4a8f5c29, 0x00000000} }; static const BIT_PE_SFAC S_Bits2PeTab44100[] = { @@ -205,8 +205,8 @@ static const BIT_PE_SFAC S_Bits2PeTab44100[] = { {128000, 0x2ae147ae, 0x1b435265, 0x223d70a4, 0x0192a737, 0x2a3d70a4, 0x1040bfe4, 0x21eb851f, 0x0192a737}, {148000, 0x3b851eb8, 0x2832069c, 0x23333333, 0x00dfb23b, 0x3428f5c3, 0x2054c288, 0x22e147ae, 0x00dfb23b}, {160000, 0x4a3d70a4, 0xc32ebe5a, 0x23851eb8, 0x01d5c316, 0x40000000, 0xcb923a2b, 0x23333333, 0x01d5c316}, - {200000, 0x00000000, 0x00000000, 0x25c28f5c, 0x0713f078, 0x00000000, 0x00000000, 0x2570a3d7, 0x072a4f17}, - {320000, 0x00000000, 0x00000000, 0x3fae147b, 0x00000000, 0x00000000, 0x00000000, 0x3fae147b, 0x00000000} + {200000, 0x25c28f40, 0x00000000, 0x25c28f5c, 0x0713f078, 0x25c28f40, 0x00000000, 0x2570a3d7, 0x072a4f17}, + {320000, 0x25c28f40, 0x00000000, 0x3fae147b, 0x00000000, 0x25c28f40, 0x00000000, 0x3fae147b, 0x00000000} }; static const BIT_PE_SFAC S_Bits2PeTab48000[] = { @@ -219,8 +219,8 @@ static const BIT_PE_SFAC S_Bits2PeTab48000[] = { {128000, 0x28f5c28f, 0x14727dcc, 0x2147ae14, 0x0218def4, 0x2851eb85, 0x0e27e0f0, 0x20f5c28f, 0x0218def4}, {148000, 0x3570a3d7, 0x1cd5f99c, 0x228f5c29, 0x01bf6476, 0x30f5c28f, 0x18777e75, 0x223d70a4, 0x01bf6476}, {160000, 0x40000000, 0xcb923a2b, 0x23333333, 0x0192a737, 0x39eb851f, 0xd08d4bae, 0x22e147ae, 0x0192a737}, - {200000, 0x00000000, 0x00000000, 0x251eb852, 0x06775a1b, 0x00000000, 0x00000000, 0x24cccccd, 0x06a4175a}, - {320000, 0x00000000, 0x00000000, 0x3ccccccd, 0x00000000, 0x00000000, 0x00000000, 0x3d1eb852, 0x00000000} + {200000, 0x25c28f40, 0x00000000, 0x251eb852, 0x06775a1b, 0x25c28f40, 0x00000000, 0x24cccccd, 0x06a4175a}, + {320000, 0x25c28f40, 0x00000000, 0x3ccccccd, 0x00000000, 0x25c28f40, 0x00000000, 0x3d1eb852, 0x00000000} }; static const BITS2PE_CFG_TAB bits2PeConfigTab[] = { @@ -258,6 +258,7 @@ static void FDKaacEnc_InitBits2PeFactor( const INT nChannels, const INT sampleRate, const INT advancedBitsToPe, + const INT dZoneQuantEnable, const INT invQuant ) { @@ -329,7 +330,32 @@ static void FDKaacEnc_InitBits2PeFactor( } /* advancedBitsToPe */ - /* return bits2pe factor */ + if (dZoneQuantEnable) + { + if(bit2PE_m >= (FL2FXCONST_DBL(0.6f))>>bit2PE_e) + { + /* Additional headroom for addition */ + bit2PE_m >>= 1; + bit2PE_e += 1; + } + + /* the quantTendencyCompensator compensates a lower bit consumption due to increasing the tendency to quantize low spectral values to the lower quantizer border for bitrates below a certain bitrate threshold --> see also function calcSfbDistLD in quantize.c */ + if ((bitRate/nChannels > 32000) && (bitRate/nChannels <= 40000)) { + bit2PE_m += (FL2FXCONST_DBL(0.4f))>>bit2PE_e; + } + else if (bitRate/nChannels > 20000) { + bit2PE_m += (FL2FXCONST_DBL(0.3f))>>bit2PE_e; + } + else if (bitRate/nChannels >= 16000) { + bit2PE_m += (FL2FXCONST_DBL(0.3f))>>bit2PE_e; + } + else { + bit2PE_m += (FL2FXCONST_DBL(0.0f))>>bit2PE_e; + } + } + + + /***** 3.) Return bits2pe factor *****/ *bits2PeFactor_m = bit2PE_m; *bits2PeFactor_e = bit2PE_e; } @@ -1649,6 +1675,7 @@ static void FDKaacEnc_adaptThresholdsToPe(CHANNEL_MAPPING* cm, QC_OUT_ELEMENT* qcElement[(8)], PSY_OUT_ELEMENT* psyOutElement[(8)], const INT desiredPe, + const INT maxIter2ndGuess, const INT processElements, const INT elementOffset) { @@ -1733,7 +1760,7 @@ static void FDKaacEnc_adaptThresholdsToPe(CHANNEL_MAPPING* cm, /* Part III: Iterate until bit constraints are met */ /* -------------------------------------------------- */ iter = 0; - while ((fixp_abs(redPeGlobal - desiredPe) > fMultI(FL2FXCONST_DBL(0.05f),desiredPe)) && (iter < 1)) { + while ((fixp_abs(redPeGlobal - desiredPe) > fMultI(FL2FXCONST_DBL(0.05f),desiredPe)) && (iter < maxIter2ndGuess)) { INT desiredPeNoAHGlobal; INT redPeNoAHGlobal = 0; @@ -2138,7 +2165,7 @@ static FIXP_DBL FDKaacEnc_bitresCalcBitFac(const INT bitresBits, bresParam->clipSpendLow, bresParam->clipSpendHigh, bresParam->minBitSpend, bresParam->maxBitSpend, bitspend_slope); - pe_pers = fDivNorm(pex - adjThrChan->peMin, adjThrChan->peMax - adjThrChan->peMin); + pe_pers = (pex > adjThrChan->peMin) ? fDivNorm(pex - adjThrChan->peMin, adjThrChan->peMax - adjThrChan->peMin) : 0; tmp_fix = fMult(((FIXP_DBL)bitSpend + (FIXP_DBL)bitSave), pe_pers); bitresFac_fix = (UNITY>>1) - ((FIXP_DBL)bitSave>>1) + (tmp_fix>>1); qbres = (DFRACT_BITS-2); @@ -2225,7 +2252,8 @@ void FDKaacEnc_AdjThrInit( INT nChannelsEff, INT sampleRate, INT advancedBitsToPe, - FIXP_DBL vbrQualFactor + FIXP_DBL vbrQualFactor, + const INT dZoneQuantEnable ) { INT i; @@ -2233,6 +2261,10 @@ void FDKaacEnc_AdjThrInit( FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f); FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f); + /* Max number of iterations in second guess is 3 for lowdelay aot and for configurations with + multiple audio elements in general, otherwise iteration value is always 1. */ + hAdjThr->maxIter2ndGuess = (advancedBitsToPe!=0 || nElements>1) ? 3 : 1; + /* common for all elements: */ /* parameters for bitres control */ hAdjThr->bresParamLong.clipSaveLow = (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */ @@ -2313,10 +2345,11 @@ void FDKaacEnc_AdjThrInit( FDKaacEnc_InitBits2PeFactor( &atsElem->bits2PeFactor_m, &atsElem->bits2PeFactor_e, - chBitrate, /* bitrate/channel*/ + chBitrate*nChannelsEff, /* overall bitrate */ nChannelsEff, /* number of channels */ sampleRate, advancedBitsToPe, + dZoneQuantEnable, invQuant ); @@ -2545,6 +2578,7 @@ void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(8)], QC_OUT* qcOut, PSY_OUT_ELEMENT* psyOutElement[(8)], INT CBRbitrateMode, + INT maxIter2ndGuess, CHANNEL_MAPPING* cm) { int i; @@ -2570,6 +2604,7 @@ void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(8)], qcElement, psyOutElement, qcElement[i]->grantedPeCorr, + maxIter2ndGuess, 1, /* Process only 1 element */ i); /* Process exactly THIS element */ diff --git a/libAACenc/src/adj_thr.h b/libAACenc/src/adj_thr.h index 69b1dcc..be68c6e 100644 --- a/libAACenc/src/adj_thr.h +++ b/libAACenc/src/adj_thr.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -118,7 +118,8 @@ void FDKaacEnc_AdjThrInit(ADJ_THR_STATE *hAdjThr, INT nChannelsEff, INT sampleRate, INT advancedBitsToPe, - FIXP_DBL vbrQualFactor); + FIXP_DBL vbrQualFactor, + const INT dZoneQuantEnable); void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState, @@ -140,6 +141,7 @@ void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(8)], QC_OUT* qcOut, PSY_OUT_ELEMENT* psyOutElement[(8)], INT CBRbitrateMode, + INT maxIter2ndGuess, CHANNEL_MAPPING* cm); void FDKaacEnc_AdjThrClose(ADJ_THR_STATE** hAdjThr); diff --git a/libAACenc/src/adj_thr_data.h b/libAACenc/src/adj_thr_data.h index 3eb7678..7c3a191 100644 --- a/libAACenc/src/adj_thr_data.h +++ b/libAACenc/src/adj_thr_data.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -145,6 +145,7 @@ typedef struct { typedef struct { BRES_PARAM bresParamLong, bresParamShort; ATS_ELEMENT* adjThrStateElem[(8)]; + INT maxIter2ndGuess; } ADJ_THR_STATE; #endif diff --git a/libAACenc/src/bandwidth.cpp b/libAACenc/src/bandwidth.cpp index 6fc7d87..6937362 100644 --- a/libAACenc/src/bandwidth.cpp +++ b/libAACenc/src/bandwidth.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -127,7 +127,7 @@ static const BANDWIDTH_TAB bandWidthTable_LD_24000[] = { { 8000, 2000, 2000}, {12000, 2000, 2300}, {16000, 2200, 2500}, - {24000, 5650, 6400}, + {24000, 5650, 7200}, {32000, 11600, 12000}, {40000, 12000, 16000}, {48000, 16000, 16000}, @@ -138,10 +138,10 @@ static const BANDWIDTH_TAB bandWidthTable_LD_24000[] = { static const BANDWIDTH_TAB bandWidthTable_LD_32000[] = { { 8000, 2000, 2000}, {12000, 2000, 2000}, - {24000, 4250, 5200}, + {24000, 4250, 7200}, {32000, 8400, 9000}, {40000, 9400, 11300}, - {48000, 11900, 13700}, + {48000, 11900, 14700}, {64000, 14800, 16000}, {76000, 16000, 16000}, {360001, 16000, 16000} diff --git a/libAACenc/src/intensity.cpp b/libAACenc/src/intensity.cpp index 6d807f7..b45b27b 100644 --- a/libAACenc/src/intensity.cpp +++ b/libAACenc/src/intensity.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -325,7 +325,6 @@ FDKaacEnc_prepareIntensityDecision(const FIXP_DBL *sfbEnergyLeft, channelCorr[sfb + sfboffs] = FL2FXCONST_DBL(0.0f); - FDK_ASSERT(50 >= 49); /* max width of scalefactorband is 96; width's are always even */ /* inv_n is scaled with factor 2 to compensate fMultDiv2() in subsequent loops */ inv_n = GetInvInt((sfbOffset[sfb + sfboffs + 1] - sfbOffset[sfb + sfboffs])>>1); diff --git a/libAACenc/src/pnsparam.cpp b/libAACenc/src/pnsparam.cpp index afc5bdd..9d59ddc 100644 --- a/libAACenc/src/pnsparam.cpp +++ b/libAACenc/src/pnsparam.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -107,6 +107,7 @@ typedef struct { typedef struct { ULONG brFrom; ULONG brTo; + UCHAR S16000; UCHAR S22050; UCHAR S24000; UCHAR S32000; @@ -115,25 +116,26 @@ typedef struct { } AUTO_PNS_TAB; static const AUTO_PNS_TAB levelTable_mono[]= { - {0, 11999, 1, 1, 1, 1, 1,}, - {12000, 19999, 1, 1, 1, 1, 1,}, - {20000, 28999, 2, 1, 1, 1, 1,}, - {29000, 40999, 4, 4, 4, 2, 2,}, - {41000, 55999, 9, 9, 7, 7, 7,}, - {56000, 79999, 0, 0, 0, 9, 9,}, - {80000, 99999, 0, 0, 0, 0, 0,}, - {100000,999999, 0, 0, 0, 0, 0,}, + {0, 11999, 0, 1, 1, 1, 1, 1,}, + {12000, 19999, 0, 1, 1, 1, 1, 1,}, + {20000, 28999, 0, 2, 1, 1, 1, 1,}, + {29000, 40999, 0, 4, 4, 4, 2, 2,}, + {41000, 55999, 0, 9, 9, 7, 7, 7,}, + {56000, 61999, 0, 0, 0, 0, 9, 9,}, + {62000, 75999, 0, 0, 0, 0, 0, 0,}, + {76000, 92999, 0, 0, 0, 0, 0, 0,}, + {93000, 999999, 0, 0, 0, 0, 0, 0,}, }; static const AUTO_PNS_TAB levelTable_stereo[]= { - {0, 11999, 1, 1, 1, 1, 1,}, - {12000, 19999, 3, 1, 1, 1, 1,}, - {20000, 28999, 3, 3, 3, 2, 2,}, - {29000, 40999, 7, 6, 6, 5, 5,}, - {41000, 55999, 9, 9, 7, 7, 7,}, - {56000, 79999, 0, 0, 0, 0, 0,}, - {80000, 99999, 0, 0, 0, 0, 0,}, - {100000,999999, 0, 0, 0, 0, 0,}, + {0, 11999, 0, 1, 1, 1, 1, 1,}, + {12000, 19999, 0, 3, 1, 1, 1, 1,}, + {20000, 28999, 0, 3, 3, 3, 2, 2,}, + {29000, 40999, 0, 7, 6, 6, 5, 5,}, + {41000, 55999, 0, 9, 9, 7, 7, 7,}, + {56000, 79999, 0, 0, 0, 0, 0, 0,}, + {80000, 99999, 0, 0, 0, 0, 0, 0,}, + {100000,999999, 0, 0, 0, 0, 0, 0,}, }; @@ -160,11 +162,11 @@ static const PNS_INFO_TAB pnsInfoTab[] = { }; static const AUTO_PNS_TAB levelTable_lowComplexity[]= { - {0, 27999, 0, 0, 0, 0, 0,}, - {28000, 31999, 2, 2, 2, 2, 2,}, - {32000, 47999, 3, 3, 3, 3, 3,}, - {48000, 48000, 4, 4, 4, 4, 4,}, - {48001, 999999, 0, 0, 0, 0, 0,}, + {0, 27999, 0, 0, 0, 0, 0, 0,}, + {28000, 31999, 0, 2, 2, 2, 2, 2,}, + {32000, 47999, 0, 3, 3, 3, 3, 3,}, + {48000, 48000, 0, 4, 4, 4, 4, 4,}, + {48001, 999999, 0, 0, 0, 0, 0, 0,}, }; /* conversion of old LC tuning tables to new (LD enc) structure (only entries which are actually used were converted) */ @@ -211,6 +213,7 @@ int FDKaacEnc_lookUpPnsUse (int bitRate, int sampleRate, int numChan, const int } switch (sampleRate) { + case 16000: hUsePns = levelTable[i].S16000; break; case 22050: hUsePns = levelTable[i].S22050; break; case 24000: hUsePns = levelTable[i].S24000; break; case 32000: hUsePns = levelTable[i].S32000; break; diff --git a/libAACenc/src/psy_configuration.cpp b/libAACenc/src/psy_configuration.cpp index 4393fa1..9a72c68 100644 --- a/libAACenc/src/psy_configuration.cpp +++ b/libAACenc/src/psy_configuration.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -634,13 +634,14 @@ AAC_ENCODER_ERROR FDKaacEnc_InitPsyConfiguration(INT bitrate, if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLine) break; } - psyConf->sfbActive = sfb; + psyConf->sfbActive = FDKmax(sfb, 1); for (sfb = 0; sfb < psyConf->sfbCnt; sfb++){ if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLineLFE) break; } psyConf->sfbActiveLFE = sfb; + psyConf->sfbActive = FDKmax(psyConf->sfbActive, psyConf->sfbActiveLFE); /* calculate minSnr */ FDKaacEnc_initMinSnr(bitrate, diff --git a/libAACenc/src/psy_main.cpp b/libAACenc/src/psy_main.cpp index 59193c7..446c894 100644 --- a/libAACenc/src/psy_main.cpp +++ b/libAACenc/src/psy_main.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -342,6 +342,7 @@ AAC_ENCODER_ERROR FDKaacEnc_psyMainInit(PSY_INTERNAL *hPsy, tnsChannels, LONG_WINDOW, hPsy->granuleLength, + isLowDelay(audioObjectType), (syntaxFlags&AC_SBR_PRESENT)?1:0, &(hPsy->psyConf[0].tnsConf), &hPsy->psyConf[0], @@ -362,6 +363,7 @@ AAC_ENCODER_ERROR FDKaacEnc_psyMainInit(PSY_INTERNAL *hPsy, tnsChannels, SHORT_WINDOW, hPsy->granuleLength, + isLowDelay(audioObjectType), (syntaxFlags&AC_SBR_PRESENT)?1:0, &hPsy->psyConf[1].tnsConf, &hPsy->psyConf[1], @@ -447,7 +449,7 @@ AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels, INT totalChannels ) { - INT commonWindow = 1; + const INT commonWindow = 1; INT maxSfbPerGroup[(2)]; INT mdctSpectrum_e; INT ch; /* counts through channels */ @@ -621,7 +623,7 @@ AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels, FDKmemclear(&psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine+wOffset], (windowLength[ch]-psyData[ch]->lowpassLine)*sizeof(FIXP_DBL)); - if (hPsyConfLong->filterbank != FB_LC) { + if ( (hPsyConfLong->filterbank != FB_LC) && (psyData[ch]->lowpassLine >= FADE_OUT_LEN) ) { /* Do blending to reduce gibbs artifacts */ for (int i=0; i<FADE_OUT_LEN; i++) { psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine+wOffset - FADE_OUT_LEN + i] = fMult(psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine+wOffset - FADE_OUT_LEN + i], fadeOutFactor[i]); @@ -763,7 +765,8 @@ AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels, /* Advance psychoacoustics: Tonality and TNS */ if (psyStatic[0]->isLFE) { - tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive = 0; + tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] = 0; + tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT] = 0; } else { @@ -815,15 +818,19 @@ AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels, &hThisPsyConf[1]->tnsConf); } - FDK_ASSERT(commonWindow=1); /* all checks for TNS do only work for common windows (which is always set)*/ + FDK_ASSERT(1==commonWindow); /* all checks for TNS do only work for common windows (which is always set)*/ for(w = 0; w < nWindows[0]; w++) { if (isShortWindow[0]) - tnsActive[w] = tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive || - ((channels == 2) ? tnsData[1]->dataRaw.Short.subBlockInfo[w].tnsActive : 0); + tnsActive[w] = tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive[HIFILT] || + tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive[LOFILT] || + tnsData[channels-1]->dataRaw.Short.subBlockInfo[w].tnsActive[HIFILT] || + tnsData[channels-1]->dataRaw.Short.subBlockInfo[w].tnsActive[LOFILT]; else - tnsActive[w] = tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive || - ((channels == 2) ? tnsData[1]->dataRaw.Long.subBlockInfo.tnsActive : 0); + tnsActive[w] = tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] || + tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT] || + tnsData[channels-1]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] || + tnsData[channels-1]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT]; } for(ch = 0; ch < channels; ch++) { @@ -1150,8 +1157,8 @@ AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels, psyData[ch]->sfbMaxScaleSpec.Long, sfbTonality[ch], psyOutChannel[ch]->tnsInfo.order[0][0], - tnsData[ch]->dataRaw.Long.subBlockInfo.predictionGain, - tnsData[ch]->dataRaw.Long.subBlockInfo.tnsActive, + tnsData[ch]->dataRaw.Long.subBlockInfo.predictionGain[HIFILT], + tnsData[ch]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT], psyOutChannel[ch]->sfbEnergyLdData, psyOutChannel[ch]->noiseNrg ); } /* !isLFE */ diff --git a/libAACenc/src/qc_data.h b/libAACenc/src/qc_data.h index a9309c8..00d6090 100644 --- a/libAACenc/src/qc_data.h +++ b/libAACenc/src/qc_data.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -269,6 +269,8 @@ typedef struct BITCNTR_STATE *hBitCounter; ADJ_THR_STATE *hAdjThr; + INT dZoneQuantEnable; /* enable dead zone quantizer */ + } QC_STATE; #endif /* _QC_DATA_H */ diff --git a/libAACenc/src/qc_main.cpp b/libAACenc/src/qc_main.cpp index b74510a..9cd73f6 100644 --- a/libAACenc/src/qc_main.cpp +++ b/libAACenc/src/qc_main.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -107,14 +107,11 @@ typedef struct { } TAB_VBR_QUAL_FACTOR; static const TAB_VBR_QUAL_FACTOR tableVbrQualFactor[] = { - {QCDATA_BR_MODE_CBR, FL2FXCONST_DBL(0.00f)}, {QCDATA_BR_MODE_VBR_1, FL2FXCONST_DBL(0.160f)}, /* 32 kbps mono AAC-LC + SBR + PS */ {QCDATA_BR_MODE_VBR_2, FL2FXCONST_DBL(0.148f)}, /* 64 kbps stereo AAC-LC + SBR */ {QCDATA_BR_MODE_VBR_3, FL2FXCONST_DBL(0.135f)}, /* 80 - 96 kbps stereo AAC-LC */ {QCDATA_BR_MODE_VBR_4, FL2FXCONST_DBL(0.111f)}, /* 128 kbps stereo AAC-LC */ - {QCDATA_BR_MODE_VBR_5, FL2FXCONST_DBL(0.070f)}, /* 192 kbps stereo AAC-LC */ - {QCDATA_BR_MODE_SFR, FL2FXCONST_DBL(0.00f)}, - {QCDATA_BR_MODE_FF, FL2FXCONST_DBL(0.00f)} + {QCDATA_BR_MODE_VBR_5, FL2FXCONST_DBL(0.070f)} /* 192 kbps stereo AAC-LC */ }; static INT isConstantBitrateMode( @@ -369,6 +366,7 @@ QCNew_bail: AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC, struct QC_INIT *init) { + int i; hQC->maxBitsPerFrame = init->maxBits; hQC->minBitsPerFrame = init->minBits; hQC->nElements = init->channelMapping->nElements; @@ -382,7 +380,7 @@ AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC, if ( isConstantBitrateMode(hQC->bitrateMode) ) { INT bitresPerChannel = (hQC->bitResTotMax / init->channelMapping->nChannelsEff); /* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir */ - hQC->bitDistributionMode = (bitresPerChannel>100) ? 0 : (bitresPerChannel>0) ? 1 : 2; + hQC->bitDistributionMode = (bitresPerChannel>BITRES_MIN_LD) ? 0 : (bitresPerChannel>0) ? 1 : 2; } else { hQC->bitDistributionMode = 0; /* full bitreservoir */ @@ -399,25 +397,22 @@ AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC, (init->averageBits/init->nSubFrames) - hQC->globHdrBits, hQC->maxBitsPerFrame/init->channelMapping->nChannelsEff); - switch(hQC->bitrateMode){ - case QCDATA_BR_MODE_CBR: - case QCDATA_BR_MODE_VBR_1: - case QCDATA_BR_MODE_VBR_2: - case QCDATA_BR_MODE_VBR_3: - case QCDATA_BR_MODE_VBR_4: - case QCDATA_BR_MODE_VBR_5: - case QCDATA_BR_MODE_SFR: - case QCDATA_BR_MODE_FF: - if((int)hQC->bitrateMode < (int)(sizeof(tableVbrQualFactor)/sizeof(TAB_VBR_QUAL_FACTOR))){ - hQC->vbrQualFactor = (FIXP_DBL)tableVbrQualFactor[hQC->bitrateMode].vbrQualFactor; - } else { - hQC->vbrQualFactor = FL2FXCONST_DBL(0.f); /* default setting */ - } - break; - case QCDATA_BR_MODE_INVALID: - default: - hQC->vbrQualFactor = FL2FXCONST_DBL(0.f); + hQC->vbrQualFactor = FL2FXCONST_DBL(0.f); + for (i=0; i<(int)(sizeof(tableVbrQualFactor)/sizeof(TAB_VBR_QUAL_FACTOR)); i++) { + if (hQC->bitrateMode==tableVbrQualFactor[i].bitrateMode) { + hQC->vbrQualFactor = (FIXP_DBL)tableVbrQualFactor[i].vbrQualFactor; break; + } + } + + if (init->channelMapping->nChannelsEff == 1 && + (init->bitrate / init->channelMapping->nChannelsEff) < 32000 && + init->advancedBitsToPe != 0 + ) + { + hQC->dZoneQuantEnable = 1; + } else { + hQC->dZoneQuantEnable = 0; } FDKaacEnc_AdjThrInit( @@ -429,7 +424,8 @@ AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC, init->channelMapping->nChannelsEff, init->sampleRate, /* output sample rate */ init->advancedBitsToPe, /* if set, calc bits2PE factor depending on samplerate */ - hQC->vbrQualFactor + hQC->vbrQualFactor, + hQC->dZoneQuantEnable ); return AAC_ENC_OK; @@ -892,6 +888,7 @@ AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC, qcOut[c], psyOut[c]->psyOutElement, isConstantBitrateMode(hQC->bitrateMode), + hQC->hAdjThr->maxIter2ndGuess, cm); } /* -end- sub frame counter */ @@ -919,6 +916,7 @@ AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC, FDKaacEnc_EstimateScaleFactors(psyOut[c]->psyOutElement[i]->psyOutChannel, qcElement[c][i]->qcOutChannel, hQC->invQuant, + hQC->dZoneQuantEnable, cm->elInfo[i].nChannelsInEl); @@ -1013,7 +1011,8 @@ AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC, qcOutCh->mdctSpectrum, qcOutCh->globalGain, qcOutCh->scf, - qcOutCh->quantSpec) ; + qcOutCh->quantSpec, + hQC->dZoneQuantEnable); /*-------------------------------------------- */ if (FDKaacEnc_calcMaxValueInSfb(psyOutCh->sfbCnt, @@ -1263,6 +1262,8 @@ AAC_ENCODER_ERROR FDKaacEnc_updateFillBits(CHANNEL_MAPPING* cm, case QCDATA_BR_MODE_VBR_4: case QCDATA_BR_MODE_VBR_5: qcOut[0]->totFillBits = (qcOut[0]->grantedDynBits - qcOut[0]->usedDynBits)&7; /* precalculate alignment bits */ + qcOut[0]->totalBits = qcOut[0]->staticBits + qcOut[0]->usedDynBits + qcOut[0]->totFillBits + qcOut[0]->elementExtBits + qcOut[0]->globalExtBits; + qcOut[0]->totFillBits += ( fixMax(0, qcKernel->minBitsPerFrame - qcOut[0]->totalBits) + 7) & ~7; break; case QCDATA_BR_MODE_CBR: @@ -1272,6 +1273,8 @@ AAC_ENCODER_ERROR FDKaacEnc_updateFillBits(CHANNEL_MAPPING* cm, /* processing fill-bits */ INT deltaBitRes = qcOut[0]->grantedDynBits - qcOut[0]->usedDynBits ; qcOut[0]->totFillBits = fixMax((deltaBitRes&7), (deltaBitRes - (fixMax(0,bitResSpace-7)&~7))); + qcOut[0]->totalBits = qcOut[0]->staticBits + qcOut[0]->usedDynBits + qcOut[0]->totFillBits + qcOut[0]->elementExtBits + qcOut[0]->globalExtBits; + qcOut[0]->totFillBits += ( fixMax(0, qcKernel->minBitsPerFrame - qcOut[0]->totalBits) + 7) & ~7; break; } /* switch (qcKernel->bitrateMode) */ diff --git a/libAACenc/src/quantize.cpp b/libAACenc/src/quantize.cpp index 5380e35..a74da0e 100644 --- a/libAACenc/src/quantize.cpp +++ b/libAACenc/src/quantize.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -104,13 +104,19 @@ amm-info@iis.fraunhofer.de static void FDKaacEnc_quantizeLines(INT gain, INT noOfLines, FIXP_DBL *mdctSpectrum, - SHORT *quaSpectrum) + SHORT *quaSpectrum, + INT dZoneQuantEnable) { int line; - FIXP_DBL k = FL2FXCONST_DBL(-0.0946f + 0.5f)>>16; + FIXP_DBL k = FL2FXCONST_DBL(0.0f); FIXP_QTD quantizer = FDKaacEnc_quantTableQ[(-gain)&3]; INT quantizershift = ((-gain)>>2)+1; + const INT kShift=16; + if (dZoneQuantEnable) + k = FL2FXCONST_DBL(0.23f)>>kShift; + else + k = FL2FXCONST_DBL(-0.0946f + 0.5f)>>kShift; for (line = 0; line < noOfLines; line++) { @@ -263,7 +269,8 @@ void FDKaacEnc_QuantizeSpectrum(INT sfbCnt, FIXP_DBL *mdctSpectrum, INT globalGain, INT *scalefactors, - SHORT *quantizedSpectrum) + SHORT *quantizedSpectrum, + INT dZoneQuantEnable) { INT sfbOffs,sfb; @@ -280,7 +287,8 @@ void FDKaacEnc_QuantizeSpectrum(INT sfbCnt, FDKaacEnc_quantizeLines(globalGain - scalefactor, /* QSS */ sfbOffset[sfbOffs+sfb+1] - sfbOffset[sfbOffs+sfb], mdctSpectrum + sfbOffset[sfbOffs+sfb], - quantizedSpectrum + sfbOffset[sfbOffs+sfb]); + quantizedSpectrum + sfbOffset[sfbOffs+sfb], + dZoneQuantEnable); } } @@ -296,7 +304,8 @@ void FDKaacEnc_QuantizeSpectrum(INT sfbCnt, FIXP_DBL FDKaacEnc_calcSfbDist(FIXP_DBL *mdctSpectrum, SHORT *quantSpectrum, INT noOfLines, - INT gain + INT gain, + INT dZoneQuantEnable ) { INT i,scale; @@ -311,7 +320,8 @@ FIXP_DBL FDKaacEnc_calcSfbDist(FIXP_DBL *mdctSpectrum, FDKaacEnc_quantizeLines(gain, 1, &mdctSpectrum[i], - &quantSpectrum[i]); + &quantSpectrum[i], + dZoneQuantEnable); if (fAbs(quantSpectrum[i])>MAX_QUANT) { return FL2FXCONST_DBL(0.0f); diff --git a/libAACenc/src/quantize.h b/libAACenc/src/quantize.h index 975b98e..16d3d4e 100644 --- a/libAACenc/src/quantize.h +++ b/libAACenc/src/quantize.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -102,12 +102,14 @@ void FDKaacEnc_QuantizeSpectrum(INT sfbCnt, INT sfbPerGroup, INT *sfbOffset, FIXP_DBL *mdctSpectrum, INT globalGain, INT *scalefactors, - SHORT *quantizedSpectrum); + SHORT *quantizedSpectrum, + INT dZoneQuantEnable); FIXP_DBL FDKaacEnc_calcSfbDist(FIXP_DBL *mdctSpectrum, SHORT *quantSpectrum, INT noOfLines, - INT gain); + INT gain, + INT dZoneQuantEnable); void FDKaacEnc_calcSfbQuantEnergyAndDist(FIXP_DBL *mdctSpectrum, SHORT *quantSpectrum, diff --git a/libAACenc/src/sf_estim.cpp b/libAACenc/src/sf_estim.cpp index 72b75a6..1cb243b 100644 --- a/libAACenc/src/sf_estim.cpp +++ b/libAACenc/src/sf_estim.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -363,7 +363,8 @@ static INT FDKaacEnc_improveScf(FIXP_DBL *spec, INT scf, INT minScf, FIXP_DBL *distLdData, - INT *minScfCalculated + INT *minScfCalculated, + INT dZoneQuantEnable ) { FIXP_DBL sfbDistLdData; @@ -375,7 +376,8 @@ static INT FDKaacEnc_improveScf(FIXP_DBL *spec, sfbDistLdData = FDKaacEnc_calcSfbDist(spec, quantSpec, sfbWidth, - scf); + scf, + dZoneQuantEnable); *minScfCalculated = scf; /* nmr > 1.25 -> try to improve nmr */ if (sfbDistLdData > (threshLdData-distFactorLdData)) { @@ -390,7 +392,8 @@ static INT FDKaacEnc_improveScf(FIXP_DBL *spec, sfbDistLdData = FDKaacEnc_calcSfbDist(spec, quantSpecTmp, sfbWidth, - scf); + scf, + dZoneQuantEnable); if (sfbDistLdData < sfbDistBestLdData) { scfBest = scf; @@ -408,7 +411,8 @@ static INT FDKaacEnc_improveScf(FIXP_DBL *spec, sfbDistLdData = FDKaacEnc_calcSfbDist(spec, quantSpecTmp, sfbWidth, - scf); + scf, + dZoneQuantEnable); if (sfbDistLdData < sfbDistBestLdData) { scfBest = scf; @@ -429,7 +433,8 @@ static INT FDKaacEnc_improveScf(FIXP_DBL *spec, sfbDistLdData = FDKaacEnc_calcSfbDist(spec, quantSpecTmp, sfbWidth, - scf); + scf, + dZoneQuantEnable); if (sfbDistLdData < sfbDistAllowedLdData) { *minScfCalculated = scfBest+1; @@ -454,6 +459,7 @@ static void FDKaacEnc_assimilateSingleScf(PSY_OUT_CHANNEL *psyOutChan, QC_OUT_CHANNEL *qcOutChannel, SHORT *quantSpec, SHORT *quantSpecTmp, + INT dZoneQuantEnable, INT *scf, INT *minScf, FIXP_DBL *sfbDist, @@ -570,7 +576,8 @@ static void FDKaacEnc_assimilateSingleScf(PSY_OUT_CHANNEL *psyOutChan, sfbDistNew = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs, quantSpecTmp+sfbOffs, sfbWidth, - scfAct); + scfAct, + dZoneQuantEnable); if (sfbDistNew < sfbDist[sfbAct]) { /* success, replace scf by new one */ @@ -629,6 +636,7 @@ static void FDKaacEnc_assimilateMultipleScf(PSY_OUT_CHANNEL *psyOutChan, QC_OUT_CHANNEL *qcOutChannel, SHORT *quantSpec, SHORT *quantSpecTmp, + INT dZoneQuantEnable, INT *scf, INT *minScf, FIXP_DBL *sfbDist, @@ -724,7 +732,8 @@ static void FDKaacEnc_assimilateMultipleScf(PSY_OUT_CHANNEL *psyOutChan, sfbDistNew[sfb] = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs, quantSpecTmp+sfbOffs, sfbWidth, - scfAct); + scfAct, + dZoneQuantEnable); if (sfbDistNew[sfb] >qcOutChannel->sfbThresholdLdData[sfb]) { /* no improvement, skip further dist. calculations */ @@ -768,6 +777,7 @@ static void FDKaacEnc_FDKaacEnc_assimilateMultipleScf2(PSY_OUT_CHANNEL *psyOutCh QC_OUT_CHANNEL *qcOutChannel, SHORT *quantSpec, SHORT *quantSpecTmp, + INT dZoneQuantEnable, INT *scf, INT *minScf, FIXP_DBL *sfbDist, @@ -883,7 +893,8 @@ static void FDKaacEnc_FDKaacEnc_assimilateMultipleScf2(PSY_OUT_CHANNEL *psyOutCh sfbDistNew[sfb] = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs[sfb], quantSpecTmp+sfbOffs[sfb], sfbOffs[sfb+1]-sfbOffs[sfb], - scfNew); + scfNew, + dZoneQuantEnable); if (sfbDistNew[sfb] > sfbDistMax[sfb]) { /* no improvement, skip further dist. calculations */ @@ -963,7 +974,8 @@ static void FDKaacEnc_FDKaacEnc_assimilateMultipleScf2(PSY_OUT_CHANNEL *psyOutCh sfbDistNew[sfb] = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs[sfb], quantSpecTmp+sfbOffs[sfb], sfbOffs[sfb+1]-sfbOffs[sfb], - scfNew); + scfNew, + dZoneQuantEnable); if (sfbDistNew[sfb] > qcOutChannel->sfbThresholdLdData[sfb]) { /* no improvement, skip further dist. calculations */ @@ -1058,7 +1070,8 @@ FDKaacEnc_FDKaacEnc_EstimateScaleFactorsChannel(QC_OUT_CHANNEL *qcOutChannel, INT *RESTRICT globalGain, FIXP_DBL *RESTRICT sfbFormFactorLdData ,const INT invQuant, - SHORT *RESTRICT quantSpec + SHORT *RESTRICT quantSpec, + const INT dZoneQuantEnable ) { INT i, j, sfb, sfbOffs; @@ -1160,7 +1173,8 @@ FDKaacEnc_FDKaacEnc_EstimateScaleFactorsChannel(QC_OUT_CHANNEL *qcOutChannel, quantSpecTmp+psyOutChannel->sfbOffsets[sfbOffs+sfb], psyOutChannel->sfbOffsets[sfbOffs+sfb+1]-psyOutChannel->sfbOffsets[sfbOffs+sfb], threshLdData, scfInt, minSfMaxQuant[sfbOffs+sfb], - &sfbDistLdData[sfbOffs+sfb], &minScfCalculated[sfbOffs+sfb] + &sfbDistLdData[sfbOffs+sfb], &minScfCalculated[sfbOffs+sfb], + dZoneQuantEnable ); } scf[sfbOffs+sfb] = scfInt; @@ -1187,20 +1201,32 @@ FDKaacEnc_FDKaacEnc_EstimateScaleFactorsChannel(QC_OUT_CHANNEL *qcOutChannel, sfbNRelevantLines); - FDKaacEnc_assimilateSingleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, scf, + FDKaacEnc_assimilateSingleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, + dZoneQuantEnable, + scf, minSfMaxQuant, sfbDistLdData, sfbConstPePart, sfbFormFactorLdData, sfbNRelevantLines, minScfCalculated, 1); + if(invQuant > 1) { + FDKaacEnc_assimilateMultipleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, + dZoneQuantEnable, + scf, + minSfMaxQuant, sfbDistLdData, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines); - FDKaacEnc_assimilateMultipleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, scf, - minSfMaxQuant, sfbDistLdData, sfbConstPePart, - sfbFormFactorLdData, sfbNRelevantLines); - + FDKaacEnc_assimilateMultipleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, + dZoneQuantEnable, + scf, + minSfMaxQuant, sfbDistLdData, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines); - FDKaacEnc_FDKaacEnc_assimilateMultipleScf2(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, scf, - minSfMaxQuant, sfbDistLdData, sfbConstPePart, - sfbFormFactorLdData, sfbNRelevantLines); + FDKaacEnc_FDKaacEnc_assimilateMultipleScf2(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, + dZoneQuantEnable, + scf, + minSfMaxQuant, sfbDistLdData, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines); + } } @@ -1223,7 +1249,8 @@ FDKaacEnc_FDKaacEnc_EstimateScaleFactorsChannel(QC_OUT_CHANNEL *qcOutChannel, FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+psyOutChannel->sfbOffsets[sfbOffs+sfb], quantSpec+psyOutChannel->sfbOffsets[sfbOffs+sfb], psyOutChannel->sfbOffsets[sfbOffs+sfb+1]-psyOutChannel->sfbOffsets[sfbOffs+sfb], - scf[sfbOffs+sfb] + scf[sfbOffs+sfb], + dZoneQuantEnable ); } } @@ -1281,6 +1308,7 @@ void FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[], QC_OUT_CHANNEL* qcOutChannel[], const int invQuant, + const INT dZoneQuantEnable, const int nChannels) { int ch; @@ -1293,7 +1321,8 @@ FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[], &qcOutChannel[ch]->globalGain, qcOutChannel[ch]->sfbFormFactorLdData ,invQuant, - qcOutChannel[ch]->quantSpec + qcOutChannel[ch]->quantSpec, + dZoneQuantEnable ); } diff --git a/libAACenc/src/sf_estim.h b/libAACenc/src/sf_estim.h index b5ac000..ef8d366 100644 --- a/libAACenc/src/sf_estim.h +++ b/libAACenc/src/sf_estim.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -110,6 +110,7 @@ void FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[], QC_OUT_CHANNEL* qcOutChannel[], const int invQuant, + const INT dZoneQuantEnable, const int nChannels); diff --git a/libAACenc/src/tns_func.h b/libAACenc/src/tns_func.h index 6ee0edb..5e5265d 100644 --- a/libAACenc/src/tns_func.h +++ b/libAACenc/src/tns_func.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -100,6 +100,7 @@ AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitrate, INT channels, INT blocktype, INT granuleLength, + INT isLowDelay, INT ldSbrPresent, TNS_CONFIG *tnsConfig, PSY_CONFIGURATION *psyConfig, diff --git a/libFDK/include/fixpoint_math.h b/libFDK/include/fixpoint_math.h index df141d3..0d50f0a 100644 --- a/libFDK/include/fixpoint_math.h +++ b/libFDK/include/fixpoint_math.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -94,6 +94,35 @@ amm-info@iis.fraunhofer.de #include "common_fix.h" +#if !defined(FUNCTION_fIsLessThan) +/** + * \brief Compares two fixpoint values incl. scaling. + * \param a_m mantissa of the first input value. + * \param a_e exponent of the first input value. + * \param b_m mantissa of the second input value. + * \param b_e exponent of the second input value. + * \return non-zero if (a_m*2^a_e) < (b_m*2^b_e), 0 otherwise + */ +FDK_INLINE INT fIsLessThan(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e) +{ + if (a_e > b_e) { + return (b_m >> fMin(a_e-b_e, DFRACT_BITS-1) > a_m); + } else { + return (a_m >> fMin(b_e-a_e, DFRACT_BITS-1) < b_m); + } +} + +FDK_INLINE INT fIsLessThan(FIXP_SGL a_m, INT a_e, FIXP_SGL b_m, INT b_e) +{ + if (a_e > b_e) { + return (b_m >> fMin(a_e-b_e, FRACT_BITS-1) > a_m); + } else { + return (a_m >> fMin(b_e-a_e, FRACT_BITS-1) < b_m); + } +} +#endif + + #define LD_DATA_SCALING (64.0f) #define LD_DATA_SHIFT 6 /* pow(2, LD_DATA_SHIFT) = LD_DATA_SCALING */ @@ -438,11 +467,11 @@ inline FIXP_DBL fAddSaturate(const FIXP_DBL a, const FIXP_DBL b) /***************************************************************************** - array for 1/n, n=1..50 + array for 1/n, n=1..80 ****************************************************************************/ - extern const FIXP_DBL invCount[50]; + extern const FIXP_DBL invCount[80]; LNK_SECTION_INITCODE inline void InitInvInt(void) {} @@ -450,14 +479,14 @@ inline FIXP_DBL fAddSaturate(const FIXP_DBL a, const FIXP_DBL b) /** * \brief Calculate the value of 1/i where i is a integer value. It supports - * input values from 1 upto 50. + * input values from 1 upto 80. * \param intValue Integer input value. * \param FIXP_DBL representation of 1/intValue */ inline FIXP_DBL GetInvInt(int intValue) { - FDK_ASSERT((intValue > 0) && (intValue < 50)); - FDK_ASSERT(intValue<50); + FDK_ASSERT((intValue > 0) && (intValue < 80)); + FDK_ASSERT(intValue<80); return invCount[intValue]; } diff --git a/libFDK/src/FDK_core.cpp b/libFDK/src/FDK_core.cpp index a706eb0..1d8ac7b 100644 --- a/libFDK/src/FDK_core.cpp +++ b/libFDK/src/FDK_core.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -93,7 +93,7 @@ amm-info@iis.fraunhofer.de /* FDK tools library info */ #define FDK_TOOLS_LIB_VL0 2 #define FDK_TOOLS_LIB_VL1 3 -#define FDK_TOOLS_LIB_VL2 2 +#define FDK_TOOLS_LIB_VL2 6 #define FDK_TOOLS_LIB_TITLE "FDK Tools" #ifdef __ANDROID__ #define FDK_TOOLS_LIB_BUILD_DATE "" diff --git a/libFDK/src/FDK_tools_rom.cpp b/libFDK/src/FDK_tools_rom.cpp index c6e517e..29e37f2 100644 --- a/libFDK/src/FDK_tools_rom.cpp +++ b/libFDK/src/FDK_tools_rom.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -1902,7 +1902,7 @@ const USHORT sqrt_tab[49]={ 0xb504}; LNK_SECTION_CONSTDATA_L1 -const FIXP_DBL invCount[50]= /* This could be 16-bit wide */ +const FIXP_DBL invCount[80]= /* This could be 16-bit wide */ { 0x00000000, 0x7fffffff, 0x40000000, 0x2aaaaaab, 0x20000000, 0x1999999a, 0x15555555, 0x12492492, 0x10000000, 0x0e38e38e, @@ -1913,7 +1913,13 @@ const FIXP_DBL invCount[50]= /* This could be 16-bit wide */ 0x04444444, 0x04210842, 0x04000000, 0x03e0f83e, 0x03c3c3c4, 0x03a83a84, 0x038e38e4, 0x03759f23, 0x035e50d8, 0x03483483, 0x03333333, 0x031f3832, 0x030c30c3, 0x02fa0be8, 0x02e8ba2f, - 0x02d82d83, 0x02c8590b, 0x02b93105, 0x02aaaaab, 0x029cbc15 + 0x02d82d83, 0x02c8590b, 0x02b93105, 0x02aaaaab, 0x029cbc15, + 0x028f5c29, 0x02828283, 0x02762762, 0x026a439f, 0x025ed098, + 0x0253c825, 0x02492492, 0x023ee090, 0x0234f72c, 0x022b63cc, + 0x02222222, 0x02192e2a, 0x02108421, 0x02082082, 0x02000000, + 0x01f81f82, 0x01f07c1f, 0x01e9131b, 0x01e1e1e2, 0x01dae607, + 0x01d41d42, 0x01cd8569, 0x01c71c72, 0x01c0e070, 0x01bacf91, + 0x01b4e81b, 0x01af286c, 0x01a98ef6, 0x01a41a42, 0x019ec8e9 }; @@ -2033,19 +2039,6 @@ static const element_list_t node_aac_cpe = { { &node_aac_cpe0, &node_aac_cpe1 } }; -#define el_mpegsres_sce &el_aac_sce[2] - -static const element_list_t node_mpegsres_sce = { - el_mpegsres_sce, - { NULL, NULL } -}; - -static const element_list_t node_mpegsres_cpe = { - el_aac_cpe1, - { NULL, NULL } -}; - - /* * AOT C- {17,23} * epConfig = 0,1 @@ -2243,7 +2236,7 @@ static const rbd_id_t el_aac_cpe1_epc1[] = { ics_info, ms, ltp_data_present, - ltp_data, + /* ltp_data, */ global_gain, section_data, scale_factor_data, @@ -2254,7 +2247,7 @@ static const rbd_id_t el_aac_cpe1_epc1[] = { next_channel, ltp_data_present, - ltp_data, + /* ltp_data, */ global_gain, section_data, scale_factor_data, @@ -2297,7 +2290,178 @@ static const element_list_t node_aac_cpe_epc1 = { { &node_aac_cpe0_epc1, &node_aac_cpe1_epc1 } }; +/* + * AOT = 20 + * epConfig = 0 + */ +static const rbd_id_t el_scal_sce_epc0[] = { + ics_info, /* ESC 1 */ + tns_data_present, + ltp_data_present, + /* ltp_data, */ + global_gain, + section_data, + scale_factor_data, + esc1_hcr, + esc2_rvlc, /* ESC 2 */ + tns_data, /* ESC 3 */ + spectral_data, /* ESC 4 */ + end_of_sequence +}; + +static const struct element_list node_scal_sce_epc0 = { + el_scal_sce_epc0, + { NULL, NULL } +}; + +static const rbd_id_t el_scal_cpe_epc0[] = { + ics_info, /* ESC 0 */ + ms, + tns_data_present, /* ESC 1 (ch 0) */ + ltp_data_present, + /* ltp_data, */ + global_gain, + section_data, + scale_factor_data, + esc1_hcr, + esc2_rvlc, /* ESC 2 (ch 0) */ + tns_data, /* ESC 3 (ch 0) */ + spectral_data, /* ESC 4 (ch 0) */ + next_channel, + tns_data_present, /* ESC 1 (ch 1) */ + ltp_data_present, + global_gain, + section_data, + scale_factor_data, + esc1_hcr, + esc2_rvlc, /* ESC 2 (ch 1) */ + tns_data, /* ESC 3 (ch 1) */ + spectral_data, /* ESC 4 (ch 1) */ + end_of_sequence +}; + +static const struct element_list node_scal_cpe_epc0 = { + el_scal_cpe_epc0, + { NULL, NULL } +}; + +/* + * AOT = 20 + * epConfig = 1 + */ +static const rbd_id_t el_scal_sce_epc1[] = { + ics_info, + tns_data_present, + ltp_data_present, + /* ltp_data, */ + global_gain, + section_data, + scale_factor_data, + esc1_hcr, + tns_data, + spectral_data, + end_of_sequence +}; + +static const struct element_list node_scal_sce_epc1 = { + el_scal_sce_epc1, + { NULL, NULL } +}; + +static const rbd_id_t el_scal_cpe_epc1[] = { + ics_info, + ms, + tns_data_present, + ltp_data_present, + /* ltp_data, */ + global_gain, + section_data, + scale_factor_data, + esc1_hcr, + next_channel, + tns_data_present, + ltp_data_present, + /* ltp_data, */ + global_gain, + section_data, + scale_factor_data, + esc1_hcr, + next_channel, + tns_data, + next_channel, + tns_data, + next_channel, + spectral_data, + next_channel, + spectral_data, + end_of_sequence +}; + +static const struct element_list node_scal_cpe_epc1 = { + el_scal_cpe_epc1, + { NULL, NULL } +}; + +/* + * Pseudo AOT for DRM/DRM+ (similar to AOT 20) + * Derived from epConfig = 1 + */ +static const rbd_id_t el_drm_sce[] = { + drmcrc_start_reg, + ics_info, + tns_data_present, + ltp_data_present, + /* ltp_data, */ + global_gain, + section_data, + scale_factor_data, + esc1_hcr, + tns_data, + drmcrc_end_reg, + spectral_data, + end_of_sequence +}; + +static const struct element_list node_drm_sce = { + el_drm_sce, + { NULL, NULL } +}; + +static const rbd_id_t el_drm_cpe[] = { + drmcrc_start_reg, + ics_info, + ms, + tns_data_present, + ltp_data_present, + /* ltp_data, */ + global_gain, + section_data, + scale_factor_data, + esc1_hcr, + next_channel, + tns_data_present, + ltp_data_present, + /* ltp_data, */ + global_gain, + section_data, + scale_factor_data, + esc1_hcr, + next_channel, + tns_data, + next_channel, + tns_data, + drmcrc_end_reg, + next_channel, + spectral_data, + next_channel, + spectral_data, + end_of_sequence +}; +static const struct element_list node_drm_cpe = { + el_drm_cpe, + { NULL, NULL } +}; /* * AOT = 39 @@ -2412,6 +2576,19 @@ const element_list_t * getBitstreamElementList(AUDIO_OBJECT_TYPE aot, SCHAR epCo return &node_aac_cpe_epc1; } break; + case AOT_ER_AAC_SCAL: + if (nChannels == 1) { + if (epConfig <= 0) + return &node_scal_sce_epc0; + else + return &node_scal_sce_epc1; + } else { + if (epConfig <= 0) + return &node_scal_cpe_epc0; + else + return &node_scal_cpe_epc1; + } + break; case AOT_ER_AAC_ELD: if (nChannels == 1) { if (epConfig <= 0) @@ -2424,11 +2601,14 @@ const element_list_t * getBitstreamElementList(AUDIO_OBJECT_TYPE aot, SCHAR epCo else return &node_eld_cpe_epc1; } - case AOT_MPEGS_RESIDUALS: + case AOT_DRM_AAC: + case AOT_DRM_SBR: + case AOT_DRM_MPEG_PS: + FDK_ASSERT(epConfig == 1); if (nChannels == 1) { - return &node_mpegsres_sce; + return &node_drm_sce; } else { - return &node_mpegsres_cpe; + return &node_drm_cpe; } break; default: diff --git a/libFDK/src/arm/qmf_arm.cpp b/libFDK/src/arm/qmf_arm.cpp index 0c0ce80..fbeebfb 100644 --- a/libFDK/src/arm/qmf_arm.cpp +++ b/libFDK/src/arm/qmf_arm.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -482,42 +482,42 @@ static void qmfSynPrototypeFirSlot1_filter(FIXP_QMF *RESTRICT realSlot, B = p_flt[4]; /* Bottom=[8] Top=[9] */ A = p_fltm[3]; /* Bottom=[316] Top=[317] */ sta0 = sta[0]; /* save state[0] */ - *sta++ = SMLAWT( sta[1], imag, B ); /* index=9...........319 */ - *sta++ = SMLAWB( sta[1], real, A ); /* index=316...........6 */ - *sta++ = SMLAWB( sta[1], imag, B ); /* index=8,18, ...318 */ + sta[0] = SMLAWT( sta[1], imag, B ); sta++; /* index=9...........319 */ + sta[0] = SMLAWB( sta[1], real, A ); sta++; /* index=316...........6 */ + sta[0] = SMLAWB( sta[1], imag, B ); sta++; /* index=8,18, ...318 */ B = p_flt[3]; /* Bottom=[6] Top=[7] */ - *sta++ = SMLAWT( sta[1], real, A ); /* index=317...........7 */ + sta[0] = SMLAWT( sta[1], real, A ); sta++; /* index=317...........7 */ A = p_fltm[4]; /* Bottom=[318] Top=[319] */ - *sta++ = SMLAWT( sta[1], imag, B ); /* index=7...........317 */ - *sta++ = SMLAWB( sta[1], real, A ); /* index=318...........8 */ - *sta++ = SMLAWB( sta[1], imag, B ); /* index=6...........316 */ + sta[0] = SMLAWT( sta[1], imag, B ); sta++; /* index=7...........317 */ + sta[0] = SMLAWB( sta[1], real, A ); sta++; /* index=318...........8 */ + sta[0] = SMLAWB( sta[1], imag, B ); sta++; /* index=6...........316 */ B = p_flt[2]; /* Bottom=[X] Top=[5] */ - *sta++ = SMLAWT( sta[1], real, A ); /* index=9...........319 */ + sta[0] = SMLAWT( sta[1], real, A ); sta++; /* index=9...........319 */ A = p_fltm[2]; /* Bottom=[X] Top=[315] */ - *sta++ = SMULWT( imag, B ); /* index=5,15, ... 315 */ + sta[0] = SMULWT( imag, B ); sta++; /* index=5,15, ... 315 */ result = SMLAWT( sta0, real, A ); /* index=315...........5 */ - *pMyTimeOut++ = result; + pMyTimeOut[0] = result; pMyTimeOut++; real = *--realSlot; imag = *--imagSlot; A = p_fltm[0]; /* Bottom=[310] Top=[311] */ B = p_flt[7]; /* Bottom=[14] Top=[15] */ result = SMLAWB( sta[0], real, A ); /* index=310...........0 */ - *sta++ = SMLAWB( sta[1], imag, B ); /* index=14..........324 */ - *pMyTimeOut++ = result; + sta[0] = SMLAWB( sta[1], imag, B ); sta++; /* index=14..........324 */ + pMyTimeOut[0] = result; pMyTimeOut++; B = p_flt[6]; /* Bottom=[12] Top=[13] */ - *sta++ = SMLAWT( sta[1], real, A ); /* index=311...........1 */ + sta[0] = SMLAWT( sta[1], real, A ); sta++; /* index=311...........1 */ A = p_fltm[1]; /* Bottom=[312] Top=[313] */ - *sta++ = SMLAWT( sta[1], imag, B ); /* index=13..........323 */ - *sta++ = SMLAWB( sta[1], real, A ); /* index=312...........2 */ - *sta++ = SMLAWB( sta[1], imag, B ); /* index=12..........322 */ - *sta++ = SMLAWT( sta[1], real, A ); /* index=313...........3 */ + sta[0] = SMLAWT( sta[1], imag, B ); sta++; /* index=13..........323 */ + sta[0] = SMLAWB( sta[1], real, A ); sta++; /* index=312...........2 */ + sta[0] = SMLAWB( sta[1], imag, B ); sta++; /* index=12..........322 */ + sta[0] = SMLAWT( sta[1], real, A ); sta++; /* index=313...........3 */ A = p_fltm[2]; /* Bottom=[314] Top=[315] */ B = p_flt[5]; /* Bottom=[10] Top=[11] */ - *sta++ = SMLAWT( sta[1], imag, B ); /* index=11..........321 */ - *sta++ = SMLAWB( sta[1], real, A ); /* index=314...........4 */ - *sta++ = SMULWB( imag, B ); /* index=10..........320 */ + sta[0] = SMLAWT( sta[1], imag, B ); sta++; /* index=11..........321 */ + sta[0] = SMLAWB( sta[1], real, A ); sta++; /* index=314...........4 */ + sta[0] = SMULWB( imag, B ); sta++; /* index=10..........320 */ p_flt += 5; @@ -566,21 +566,21 @@ INT qmfSynPrototypeFirSlot2( A = p_fltm[0]; /* Bottom=[310] Top=[311] */ B = p_flt[7]; /* Bottom=[14] Top=[15] */ result = SMLAWB( sta[0], real, A ); /* index=310...........0 */ - *sta++ = SMLAWB( sta[1], imag, B ); /* index=14..........324 */ + sta[0] = SMLAWB( sta[1], imag, B ); sta++; /* index=14..........324 */ B = p_flt[6]; /* Bottom=[12] Top=[13] */ - *sta++ = SMLAWT( sta[1], real, A ); /* index=311...........1 */ + sta[0] = SMLAWT( sta[1], real, A ); sta++; /* index=311...........1 */ A = p_fltm[1]; /* Bottom=[312] Top=[313] */ - *sta++ = SMLAWT( sta[1], imag, B ); /* index=13..........323 */ - *sta++ = SMLAWB( sta[1], real, A ); /* index=312...........2 */ - *sta++ = SMLAWB( sta[1], imag, B ); /* index=12..........322 */ - *sta++ = SMLAWT( sta[1], real, A ); /* index=313...........3 */ + sta[0] = SMLAWT( sta[1], imag, B ); sta++; /* index=13..........323 */ + sta[0] = SMLAWB( sta[1], real, A ); sta++; /* index=312...........2 */ + sta[0] = SMLAWB( sta[1], imag, B ); sta++; /* index=12..........322 */ + sta[0] = SMLAWT( sta[1], real, A ); sta++; /* index=313...........3 */ A = p_fltm[2]; /* Bottom=[314] Top=[315] */ B = p_flt[5]; /* Bottom=[10] Top=[11] */ - *sta++ = SMLAWT( sta[1], imag, B ); /* index=11..........321 */ - *sta++ = SMLAWB( sta[1], real, A ); /* index=314...........4 */ - *sta++ = SMULWB( imag, B ); /* index=10..........320 */ + sta[0] = SMLAWT( sta[1], imag, B ); sta++; /* index=11..........321 */ + sta[0] = SMLAWB( sta[1], real, A ); sta++; /* index=314...........4 */ + sta[0] = SMULWB( imag, B ); sta++; /* index=10..........320 */ - *pMyTimeOut++ = result; + pMyTimeOut[0] = result; pMyTimeOut++; p_fltm -= 5; p_flt += 5; @@ -610,8 +610,8 @@ INT qmfSynPrototypeFirSlot2( { FIXP_DBL result1, result2; - result1 = *pMyTimeOut++; - result2 = *pMyTimeOut++; + result1 = pMyTimeOut[0]; pMyTimeOut++; + result2 = pMyTimeOut[0]; pMyTimeOut++; result1 = fMult(result1,gain); timeOut -= stride; @@ -635,8 +635,8 @@ INT qmfSynPrototypeFirSlot2( timeOut[0] = result2 << scale; #endif - result1 = *pMyTimeOut++; - result2 = *pMyTimeOut++; + result1 = pMyTimeOut[0]; pMyTimeOut++; + result2 = pMyTimeOut[0]; pMyTimeOut++; result1 = fMult(result1,gain); timeOut -= stride; @@ -666,8 +666,8 @@ INT qmfSynPrototypeFirSlot2( for (no_channels>>=2; no_channels--;) { FIXP_DBL result1, result2; - result1 = *pMyTimeOut++; - result2 = *pMyTimeOut++; + result1 = pMyTimeOut[0]; pMyTimeOut++; + result2 = pMyTimeOut[0]; pMyTimeOut++; timeOut -= stride; if (result1 < 0) result1 += add_neg; if (result1 < max_neg) result1 = max_neg; @@ -688,8 +688,8 @@ INT qmfSynPrototypeFirSlot2( timeOut[0] = result2 << scale; #endif - result1 = *pMyTimeOut++; - result2 = *pMyTimeOut++; + result1 = pMyTimeOut[0]; pMyTimeOut++; + result2 = pMyTimeOut[0]; pMyTimeOut++; timeOut -= stride; if (result1 < 0) result1 += add_neg; if (result1 < max_neg) result1 = max_neg; diff --git a/libMpegTPDec/src/tpdec_asc.cpp b/libMpegTPDec/src/tpdec_asc.cpp index bae271e..96a1b35 100644 --- a/libMpegTPDec/src/tpdec_asc.cpp +++ b/libMpegTPDec/src/tpdec_asc.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -1126,6 +1126,8 @@ TRANSPORTDEC_ERROR EldSpecificConfig_Parse( if ( 0 != ld_sbr_header(asc, hBs, cb) ) { return TRANSPORTDEC_PARSE_ERROR; } + } else { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; } } esc->m_useLdQmfTimeAlign = 0; @@ -1146,7 +1148,7 @@ TRANSPORTDEC_ERROR EldSpecificConfig_Parse( switch (eldExtType) { default: - for(cnt=0; cnt<len; cnt++) { + for(cnt=0; cnt<eldExtLen; cnt++) { FDKreadBits(hBs, 8 ); } break; @@ -1372,4 +1374,133 @@ TRANSPORTDEC_ERROR AudioSpecificConfig_Parse( return (ErrorStatus); } +TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse( + CSAudioSpecificConfig *self, + HANDLE_FDK_BITSTREAM bs + ) +{ + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + AudioSpecificConfig_Init(self); + + if ((INT)FDKgetValidBits(bs) < 20) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + else { + /* DRM - Audio information data entity - type 9 + - Short Id 2 bits + - Stream Id 2 bits + - audio coding 2 bits + - SBR flag 1 bit + - audio mode 2 bits + - audio sampling rate 3 bits + - text flag 1 bit + - enhancement flag 1 bit + - coder field 5 bits + - rfa 1 bit */ + + int audioCoding, audioMode, cSamplingFreq, coderField, sfIdx, sbrFlag; + + /* Read the SDC field */ + FDKreadBits(bs,4); /* Short and Stream Id */ + + audioCoding = FDKreadBits(bs, 2); + sbrFlag = FDKreadBits(bs, 1); + audioMode = FDKreadBits(bs, 2); + cSamplingFreq = FDKreadBits(bs, 3); /* audio sampling rate */ + + FDKreadBits(bs, 2); /* Text and enhancement flag */ + coderField = FDKreadBits(bs, 5); + FDKreadBits(bs, 1); /* rfa */ + + /* Evaluate configuration and fill the ASC */ + switch (cSamplingFreq) { + case 0: /* 8 kHz */ + sfIdx = 11; + break; + case 1: /* 12 kHz */ + sfIdx = 9; + break; + case 2: /* 16 kHz */ + sfIdx = 8; + break; + case 3: /* 24 kHz */ + sfIdx = 6; + break; + case 5: /* 48 kHz */ + sfIdx = 3; + break; + case 4: /* reserved */ + case 6: /* reserved */ + case 7: /* reserved */ + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + + self->m_samplingFrequencyIndex = sfIdx; + self->m_samplingFrequency = SamplingRateTable[sfIdx]; + + if ( sbrFlag ) { + UINT i; + int tmp = -1; + self->m_sbrPresentFlag = 1; + self->m_extensionAudioObjectType = AOT_SBR; + self->m_extensionSamplingFrequency = self->m_samplingFrequency << 1; + for (i=0; i<(sizeof(SamplingRateTable)/sizeof(SamplingRateTable[0])); i++){ + if (SamplingRateTable[i] == self->m_extensionSamplingFrequency){ + tmp = i; + break; + } + } + self->m_extensionSamplingFrequencyIndex = tmp; + } + + switch (audioCoding) { + case 0: /* AAC */ + self->m_aot = AOT_DRM_AAC ; /* Set pseudo AOT for Drm AAC */ + + switch (audioMode) { + case 1: /* parametric stereo */ + self->m_psPresentFlag = 1; + case 0: /* mono */ + self->m_channelConfiguration = 1; + break; + case 2: /* stereo */ + self->m_channelConfiguration = 2; + break; + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + self->m_vcb11Flag = 1; + self->m_hcrFlag = 1; + self->m_samplesPerFrame = 960; + self->m_epConfig = 1; + break; + case 1: /* CELP */ + self->m_aot = AOT_ER_CELP; + self->m_channelConfiguration = 1; + break; + case 2: /* HVXC */ + self->m_aot = AOT_ER_HVXC; + self->m_channelConfiguration = 1; + break; + case 3: /* reserved */ + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + self->m_aot = AOT_NONE; + break; + } + + if (self->m_psPresentFlag && !self->m_sbrPresentFlag) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + +bail: + return (ErrorStatus); +} diff --git a/libAACenc/src/aacenc_hcr.h b/libMpegTPDec/src/tpdec_drm.cpp index 934247a..df319e5 100644 --- a/libAACenc/src/aacenc_hcr.h +++ b/libMpegTPDec/src/tpdec_drm.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -81,16 +81,66 @@ www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ----------------------------------------------------------------------------------------------------------- */ -/*************************** MPEG AAC Audio Encoder ************************* +/***************************** MPEG-4 AAC Decoder ************************** - Initial author: R. Boehm - contents/description: huffman codeword reordering - based on source from aacErrRobTrans + Author(s): Christian Griebel + Description: DRM transport stuff ******************************************************************************/ -#ifndef _AACENC_HCR -#define _AACENC_HCR_H +#include "tpdec_drm.h" + + +#include "FDK_bitstream.h" + + + +void drmRead_CrcInit(HANDLE_DRM pDrm) /*!< pointer to drm crc info stucture */ +{ + FDK_ASSERT(pDrm != NULL); + + FDKcrcInit(&pDrm->crcInfo, 0x001d, 0xFFFF, 8); +} + +int drmRead_CrcStartReg( + HANDLE_DRM pDrm, /*!< pointer to drm stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ + ) +{ + FDK_ASSERT(pDrm != NULL); + + FDKcrcReset(&pDrm->crcInfo); + + pDrm->crcReadValue = FDKreadBits(hBs, 8); + + return ( FDKcrcStartReg(&pDrm->crcInfo, hBs, mBits) ); + +} + +void drmRead_CrcEndReg( + HANDLE_DRM pDrm, /*!< pointer to drm crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ + ) +{ + FDK_ASSERT(pDrm != NULL); + + FDKcrcEndReg(&pDrm->crcInfo, hBs, reg); +} + +TRANSPORTDEC_ERROR drmRead_CrcCheck( HANDLE_DRM pDrm ) +{ + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + USHORT crc; + + crc = FDKcrcGetCRC(&pDrm->crcInfo) ^ 0xFF; + if (crc != pDrm->crcReadValue) + { + return (TRANSPORTDEC_CRC_ERROR); + } + + return (ErrorStatus); +} -#endif /* ifndef _AACENC_HCR */ diff --git a/libAACenc/src/aacenc_hcr.cpp b/libMpegTPDec/src/tpdec_drm.h index 316623a..2161b4c 100644 --- a/libAACenc/src/aacenc_hcr.cpp +++ b/libMpegTPDec/src/tpdec_drm.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -81,13 +81,114 @@ www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ----------------------------------------------------------------------------------------------------------- */ -/*************************** MPEG AAC Audio Encoder ************************* +/***************************** MPEG-4 AAC Decoder ************************** - Initial author: R. Boehm - contents/description: huffman codeword reordering - based on source from aacErrRobTrans + Author(s): Josef Hoepfl + Description: DRM interface ******************************************************************************/ -#include "aacenc_hcr.h" - +#ifndef TPDEC_DRM_H +#define TPDEC_DRM_H + +#include "tpdec_lib.h" + + +#include "FDK_crc.h" + +typedef struct { + + FDK_CRCINFO crcInfo; /* CRC state info */ + USHORT crcReadValue; /* CRC value read from bitstream data */ + +} STRUCT_DRM; + +typedef STRUCT_DRM *HANDLE_DRM; + +/*! + \brief Initialize DRM CRC + + The function initialzes the crc buffer and the crc lookup table. + + \return none +*/ +void drmRead_CrcInit( HANDLE_DRM pDrm ); + +/** + * \brief Starts CRC region with a maximum number of bits + * If mBits is positive zero padding will be used for CRC calculation, if there + * are less than mBits bits available. + * If mBits is negative no zero padding is done. + * If mBits is zero the memory for the buffer is allocated dynamically, the + * number of bits is not limited. + * + * \param pDrm DRM data handle + * \param hBs bitstream handle, on which the CRC region referes to + * \param mBits max number of bits in crc region to be considered + * + * \return ID for the created region, -1 in case of an error + */ +int drmRead_CrcStartReg( + HANDLE_DRM pDrm, + HANDLE_FDK_BITSTREAM hBs, + int mBits + ); + +/** + * \brief Ends CRC region identified by reg + * + * \param pDrm DRM data handle + * \param hBs bitstream handle, on which the CRC region referes to + * \param reg CRC regions ID returned by drmRead_CrcStartReg() + * + * \return none + */ +void drmRead_CrcEndReg( + HANDLE_DRM pDrm, + HANDLE_FDK_BITSTREAM hBs, + int reg + ); + +/** + * \brief Check CRC + * + * Checks if the currently calculated CRC matches the CRC field read from the bitstream + * Deletes all CRC regions. + * + * \param pDrm DRM data handle + * + * \return Returns 0 if they are identical otherwise 1 + */ +TRANSPORTDEC_ERROR drmRead_CrcCheck( HANDLE_DRM pDrm ); + +/** + * \brief Check if we have a valid DRM frame at the current bitbuffer position + * + * This function assumes enough bits in buffer for the current frame. + * It reads out the header bits to prepare the bitbuffer for the decode loop. + * In case the header bits show an invalid bitstream/frame, the whole frame is skipped. + * + * \param pDrm DRM data handle which is filled with parsed DRM header data + * \param bs handle of bitstream from whom the DRM header is read + * + * \return error status + */ +TRANSPORTDEC_ERROR drmRead_DecodeHeader( + HANDLE_DRM pDrm, + HANDLE_FDK_BITSTREAM bs + ); + +/** + * \brief Parse a Drm specific SDC audio config from a given bitstream handle. + * + * \param pAsc A pointer to an allocated CSAudioSpecificConfig struct. + * \param hBs Bitstream handle. + * + * \return Total element count including all SCE, CPE and LFE. + */ +TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse( CSAudioSpecificConfig *pAsc, + HANDLE_FDK_BITSTREAM hBs ); + + + +#endif /* TPDEC_DRM_H */ diff --git a/libMpegTPDec/src/tpdec_lib.cpp b/libMpegTPDec/src/tpdec_lib.cpp index 445615d..24f755b 100644 --- a/libMpegTPDec/src/tpdec_lib.cpp +++ b/libMpegTPDec/src/tpdec_lib.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -102,6 +102,7 @@ amm-info@iis.fraunhofer.de #include "tpdec_latm.h" +#include "tpdec_drm.h" #define MODULE_NAME "transportDec" @@ -113,6 +114,7 @@ typedef union { CLatmDemux latm; + STRUCT_DRM drm; } transportdec_parser_t; @@ -182,6 +184,9 @@ HANDLE_TRANSPORTDEC transportDec_Open( const TRANSPORT_TYPE transportFmt, const hInput->numberOfRawDataBlocks = 0; break; + case TT_DRM: + drmRead_CrcInit(&hInput->parser.drm); + break; case TT_MP4_LATM_MCP0: case TT_MP4_LATM_MCP1: @@ -253,6 +258,18 @@ TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, UCHAR * } } break; + case TT_DRM: + fConfigFound = 1; + err = DrmRawSdcAudioConfig_Parse(&hTp->asc[layer], hBs); + if (err == TRANSPORTDEC_OK) { + int errC; + + errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer]); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + break; } if (err == TRANSPORTDEC_OK && fConfigFound) { @@ -1083,6 +1100,7 @@ TRANSPORTDEC_ERROR transportDec_ReadAccessUnit( const HANDLE_TRANSPORTDEC hTp, c break; case TT_MP4_RAW: + case TT_DRM: /* One Access Unit was filled into buffer. So get the length out of the buffer. */ hTp->auLength[layer] = FDKgetValidBits(hBs); @@ -1100,7 +1118,6 @@ TRANSPORTDEC_ERROR transportDec_ReadAccessUnit( const HANDLE_TRANSPORTDEC hTp, c } break; - case TT_RSVD50: case TT_MP4_ADTS: case TT_MP4_LOAS: err = transportDec_readStream(hTp, layer); @@ -1284,6 +1301,7 @@ TRANSPORTDEC_ERROR transportDec_GetLibInfo( LIB_INFO *info ) | CAPF_LATM | CAPF_LOAS | CAPF_RAWPACKETS + | CAPF_DRM ; return TRANSPORTDEC_OK; /* FDKERR_NOERROR; */ @@ -1295,6 +1313,8 @@ int transportDec_CrcStartReg(HANDLE_TRANSPORTDEC pTp, INT mBits) switch (pTp->transportFmt) { case TT_MP4_ADTS: return adtsRead_CrcStartReg(&pTp->parser.adts, &pTp->bitStream[0], mBits); + case TT_DRM: + return drmRead_CrcStartReg(&pTp->parser.drm, &pTp->bitStream[0], mBits); default: return 0; } @@ -1306,6 +1326,9 @@ void transportDec_CrcEndReg(HANDLE_TRANSPORTDEC pTp, INT reg) case TT_MP4_ADTS: adtsRead_CrcEndReg(&pTp->parser.adts, &pTp->bitStream[0], reg); break; + case TT_DRM: + drmRead_CrcEndReg(&pTp->parser.drm, &pTp->bitStream[0], reg); + break; default: break; } @@ -1322,6 +1345,9 @@ TRANSPORTDEC_ERROR transportDec_CrcCheck(HANDLE_TRANSPORTDEC pTp) transportDec_AdjustEndOfAccessUnit(pTp); } return adtsRead_CrcCheck(&pTp->parser.adts); + case TT_DRM: + return drmRead_CrcCheck(&pTp->parser.drm); + break; default: return TRANSPORTDEC_OK; } diff --git a/libMpegTPDec/src/version b/libMpegTPDec/src/version index fc7e5f0..75e22c9 100644 --- a/libMpegTPDec/src/version +++ b/libMpegTPDec/src/version @@ -2,7 +2,7 @@ /* library info */ #define TP_LIB_VL0 2 #define TP_LIB_VL1 3 -#define TP_LIB_VL2 4 +#define TP_LIB_VL2 7 #define TP_LIB_TITLE "MPEG Transport" #ifdef __ANDROID__ #define TP_LIB_BUILD_DATE "" diff --git a/libMpegTPEnc/src/tpenc_latm.cpp b/libMpegTPEnc/src/tpenc_latm.cpp index 58e51ef..f292019 100644 --- a/libMpegTPEnc/src/tpenc_latm.cpp +++ b/libMpegTPEnc/src/tpenc_latm.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -296,6 +296,7 @@ CreateStreamMuxConfig( USHORT coreFrameOffset=0; + hAss->taraBufferFullness = 0xFF; hAss->audioMuxVersionA = 0; /* for future extensions */ hAss->streamMuxConfigBits = 0; @@ -339,13 +340,7 @@ CreateStreamMuxConfig( hAss->streamMuxConfigBits+=1; } if( (useSameConfig == 0) || (transLayer==0) ) { - UINT bits; - - if ( hAss->audioMuxVersion == 1 ) { - FDKpushFor(hBs, 2); /* align to ASC, even if we do not know the length of the "ascLen" field yet */ - } - - bits = FDKgetValidBits( hBs ); + const UINT alignAnchor = FDKgetValidBits(hBs); transportEnc_writeASC( hBs, @@ -353,19 +348,24 @@ CreateStreamMuxConfig( cb ); - bits = FDKgetValidBits( hBs ) - bits; - if ( hAss->audioMuxVersion == 1 ) { - FDKpushBack(hBs, bits+2); - hAss->streamMuxConfigBits += transportEnc_LatmWriteValue( hBs, bits ); + UINT ascLen = transportEnc_LatmWriteValue(hBs, 0); + FDKbyteAlign(hBs, alignAnchor); + ascLen = FDKgetValidBits(hBs) - alignAnchor - ascLen; + FDKpushBack(hBs, FDKgetValidBits(hBs) - alignAnchor); + + transportEnc_LatmWriteValue(hBs, ascLen); + transportEnc_writeASC( hBs, hAss->config[prog][layer], cb ); + + FDKbyteAlign(hBs, alignAnchor); /* asc length fillbits */ } - hAss->streamMuxConfigBits += bits; /* add asc length to smc summary */ + hAss->streamMuxConfigBits += FDKgetValidBits(hBs) - alignAnchor; /* add asc length to smc summary */ } transLayer++; @@ -384,7 +384,6 @@ CreateStreamMuxConfig( case AOT_ER_AAC_LD : case AOT_ER_AAC_ELD : case AOT_USAC: - case AOT_RSVD50: p_linfo->frameLengthType = 0; FDKwriteBits( hBs, p_linfo->frameLengthType, 3 ); /* frameLengthType */ diff --git a/libMpegTPEnc/src/version b/libMpegTPEnc/src/version index fc7e5f0..8742568 100644 --- a/libMpegTPEnc/src/version +++ b/libMpegTPEnc/src/version @@ -2,7 +2,7 @@ /* library info */ #define TP_LIB_VL0 2 #define TP_LIB_VL1 3 -#define TP_LIB_VL2 4 +#define TP_LIB_VL2 6 #define TP_LIB_TITLE "MPEG Transport" #ifdef __ANDROID__ #define TP_LIB_BUILD_DATE "" diff --git a/libSBRdec/include/sbrdecoder.h b/libSBRdec/include/sbrdecoder.h index 174fb5c..3bb9ba3 100644 --- a/libSBRdec/include/sbrdecoder.h +++ b/libSBRdec/include/sbrdecoder.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -262,6 +262,7 @@ void sbrDecoder_drcDisable ( HANDLE_SBRDECODER self, * into *count if a payload length is given (byPayLen > 0). If no SBR payload length is * given (bsPayLen < 0) then the bit stream position on return will be random after this * function call in case of errors, and any further decoding will be completely pointless. + * This function accepts either normal ordered SBR data or reverse ordered DRM SBR data. * * \param self SBR decoder handle. * \param hBs Bit stream handle as data source. diff --git a/libSBRdec/src/env_calc.cpp b/libSBRdec/src/env_calc.cpp index ade57fc..fa5330a 100644 --- a/libSBRdec/src/env_calc.cpp +++ b/libSBRdec/src/env_calc.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -151,13 +151,13 @@ typedef struct } ENV_CALC_NRGS; -/*static*/ void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, +static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, SCHAR *filtBuffer_e, FIXP_DBL *NrgGain, SCHAR *NrgGain_e, int subbands); -/*static*/ void calcNrgPerSubband(FIXP_DBL **analysBufferReal, +static void calcNrgPerSubband(FIXP_DBL **analysBufferReal, FIXP_DBL **analysBufferImag, int lowSubband, int highSubband, int start_pos, int next_pos, @@ -165,7 +165,7 @@ ENV_CALC_NRGS; FIXP_DBL *nrgEst, SCHAR *nrgEst_e ); -/*static*/ void calcNrgPerSfb(FIXP_DBL **analysBufferReal, +static void calcNrgPerSfb(FIXP_DBL **analysBufferReal, FIXP_DBL **analysBufferImag, int nSfb, UCHAR *freqBandTable, @@ -174,13 +174,13 @@ ENV_CALC_NRGS; FIXP_DBL *nrg_est, SCHAR *nrg_est_e ); -/*static*/ void calcSubbandGain(FIXP_DBL nrgRef, SCHAR nrgRef_e, ENV_CALC_NRGS* nrgs, int c, +static void calcSubbandGain(FIXP_DBL nrgRef, SCHAR nrgRef_e, ENV_CALC_NRGS* nrgs, int c, FIXP_DBL tmpNoise, SCHAR tmpNoise_e, UCHAR sinePresentFlag, UCHAR sineMapped, int noNoiseFlag); -/*static*/ void calcAvgGain(ENV_CALC_NRGS* nrgs, +static void calcAvgGain(ENV_CALC_NRGS* nrgs, int lowSubband, int highSubband, FIXP_DBL *sumRef_m, @@ -188,7 +188,7 @@ ENV_CALC_NRGS; FIXP_DBL *ptrAvgGain_m, SCHAR *ptrAvgGain_e); -/*static*/ void adjustTimeSlotLC(FIXP_DBL *ptrReal, +static void adjustTimeSlot_EldGrid(FIXP_DBL *ptrReal, ENV_CALC_NRGS* nrgs, UCHAR *ptrHarmIndex, int lowSubbands, @@ -196,8 +196,17 @@ ENV_CALC_NRGS; int scale_change, int noNoiseFlag, int *ptrPhaseIndex, - int fCldfb); -/*static*/ void adjustTimeSlotHQ(FIXP_DBL *ptrReal, + int scale_diff_low); + +static void adjustTimeSlotLC(FIXP_DBL *ptrReal, + ENV_CALC_NRGS* nrgs, + UCHAR *ptrHarmIndex, + int lowSubbands, + int noSubbands, + int scale_change, + int noNoiseFlag, + int *ptrPhaseIndex); +static void adjustTimeSlotHQ(FIXP_DBL *ptrReal, FIXP_DBL *ptrImag, HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS* nrgs, @@ -224,7 +233,7 @@ ENV_CALC_NRGS; Additionally, the flags in harmFlagsPrev are being updated by this function for the next frame. */ -/*static*/ void mapSineFlags(UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per band) */ +static void mapSineFlags(UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per band) */ int nSfb, /*!< Number of bands in the table */ UCHAR *addHarmonics, /*!< vector with 1 flag per sfb */ int *harmFlagsPrev, /*!< Packed 'addHarmonics' */ @@ -990,7 +999,6 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling /* Prevent the smoothing filter from running on constant levels */ if (j-start_pos < smooth_length) smooth_ratio = FDK_sbrDecoder_sbr_smoothFilter[j-start_pos]; - else smooth_ratio = FL2FXCONST_SGL(0.0f); @@ -1007,7 +1015,8 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling } else { - adjustTimeSlotLC(&analysBufferReal[j][lowSubband], + if (flags & SBRDEC_ELD_GRID) { + adjustTimeSlot_EldGrid(&analysBufferReal[j][lowSubband], pNrgs, &h_sbr_cal_env->harmIndex, lowSubband, @@ -1015,7 +1024,18 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling scale_change, noNoiseFlag, &h_sbr_cal_env->phaseIndex, - (flags & SBRDEC_ELD_GRID)); + EXP2SCALE(adj_e) - sbrScaleFactor->lb_scale); + } else + { + adjustTimeSlotLC(&analysBufferReal[j][lowSubband], + pNrgs, + &h_sbr_cal_env->harmIndex, + lowSubband, + noSubbands, + scale_change, + noNoiseFlag, + &h_sbr_cal_env->phaseIndex); + } } } // for @@ -1176,7 +1196,7 @@ resetSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv) /*!< pointer to env can be performed. This function is called once for each envelope before adjusting. */ -/*static*/ void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, /*!< bufferd gains */ +static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, /*!< bufferd gains */ SCHAR *filtBuffer_e, /*!< exponents of bufferd gains */ FIXP_DBL *nrgGain, /*!< gains for current envelope */ SCHAR *nrgGain_e, /*!< exponents of gains for current envelope */ @@ -1331,7 +1351,7 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output This function is used when interpolFreq is true. */ -/*static*/ void calcNrgPerSubband(FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ +static void calcNrgPerSubband(FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */ int lowSubband, /*!< Begin of the SBR frequency range */ int highSubband, /*!< High end of the SBR frequency range */ @@ -1452,7 +1472,7 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output This function is used when interpolFreq is false. */ -/*static*/ void calcNrgPerSfb(FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ +static void calcNrgPerSfb(FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */ int nSfb, /*!< Number of scale factor bands */ UCHAR *freqBandTable, /*!< First Subband for each Sfb */ @@ -1585,7 +1605,7 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output The resulting energy gain is given by mantissa and exponent. */ -/*static*/ void calcSubbandGain(FIXP_DBL nrgRef, /*!< Reference Energy according to envelope data */ +static void calcSubbandGain(FIXP_DBL nrgRef, /*!< Reference Energy according to envelope data */ SCHAR nrgRef_e, /*!< Reference Energy according to envelope data (exponent) */ ENV_CALC_NRGS* nrgs, int i, @@ -1689,7 +1709,7 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output The result is used as a relative limit for all gains within the current "limiter band" (a certain frequency range). */ -/*static*/ void calcAvgGain(ENV_CALC_NRGS* nrgs, +static void calcAvgGain(ENV_CALC_NRGS* nrgs, int lowSubband, /*!< Begin of the limiter band */ int highSubband, /*!< High end of the limiter band */ FIXP_DBL *ptrSumRef, @@ -1728,21 +1748,101 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output *ptrSumRef_e = sumRef_e; } +static void adjustTimeSlot_EldGrid( + FIXP_DBL *ptrReal, /*!< Subband samples to be adjusted, real part */ + ENV_CALC_NRGS* nrgs, + UCHAR *ptrHarmIndex, /*!< Harmonic index */ + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + int noNoiseFlag, /*!< Flag to suppress noise addition */ + int *ptrPhaseIndex, /*!< Start index to random number array */ + int scale_diff_low) /*!< */ +{ + int k; + FIXP_DBL signalReal, sbNoise; + int tone_count = 0; + + FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *pNoiseLevel = nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + + int phaseIndex = *ptrPhaseIndex; + UCHAR harmIndex = *ptrHarmIndex; + + static const INT harmonicPhase [2][4] = { + { 1, 0, -1, 0}, + { 0, 1, 0, -1} + }; + + static const FIXP_DBL harmonicPhaseX [2][4] = { + { FL2FXCONST_DBL(2.0*1.245183154539139e-001), FL2FXCONST_DBL(2.0*-1.123767859325028e-001), FL2FXCONST_DBL(2.0*-1.245183154539139e-001), FL2FXCONST_DBL(2.0* 1.123767859325028e-001) }, + { FL2FXCONST_DBL(2.0*1.245183154539139e-001), FL2FXCONST_DBL(2.0* 1.123767859325028e-001), FL2FXCONST_DBL(2.0*-1.245183154539139e-001), FL2FXCONST_DBL(2.0*-1.123767859325028e-001) } + }; + + for (k=0; k < noSubbands; k++) { + + phaseIndex = (phaseIndex + 1) & (SBR_NF_NO_RANDOM_VAL - 1); + + if( (pSineLevel[0] != FL2FXCONST_DBL(0.0f)) || (noNoiseFlag == 1) ){ + sbNoise = FL2FXCONST_DBL(0.0f); + } else { + sbNoise = pNoiseLevel[0]; + } + + signalReal = fMultDiv2(*ptrReal,*pGain) << ((int)scale_change); + + signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[phaseIndex][0], sbNoise)<<4); + + signalReal += pSineLevel[0] * harmonicPhase[0][harmIndex]; + + *ptrReal = signalReal; + + if (k == 0) { + *(ptrReal-1) += scaleValue(fMultDiv2(harmonicPhaseX[lowSubband&1][harmIndex], pSineLevel[0]), -scale_diff_low) ; + if (k < noSubbands - 1) { + *(ptrReal) += fMultDiv2(pSineLevel[1], harmonicPhaseX[(lowSubband+1)&1][harmIndex]); + } + } + if (k > 0 && k < noSubbands - 1 && tone_count < 16) { + *(ptrReal) += fMultDiv2(pSineLevel[- 1], harmonicPhaseX [(lowSubband+k)&1] [harmIndex]); + *(ptrReal) += fMultDiv2(pSineLevel[+ 1], harmonicPhaseX [(lowSubband+k+1)&1][harmIndex]); + } + if (k == noSubbands - 1 && tone_count < 16) { + if (k > 0) { + *(ptrReal) += fMultDiv2(pSineLevel[- 1], harmonicPhaseX [(lowSubband+k)&1][harmIndex]); + } + if (k + lowSubband + 1< 63) { + *(ptrReal+1) += fMultDiv2(pSineLevel[0], harmonicPhaseX[(lowSubband+k+1)&1][harmIndex]); + } + } + + if(pSineLevel[0] != FL2FXCONST_DBL(0.0f)){ + tone_count++; + } + ptrReal++; + pNoiseLevel++; + pGain++; + pSineLevel++; + } + + *ptrHarmIndex = (harmIndex + 1) & 3; + *ptrPhaseIndex = phaseIndex & (SBR_NF_NO_RANDOM_VAL - 1); +} /*! \brief Amplify one timeslot of the signal with the calculated gains and add the noisefloor. */ -/*static*/ void adjustTimeSlotLC(FIXP_DBL *ptrReal, /*!< Subband samples to be adjusted, real part */ +static void adjustTimeSlotLC(FIXP_DBL *ptrReal, /*!< Subband samples to be adjusted, real part */ ENV_CALC_NRGS* nrgs, UCHAR *ptrHarmIndex, /*!< Harmonic index */ int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ int noSubbands, /*!< Number of QMF subbands */ int scale_change, /*!< Number of bits to shift adjusted samples */ int noNoiseFlag, /*!< Flag to suppress noise addition */ - int *ptrPhaseIndex, /*!< Start index to random number array */ - int fCldfb) /*!< CLDFB 80 flag */ + int *ptrPhaseIndex) /*!< Start index to random number array */ { FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */ FIXP_DBL *pNoiseLevel = nrgs->noiseLevel; /*!< Noise levels of current envelope */ @@ -1775,41 +1875,10 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output sineLevelNext = (noSubbands > 1) ? pSineLevel[0] : FL2FXCONST_DBL(0.0f); if (sineLevel!=FL2FXCONST_DBL(0.0f)) tone_count++; - else if (!noNoiseFlag) /* Add noisefloor to the amplified signal */ signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4); - if (fCldfb) { - - if (!(harmIndex&0x1)) { - /* harmIndex 0,2 */ - signalReal += (harmIndex&0x2) ? -sineLevel : sineLevel; - *ptrReal++ = signalReal; - } - else { - /* harmIndex 1,3 in combination with freqInvFlag */ - int shift = (int) (scale_change+1); - shift = (shift>=0) ? fixMin(DFRACT_BITS-1,shift) : fixMax(-(DFRACT_BITS-1),shift); - - FIXP_DBL tmp1 = scaleValue( fMultDiv2(C1_CLDFB, sineLevel), -shift ); - - FIXP_DBL tmp2 = fMultDiv2(C1_CLDFB, sineLevelNext); - - - /* save switch and compare operations and reduce to XOR statement */ - if ( ((harmIndex>>1)&0x1)^freqInvFlag) { - *(ptrReal-1) += tmp1; - signalReal -= tmp2; - } else { - *(ptrReal-1) -= tmp1; - signalReal += tmp2; - } - *ptrReal++ = signalReal; - freqInvFlag = !freqInvFlag; - } - - } else { if (!(harmIndex&0x1)) { /* harmIndex 0,2 */ @@ -1933,8 +2002,9 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output *ptrHarmIndex = (harmIndex + 1) & 3; *ptrPhaseIndex = index & (SBR_NF_NO_RANDOM_VAL - 1); } -void adjustTimeSlotHQ(FIXP_DBL *RESTRICT ptrReal, /*!< Subband samples to be adjusted, real part */ - FIXP_DBL *RESTRICT ptrImag, /*!< Subband samples to be adjusted, imag part */ +static void adjustTimeSlotHQ( + FIXP_DBL *RESTRICT ptrReal, /*!< Subband samples to be adjusted, real part */ + FIXP_DBL *RESTRICT ptrImag, /*!< Subband samples to be adjusted, imag part */ HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS* nrgs, int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ @@ -2137,7 +2207,6 @@ ResetLimiterBands ( UCHAR *limiterBandTable, /*!< Resulting band borders in QM UCHAR workLimiterBandTable[MAX_FREQ_COEFFS / 2 + MAX_NUM_PATCHES + 1]; int patchBorders[MAX_NUM_PATCHES + 1]; int kx, k2; - FIXP_DBL temp; int lowSubband = freqBandTable[0]; int highSubband = freqBandTable[noFreqBands]; @@ -2169,13 +2238,32 @@ ResetLimiterBands ( UCHAR *limiterBandTable, /*!< Resulting band borders in QM while (hiLimIndex <= tempNoLim) { + FIXP_DBL div_m, oct_m, temp; + INT div_e = 0, oct_e = 0, temp_e = 0; + k2 = workLimiterBandTable[hiLimIndex] + lowSubband; kx = workLimiterBandTable[loLimIndex] + lowSubband; - temp = FX_SGL2FX_DBL(FDK_getNumOctavesDiv8(kx,k2)); /* Number of octaves */ - temp = fMult(temp, FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[limiterBands]); + div_m = fDivNorm(k2, kx, &div_e); + + /* calculate number of octaves */ + oct_m = fLog2(div_m, div_e, &oct_e); + + /* multiply with limiterbands per octave */ + /* values 1, 1.2, 2, 3 -> scale factor of 2 */ + temp = fMultNorm(oct_m, FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[limiterBands], &temp_e); + + /* overall scale factor of temp ist addition of scalefactors from log2 calculation, + limiter bands scalefactor (2) and limiter bands multiplication */ + temp_e += oct_e + 2; + + /* div can be a maximum of 64 (k2 = 64 and kx = 1) + -> oct can be a maximum of 6 + -> temp can be a maximum of 18 (as limiterBandsPerOctoave is a maximum factor of 3) + -> we need a scale factor of 5 for comparisson + */ + if (temp >> (5 - temp_e) < FL2FXCONST_DBL (0.49f) >> 5) { - if (temp < FL2FXCONST_DBL (0.49f)>>5) { if (workLimiterBandTable[hiLimIndex] == workLimiterBandTable[loLimIndex]) { workLimiterBandTable[hiLimIndex] = highSubband; nBands--; diff --git a/libSBRdec/src/env_dec.cpp b/libSBRdec/src/env_dec.cpp index 24b2d3b..c65c169 100644 --- a/libSBRdec/src/env_dec.cpp +++ b/libSBRdec/src/env_dec.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -369,7 +369,7 @@ leanSbrConcealment(HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control d FIXP_SGL step; /* speed of fade */ int i; - int currentStartPos = h_prev_data->stopPos - hHeaderData->numberTimeSlots; + int currentStartPos = FDKmax(0, h_prev_data->stopPos - hHeaderData->numberTimeSlots); int currentStopPos = hHeaderData->numberTimeSlots; diff --git a/libSBRdec/src/env_extr.cpp b/libSBRdec/src/env_extr.cpp index 6cb0b99..dacd951 100644 --- a/libSBRdec/src/env_extr.cpp +++ b/libSBRdec/src/env_extr.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -327,7 +327,7 @@ sbrGetHeaderData (HANDLE_SBR_HEADER_DATA hHeaderData, } /* Look for new settings. IEC 14496-3, 4.6.18.3.1 */ - if(hHeaderData->syncState != SBR_ACTIVE || + if(hHeaderData->syncState < SBR_HEADER || lastHeader.startFreq != pBsData->startFreq || lastHeader.stopFreq != pBsData->stopFreq || lastHeader.freqScale != pBsData->freqScale || diff --git a/libSBRdec/src/env_extr.h b/libSBRdec/src/env_extr.h index ab6b704..0518ea9 100644 --- a/libSBRdec/src/env_extr.h +++ b/libSBRdec/src/env_extr.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -125,6 +125,7 @@ amm-info@iis.fraunhofer.de typedef enum { HEADER_NOT_PRESENT, + HEADER_ERROR, HEADER_OK, HEADER_RESET } @@ -132,10 +133,10 @@ SBR_HEADER_STATUS; typedef enum { - SBR_NOT_INITIALIZED, - UPSAMPLING, - SBR_HEADER, - SBR_ACTIVE + SBR_NOT_INITIALIZED = 0, + UPSAMPLING = 1, + SBR_HEADER = 2, + SBR_ACTIVE = 3 } SBR_SYNC_STATE; @@ -179,6 +180,7 @@ typedef FREQ_BAND_DATA *HANDLE_FREQ_BAND_DATA; #define SBRDEC_LOW_POWER 16 /* Flag indicating that Low Power QMF mode shall be used. */ #define SBRDEC_PS_DECODED 32 /* Flag indicating that PS was decoded and rendered. */ #define SBRDEC_LD_MPS_QMF 512 /* Flag indicating that the LD-MPS QMF shall be used. */ +#define SBRDEC_SYNTAX_DRM 2048 /* Flag indicating that DRM30/DRM+ reverse syntax is being used. */ #define SBRDEC_DOWNSAMPLE 8192 /* Flag indicating that the downsampling mode is used. */ #define SBRDEC_FLUSH 16384 /* Flag is used to flush all elements in use. */ #define SBRDEC_FORCE_RESET 32768 /* Flag is used to force a reset of all elements in use. */ diff --git a/libSBRdec/src/sbr_dec.cpp b/libSBRdec/src/sbr_dec.cpp index 1282338..0864348 100644 --- a/libSBRdec/src/sbr_dec.cpp +++ b/libSBRdec/src/sbr_dec.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -225,7 +225,14 @@ static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< hand } if (resetAnaQmf) { - int qmfErr = qmfInitAnalysisFilterBank ( + QMF_FILTER_BANK prvAnaQmf; + int qmfErr; + + /* Store current configuration */ + FDKmemcpy(&prvAnaQmf, &hSbrDec->AnalysiscQMF, sizeof(QMF_FILTER_BANK)); + + /* Reset analysis QMF */ + qmfErr = qmfInitAnalysisFilterBank ( &hSbrDec->AnalysiscQMF, hSbrDec->anaQmfStates, hSbrDec->AnalysiscQMF.no_col, @@ -234,13 +241,22 @@ static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< hand hSbrDec->AnalysiscQMF.no_channels, anaQmfFlags | QMF_FLAG_KEEP_STATES ); + if (qmfErr != 0) { - FDK_ASSERT(0); + /* Restore old configuration of analysis QMF */ + FDKmemcpy(&hSbrDec->AnalysiscQMF, &prvAnaQmf, sizeof(QMF_FILTER_BANK)); } } if (resetSynQmf) { - int qmfErr = qmfInitSynthesisFilterBank ( + QMF_FILTER_BANK prvSynQmf; + int qmfErr; + + /* Store current configuration */ + FDKmemcpy(&prvSynQmf, &hSbrDec->SynthesisQMF, sizeof(QMF_FILTER_BANK)); + + /* Reset synthesis QMF */ + qmfErr = qmfInitSynthesisFilterBank ( &hSbrDec->SynthesisQMF, hSbrDec->pSynQmfStates, hSbrDec->SynthesisQMF.no_col, @@ -251,7 +267,8 @@ static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< hand ); if (qmfErr != 0) { - FDK_ASSERT(0); + /* Restore old configuration of synthesis QMF */ + FDKmemcpy(&hSbrDec->SynthesisQMF, &prvSynQmf, sizeof(QMF_FILTER_BANK)); } } } @@ -321,7 +338,8 @@ sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */ const int applyProcessing, /*!< Flag for SBR operation */ HANDLE_PS_DEC h_ps_d, - const UINT flags + const UINT flags, + const int codecFrameSize ) { int i, slot, reserve; @@ -348,6 +366,33 @@ sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ if (flags & SBRDEC_ELD_GRID) { /* Choose the right low delay filter bank */ changeQmfType( hSbrDec, (flags & SBRDEC_LD_MPS_QMF) ? 1 : 0 ); + + /* If the LD-MPS QMF is not available delay the signal by (96-48*ldSbrSamplingRate) + * samples according to ISO/IEC 14496-3:2009/FDAM 2:2010(E) chapter 4.5.2.13. */ + if ( (flags & SBRDEC_LD_MPS_QMF) + && (hSbrDec->AnalysiscQMF.flags & QMF_FLAG_CLDFB) ) + { + INT_PCM *pDlyBuf = hSbrDec->coreDelayBuf; /* DLYBUF */ + int smpl, delay = 96 >> (!(flags & SBRDEC_DOWNSAMPLE) ? 1 : 0); + /* Create TMPBUF */ + C_AALLOC_SCRATCH_START(pcmTemp, INT_PCM, (96)); + /* Copy delay samples from INBUF to TMPBUF */ + for (smpl = 0; smpl < delay; smpl += 1) { + pcmTemp[smpl] = timeIn[(codecFrameSize-delay+smpl)*strideIn]; + } + /* Move input signal remainder to the very end of INBUF */ + for (smpl = (codecFrameSize-delay-1)*strideIn; smpl >= 0; smpl -= strideIn) { + timeIn[smpl+delay] = timeIn[smpl]; + } + /* Copy delayed samples from last frame from DLYBUF to the very beginning of INBUF */ + for (smpl = 0; smpl < delay; smpl += 1) { + timeIn[smpl*strideIn] = pDlyBuf[smpl]; + } + /* Copy TMPBUF to DLYBUF */ + FDKmemcpy(pDlyBuf, pcmTemp, delay*sizeof(INT_PCM)); + /* Destory TMPBUF */ + C_AALLOC_SCRATCH_END(pcmTemp, INT_PCM, (96)); + } } /* @@ -761,7 +806,7 @@ createSbrDec (SBR_CHANNEL * hSbrChannel, { int qmfErr; /* Adapted QMF analysis post-twiddles for down-sampled HQ SBR */ - const UINT downSampledFlag = (downsampleFac==2) ? QMF_FLAG_DOWNSAMPLED : 0; + const UINT downSampledFlag = (flags & SBRDEC_DOWNSAMPLE) ? QMF_FLAG_DOWNSAMPLED : 0; qmfErr = qmfInitAnalysisFilterBank ( &hs->AnalysiscQMF, @@ -836,6 +881,9 @@ createSbrDec (SBR_CHANNEL * hSbrChannel, } } + /* Clear input delay line */ + FDKmemclear(hs->coreDelayBuf, (96)*sizeof(INT_PCM)); + /* assign qmf time slots */ assignTimeSlots( &hSbrChannel->SbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, qmfFlags & QMF_FLAG_LP); diff --git a/libSBRdec/src/sbr_dec.h b/libSBRdec/src/sbr_dec.h index 175e7b2..edde637 100644 --- a/libSBRdec/src/sbr_dec.h +++ b/libSBRdec/src/sbr_dec.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -118,6 +118,9 @@ typedef struct FIXP_DBL * WorkBuffer1; FIXP_DBL * WorkBuffer2; + /* Delayed time input signal needed to align CLDFD with LD-MPS QMF. */ + INT_PCM coreDelayBuf[(96)]; + /* QMF filter states */ FIXP_QAS anaQmfStates[(320)]; FIXP_QSS * pSynQmfStates; @@ -182,7 +185,8 @@ sbr_dec (HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */ const int applyProcessing, /*!< Flag for SBR operation */ HANDLE_PS_DEC h_ps_d, - const UINT flags + const UINT flags, + const int codecFrameSize ); diff --git a/libSBRdec/src/sbr_ram.h b/libSBRdec/src/sbr_ram.h index f12631d..7ab5044 100644 --- a/libSBRdec/src/sbr_ram.h +++ b/libSBRdec/src/sbr_ram.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -135,6 +135,7 @@ struct SBR_DECODER_INSTANCE USHORT codecFrameSize; UCHAR synDownsampleFac; UCHAR numDelayFrames; /* The current number of additional delay frames used for processing. */ + UCHAR numFlushedFrames; /* The variable counts the number of frames which are flushed consecutively. */ UINT flags; diff --git a/libSBRdec/src/sbr_rom.cpp b/libSBRdec/src/sbr_rom.cpp index e84c3cd..c48ce35 100644 --- a/libSBRdec/src/sbr_rom.cpp +++ b/libSBRdec/src/sbr_rom.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -189,6 +189,15 @@ const FIXP_SGL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[4] = FL2FXCONST_SGL(3.0f / 4.0f) }; +/*! Constants for calculating the number of limiter bands */ +const FIXP_DBL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[4] = +{ + FL2FXCONST_DBL(1.0f / 4.0f), + FL2FXCONST_DBL(1.2f / 4.0f), + FL2FXCONST_DBL(2.0f / 4.0f), + FL2FXCONST_DBL(3.0f / 4.0f) +}; + /*! Ratio of old gains and noise levels for the first 4 timeslots of an envelope */ const FIXP_SGL FDK_sbrDecoder_sbr_smoothFilter[4] = { FL2FXCONST_SGL(0.66666666666666f), diff --git a/libSBRdec/src/sbr_rom.h b/libSBRdec/src/sbr_rom.h index c318870..1f800bc 100644 --- a/libSBRdec/src/sbr_rom.h +++ b/libSBRdec/src/sbr_rom.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -124,6 +124,7 @@ extern const FIXP_DBL FDK_sbrDecoder_sbr_whFactorsTable[NUM_WHFACTOR_TABLE_ENTRI extern const FIXP_SGL FDK_sbrDecoder_sbr_limGains_m[4]; extern const UCHAR FDK_sbrDecoder_sbr_limGains_e[4]; extern const FIXP_SGL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[4]; +extern const FIXP_DBL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[4]; extern const FIXP_SGL FDK_sbrDecoder_sbr_smoothFilter[4]; extern const FIXP_SGL FDK_sbrDecoder_sbr_randomPhase[SBR_NF_NO_RANDOM_VAL][2]; extern const FIXP_SGL harmonicPhaseX [2][4]; diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp index 619e4fd..f9ded54 100644 --- a/libSBRdec/src/sbrdecoder.cpp +++ b/libSBRdec/src/sbrdecoder.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -128,6 +128,7 @@ amm-info@iis.fraunhofer.de #include "lpp_tran.h" #include "transcendent.h" +#include "FDK_crc.h" #include "sbrdec_drc.h" @@ -137,7 +138,7 @@ amm-info@iis.fraunhofer.de /* Decoder library info */ #define SBRDECODER_LIB_VL0 2 #define SBRDECODER_LIB_VL1 2 -#define SBRDECODER_LIB_VL2 6 +#define SBRDECODER_LIB_VL2 12 #define SBRDECODER_LIB_TITLE "SBR Decoder" #ifdef __ANDROID__ #define SBRDECODER_LIB_BUILD_DATE "" @@ -194,6 +195,33 @@ static void copySbrHeader( HANDLE_SBR_HEADER_DATA hDst, const HANDLE_SBR_HEADER_ hDst->freqBandData.freqBandTable[1] = hDst->freqBandData.freqBandTableHi; } +static int compareSbrHeader( const HANDLE_SBR_HEADER_DATA hHdr1, const HANDLE_SBR_HEADER_DATA hHdr2 ) +{ + int result = 0; + + /* compare basic data */ + result |= (hHdr1->syncState != hHdr2->syncState) ? 1 : 0; + result |= (hHdr1->status != hHdr2->status) ? 1 : 0; + result |= (hHdr1->frameErrorFlag != hHdr2->frameErrorFlag) ? 1 : 0; + result |= (hHdr1->numberTimeSlots != hHdr2->numberTimeSlots) ? 1 : 0; + result |= (hHdr1->numberOfAnalysisBands != hHdr2->numberOfAnalysisBands) ? 1 : 0; + result |= (hHdr1->timeStep != hHdr2->timeStep) ? 1 : 0; + result |= (hHdr1->sbrProcSmplRate != hHdr2->sbrProcSmplRate) ? 1 : 0; + + /* compare bitstream data */ + result |= FDKmemcmp( &hHdr1->bs_data, &hHdr2->bs_data, sizeof(SBR_HEADER_DATA_BS) ); + result |= FDKmemcmp( &hHdr1->bs_info, &hHdr2->bs_info, sizeof(SBR_HEADER_DATA_BS_INFO) ); + + /* compare frequency band data */ + result |= FDKmemcmp( &hHdr1->freqBandData, &hHdr2->freqBandData, (8+MAX_NUM_LIMITERS+1)*sizeof(UCHAR) ); + result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableLo, hHdr2->freqBandData.freqBandTableLo, (MAX_FREQ_COEFFS/2+1)*sizeof(UCHAR) ); + result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableHi, hHdr2->freqBandData.freqBandTableHi, (MAX_FREQ_COEFFS+1)*sizeof(UCHAR) ); + result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableNoise, hHdr2->freqBandData.freqBandTableNoise, (MAX_NOISE_COEFFS+1)*sizeof(UCHAR) ); + result |= FDKmemcmp( hHdr1->freqBandData.v_k_master, hHdr2->freqBandData.v_k_master, (MAX_FREQ_COEFFS+1)*sizeof(UCHAR) ); + + return result; +} + /*! \brief Reset SBR decoder. @@ -318,7 +346,6 @@ SBR_ERROR sbrDecoder_ResetElement ( case AOT_PS: case AOT_ER_AAC_SCAL: case AOT_DRM_AAC: - case AOT_DRM_SURROUND: if (CreatePsDec ( &self->hParametricStereoDec, samplesPerFrame )) { sbrError = SBRDEC_CREATE_ERROR; goto bail; @@ -392,6 +419,7 @@ int sbrDecoder_isCoreCodecValid(AUDIO_OBJECT_TYPE coreCodec) case AOT_PS: case AOT_ER_AAC_SCAL: case AOT_ER_AAC_ELD: + case AOT_DRM_AAC: return 1; default: return 0; @@ -464,6 +492,8 @@ SBR_ERROR sbrDecoder_InitElement ( self->flags = 0; self->flags |= (coreCodec == AOT_ER_AAC_ELD) ? SBRDEC_ELD_GRID : 0; + self->flags |= (coreCodec == AOT_ER_AAC_SCAL) ? SBRDEC_SYNTAX_SCAL : 0; + self->flags |= (coreCodec == AOT_DRM_AAC) ? SBRDEC_SYNTAX_SCAL|SBRDEC_SYNTAX_DRM : 0; /* Init SBR elements */ { @@ -503,7 +533,6 @@ SBR_ERROR sbrDecoder_InitElement ( case AOT_PS: case AOT_ER_AAC_SCAL: case AOT_DRM_AAC: - case AOT_DRM_SURROUND: elChannels = 2; break; default: @@ -930,24 +959,73 @@ SBR_ERROR sbrDecoder_Parse( ) { SBR_DECODER_ELEMENT *hSbrElement; - HANDLE_SBR_HEADER_DATA hSbrHeader; + HANDLE_SBR_HEADER_DATA hSbrHeader = NULL; HANDLE_SBR_CHANNEL *pSbrChannel; SBR_FRAME_DATA *hFrameDataLeft; SBR_FRAME_DATA *hFrameDataRight; SBR_ERROR errorStatus = SBRDEC_OK; - SBR_SYNC_STATE initialSyncState; SBR_HEADER_STATUS headerStatus = HEADER_NOT_PRESENT; INT startPos; INT CRCLen = 0; + HANDLE_FDK_BITSTREAM hBsOriginal = hBs; + FDK_CRCINFO crcInfo; /* shall be used for all other CRCs in the future (TBD) */ + INT crcReg = 0; + USHORT drmSbrCrc = 0; int stereo; int fDoDecodeSbrData = 1; int lastSlot, lastHdrSlot = 0, thisHdrSlot; + /* Reverse bits of DRM SBR payload */ + if ( (self->flags & SBRDEC_SYNTAX_DRM) && *count > 0 ) + { + UCHAR *bsBufferDrm = (UCHAR*)self->workBuffer1; + HANDLE_FDK_BITSTREAM hBsBwd = (HANDLE_FDK_BITSTREAM) (bsBufferDrm + (512)); + int dataBytes, dataBits; + + dataBits = *count; + + if (dataBits > ((512)*8)) { + /* do not flip more data than needed */ + dataBits = (512)*8; + } + + dataBytes = (dataBits+7)>>3; + + int j; + + if ((j = (int)FDKgetValidBits(hBs)) != 8) { + FDKpushBiDirectional(hBs, (j-8)); + } + + j = 0; + for ( ; dataBytes > 0; dataBytes--) + { + int i; + UCHAR tmpByte; + UCHAR buffer = 0x00; + + tmpByte = (UCHAR) FDKreadBits(hBs, 8); + for (i = 0; i < 4; i++) { + int shift = 2 * i + 1; + buffer |= (tmpByte & (0x08>>i)) << shift; + buffer |= (tmpByte & (0x10<<i)) >> shift; + } + bsBufferDrm[j++] = buffer; + FDKpushBack(hBs, 16); + } + + FDKinitBitStream(hBsBwd, bsBufferDrm, (512), dataBits, BS_READER); + + /* Use reversed data */ + hBs = hBsBwd; + bsPayLen = *count; + } + /* Remember start position of SBR element */ startPos = FDKgetValidBits(hBs); @@ -972,7 +1050,6 @@ SBR_ERROR sbrDecoder_Parse( hFrameDataLeft = &self->pSbrElement[elementIndex]->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; hFrameDataRight = &self->pSbrElement[elementIndex]->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; - initialSyncState = hSbrHeader->syncState; /* reset PS flag; will be set after PS was found */ self->flags &= ~SBRDEC_PS_DECODED; @@ -1008,12 +1085,19 @@ SBR_ERROR sbrDecoder_Parse( */ if (fDoDecodeSbrData) { - if (crcFlag == 1) { + if (crcFlag) { switch (self->coreCodec) { case AOT_ER_AAC_ELD: FDKpushFor (hBs, 10); /* check sbrcrc later: we don't know the payload length now */ break; + case AOT_DRM_AAC: + drmSbrCrc = (USHORT)FDKreadBits(hBs, 8); + /* Setup CRC decoder */ + FDKcrcInit(&crcInfo, 0x001d, 0xFFFF, 8); + /* Start CRC region */ + crcReg = FDKcrcStartReg(&crcInfo, hBs, 0); + break; default: CRCLen = bsPayLen - 10; /* change: 0 => i */ if (CRCLen < 0) { @@ -1058,6 +1142,7 @@ SBR_ERROR sbrDecoder_Parse( hSbrHeader->syncState = SBR_HEADER; } else { hSbrHeader->syncState = SBR_NOT_INITIALIZED; + headerStatus = HEADER_ERROR; } } @@ -1107,7 +1192,7 @@ SBR_ERROR sbrDecoder_Parse( valBits = (INT)FDKgetValidBits(hBs); } - if ( crcFlag == 1 ) { + if ( crcFlag ) { switch (self->coreCodec) { case AOT_ER_AAC_ELD: { @@ -1119,6 +1204,14 @@ SBR_ERROR sbrDecoder_Parse( FDKpushFor(hBs, crcLen); } break; + case AOT_DRM_AAC: + /* End CRC region */ + FDKcrcEndReg(&crcInfo, hBs, crcReg); + /* Check CRC */ + if ((FDKcrcGetCRC(&crcInfo)^0xFF) != drmSbrCrc) { + fDoDecodeSbrData = 0; + } + break; default: break; } @@ -1169,8 +1262,25 @@ SBR_ERROR sbrDecoder_Parse( } bail: - if (errorStatus == SBRDEC_OK) { - if (headerStatus == HEADER_NOT_PRESENT) { + + if ( self->flags & SBRDEC_SYNTAX_DRM ) + { + hBs = hBsOriginal; + } + + if ( (errorStatus == SBRDEC_OK) + || ( (errorStatus == SBRDEC_PARSE_ERROR) + && (headerStatus != HEADER_ERROR) ) ) + { + int useOldHdr = ( (headerStatus == HEADER_NOT_PRESENT) + || (headerStatus == HEADER_ERROR) ) ? 1 : 0; + + if (!useOldHdr && (thisHdrSlot != lastHdrSlot)) { + useOldHdr |= ( compareSbrHeader( hSbrHeader, + &self->sbrHeader[elementIndex][lastHdrSlot] ) == 0 ) ? 1 : 0; + } + + if (useOldHdr != 0) { /* Use the old header for this frame */ hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = lastHdrSlot; } else { @@ -1231,12 +1341,21 @@ sbrDecoder_DecodeElement ( int numElementChannels = hSbrElement->nChannels; /* Number of channels of the current SBR element */ if (self->flags & SBRDEC_FLUSH) { - /* Move frame pointer to the next slot which is up to be decoded/applied next */ - hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1); - /* Update header and frame data pointer because they have already been set */ - hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]]; - hFrameDataLeft = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; - hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; + if ( self->numFlushedFrames > self->numDelayFrames ) { + int hdrIdx; + /* No valid SBR payload available, hence switch to upsampling (in all headers) */ + for (hdrIdx = 0; hdrIdx < ((1)+1); hdrIdx += 1) { + self->sbrHeader[elementIndex][hdrIdx].syncState = UPSAMPLING; + } + } + else { + /* Move frame pointer to the next slot which is up to be decoded/applied next */ + hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1); + /* Update header and frame data pointer because they have already been set */ + hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]]; + hFrameDataLeft = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; + hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; + } } /* Update the header error flag */ @@ -1356,7 +1475,8 @@ sbrDecoder_DecodeElement ( &pSbrChannel[0]->prevFrameData, (hSbrHeader->syncState == SBR_ACTIVE), h_ps_d, - self->flags + self->flags, + codecFrameSize ); if (stereo) { @@ -1373,7 +1493,8 @@ sbrDecoder_DecodeElement ( &pSbrChannel[1]->prevFrameData, (hSbrHeader->syncState == SBR_ACTIVE), NULL, - self->flags + self->flags, + codecFrameSize ); } @@ -1389,20 +1510,21 @@ sbrDecoder_DecodeElement ( if ( !(self->flags & SBRDEC_PS_DECODED) ) { /* A decoder which is able to decode PS has to produce a stereo output even if no PS data is availble. */ /* So copy left channel to right channel. */ + int copyFrameSize = codecFrameSize * 2 / self->synDownsampleFac; if (interleaved) { INT_PCM *ptr; INT i; FDK_ASSERT(strideOut == 2); ptr = timeData; - for (i = codecFrameSize; i--; ) + for (i = copyFrameSize>>1; i--; ) { INT_PCM tmp; /* This temporal variable is required because some compilers can't do *ptr++ = *ptr++ correctly. */ tmp = *ptr++; *ptr++ = tmp; tmp = *ptr++; *ptr++ = tmp; } } else { - FDKmemcpy( timeData+2*codecFrameSize, timeData, 2*codecFrameSize*sizeof(INT_PCM) ); + FDKmemcpy( timeData+copyFrameSize, timeData, copyFrameSize*sizeof(INT_PCM) ); } } *numOutChannels = 2; /* Output minimum two channels when PS is enabled. */ @@ -1466,14 +1588,23 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self, self->flags &= ~SBRDEC_PS_DECODED; } + if ( self->flags & SBRDEC_FLUSH ) { + /* flushing is signalized, hence increment the flush frame counter */ + self->numFlushedFrames++; + } + else { + /* no flushing is signalized, hence reset the flush frame counter */ + self->numFlushedFrames = 0; + } + /* Loop over SBR elements */ for (sbrElementNum = 0; sbrElementNum<self->numSbrElements; sbrElementNum++) { int numElementChan; if (psPossible && self->pSbrElement[sbrElementNum]->pSbrChannel[1] == NULL) { - errorStatus = SBRDEC_UNSUPPORTED_CONFIG; - goto bail; + /* Disable PS and try decoding SBR mono. */ + psPossible = 0; } numElementChan = (self->pSbrElement[sbrElementNum]->elementID == ID_CPE) ? 2 : 1; @@ -1581,6 +1712,7 @@ INT sbrDecoder_GetLibInfo( LIB_INFO *info ) | CAPF_SBR_HQ | CAPF_SBR_LP | CAPF_SBR_PS_MPEG + | CAPF_SBR_DRM_BS | CAPF_SBR_CONCEALMENT | CAPF_SBR_DRC ; @@ -1609,6 +1741,9 @@ UINT sbrDecoder_GetDelay( const HANDLE_SBRDECODER self ) /* Low delay SBR: */ { outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 32 : 64; /* QMF synthesis */ + if (flags & SBRDEC_LD_MPS_QMF) { + outputDelay += 32; + } } } else if (!IS_USAC(self->coreCodec)) { diff --git a/libSBRenc/include/sbr_encoder.h b/libSBRenc/include/sbr_encoder.h index 93dc46d..aec0398 100644 --- a/libSBRenc/include/sbr_encoder.h +++ b/libSBRenc/include/sbr_encoder.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -135,6 +135,12 @@ enum SBR_SYNTAX_DRM_CRC = 0x0008 }; +typedef enum +{ + FREQ_RES_LOW = 0, + FREQ_RES_HIGH +} FREQ_RES; + typedef struct { CODEC_TYPE coreCoder; /*!< LC or ELD */ @@ -168,8 +174,9 @@ typedef struct sbrConfiguration INT dynBwSupported; /*!< Flag: support for dynamic bandwidth in this combination. */ INT parametricCoding; /*!< Flag: usage of parametric coding tool. */ INT downSampleFactor; /*!< Sampling rate relation between the SBR and the core encoder. */ - int freq_res_fixfix[3]; /*!< Frequency resolution of envelopes in frame class FIXFIX - 0=1 Env; 1=2 Env; 2=4 Env; */ + FREQ_RES freq_res_fixfix[2];/*!< Frequency resolution of envelopes in frame class FIXFIX, for non-split case and split case */ + UCHAR fResTransIsLow; /*!< Frequency resolution of envelopes in transient frames: low (0) or variable (1) */ + /* core coder dependent tuning parameters */ @@ -221,6 +228,8 @@ typedef struct sbrConfiguration INT sbr_interpol_freq; /*!< Flag: use interpolation in freq. direction. */ INT sbr_smoothing_length; /*!< Flag: choose length 4 or 0 (=on, off). */ UCHAR init_amp_res_FF; + FIXP_DBL threshold_AmpRes_FF_m; + SCHAR threshold_AmpRes_FF_e; } sbrConfiguration, *sbrConfigurationPtr ; typedef struct SBR_CONFIG_DATA @@ -237,7 +246,7 @@ typedef struct SBR_CONFIG_DATA INT noQmfBands; /**< Number of QMF frequency bands. */ INT noQmfSlots; /**< Number of QMF slots. */ - UCHAR *freqBandTable[2]; /**< Frequency table for low and hires, only MAX_FREQ_COEFFS/2 +1 coeefs actually needed for lowres. */ + UCHAR *freqBandTable[2]; /**< Frequency table for low and hires, only MAX_FREQ_COEFFS/2 +1 coeffs actually needed for lowres. */ UCHAR *v_k_master; /**< Master BandTable where freqBandTable is derived from. */ @@ -249,6 +258,8 @@ typedef struct SBR_CONFIG_DATA INT xposCtrlSwitch; /**< Flag indicates whether to switch xpos ctrl on the fly. */ INT switchTransposers; /**< Flag indicates whether to switch xpos on the fly . */ UCHAR initAmpResFF; + FIXP_DBL thresholdAmpResFF_m; + SCHAR thresholdAmpResFF_e; } SBR_CONFIG_DATA, *HANDLE_SBR_CONFIG_DATA; typedef struct { diff --git a/libSBRenc/src/bit_sbr.cpp b/libSBRenc/src/bit_sbr.cpp index 963aeff..9200e01 100644 --- a/libSBRenc/src/bit_sbr.cpp +++ b/libSBRenc/src/bit_sbr.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -283,9 +283,7 @@ void sbrEncoder_GetHeader(SBR_ENCODER *sbrEncoder, INT element_index, int fSendHeaders) { - int bits; - - bits = encodeSbrHeaderData (&sbrEncoder->sbrElement[element_index]->sbrHeaderData, hBs); + encodeSbrHeaderData (&sbrEncoder->sbrElement[element_index]->sbrHeaderData, hBs); if (fSendHeaders == 0) { /* Prevent header being embedded into the SBR payload. */ diff --git a/libSBRenc/src/bit_sbr.h b/libSBRenc/src/bit_sbr.h index 1ce2c1e..de4ac89 100644 --- a/libSBRenc/src/bit_sbr.h +++ b/libSBRenc/src/bit_sbr.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -141,8 +141,8 @@ struct SBR_ENV_DATA { INT sbr_xpos_ctrl; - INT freq_res_fixfix; - + FREQ_RES freq_res_fixfix[2]; + UCHAR fResTransIsLow; INVF_MODE sbr_invf_mode; INVF_MODE sbr_invf_mode_vec[MAX_NUM_NOISE_VALUES]; @@ -205,6 +205,8 @@ struct SBR_ENV_DATA INT balance; AMP_RES init_sbr_amp_res; AMP_RES currentAmpResFF; + FIXP_DBL ton_HF[SBR_GLOBAL_TONALITY_VALUES]; /* tonality is scaled by 2^19/0.524288f (fract part of RELAXATION) */ + FIXP_DBL global_tonality; /* extended data */ INT extended_data; diff --git a/libSBRenc/src/env_est.cpp b/libSBRenc/src/env_est.cpp index 929f229..4fcda51 100644 --- a/libSBRenc/src/env_est.cpp +++ b/libSBRenc/src/env_est.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -103,6 +103,114 @@ static const UCHAR panTable[2][10] = { { 0, 2, 4, 6, 8,12,16,20,24}, static const UCHAR maxIndex[2] = {9, 5}; +/****************************************************************************** + Functionname: FDKsbrEnc_GetTonality +******************************************************************************/ +/***************************************************************************/ +/*! + + \brief Calculates complete energy per band from the energy values + of the QMF subsamples. + + \brief quotaMatrix - calculated in FDKsbrEnc_CalculateTonalityQuotas() + \brief noEstPerFrame - number of estimations per frame + \brief startIndex - start index for the quota matrix + \brief Energies - energy matrix + \brief startBand - start band + \brief stopBand - number of QMF bands + \brief numberCols - number of QMF subsamples + + \return mean tonality of the 5 bands with the highest energy + scaled by 2^(RELAXATION_SHIFT+2)*RELAXATION_FRACT + +****************************************************************************/ +static FIXP_DBL FDKsbrEnc_GetTonality( + const FIXP_DBL *const *quotaMatrix, + const INT noEstPerFrame, + const INT startIndex, + const FIXP_DBL *const *Energies, + const UCHAR startBand, + const INT stopBand, + const INT numberCols + ) +{ + UCHAR b, e, k; + INT no_enMaxBand[SBR_MAX_ENERGY_VALUES] = { -1, -1, -1, -1, -1 }; + FIXP_DBL energyMax[SBR_MAX_ENERGY_VALUES] = { FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f) }; + FIXP_DBL energyMaxMin = MAXVAL_DBL; /* min. energy in energyMax array */ + UCHAR posEnergyMaxMin = 0; /* min. energy in energyMax array position */ + FIXP_DBL tonalityBand[SBR_MAX_ENERGY_VALUES] = { FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f) }; + FIXP_DBL globalTonality = FL2FXCONST_DBL(0.0f); + FIXP_DBL energyBand[QMF_CHANNELS]; + INT maxNEnergyValues; /* max. number of max. energy values */ + + /*** Sum up energies for each band ***/ + FDK_ASSERT(numberCols==15||numberCols==16); + /* numberCols is always 15 or 16 for ELD. In case of 16 bands, the + energyBands are initialized with the [15]th column. + The rest of the column energies are added in the next step. */ + if (numberCols==15) { + for (b=startBand; b<stopBand; b++) { + energyBand[b]=FL2FXCONST_DBL(0.0f); + } + } else { + for (b=startBand; b<stopBand; b++) { + energyBand[b]=Energies[15][b]>>4; + } + } + + for (k=0; k<15; k++) { + for (b=startBand; b<stopBand; b++) { + energyBand[b] += Energies[k][b]>>4; + } + } + + /*** Determine 5 highest band-energies ***/ + maxNEnergyValues = fMin(SBR_MAX_ENERGY_VALUES, stopBand-startBand); + + /* Get min. value in energyMax array */ + energyMaxMin = energyMax[0] = energyBand[startBand]; + no_enMaxBand[0] = startBand; + posEnergyMaxMin = 0; + for (k=1; k<maxNEnergyValues; k++) { + energyMax[k] = energyBand[startBand+k]; + no_enMaxBand[k] = startBand+k; + if (energyMaxMin > energyMax[k]) { + energyMaxMin = energyMax[k]; + posEnergyMaxMin = k; + } + } + + for (b=startBand+maxNEnergyValues; b<stopBand; b++) { + if (energyBand[b] > energyMaxMin) { + energyMax[posEnergyMaxMin] = energyBand[b]; + no_enMaxBand[posEnergyMaxMin] = b; + + /* Again, get min. value in energyMax array */ + energyMaxMin = energyMax[0]; + posEnergyMaxMin = 0; + for (k=1; k<maxNEnergyValues; k++) { + if (energyMaxMin > energyMax[k]) { + energyMaxMin = energyMax[k]; + posEnergyMaxMin = k; + } + } + } + } + /*** End determine 5 highest band-energies ***/ + + /* Get tonality values for 5 highest energies */ + for (e=0; e<maxNEnergyValues; e++) { + tonalityBand[e]=FL2FXCONST_DBL(0.0f); + for (k=0; k<noEstPerFrame; k++) { + tonalityBand[e] += quotaMatrix[startIndex + k][no_enMaxBand[e]] >> 1; + } + globalTonality += tonalityBand[e] >> 2; /* headroom of 2+1 (max. 5 additions) */ + } + + return globalTonality; +} + /***************************************************************************/ /*! @@ -919,10 +1027,42 @@ FDKsbrEnc_extractSbrEnvelope1 ( hEnvChan->qmfScale); + if(h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + FIXP_DBL tonality = FDKsbrEnc_GetTonality ( + hEnvChan->TonCorr.quotaMatrix, + hEnvChan->TonCorr.numberOfEstimatesPerFrame, + hEnvChan->TonCorr.startIndexMatrix, + sbrExtrEnv->YBuffer + sbrExtrEnv->YBufferWriteOffset, + h_con->freqBandTable[HI][0]+1, + h_con->noQmfBands, + sbrExtrEnv->no_cols + ); + + hEnvChan->encEnvData.ton_HF[1] = hEnvChan->encEnvData.ton_HF[0]; + hEnvChan->encEnvData.ton_HF[0] = tonality; + + /* tonality is scaled by 2^19/0.524288f (fract part of RELAXATION) */ + hEnvChan->encEnvData.global_tonality = (hEnvChan->encEnvData.ton_HF[0]>>1) + (hEnvChan->encEnvData.ton_HF[1]>>1); + } + + /* Transient detection COEFF Transform OK */ + if(h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + { + FDKsbrEnc_fastTransientDetect( + &hEnvChan->sbrFastTransientDetector, + sbrExtrEnv->YBuffer, + sbrExtrEnv->YBufferScale, + sbrExtrEnv->YBufferWriteOffset, + eData->transient_info + ); + + } + else + { FDKsbrEnc_transientDetect(&hEnvChan->sbrTransientDetector, sbrExtrEnv->YBuffer, sbrExtrEnv->YBufferScale, @@ -931,6 +1071,7 @@ FDKsbrEnc_extractSbrEnvelope1 ( sbrExtrEnv->YBufferSzShift, sbrExtrEnv->time_step, hEnvChan->SbrEnvFrame.frameMiddleSlot); + } @@ -951,7 +1092,8 @@ FDKsbrEnc_extractSbrEnvelope1 ( sbrExtrEnv->YBufferSzShift, h_con->nSfb[1], sbrExtrEnv->time_step, - sbrExtrEnv->no_cols); + sbrExtrEnv->no_cols, + &hEnvChan->encEnvData.global_tonality); } @@ -1128,12 +1270,26 @@ FDKsbrEnc_extractSbrEnvelope2 ( && ( ed->nEnvelopes == 1 ) ) { - if (hEnvChan->encEnvData.ldGrid) - hEnvChan->encEnvData.currentAmpResFF = (AMP_RES)h_con->initAmpResFF; - else + if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + { + /* Note: global_tonaliy_float_value == ((float)hEnvChan->encEnvData.global_tonality/((INT64)(1)<<(31-(19+2)))/0.524288*(2.0/3.0))); + threshold_float_value == ((float)h_con->thresholdAmpResFF_m/((INT64)(1)<<(31-(h_con->thresholdAmpResFF_e)))/0.524288*(2.0/3.0))); */ + /* decision of SBR_AMP_RES */ + if (fIsLessThan( /* global_tonality > threshold ? */ + h_con->thresholdAmpResFF_m, h_con->thresholdAmpResFF_e, + hEnvChan->encEnvData.global_tonality, RELAXATION_SHIFT+2 ) + ) + { + hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_1_5; + } + else { + hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_3_0; + } + } else { hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_1_5; + } - if ( hEnvChan->encEnvData.currentAmpResFF != hEnvChan->encEnvData.init_sbr_amp_res) { + if ( hEnvChan->encEnvData.currentAmpResFF != hEnvChan->encEnvData.init_sbr_amp_res) { FDKsbrEnc_InitSbrHuffmanTables(&hEnvChan->encEnvData, &hEnvChan->sbrCodeEnvelope, @@ -1172,7 +1328,12 @@ FDKsbrEnc_extractSbrEnvelope2 ( } /* Low energy in low band fix */ - if ( hEnvChan->sbrTransientDetector.prevLowBandEnergy < hEnvChan->sbrTransientDetector.prevHighBandEnergy && hEnvChan->sbrTransientDetector.prevHighBandEnergy > FL2FX_DBL(0.03)) + if ( hEnvChan->sbrTransientDetector.prevLowBandEnergy < hEnvChan->sbrTransientDetector.prevHighBandEnergy + && hEnvChan->sbrTransientDetector.prevHighBandEnergy > FL2FX_DBL(0.03) + /* The fix needs the non-fast transient detector running. + It sets prevLowBandEnergy and prevHighBandEnergy. */ + && !(h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + ) { int i; diff --git a/libSBRenc/src/env_est.h b/libSBRenc/src/env_est.h index 5e632a4..e17a974 100644 --- a/libSBRenc/src/env_est.h +++ b/libSBRenc/src/env_est.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -127,6 +127,7 @@ typedef SBR_EXTRACT_ENVELOPE *HANDLE_SBR_EXTRACT_ENVELOPE; struct ENV_CHANNEL { + FAST_TRAN_DETECTOR sbrFastTransientDetector; SBR_TRANSIENT_DETECTOR sbrTransientDetector; SBR_CODE_ENVELOPE sbrCodeEnvelope; SBR_CODE_ENVELOPE sbrCodeNoiseFloor; diff --git a/libSBRenc/src/fram_gen.cpp b/libSBRenc/src/fram_gen.cpp index 86c3c81..9a35111 100644 --- a/libSBRenc/src/fram_gen.cpp +++ b/libSBRenc/src/fram_gen.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -266,7 +266,7 @@ static void calcCtrlSignal (HANDLE_SBR_GRID hSbrGrid, FRAME_CLASS frameClass, static void ctrlSignal2FrameInfo (HANDLE_SBR_GRID hSbrGrid, HANDLE_SBR_FRAME_INFO hFrameInfo, - INT freq_res_fixfix); + FREQ_RES *freq_res_fixfix); /* table for 8 time slot index */ @@ -341,8 +341,9 @@ static const FREQ_RES freqRes_table_16[16] = { static void generateFixFixOnly ( HANDLE_SBR_FRAME_INFO hSbrFrameInfo, HANDLE_SBR_GRID hSbrGrid, int tranPosInternal, - int numberTimeSlots - ); + int numberTimeSlots, + UCHAR fResTransIsLow + ); /*! @@ -402,11 +403,10 @@ FDKsbrEnc_frameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, const int *v_tuningFreq = v_tuning + 3; hSbrEnvFrame->v_tuningSegm = v_tuningSegm; - INT freq_res_fixfix = hSbrEnvFrame->freq_res_fixfix; if (ldGrid) { /* in case there was a transient at the very end of the previous frame, start with a transient envelope */ - if(v_transient_info_pre[1] && (numberTimeSlots - v_transient_info_pre[0] < minFrameTranDistance)){ + if ( !tranFlag && v_transient_info_pre[1] && (numberTimeSlots - v_transient_info_pre[0] < minFrameTranDistance) ){ tranFlag = 1; tranPos = 0; } @@ -529,7 +529,8 @@ FDKsbrEnc_frameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, generateFixFixOnly ( &(hSbrEnvFrame->SbrFrameInfo), &(hSbrEnvFrame->SbrGrid), tranPosInternal, - numberTimeSlots + numberTimeSlots, + hSbrEnvFrame->fResTransIsLow ); return &(hSbrEnvFrame->SbrFrameInfo); @@ -677,7 +678,7 @@ FDKsbrEnc_frameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, ---------------------------------------------------------------------------*/ ctrlSignal2FrameInfo (&hSbrEnvFrame->SbrGrid, &hSbrEnvFrame->SbrFrameInfo, - freq_res_fixfix); + hSbrEnvFrame->freq_res_fixfix); return &hSbrEnvFrame->SbrFrameInfo; } @@ -692,7 +693,8 @@ FDKsbrEnc_frameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, static void generateFixFixOnly ( HANDLE_SBR_FRAME_INFO hSbrFrameInfo, HANDLE_SBR_GRID hSbrGrid, int tranPosInternal, - int numberTimeSlots + int numberTimeSlots, + UCHAR fResTransIsLow ) { int nEnv, i, k=0, tranIdx; @@ -727,8 +729,12 @@ static void generateFixFixOnly ( HANDLE_SBR_FRAME_INFO hSbrFrameInfo, /* adjust segment-frequency-resolution according to the segment-length */ for (i=0; i<nEnv; i++){ k = hSbrFrameInfo->borders[i+1] - hSbrFrameInfo->borders[i]; - hSbrFrameInfo->freqRes[i] = freqResTable[k]; - hSbrGrid->v_f[i] = freqResTable[k]; + if (!fResTransIsLow) + hSbrFrameInfo->freqRes[i] = freqResTable[k]; + else + hSbrFrameInfo->freqRes[i] = FREQ_RES_LOW; + + hSbrGrid->v_f[i] = hSbrFrameInfo->freqRes[i]; } hSbrFrameInfo->nEnvelopes = nEnv; @@ -765,15 +771,16 @@ static void generateFixFixOnly ( HANDLE_SBR_FRAME_INFO hSbrFrameInfo, *******************************************************************************/ void -FDKsbrEnc_initFrameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, - INT allowSpread, - INT numEnvStatic, - INT staticFraming, - INT timeSlots, - INT freq_res_fixfix - ,int ldGrid - ) - +FDKsbrEnc_initFrameInfoGenerator ( + HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, + INT allowSpread, + INT numEnvStatic, + INT staticFraming, + INT timeSlots, + const FREQ_RES* freq_res_fixfix + ,UCHAR fResTransIsLow, + INT ldGrid + ) { /* FH 00-06-26 */ FDKmemclear(hSbrEnvFrame,sizeof(SBR_ENVELOPE_FRAME )); @@ -786,7 +793,9 @@ FDKsbrEnc_initFrameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, hSbrEnvFrame->allowSpread = allowSpread; hSbrEnvFrame->numEnvStatic = numEnvStatic; hSbrEnvFrame->staticFraming = staticFraming; - hSbrEnvFrame->freq_res_fixfix = freq_res_fixfix; + hSbrEnvFrame->freq_res_fixfix[0] = freq_res_fixfix[0]; + hSbrEnvFrame->freq_res_fixfix[1] = freq_res_fixfix[1]; + hSbrEnvFrame->fResTransIsLow = fResTransIsLow; hSbrEnvFrame->length_v_bord = 0; hSbrEnvFrame->length_v_bordFollow = 0; @@ -804,6 +813,7 @@ FDKsbrEnc_initFrameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, hSbrEnvFrame->dmin = 2; hSbrEnvFrame->dmax = 16; hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_512LD; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; } else switch(timeSlots){ case NUMBER_TIME_SLOTS_1920: @@ -1862,19 +1872,28 @@ createDefFrameInfo(HANDLE_SBR_FRAME_INFO hSbrFrameInfo, INT nEnv, INT nTimeSlots Functionname: ctrlSignal2FrameInfo ******************************************************************************* - Description: Calculates frame_info struct from control signal. + Description: Convert "clear-text" sbr_grid() to "frame info" used by the + envelope and noise floor estimators. + This is basically (except for "low level" calculations) the + bitstream decoder defined in the MPEG-4 standard, sub clause + 4.6.18.3.3, Time / Frequency Grid. See inline comments for + explanation of the shorten and noise border algorithms. Arguments: hSbrGrid - source hSbrFrameInfo - destination + freq_res_fixfix - frequency resolution for FIXFIX frames Return: void; hSbrFrameInfo contains the updated FRAME_INFO struct *******************************************************************************/ static void -ctrlSignal2FrameInfo (HANDLE_SBR_GRID hSbrGrid, - HANDLE_SBR_FRAME_INFO hSbrFrameInfo, - INT freq_res_fixfix) +ctrlSignal2FrameInfo ( + HANDLE_SBR_GRID hSbrGrid, /* input : the grid handle */ + HANDLE_SBR_FRAME_INFO hSbrFrameInfo, /* output: the frame info handle */ + FREQ_RES *freq_res_fixfix /* in/out: frequency resolution for FIXFIX frames */ + ) { + INT frameSplit = 0; INT nEnv = 0, border = 0, i, k, p /*?*/; INT *v_r = hSbrGrid->bs_rel_bord; INT *v_f = hSbrGrid->v_f; @@ -1887,17 +1906,10 @@ ctrlSignal2FrameInfo (HANDLE_SBR_GRID hSbrGrid, case FIXFIX: createDefFrameInfo(hSbrFrameInfo, hSbrGrid->bs_num_env, numberTimeSlots); - /* At this point all frequency resolutions are set to FREQ_RES_HIGH, so - * only if freq_res_fixfix is set to FREQ_RES_LOW, they all have to be - * changed. - * snd */ - if (freq_res_fixfix == FREQ_RES_LOW) { - for (i = 0; i < hSbrFrameInfo->nEnvelopes; i++) { - hSbrFrameInfo->freqRes[i] = FREQ_RES_LOW; - } + frameSplit = (hSbrFrameInfo->nEnvelopes > 1); + for (i = 0; i < hSbrFrameInfo->nEnvelopes; i++) { + hSbrGrid->v_f[i] = hSbrFrameInfo->freqRes[i] = freq_res_fixfix[frameSplit]; } - /* ELD: store current frequency resolution */ - hSbrGrid->v_f[0] = hSbrFrameInfo->freqRes[0]; break; case FIXVAR: diff --git a/libSBRenc/src/fram_gen.h b/libSBRenc/src/fram_gen.h index 3769266..00473d4 100644 --- a/libSBRenc/src/fram_gen.h +++ b/libSBRenc/src/fram_gen.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -89,6 +89,7 @@ amm-info@iis.fraunhofer.de #define _FRAM_GEN_H #include "sbr_def.h" /* for MAX_ENVELOPES and MAX_NOISE_ENVELOPES in struct FRAME_INFO and CODEC_TYPE */ +#include "sbr_encoder.h" /* for FREQ_RES */ #define MAX_ENVELOPES_VARVAR MAX_ENVELOPES /*!< worst case number of envelopes in a VARVAR frame */ #define MAX_ENVELOPES_FIXVAR_VARFIX 4 /*!< worst case number of envelopes in VARFIX and FIXVAR frames */ @@ -114,7 +115,7 @@ typedef enum { #define NUMBER_TIME_SLOTS_1920 15 #define LD_PRETRAN_OFF 3 -#define FRAME_MIDDLE_SLOT_512LD 0 +#define FRAME_MIDDLE_SLOT_512LD 4 #define NUMBER_TIME_SLOTS_512LD 8 #define TRANSIENT_OFFSET_LD 0 @@ -248,9 +249,10 @@ typedef struct INT frameMiddleSlot; /*!< transient detector offset in SBR timeslots */ /* basic tuning parameters */ - INT staticFraming; /*!< 1: run static framing in time, i.e. exclusive use of bs_frame_class = FIXFIX */ - INT numEnvStatic; /*!< number of envelopes per frame for static framing */ - INT freq_res_fixfix; /*!< envelope frequency resolution to use for bs_frame_class = FIXFIX */ + INT staticFraming; /*!< 1: run static framing in time, i.e. exclusive use of bs_frame_class = FIXFIX */ + INT numEnvStatic; /*!< number of envelopes per frame for static framing */ + FREQ_RES freq_res_fixfix[2]; /*!< envelope frequency resolution to use for bs_frame_class = FIXFIX; single env and split */ + UCHAR fResTransIsLow; /*!< frequency resolution for transient frames - always low (0) or according to table (1) */ /* expert tuning parameters */ const int *v_tuningSegm; /*!< segment lengths to use around transient */ @@ -286,14 +288,16 @@ typedef SBR_ENVELOPE_FRAME *HANDLE_SBR_ENVELOPE_FRAME; void -FDKsbrEnc_initFrameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, - INT allowSpread, - INT numEnvStatic, - INT staticFraming, - INT timeSlots, - INT freq_res_fixfix - ,int ldGrid - ); +FDKsbrEnc_initFrameInfoGenerator ( + HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, + INT allowSpread, + INT numEnvStatic, + INT staticFraming, + INT timeSlots, + const FREQ_RES* freq_res_fixfix + ,UCHAR fResTransIsLow, + INT ldGrid + ); HANDLE_SBR_FRAME_INFO FDKsbrEnc_frameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, diff --git a/libSBRenc/src/mh_det.cpp b/libSBRenc/src/mh_det.cpp index 73d1b8b..bc80a15 100644 --- a/libSBRenc/src/mh_det.cpp +++ b/libSBRenc/src/mh_det.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -663,10 +663,27 @@ static void transientCleanUp(FIXP_DBL **quotaBuffer, } -/**************************************************************************/ +/*****************************************************************************/ /*! - \brief Do detection for one tonality estimate. + \brief Detection for one tonality estimate. + + This is the actual missing harmonics detection, using information from the + previous detection. + + If a missing harmonic was detected (in a previous frame) due to too high + tonality differences, but there was not enough tonality difference in the + current frame, the detection algorithm still continues to trace the strongest + tone in the scalefactor band (assuming that this is the tone that is going to + be replaced in the decoder). This is done to avoid abrupt endings of sines + fading out (e.g. in the glockenspiel). + + The function also tries to estimate where one sine is going to be replaced + with multiple sines (due to the patching). This is done by comparing the + tonality flatness measure of the original and the SBR signal. + The function also tries to estimate (for the scalefactor bands only + containing one qmf subband) when a strong tone in the original will be + replaced by a strong tone in the adjacent QMF subband. \return none. @@ -694,10 +711,10 @@ static void detection(FIXP_DBL *quotaBuffer, for(i=0;i<nSfb;i++){ thresTemp = (guideVectors.guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)) - ? fixMax(fMult(mhThresh.decayGuideDiff,guideVectors.guideVectorDiff[i]), mhThresh.thresHoldDiffGuide) + ? fMax(fMult(mhThresh.decayGuideDiff,guideVectors.guideVectorDiff[i]), mhThresh.thresHoldDiffGuide) : mhThresh.thresHoldDiff; - thresTemp = fixMin(thresTemp, mhThresh.thresHoldDiff); + thresTemp = fMin(thresTemp, mhThresh.thresHoldDiff); if(pDiffVecScfb[i] > thresTemp){ pHarmVec[i] = 1; @@ -813,8 +830,11 @@ static void detectionWithPrediction(FIXP_DBL **quotaBuffer, if(newDetectionAllowed){ + /* Since we don't want to use the transient region for detection (since the tonality values + tend to be a bit unreliable for this region) the guide-values are copied to the current + starting point. */ if(totNoEst > 1){ - start = detectionStart; + start = detectionStart+1; if (start != 0) { FDKmemcpy(guideVectors[start].guideVectorDiff,guideVectors[0].guideVectorDiff,nSfb*sizeof(FIXP_DBL)); diff --git a/libSBRenc/src/nf_est.cpp b/libSBRenc/src/nf_est.cpp index 7a3c022..a4c5574 100644 --- a/libSBRenc/src/nf_est.cpp +++ b/libSBRenc/src/nf_est.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -268,8 +268,9 @@ qmfBasedNoiseFloorDetection(FIXP_DBL *noiseLevel, /*!< Pointer to v /* * Add a noise floor offset to compensate for bias in the detector *****************************************************************/ - if(!missingHarmonicFlag) - *noiseLevel = fMult(*noiseLevel, noiseFloorOffset)<<(NOISE_FLOOR_OFFSET_SCALING); + if(!missingHarmonicFlag) { + *noiseLevel = fixMin(fMult(*noiseLevel, noiseFloorOffset), (FIXP_DBL)MAXVAL_DBL>>NOISE_FLOOR_OFFSET_SCALING) << NOISE_FLOOR_OFFSET_SCALING; + } /* * check to see that we don't exceed the maximum allowed level @@ -297,7 +298,7 @@ FDKsbrEnc_sbrNoiseFloorEstimateQmf(HANDLE_SBR_NOISE_FLOOR_ESTIMATE h_sbrNoiseFlo SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component will be missing. */ INT startIndex, /*!< Start index. */ - int numberOfEstimatesPerFrame, /*!< The number of tonality estimates per frame. */ + UINT numberOfEstimatesPerFrame, /*!< The number of tonality estimates per frame. */ int transientFrame, /*!< A flag indicating if a transient is present. */ INVF_MODE* pInvFiltLevels, /*!< Pointer to the vector holding the inverse filtering levels. */ UINT sbrSyntaxFlags diff --git a/libSBRenc/src/nf_est.h b/libSBRenc/src/nf_est.h index d407274..f26f74f 100644 --- a/libSBRenc/src/nf_est.h +++ b/libSBRenc/src/nf_est.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -119,7 +119,7 @@ FDKsbrEnc_sbrNoiseFloorEstimateQmf(HANDLE_SBR_NOISE_FLOOR_ESTIMATE h_sbrNoiseFlo SCHAR* indexVector, /*!< Index vector to obtain the patched data. */ INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component will be missing. */ INT startIndex, /*!< Start index. */ - int numberOfEstimatesPerFrame, /*!< The number of tonality estimates per frame. */ + UINT numberOfEstimatesPerFrame, /*!< The number of tonality estimates per frame. */ INT transientFrame, /*!< A flag indicating if a transient is present. */ INVF_MODE* pInvFiltLevels, /*!< Pointer to the vector holding the inverse filtering levels. */ UINT sbrSyntaxFlags diff --git a/libSBRenc/src/ps_bitenc.cpp b/libSBRenc/src/ps_bitenc.cpp index b1fe12e..420ea15 100644 --- a/libSBRenc/src/ps_bitenc.cpp +++ b/libSBRenc/src/ps_bitenc.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -261,21 +261,23 @@ static const UINT opdDeltaTime_Code[] = 0x00000001, 0x00000002, 0x00000001, 0x00000007, 0x00000006, 0000000000, 0x00000002, 0x00000003 }; -static const INT psBands[] = +static INT getNoBands(const INT mode) { - PS_BANDS_COARSE, - PS_BANDS_MID -}; - -static INT getNoBands(PS_RESOLUTION mode) -{ - if(mode>=6) - return 0; + INT noBands = 0; - if(mode>=3) - mode = (PS_RESOLUTION)(mode-3); + switch (mode) { + case 0: case 3: /* coarse */ + noBands = PS_BANDS_COARSE; + break; + case 1: case 4: /* mid */ + noBands = PS_BANDS_MID; + break; + case 2: case 5: /* fine not supported */ + default: /* coarse as default */ + noBands = PS_BANDS_COARSE; + } - return psBands[mode]; + return noBands; } static INT getIIDRes(INT iidMode) @@ -524,7 +526,7 @@ static INT encodeIpdOpd(HANDLE_PS_OUT psOut, bitCnt += FDKsbrEnc_EncodeIpd( hBitBuf, psOut->ipd[env], ipdLast, - getNoBands((PS_RESOLUTION)psOut->iidMode), + getNoBands(psOut->iidMode), psOut->deltaIPD[env], &error); @@ -532,7 +534,7 @@ static INT encodeIpdOpd(HANDLE_PS_OUT psOut, bitCnt += FDKsbrEnc_EncodeOpd( hBitBuf, psOut->opd[env], opdLast, - getNoBands((PS_RESOLUTION)psOut->iidMode), + getNoBands(psOut->iidMode), psOut->deltaOPD[env], &error ); } @@ -661,7 +663,7 @@ INT FDKsbrEnc_WritePSBitstream(const HANDLE_PS_OUT psOut, bitCnt += FDKsbrEnc_EncodeIid( hBitBuf, psOut->iid[env], iidLast, - getNoBands((PS_RESOLUTION)psOut->iidMode), + getNoBands(psOut->iidMode), (PS_IID_RESOLUTION)getIIDRes(psOut->iidMode), psOut->deltaIID[env], &error ); @@ -677,7 +679,7 @@ INT FDKsbrEnc_WritePSBitstream(const HANDLE_PS_OUT psOut, bitCnt += FDKsbrEnc_EncodeIcc( hBitBuf, psOut->icc[env], iccLast, - getNoBands((PS_RESOLUTION)psOut->iccMode), + getNoBands(psOut->iccMode), psOut->deltaICC[env], &error); diff --git a/libSBRenc/src/ps_encode.cpp b/libSBRenc/src/ps_encode.cpp index 2ae2788..fec39e8 100644 --- a/libSBRenc/src/ps_encode.cpp +++ b/libSBRenc/src/ps_encode.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -149,21 +149,21 @@ typedef enum { static const FIXP_DBL iidQuant_fx[15] = { - 0xce000000, 0xdc000000, 0xe4000000, 0xec000000, 0xf2000000, 0xf8000000, 0xfc000000, 0x00000000, - 0x04000000, 0x08000000, 0x0e000000, 0x14000000, 0x1c000000, 0x24000000, 0x32000000 + (FIXP_DBL)0xce000000, (FIXP_DBL)0xdc000000, (FIXP_DBL)0xe4000000, (FIXP_DBL)0xec000000, (FIXP_DBL)0xf2000000, (FIXP_DBL)0xf8000000, (FIXP_DBL)0xfc000000, (FIXP_DBL)0x00000000, + (FIXP_DBL)0x04000000, (FIXP_DBL)0x08000000, (FIXP_DBL)0x0e000000, (FIXP_DBL)0x14000000, (FIXP_DBL)0x1c000000, (FIXP_DBL)0x24000000, (FIXP_DBL)0x32000000 }; static const FIXP_DBL iidQuantFine_fx[31] = { - 0x9c000001, 0xa6000001, 0xb0000001, 0xba000001, 0xc4000000, 0xce000000, 0xd4000000, 0xda000000, - 0xe0000000, 0xe6000000, 0xec000000, 0xf0000000, 0xf4000000, 0xf8000000, 0xfc000000, 0x00000000, - 0x04000000, 0x08000000, 0x0c000000, 0x10000000, 0x14000000, 0x1a000000, 0x20000000, 0x26000000, - 0x2c000000, 0x32000000, 0x3c000000, 0x45ffffff, 0x4fffffff, 0x59ffffff, 0x63ffffff + (FIXP_DBL)0x9c000001, (FIXP_DBL)0xa6000001, (FIXP_DBL)0xb0000001, (FIXP_DBL)0xba000001, (FIXP_DBL)0xc4000000, (FIXP_DBL)0xce000000, (FIXP_DBL)0xd4000000, (FIXP_DBL)0xda000000, + (FIXP_DBL)0xe0000000, (FIXP_DBL)0xe6000000, (FIXP_DBL)0xec000000, (FIXP_DBL)0xf0000000, (FIXP_DBL)0xf4000000, (FIXP_DBL)0xf8000000, (FIXP_DBL)0xfc000000, (FIXP_DBL)0x00000000, + (FIXP_DBL)0x04000000, (FIXP_DBL)0x08000000, (FIXP_DBL)0x0c000000, (FIXP_DBL)0x10000000, (FIXP_DBL)0x14000000, (FIXP_DBL)0x1a000000, (FIXP_DBL)0x20000000, (FIXP_DBL)0x26000000, + (FIXP_DBL)0x2c000000, (FIXP_DBL)0x32000000, (FIXP_DBL)0x3c000000, (FIXP_DBL)0x45ffffff, (FIXP_DBL)0x4fffffff, (FIXP_DBL)0x59ffffff, (FIXP_DBL)0x63ffffff }; static const FIXP_DBL iccQuant[8] = { - 0x7fffffff, 0x77ef9d7f, 0x6babc97f, 0x4ceaf27f, 0x2f0ed3c0, 0x00000000, 0xb49ba601, 0x80000000 + (FIXP_DBL)0x7fffffff, (FIXP_DBL)0x77ef9d7f, (FIXP_DBL)0x6babc97f, (FIXP_DBL)0x4ceaf27f, (FIXP_DBL)0x2f0ed3c0, (FIXP_DBL)0x00000000, (FIXP_DBL)0xb49ba601, (FIXP_DBL)0x80000000 }; static FDK_PSENC_ERROR InitPSData( diff --git a/libSBRenc/src/sbr_def.h b/libSBRenc/src/sbr_def.h index 8b7cfc6..85ac587 100644 --- a/libSBRenc/src/sbr_def.h +++ b/libSBRenc/src/sbr_def.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -122,6 +122,8 @@ amm-info@iis.fraunhofer.de /************ Definitions ***************/ #define SBR_COMP_MODE_DELTA 0 #define SBR_COMP_MODE_CTS 1 +#define SBR_MAX_ENERGY_VALUES 5 +#define SBR_GLOBAL_TONALITY_VALUES 2 #define MAX_NUM_CHANNELS 2 @@ -232,6 +234,8 @@ amm-info@iis.fraunhofer.de #define FREQ 0 #define TIME 1 +/* qmf data scaling */ +#define QMF_SCALE_OFFSET 7 /* huffman tables */ #define CODE_BOOK_SCF_LAV00 60 @@ -268,12 +272,4 @@ typedef enum } INVF_MODE; -typedef enum -{ - FREQ_RES_LOW = 0, - FREQ_RES_HIGH -} -FREQ_RES; - - #endif diff --git a/libSBRenc/src/sbr_encoder.cpp b/libSBRenc/src/sbr_encoder.cpp index abe9793..86a3f91 100644 --- a/libSBRenc/src/sbr_encoder.cpp +++ b/libSBRenc/src/sbr_encoder.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -103,7 +103,7 @@ amm-info@iis.fraunhofer.de #define SBRENCODER_LIB_VL0 3 #define SBRENCODER_LIB_VL1 3 -#define SBRENCODER_LIB_VL2 4 +#define SBRENCODER_LIB_VL2 12 @@ -170,7 +170,6 @@ getSbrTuningTableIndex(UINT bitrate, /*! the total bitrate in bits/sec */ { int i, bitRateClosestLowerIndex=-1, bitRateClosestUpperIndex=-1, found = 0; UINT bitRateClosestUpper = 0, bitRateClosestLower=DISTANCE_CEIL_VALUE; - int isforThisCodec=0; #define isForThisCore(i) \ ( ( sbrTuningTable[i].coreCoder == CODEC_AACLD && core == AOT_ER_AAC_ELD ) || \ @@ -413,6 +412,23 @@ FDKsbrEnc_AdjustSbrSettings (const sbrConfigurationPtr config, /*! output, modif config->codecSettings.transFac = transFac; config->codecSettings.standardBitrate = standardBitrate; + if (bitRate < 28000) { + config->threshold_AmpRes_FF_m = (FIXP_DBL)MAXVAL_DBL; + config->threshold_AmpRes_FF_e = 7; + } + else if (bitRate >= 28000 && bitRate <= 48000) { + /* The float threshold is 75 + 0.524288f is fractional part of RELAXATION, the quotaMatrix and therefore tonality are scaled by this + 2/3 is because the original implementation divides the tonality values by 3, here it's divided by 2 + 128 compensates the necessary shiftfactor of 7 */ + config->threshold_AmpRes_FF_m = FL2FXCONST_DBL(75.0f*0.524288f/(2.0f/3.0f)/128.0f); + config->threshold_AmpRes_FF_e = 7; + } + else if (bitRate > 48000) { + config->threshold_AmpRes_FF_m = FL2FXCONST_DBL(0); + config->threshold_AmpRes_FF_e = 0; + } + if (bitRate==0) { /* map vbr quality to bitrate */ if (vbrMode < 30) @@ -468,6 +484,57 @@ FDKsbrEnc_AdjustSbrSettings (const sbrConfigurationPtr config, /*! output, modif config->stereoMode = sbrTuningTable[idx].stereoMode ; config->freqScale = sbrTuningTable[idx].freqScale ; + if (numChannels == 1) { + /* stereo case */ + switch (core) { + case AOT_AAC_LC: + if (bitRate <= (useSpeechConfig?24000U:20000U)) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency resolution for non-split frames */ + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency resolution for split frames */ + } + break; + case AOT_ER_AAC_ELD: + if (bitRate < 36000) + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency resolution for split frames */ + if (bitRate < 26000) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency resolution for non-split frames */ + config->fResTransIsLow = 1; /* for transient frames, set low frequency resolution */ + } + break; + default: + break; + } + } + else { + /* stereo case */ + switch (core) { + case AOT_AAC_LC: + if (bitRate <= 28000) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency resolution for non-split frames */ + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency resolution for split frames */ + } + break; + case AOT_ER_AAC_ELD: + if (bitRate < 72000) { + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency resolution for split frames */ + } + if (bitRate < 52000) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency resolution for non-split frames */ + config->fResTransIsLow = 1; /* for transient frames, set low frequency resolution */ + } + break; + default: + break; + } + if (bitRate <= 28000) { + /* + additionally restrict frequency resolution in FIXFIX frames + to further reduce SBR payload size */ + config->freq_res_fixfix[0] = FREQ_RES_LOW; + config->freq_res_fixfix[1] = FREQ_RES_LOW; + } + } + /* adjust usage of parametric coding dependent on bitrate and speech config flag */ if (useSpeechConfig) config->parametricCoding = 0; @@ -516,6 +583,7 @@ static UINT FDKsbrEnc_InitializeSbrDefaults (sbrConfigurationPtr config, INT downSampleFactor, UINT codecGranuleLen + ,const INT isLowDelay ) { if ( (downSampleFactor < 1 || downSampleFactor > 2) || @@ -526,7 +594,11 @@ FDKsbrEnc_InitializeSbrDefaults (sbrConfigurationPtr config, config->useWaveCoding = 0; config->crcSbr = 0; config->dynBwSupported = 1; - config->tran_thr = 13000; + if (isLowDelay) + config->tran_thr = 6000; + else + config->tran_thr = 13000; + config->parametricCoding = 1; config->sbrFrameSize = codecGranuleLen * downSampleFactor; @@ -559,7 +631,9 @@ FDKsbrEnc_InitializeSbrDefaults (sbrConfigurationPtr config, config->noiseFloorOffset = 0; config->startFreq = 5; /* 5.9 respectively 6.0 kHz at fs = 44.1/48 kHz */ config->stopFreq = 9; /* 16.2 respectively 16.8 kHz at fs = 44.1/48 kHz */ - + config->freq_res_fixfix[0] = FREQ_RES_HIGH; /* non-split case */ + config->freq_res_fixfix[1] = FREQ_RES_HIGH; /* split case */ + config->fResTransIsLow = 0; /* for transient frames, set variable frequency resolution according to freqResTable */ /* header_extra_1 */ config->freqScale = SBR_FREQ_SCALE_DEFAULT; @@ -854,7 +928,7 @@ FDKsbrEnc_EnvEncodeFrame(HANDLE_SBR_ENCODER hEnvEncoder, int clearOutput /*!< Do not consider any input signal */ ) { - HANDLE_SBR_ELEMENT hSbrElement = hEnvEncoder->sbrElement[iElement]; + HANDLE_SBR_ELEMENT hSbrElement = NULL; FDK_CRCINFO crcInfo; INT crcReg; INT ch; @@ -1207,7 +1281,10 @@ initEnvChannel ( HANDLE_SBR_CONFIG_DATA sbrConfigData, FDK_ASSERT(params->e >= 0); - hEnv->encEnvData.freq_res_fixfix = 1; + hEnv->encEnvData.freq_res_fixfix[0] = params->freq_res_fixfix[0]; + hEnv->encEnvData.freq_res_fixfix[1] = params->freq_res_fixfix[1]; + hEnv->encEnvData.fResTransIsLow = params->fResTransIsLow; + hEnv->fLevelProtect = 0; hEnv->encEnvData.ldGrid = (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) ? 1 : 0; @@ -1349,11 +1426,29 @@ initEnvChannel ( HANDLE_SBR_CONFIG_DATA sbrConfigData, e, params->stat, timeSlots, - hEnv->encEnvData.freq_res_fixfix - ,hEnv->encEnvData.ldGrid + hEnv->encEnvData.freq_res_fixfix, + hEnv->encEnvData.fResTransIsLow, + hEnv->encEnvData.ldGrid ); + if(sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + { + INT bandwidth_qmf_slot = (sbrConfigData->sampleFreq>>1) / (sbrConfigData->noQmfBands); + if(FDKsbrEnc_InitSbrFastTransientDetector( + &hEnv->sbrFastTransientDetector, + sbrConfigData->noQmfSlots, + bandwidth_qmf_slot, + sbrConfigData->noQmfBands, + sbrConfigData->freqBandTable[0][0] + )) + return(1); + } + + /* The transient detector has to be initialized also if the fast transient + detector was active, because the values from the transient detector + structure are used. */ if(FDKsbrEnc_InitSbrTransientDetector (&hEnv->sbrTransientDetector, + sbrConfigData->sbrSyntaxFlags, sbrConfigData->frameSize, sbrConfigData->sampleFreq, params, @@ -1553,12 +1648,6 @@ INT FDKsbrEnc_EnvInit ( hSbrElement->sbrConfigData.sbrSyntaxFlags = 0; switch (aot) { - case AOT_DRM_MPEG_PS: - case AOT_DRM_SBR: - hSbrElement->sbrConfigData.sbrSyntaxFlags |= SBR_SYNTAX_SCALABLE; - hSbrElement->sbrConfigData.sbrSyntaxFlags |= SBR_SYNTAX_DRM_CRC; - hSbrElement->sbrConfigData.sbrSyntaxFlags |= SBR_SYNTAX_CRC; - break; case AOT_ER_AAC_ELD: hSbrElement->sbrConfigData.sbrSyntaxFlags |= SBR_SYNTAX_LOW_DELAY; break; @@ -1665,6 +1754,8 @@ INT FDKsbrEnc_EnvInit ( /* other switches */ hSbrElement->sbrConfigData.useWaveCoding = params->useWaveCoding; hSbrElement->sbrConfigData.useParametricCoding = params->parametricCoding; + hSbrElement->sbrConfigData.thresholdAmpResFF_m = params->threshold_AmpRes_FF_m; + hSbrElement->sbrConfigData.thresholdAmpResFF_e = params->threshold_AmpRes_FF_e; /* init freq band table */ if(updateFreqBandTable(&hSbrElement->sbrConfigData, @@ -1848,7 +1939,7 @@ INT sbrEncoder_Init( - if ( (aot==AOT_PS) || (aot==AOT_MP2_PS) || (aot==AOT_DABPLUS_PS) || (aot==AOT_DRM_MPEG_PS) ) { + if ( (aot==AOT_PS) ) { usePs = 1; } if ( aot==AOT_ER_AAC_ELD ) { @@ -2006,7 +2097,8 @@ INT sbrEncoder_Init( */ if ( ! FDKsbrEnc_InitializeSbrDefaults ( &sbrConfig[el], *downSampleFactor, - coreFrameLength + coreFrameLength, + IS_LOWDELAY(aot) ) ) { error = 1; diff --git a/libSBRenc/src/sbr_rom.cpp b/libSBRenc/src/sbr_rom.cpp index a2b6527..7a51668 100644 --- a/libSBRenc/src/sbr_rom.cpp +++ b/libSBRenc/src/sbr_rom.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -684,6 +684,9 @@ const sbrTuningTable_t sbrTuningTable[] = /** AAC LOW DELAY SECTION **/ + /* 24 kHz dual rate - 12kHz singlerate is not allowed (deactivated in FDKsbrEnc_IsSbrSettingAvail()) */ + { CODEC_AACLD, 8000, 32000, 12000, 1, 1, 1, 0, 0, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 8 kbit/s */ + /*** mono ***/ /* 16/32 kHz dual rate not yet tuned ->alb copied from non LD tables*/ { CODEC_AACLD, 16000, 18000, 16000, 1, 4, 5, 9, 7, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s wrr: tuned */ @@ -702,10 +705,10 @@ const sbrTuningTable_t sbrTuningTable[] = { CODEC_AACLD, 52000, 64001, 22050, 1, 13,11,11,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 56 kbit/s */ /* 24/48 kHz dual rate */ - { CODEC_AACLD, 20000, 22000, 24000, 1, 4, 1, 8, 4, 2, 3, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */ + { CODEC_AACLD, 20000, 22000, 24000, 1, 3, 4, 8, 8, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */ { CODEC_AACLD, 22000, 28000, 24000, 1, 3, 8, 8, 7, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 24 kbit/s */ { CODEC_AACLD, 28000, 36000, 24000, 1, 4, 8, 8, 7, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 32 kbit/s */ - { CODEC_AACLD, 36000, 56000, 24000, 1, 8, 9, 9, 9, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 40 kbit/s */ + { CODEC_AACLD, 36000, 56000, 24000, 1, 8, 9, 9, 8, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 40 kbit/s */ { CODEC_AACLD, 56000, 64001, 24000, 1, 13,11,11,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 64 kbit/s */ /* 32/64 kHz dual rate */ /* placebo settings */ /*jgr: new, copy from CODEC_AAC */ @@ -722,7 +725,7 @@ const sbrTuningTable_t sbrTuningTable[] = { CODEC_AACLD, 100000,160001, 44100, 1, 13,13,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 128 */ /* 48/96 kHz dual rate */ /* 32 and 40kbps line tuned for dual-rate SBR */ - { CODEC_AACLD, 36000, 60000, 48000, 1, 8, 7, 6, 9, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 40 */ + { CODEC_AACLD, 36000, 60000, 48000, 1, 4, 7, 4, 4, 2, 0, 3, SBR_MONO, 3 }, /* nominal: 40 */ { CODEC_AACLD, 60000, 72000, 48000, 1, 9, 9,10,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 64 */ { CODEC_AACLD, 72000,100000, 48000, 1, 11,11,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 80 */ { CODEC_AACLD, 100000,160001, 48000, 1, 13,13,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 128 */ diff --git a/libSBRenc/src/ton_corr.cpp b/libSBRenc/src/ton_corr.cpp index 224da11..af5afba 100644 --- a/libSBRenc/src/ton_corr.cpp +++ b/libSBRenc/src/ton_corr.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -682,7 +682,7 @@ FDKsbrEnc_InitTonCorrParamExtr (INT frameSize, /*!< Current /* Reset the patching and allocate memory for the quota matrix. - Assing parameters for the LPC analysis. + Assuming parameters for the LPC analysis. */ if (sbrCfg->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { switch (timeSlots) { @@ -690,7 +690,7 @@ FDKsbrEnc_InitTonCorrParamExtr (INT frameSize, /*!< Current hTonCorr->lpcLength[0] = 8 - LPC_ORDER; hTonCorr->lpcLength[1] = 7 - LPC_ORDER; hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD; - hTonCorr->numberOfEstimatesPerFrame = sbrCfg->noQmfSlots / 7; + hTonCorr->numberOfEstimatesPerFrame = 2; /* sbrCfg->noQmfSlots / 7 */ hTonCorr->frameStartIndexInvfEst = 0; hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; break; @@ -698,7 +698,7 @@ FDKsbrEnc_InitTonCorrParamExtr (INT frameSize, /*!< Current hTonCorr->lpcLength[0] = 8 - LPC_ORDER; hTonCorr->lpcLength[1] = 8 - LPC_ORDER; hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD; - hTonCorr->numberOfEstimatesPerFrame = sbrCfg->noQmfSlots / 8; + hTonCorr->numberOfEstimatesPerFrame = 2; /* sbrCfg->noQmfSlots / 8 */ hTonCorr->frameStartIndexInvfEst = 0; hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; break; diff --git a/libSBRenc/src/ton_corr.h b/libSBRenc/src/ton_corr.h index 8c8425c..504ab03 100644 --- a/libSBRenc/src/ton_corr.h +++ b/libSBRenc/src/ton_corr.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -118,7 +118,7 @@ typedef struct INT bufferLength; /*!< Length of the r and i buffers. */ INT stepSize; /*!< Stride for the lpc estimate. */ INT numberOfEstimates; /*!< The total number of estiamtes, available in the quotaMatrix.*/ - INT numberOfEstimatesPerFrame; /*!< The number of estimates per frame available in the quotaMatrix.*/ + UINT numberOfEstimatesPerFrame; /*!< The number of estimates per frame available in the quotaMatrix.*/ INT lpcLength[2]; /*!< Segment length used for second order LPC analysis.*/ INT nextSample; /*!< Where to start the LPC analysis of the current frame.*/ INT move; /*!< How many estimates to move in the quotaMatrix, when buffering. */ diff --git a/libSBRenc/src/tran_det.cpp b/libSBRenc/src/tran_det.cpp index 1e0a59f..33ea60e 100644 --- a/libSBRenc/src/tran_det.cpp +++ b/libSBRenc/src/tran_det.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -89,7 +89,7 @@ amm-info@iis.fraunhofer.de #include "genericStds.h" -#define NORM_QMF_ENERGY 5.684341886080801486968994140625e-14 /* 2^-44 */ +#define NORM_QMF_ENERGY 9.31322574615479E-10 /* 2^-30 */ /* static FIXP_DBL ABS_THRES = fixMax( FL2FXCONST_DBL(1.28e5 * NORM_QMF_ENERGY), (FIXP_DBL)1) Minimum threshold for detecting changes */ #define ABS_THRES ((FIXP_DBL)16) @@ -106,22 +106,30 @@ amm-info@iis.fraunhofer.de \return calculated value *******************************************************************************/ +#define NRG_SHIFT 3 /* for energy summation */ + static FIXP_DBL spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS], INT *scaleEnergies, FIXP_DBL EnergyTotal, INT nSfb, INT start, INT border, - INT stop) + INT YBufferWriteOffset, + INT stop, + INT *result_e) { INT i,j; INT len1,len2; - FIXP_DBL delta,tmp0,tmp1,tmp2; - FIXP_DBL accu1,accu2,delta_sum,result; + SCHAR energies_e_diff[NUMBER_TIME_SLOTS_2304], energies_e, energyTotal_e=19, energies_e_add; + SCHAR prevEnergies_e_diff, newEnergies_e_diff; + FIXP_DBL tmp0,tmp1; + FIXP_DBL accu1,accu2,accu1_init,accu2_init; + FIXP_DBL delta, delta_sum; + INT accu_e, tmp_e; - FDK_ASSERT(scaleEnergies[0] >= 0); + delta_sum = FL2FXCONST_DBL(0.0f); + *result_e = 0; - /* equal for aac (would be not equal for mp3) */ len1 = border-start; len2 = stop-border; @@ -130,43 +138,91 @@ static FIXP_DBL spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FRE pos_weight = FL2FXCONST_DBL(0.5f) - (len1*GetInvInt(len1+len2)); pos_weight = /*FL2FXCONST_DBL(1.0)*/ (FIXP_DBL)MAXVAL_DBL - (fMult(pos_weight, pos_weight)<<2); - delta_sum = FL2FXCONST_DBL(0.0f); + /*** Calc scaling for energies ***/ + FDK_ASSERT(scaleEnergies[0] >= 0); + FDK_ASSERT(scaleEnergies[1] >= 0); + + energies_e = 19 - FDKmin(scaleEnergies[0], scaleEnergies[1]); + + /* limit shift for energy accumulation, energies_e can be -10 min. */ + if (energies_e < -10) { + energies_e_add = -10 - energies_e; + energies_e = -10; + } else if (energies_e > 17) { + energies_e_add = energies_e - 17; + energies_e = 17; + } else { + energies_e_add = 0; + } + + /* compensate scaling differences between scaleEnergies[0] and scaleEnergies[1] */ + prevEnergies_e_diff = scaleEnergies[0] - FDKmin(scaleEnergies[0], scaleEnergies[1]) + energies_e_add + NRG_SHIFT; + newEnergies_e_diff = scaleEnergies[1] - FDKmin(scaleEnergies[0], scaleEnergies[1]) + energies_e_add + NRG_SHIFT; + + prevEnergies_e_diff = fMin(prevEnergies_e_diff, DFRACT_BITS-1); + newEnergies_e_diff = fMin(newEnergies_e_diff, DFRACT_BITS-1); + + for (i=start; i<YBufferWriteOffset; i++) { + energies_e_diff[i] = prevEnergies_e_diff; + } + for (i=YBufferWriteOffset; i<stop; i++) { + energies_e_diff[i] = newEnergies_e_diff; + } /* Sum up energies of all QMF-timeslots for both halfs */ + FDK_ASSERT(len1<=8); /* otherwise an overflow is possible */ + FDK_ASSERT(len2<=8); /* otherwise an overflow is possible */ + /* init with some energy to prevent division by zero + and to prevent splitting for very low levels */ + accu1_init = scaleValue((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY))),-energies_e); + accu2_init = scaleValue((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY))),-energies_e); + accu1_init = fMult(accu1_init, (FIXP_DBL)len1<<((DFRACT_BITS-1)-NRG_SHIFT-1))<<1; + accu2_init = fMult(accu2_init, (FIXP_DBL)len2<<((DFRACT_BITS-1)-NRG_SHIFT-1))<<1; + for (j=0; j<nSfb; j++) { - #define NRG_SCALE 3 - /* init with some energy to prevent division by zero - and to prevent splitting for very low levels */ - accu1 = ((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY*8.0/32))) << fixMin(scaleEnergies[0],25))>>NRG_SCALE; /* complex init for compare with original version */ - accu2 = ((FL2FXCONST_DBL((1.0e6*NORM_QMF_ENERGY*8.0/32))) << fixMin(scaleEnergies[0],25))>>NRG_SCALE; /* can be simplified in dsp implementation */ + + accu1 = accu1_init; + accu2 = accu2_init; + accu_e = energies_e+3; /* Sum up energies in first half */ for (i=start; i<border; i++) { - accu1 += (Energies[i][j]>>NRG_SCALE); + accu1 += scaleValue(Energies[i][j], -energies_e_diff[i]); } /* Sum up energies in second half */ for (i=border; i<stop; i++) { - accu2 += (Energies[i][j]>>NRG_SCALE); + accu2 += scaleValue(Energies[i][j], -energies_e_diff[i]); } /* Energy change in current band */ - tmp0 = CalcLdData(accu2); - tmp1 = CalcLdData(accu1); - tmp2 = (tmp0 - tmp1 + CalcLdData(len1)-CalcLdData(len2)); - delta = fixp_abs(fMult(tmp2, FL2FXCONST_DBL(0.6931471806f))); + #define LN2 FL2FXCONST_DBL(0.6931471806f) /* ln(2) */ + tmp0 = fLog2(accu2, accu_e) - fLog2(accu1, accu_e); + tmp1 = fLog2((FIXP_DBL)len1, 31) - fLog2((FIXP_DBL)len2, 31); + delta = fMult(LN2, (tmp0 + tmp1)); + delta = (FIXP_DBL)FDKabs( delta ); /* Weighting with amplitude ratio of this band */ - result = (EnergyTotal == FL2FXCONST_DBL(0.0f)) - ? FL2FXCONST_DBL(0.f) - : FDKsbrEnc_LSI_divide_scale_fract( (accu1+accu2), - (EnergyTotal>>NRG_SCALE)+(FIXP_DBL)1, - (FIXP_DBL)MAXVAL_DBL >> fixMin(scaleEnergies[0],(DFRACT_BITS-1)) ); + accu_e++; + accu1>>=1; + accu2>>=1; + if (accu_e & 1) { + accu_e++; + accu1>>=1; + accu2>>=1; + } - delta_sum += (FIXP_DBL)(fMult(sqrtFixp(result), delta)); + delta_sum += fMult(sqrtFixp(accu1+accu2), delta); + *result_e = ((accu_e>>1) + LD_DATA_SHIFT); } + energyTotal_e+=1; /* for a defined square result exponent, the exponent has to be even */ + EnergyTotal<<=1; + delta_sum = fMult(delta_sum, invSqrtNorm2(EnergyTotal, &tmp_e)); + *result_e = *result_e + (tmp_e-(energyTotal_e>>1)); + return fMult(delta_sum, pos_weight); + } @@ -175,9 +231,12 @@ static FIXP_DBL spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FRE ******************************************************************************* \brief Calculates total lowband energy - The return value nrgTotal is scaled by the factor (1/32.0) + The input values Energies[0] (low-band) are scaled by the factor + 2^(14-*scaleEnergies[0]) + The input values Energies[1] (high-band) are scaled by the factor + 2^(14-*scaleEnergies[1]) - \return total energy in the lowband + \return total energy in the lowband, scaled by the factor 2^19 *******************************************************************************/ static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies, int *scaleEnergies, @@ -194,6 +253,7 @@ static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies, int ts,k; /* Sum up lowband energy from one frame at offset tran_off */ + /* freqBandTable[LORES] has MAX_FREQ_COEFFS/2 +1 coeefs max. */ for (ts=tran_offdiv2; ts<YBufferWriteOffset; ts++) { for (k = 0; k < freqBandTable[0]; k++) { accu1 += Energies[ts][k] >> 6; @@ -201,12 +261,12 @@ static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies, } for (; ts<tran_offdiv2+(slots>>nrgSzShift); ts++) { for (k = 0; k < freqBandTable[0]; k++) { - accu2 += Energies[ts][k] >> 6; + accu2 += Energies[ts][k] >> 9; } } - nrgTotal = ( (accu1 >> fixMin(scaleEnergies[0],(DFRACT_BITS-1))) - + (accu2 >> fixMin(scaleEnergies[1],(DFRACT_BITS-1))) ) << (2); + nrgTotal = ( scaleValueSaturate(accu1, 1-scaleEnergies[0]) ) + + ( scaleValueSaturate(accu2, 4-scaleEnergies[1]) ); return(nrgTotal); } @@ -222,21 +282,23 @@ static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies, is 1 SBR-band. Therefore the data to be fed into the spectralChange function is reduced. - The values EnergiesM are scaled by the factor (1/32.0) and scaleEnergies[0] - The return value nrgTotal is scaled by the factor (1/32.0) + The values EnergiesM are scaled by the factor (2^19-scaleEnergies[0]) for + slots<YBufferWriteOffset and by the factor (2^19-scaleEnergies[1]) for + slots>=YBufferWriteOffset. - \return total energy in the highband + \return total energy in the highband, scaled by factor 2^19 *******************************************************************************/ static FIXP_DBL addHighbandEnergies(FIXP_DBL **RESTRICT Energies, /*!< input */ INT *scaleEnergies, + INT YBufferWriteOffset, FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS], /*!< Combined output */ UCHAR *RESTRICT freqBandTable, INT nSfb, INT sbrSlots, INT timeStep) { - INT i,j,k,slotIn,slotOut,scale; + INT i,j,k,slotIn,slotOut,scale[2]; INT li,ui; FIXP_DBL nrgTotal; FIXP_DBL accu = FL2FXCONST_DBL(0.0f); @@ -245,7 +307,7 @@ static FIXP_DBL addHighbandEnergies(FIXP_DBL **RESTRICT Energies, /*!< input */ combine QMF-bands to SBR-bands, combine Left and Right channel */ for (slotOut=0; slotOut<sbrSlots; slotOut++) { - slotIn = 2*slotOut; + slotIn = timeStep*slotOut; for (j=0; j<nSfb; j++) { accu = FL2FXCONST_DBL(0.0f); @@ -262,19 +324,29 @@ static FIXP_DBL addHighbandEnergies(FIXP_DBL **RESTRICT Energies, /*!< input */ } } - scale = fixMin(8,scaleEnergies[0]); /* scale energies down before add up */ + /* scale energies down before add up */ + scale[0] = fixMin(8,scaleEnergies[0]); + scale[1] = fixMin(8,scaleEnergies[1]); - if ((scaleEnergies[0]-1) > (DFRACT_BITS-1) ) + if ((scaleEnergies[0]-scale[0]) > (DFRACT_BITS-1) || (scaleEnergies[1]-scale[0]) > (DFRACT_BITS-1)) nrgTotal = FL2FXCONST_DBL(0.0f); else { /* Now add all energies */ accu = FL2FXCONST_DBL(0.0f); - for (slotOut=0; slotOut<sbrSlots; slotOut++) { + + for (slotOut=0; slotOut<YBufferWriteOffset; slotOut++) { + for (j=0; j<nSfb; j++) { + accu += (EnergiesM[slotOut][j] >> scale[0]); + } + } + nrgTotal = accu >> (scaleEnergies[0]-scale[0]); + + for (slotOut=YBufferWriteOffset; slotOut<sbrSlots; slotOut++) { for (j=0; j<nSfb; j++) { - accu += (EnergiesM[slotOut][j] >> scale); + accu += (EnergiesM[slotOut][j] >> scale[0]); } } - nrgTotal = accu >> (scaleEnergies[0]-scale); + nrgTotal = accu >> (scaleEnergies[1]-scale[1]); } return(nrgTotal); @@ -299,18 +371,23 @@ FDKsbrEnc_frameSplitter(FIXP_DBL **Energies, int YBufferSzShift, int nSfb, int timeStep, - int no_cols) + int no_cols, + FIXP_DBL* tonality) { if (tran_vector[1]==0) /* no transient was detected */ { FIXP_DBL delta; - FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS]; + INT delta_e; + FIXP_DBL (*EnergiesM)[MAX_FREQ_COEFFS]; FIXP_DBL EnergyTotal,newLowbandEnergy,newHighbandEnergy; INT border; INT sbrSlots = fMultI(GetInvInt(timeStep),no_cols); + C_ALLOC_SCRATCH_START(_EnergiesM, FIXP_DBL, NUMBER_TIME_SLOTS_2304*MAX_FREQ_COEFFS) FDK_ASSERT( sbrSlots * timeStep == no_cols ); + EnergiesM = (FIXP_DBL(*)[MAX_FREQ_COEFFS])_EnergiesM; + /* Get Lowband-energy over a range of 2 frames (Look half a frame back and ahead). */ @@ -324,16 +401,13 @@ FDKsbrEnc_frameSplitter(FIXP_DBL **Energies, newHighbandEnergy = addHighbandEnergies(Energies, scaleEnergies, + YBufferWriteOffset, EnergiesM, freqBandTable, nSfb, sbrSlots, timeStep); - if ( h_sbrTransientDetector->frameShift != 0 ) { - if (tran_vector[1]==0) - tran_vector[0] = 0; - } else { /* prevLowBandEnergy: Corresponds to 1 frame, starting with half a frame look-behind newLowbandEnergy: Corresponds to 1 frame, starting in the middle of the current frame */ @@ -343,23 +417,39 @@ FDKsbrEnc_frameSplitter(FIXP_DBL **Energies, of a FIXFIX-frame with 2 envelopes. */ border = (sbrSlots+1) >> 1; + if ( (INT)EnergyTotal&0xffffffe0 && (scaleEnergies[0]<32 || scaleEnergies[1]<32) ) /* i.e. > 31 */ { delta = spectralChange(EnergiesM, scaleEnergies, EnergyTotal, nSfb, 0, border, - sbrSlots); + YBufferWriteOffset, + sbrSlots, + &delta_e + ); + } else { + delta = FL2FXCONST_DBL(0.0f); + delta_e = 0; + + /* set tonality to 0 when energy is very low, since the amplitude + resolution should then be low as well */ + *tonality = FL2FXCONST_DBL(0.0f); + } + - if (delta > (h_sbrTransientDetector->split_thr >> LD_DATA_SHIFT)) /* delta scaled by 1/64 */ + if ( fIsLessThan(h_sbrTransientDetector->split_thr_m, h_sbrTransientDetector->split_thr_e, delta, delta_e) ) { tran_vector[0] = 1; /* Set flag for splitting */ - else + } else { tran_vector[0] = 0; + } + } /* Update prevLowBandEnergy */ h_sbrTransientDetector->prevLowBandEnergy = newLowbandEnergy; h_sbrTransientDetector->prevHighBandEnergy = newHighbandEnergy; + C_ALLOC_SCRATCH_END(_EnergiesM, FIXP_DBL, NUMBER_TIME_SLOTS_2304*MAX_FREQ_COEFFS) } } @@ -636,6 +726,7 @@ FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTran, int FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, + UINT sbrSyntaxFlags, /* SBR syntax flags derived from AOT. */ INT frameSize, INT sampleFreq, sbrConfigurationPtr params, @@ -649,8 +740,8 @@ FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientD { INT totalBitrate = params->codecSettings.standardBitrate * params->codecSettings.nChannels; INT codecBitrate = params->codecSettings.bitRate; - FIXP_DBL bitrateFactor_fix, framedur_fix; - INT scale_0, scale_1; + FIXP_DBL bitrateFactor_m, framedur_fix; + INT bitrateFactor_e, tmp_e; FDKmemclear(h_sbrTransientDetector,sizeof(SBR_TRANSIENT_DETECTOR)); @@ -658,11 +749,12 @@ FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientD h_sbrTransientDetector->tran_off = tran_off; if(codecBitrate) { - bitrateFactor_fix = fDivNorm((FIXP_DBL)totalBitrate, (FIXP_DBL)(codecBitrate<<2),&scale_0); + bitrateFactor_m = fDivNorm((FIXP_DBL)totalBitrate, (FIXP_DBL)(codecBitrate<<2),&bitrateFactor_e); + bitrateFactor_e += 2; } else { - bitrateFactor_fix = FL2FXCONST_DBL(1.0/4.0); - scale_0 = 0; + bitrateFactor_m = FL2FXCONST_DBL(1.0/4.0); + bitrateFactor_e = 2; } framedur_fix = fDivNorm(frameSize, sampleFreq); @@ -674,9 +766,13 @@ FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientD FIXP_DBL tmp = framedur_fix - FL2FXCONST_DBL(0.010); tmp = fixMax(tmp, FL2FXCONST_DBL(0.0001)); - tmp = fDivNorm(FL2FXCONST_DBL(0.000075), fPow2(tmp), &scale_1); + tmp = fDivNorm(FL2FXCONST_DBL(0.000075), fPow2(tmp), &tmp_e); + + bitrateFactor_e = (tmp_e + bitrateFactor_e); - scale_1 = -(scale_1 + scale_0 + 2); + if(sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + bitrateFactor_e--; /* divide by 2 */ + } FDK_ASSERT(no_cols <= QMF_MAX_TIME_SLOTS); FDK_ASSERT(no_rows <= QMF_CHANNELS); @@ -684,14 +780,8 @@ FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientD h_sbrTransientDetector->no_cols = no_cols; h_sbrTransientDetector->tran_thr = (FIXP_DBL)((params->tran_thr << (32-24-1)) / no_rows); h_sbrTransientDetector->tran_fc = tran_fc; - - if (scale_1>=0) { - h_sbrTransientDetector->split_thr = fMult(tmp, bitrateFactor_fix) >> scale_1; - } - else { - h_sbrTransientDetector->split_thr = fMult(tmp, bitrateFactor_fix) << (-scale_1); - } - + h_sbrTransientDetector->split_thr_m = fMult(tmp, bitrateFactor_m); + h_sbrTransientDetector->split_thr_e = bitrateFactor_e; h_sbrTransientDetector->no_rows = no_rows; h_sbrTransientDetector->mode = params->tran_det_mode; h_sbrTransientDetector->prevLowBandEnergy = FL2FXCONST_DBL(0.0f); @@ -699,3 +789,281 @@ FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientD return (0); } + +#define ENERGY_SCALING_SIZE 32 + +INT FDKsbrEnc_InitSbrFastTransientDetector( + HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const INT time_slots_per_frame, + const INT bandwidth_qmf_slot, + const INT no_qmf_channels, + const INT sbr_qmf_1st_band + ) +{ + + int i, e; + int buff_size; + FIXP_DBL myExp; + FIXP_DBL myExpSlot; + + h_sbrFastTransientDetector->lookahead = TRAN_DET_LOOKAHEAD; + h_sbrFastTransientDetector->nTimeSlots = time_slots_per_frame; + + buff_size = h_sbrFastTransientDetector->nTimeSlots + h_sbrFastTransientDetector->lookahead; + + for(i=0; i< buff_size; i++) { + h_sbrFastTransientDetector->delta_energy[i] = FL2FXCONST_DBL(0.0f); + h_sbrFastTransientDetector->energy_timeSlots[i] = FL2FXCONST_DBL(0.0f); + h_sbrFastTransientDetector->lowpass_energy[i] = FL2FXCONST_DBL(0.0f); + h_sbrFastTransientDetector->transientCandidates[i] = 0; + } + + FDK_ASSERT(bandwidth_qmf_slot > 0.f); + h_sbrFastTransientDetector->stopBand = fMin(TRAN_DET_STOP_FREQ/bandwidth_qmf_slot, no_qmf_channels); + h_sbrFastTransientDetector->startBand = fMin(sbr_qmf_1st_band, h_sbrFastTransientDetector->stopBand - TRAN_DET_MIN_QMFBANDS); + + FDK_ASSERT(h_sbrFastTransientDetector->startBand < no_qmf_channels); + FDK_ASSERT(h_sbrFastTransientDetector->startBand < h_sbrFastTransientDetector->stopBand); + FDK_ASSERT(h_sbrFastTransientDetector->startBand > 1); + FDK_ASSERT(h_sbrFastTransientDetector->stopBand > 1); + + /* the energy weighting and adding up has a headroom of 6 Bits, + so up to 64 bands can be added without potential overflow. */ + FDK_ASSERT(h_sbrFastTransientDetector->stopBand - h_sbrFastTransientDetector->startBand <= 64); + + /* QMF_HP_dB_SLOPE_FIX says that we want a 20 dB per 16 kHz HP filter. + The following lines map this to the QMF bandwidth. */ + #define EXP_E 7 /* QMF_CHANNELS (=64) multiplications max, max. allowed sum is 0.5 */ + myExp = fMultNorm(QMF_HP_dBd_SLOPE_FIX, (FIXP_DBL)bandwidth_qmf_slot, &e); + myExp = scaleValueSaturate(myExp, e+0+DFRACT_BITS-1-EXP_E); + myExpSlot = myExp; + + for(i=0; i<QMF_CHANNELS; i++){ + /* Calculate dBf over all qmf bands: + dBf = (10^(0.002266f/10*bw(slot)))^(band) = + = 2^(log2(10)*0.002266f/10*bw(slot)*band) = + = 2^(0.00075275f*bw(slot)*band) */ + + FIXP_DBL dBf_m; /* dBf mantissa */ + INT dBf_e; /* dBf exponent */ + INT tmp; + + INT dBf_int; /* dBf integer part */ + FIXP_DBL dBf_fract; /* dBf fractional part */ + + /* myExp*(i+1) = myExp_int - myExp_fract + myExp*(i+1) is split up here for better accuracy of CalcInvLdData(), + for its result can be split up into an integer and a fractional part */ + + /* Round up to next integer */ + FIXP_DBL myExp_int = (myExpSlot & (FIXP_DBL)0xfe000000) + (FIXP_DBL)0x02000000; + + /* This is the fractional part that needs to be substracted */ + FIXP_DBL myExp_fract = myExp_int - myExpSlot; + + /* Calc integer part */ + dBf_int = CalcInvLdData(myExp_int); + /* The result needs to be re-scaled. The ld(myExp_int) had been scaled by EXP_E, + the CalcInvLdData expects the operand to be scaled by LD_DATA_SHIFT. + Therefore, the correctly scaled result is dBf_int^(2^(EXP_E-LD_DATA_SHIFT)), + which is dBf_int^2 */ + dBf_int *= dBf_int; + + /* Calc fractional part */ + dBf_fract = CalcInvLdData(-myExp_fract); + /* The result needs to be re-scaled. The ld(myExp_fract) had been scaled by EXP_E, + the CalcInvLdData expects the operand to be scaled by LD_DATA_SHIFT. + Therefore, the correctly scaled result is dBf_fract^(2^(EXP_E-LD_DATA_SHIFT)), + which is dBf_fract^2 */ + dBf_fract = fMultNorm(dBf_fract, dBf_fract, &tmp); + + /* Get worst case scaling of multiplication result */ + dBf_e = (DFRACT_BITS-1 - tmp) - CountLeadingBits(dBf_int); + + /* Now multiply integer with fractional part of the result, thus resulting + in the overall accurate fractional result */ + dBf_m = fMultNorm(dBf_int, dBf_fract, &e); + dBf_m = scaleValueSaturate(dBf_m, e+DFRACT_BITS-1+tmp-dBf_e); + myExpSlot += myExp; + + /* Keep the results */ + h_sbrFastTransientDetector->dBf_m[i] = dBf_m; + h_sbrFastTransientDetector->dBf_e[i] = dBf_e; + + } + + /* Make sure that dBf is greater than 1.0 (because it should be a highpass) */ + /* ... */ + + return 0; +} + +void FDKsbrEnc_fastTransientDetect( + const HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const FIXP_DBL *const *Energies, + const int *const scaleEnergies, + const INT YBufferWriteOffset, + UCHAR *const tran_vector + ) +{ + int timeSlot, band; + + FIXP_DBL max_delta_energy; /* helper to store maximum energy ratio */ + int max_delta_energy_scale; /* helper to store scale of maximum energy ratio */ + int ind_max = 0; /* helper to store index of maximum energy ratio */ + int isTransientInFrame = 0; + + const int nTimeSlots = h_sbrFastTransientDetector->nTimeSlots; + const int lookahead = h_sbrFastTransientDetector->lookahead; + const int startBand = h_sbrFastTransientDetector->startBand; + const int stopBand = h_sbrFastTransientDetector->stopBand; + + int * transientCandidates = h_sbrFastTransientDetector->transientCandidates; + + FIXP_DBL * energy_timeSlots = h_sbrFastTransientDetector->energy_timeSlots; + int * energy_timeSlots_scale = h_sbrFastTransientDetector->energy_timeSlots_scale; + + FIXP_DBL * delta_energy = h_sbrFastTransientDetector->delta_energy; + int * delta_energy_scale = h_sbrFastTransientDetector->delta_energy_scale; + + const FIXP_DBL thr = TRAN_DET_THRSHLD; + const INT thr_scale = TRAN_DET_THRSHLD_SCALE; + + /*reset transient info*/ + tran_vector[2] = 0; + + /* reset transient candidates */ + FDKmemclear(transientCandidates+lookahead, nTimeSlots*sizeof(int)); + + for(timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) { + int i, norm; + FIXP_DBL tmpE = FL2FXCONST_DBL(0.0f); + int headroomEnSlot = DFRACT_BITS-1; + + FIXP_DBL smallNRG = FL2FXCONST_DBL(1e-2f); + FIXP_DBL denominator; + INT denominator_scale; + + /* determine minimum headroom of energy values for this timeslot */ + for(band = startBand; band < stopBand; band++) { + int tmp_headroom = fNormz(Energies[timeSlot][band])-1; + if(tmp_headroom < headroomEnSlot){ + headroomEnSlot = tmp_headroom; + } + } + + for(i = 0, band = startBand; band < stopBand; band++, i++) { + /* energy is weighted by weightingfactor stored in dBf_m array */ + /* dBf_m index runs from 0 to stopBand-startband */ + /* energy shifted by calculated headroom for maximum precision */ + FIXP_DBL weightedEnergy = fMult(Energies[timeSlot][band]<<headroomEnSlot, h_sbrFastTransientDetector->dBf_m[i]); + + /* energy is added up */ + /* shift by 6 to have a headroom for maximum 64 additions */ + /* shift by dBf_e to handle weighting factor dependent scale factors */ + tmpE += weightedEnergy >> (6 + (10 - h_sbrFastTransientDetector->dBf_e[i])); + } + + /* store calculated energy for timeslot */ + energy_timeSlots[timeSlot] = tmpE; + + /* calculate overall scale factor for energy of this timeslot */ + /* = original scale factor of energies (-scaleEnergies[0]+2*QMF_SCALE_OFFSET or -scaleEnergies[1]+2*QMF_SCALE_OFFSET */ + /* depending on YBufferWriteOffset) */ + /* + weighting factor scale (10) */ + /* + adding up scale factor ( 6) */ + /* - headroom of energy value (headroomEnSlot) */ + if(timeSlot < YBufferWriteOffset){ + energy_timeSlots_scale[timeSlot] = (-scaleEnergies[0]+2*QMF_SCALE_OFFSET) + (10+6) - headroomEnSlot; + } else { + energy_timeSlots_scale[timeSlot] = (-scaleEnergies[1]+2*QMF_SCALE_OFFSET) + (10+6) - headroomEnSlot; + } + + /* Add a small energy to the denominator, thus making the transient + detection energy-dependent. Loud transients are being detected, + silent ones not. */ + + /* make sure that smallNRG does not overflow */ + if ( -energy_timeSlots_scale[timeSlot-1] + 1 > 5 ) + { + denominator = smallNRG; + denominator_scale = 0; + } else { + /* Leave an additional headroom of 1 bit for this addition. */ + smallNRG = scaleValue(smallNRG, -(energy_timeSlots_scale[timeSlot-1] + 1)); + denominator = (energy_timeSlots[timeSlot-1]>>1) + smallNRG; + denominator_scale = energy_timeSlots_scale[timeSlot-1]+1; + } + + delta_energy[timeSlot] = fDivNorm(energy_timeSlots[timeSlot], denominator, &norm); + delta_energy_scale[timeSlot] = energy_timeSlots_scale[timeSlot] - denominator_scale + norm; + } + + /*get transient candidates*/ + /* For every timeslot, check if delta(E) exceeds the threshold. If it did, + it could potentially be marked as a transient candidate. However, the 2 + slots before the current one must not be transients with an energy higher + than 1.4*E(current). If both aren't transients or if the energy of the + current timesolot is more than 1.4 times higher than the energy in the + last or the one before the last slot, it is marked as a transient.*/ + + FDK_ASSERT(lookahead >= 2); + for(timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) { + FIXP_DBL energy_cur_slot_weighted = fMult(energy_timeSlots[timeSlot],FL2FXCONST_DBL(1.0f/1.4f)); + if( !fIsLessThan(delta_energy[timeSlot], delta_energy_scale[timeSlot], thr, thr_scale) && + ( ((transientCandidates[timeSlot-2]==0) && (transientCandidates[timeSlot-1]==0)) || + !fIsLessThan(energy_cur_slot_weighted, energy_timeSlots_scale[timeSlot], energy_timeSlots[timeSlot-1], energy_timeSlots_scale[timeSlot-1] ) || + !fIsLessThan(energy_cur_slot_weighted, energy_timeSlots_scale[timeSlot], energy_timeSlots[timeSlot-2], energy_timeSlots_scale[timeSlot-2] ) + ) + ) +{ + /* in case of strong transients, subsequent + * qmf slots might be recognized as transients. */ + transientCandidates[timeSlot] = 1; + } + } + + /*get transient with max energy*/ + max_delta_energy = FL2FXCONST_DBL(0.0f); + max_delta_energy_scale = 0; + ind_max = 0; + isTransientInFrame = 0; + for(timeSlot = 0; timeSlot < nTimeSlots; timeSlot++) { + int scale = fMax(delta_energy_scale[timeSlot], max_delta_energy_scale); + if(transientCandidates[timeSlot] && ( (delta_energy[timeSlot] >> (scale - delta_energy_scale[timeSlot])) > (max_delta_energy >> (scale - max_delta_energy_scale)) ) ) { + max_delta_energy = delta_energy[timeSlot]; + max_delta_energy_scale = scale; + ind_max = timeSlot; + isTransientInFrame = 1; + } + } + + /*from all transient candidates take the one with the biggest energy*/ + if(isTransientInFrame) { + tran_vector[0] = ind_max; + tran_vector[1] = 1; + } else { + /*reset transient info*/ + tran_vector[0] = tran_vector[1] = 0; + } + + /*check for transients in lookahead*/ + for(timeSlot = nTimeSlots; timeSlot < nTimeSlots + lookahead; timeSlot++) { + if(transientCandidates[timeSlot]) { + tran_vector[2] = 1; + } + } + + /*update buffers*/ + for(timeSlot = 0; timeSlot < lookahead; timeSlot++) { + transientCandidates[timeSlot] = transientCandidates[nTimeSlots + timeSlot]; + + /* fixpoint stuff */ + energy_timeSlots[timeSlot] = energy_timeSlots[nTimeSlots + timeSlot]; + energy_timeSlots_scale[timeSlot] = energy_timeSlots_scale[nTimeSlots + timeSlot]; + + delta_energy[timeSlot] = delta_energy[nTimeSlots + timeSlot]; + delta_energy_scale[timeSlot] = delta_energy_scale[nTimeSlots + timeSlot]; + } +} + diff --git a/libSBRenc/src/tran_det.h b/libSBRenc/src/tran_det.h index 95b5d2e..6fe1023 100644 --- a/libSBRenc/src/tran_det.h +++ b/libSBRenc/src/tran_det.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -96,7 +96,8 @@ typedef struct FIXP_DBL transients[QMF_MAX_TIME_SLOTS+(QMF_MAX_TIME_SLOTS/2)]; FIXP_DBL thresholds[QMF_CHANNELS]; FIXP_DBL tran_thr; /* Master threshold for transient signals */ - FIXP_DBL split_thr; /* Threshold for splitting FIXFIX-frames into 2 env */ + FIXP_DBL split_thr_m; /* Threshold for splitting FIXFIX-frames into 2 env */ + INT split_thr_e; /* Scale for splitting threshold */ FIXP_DBL prevLowBandEnergy; /* Energy of low band */ FIXP_DBL prevHighBandEnergy; /* Energy of high band */ INT tran_fc; /* Number of lowband subbands to discard */ @@ -112,6 +113,57 @@ SBR_TRANSIENT_DETECTOR; typedef SBR_TRANSIENT_DETECTOR *HANDLE_SBR_TRANSIENT_DETECTOR; +#define TRAN_DET_LOOKAHEAD 2 +#define TRAN_DET_START_FREQ 4500 /*start frequency for transient detection*/ +#define TRAN_DET_STOP_FREQ 13500 /*stop frequency for transient detection*/ +#define TRAN_DET_MIN_QMFBANDS 4 /* minimum qmf bands for transient detection */ +#define QMF_HP_dBd_SLOPE_FIX FL2FXCONST_DBL(0.00075275f) /* 0.002266f/10 * log2(10) */ +#define TRAN_DET_THRSHLD FL2FXCONST_DBL(3.2f/4.f) +#define TRAN_DET_THRSHLD_SCALE (2) + +typedef struct +{ + INT transientCandidates[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD]; + INT nTimeSlots; + INT lookahead; + INT startBand; + INT stopBand; + + FIXP_DBL dBf_m[QMF_CHANNELS]; + INT dBf_e[QMF_CHANNELS]; + + FIXP_DBL energy_timeSlots[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD]; + INT energy_timeSlots_scale[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD]; + + FIXP_DBL delta_energy[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD]; + INT delta_energy_scale[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD]; + + FIXP_DBL lowpass_energy[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD]; + INT lowpass_energy_scale[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD]; +#if defined (FTD_LOG) + FDKFILE *ftd_log; +#endif +} +FAST_TRAN_DETECTOR; +typedef FAST_TRAN_DETECTOR *HANDLE_FAST_TRAN_DET; + + +INT FDKsbrEnc_InitSbrFastTransientDetector( + HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const INT time_slots_per_frame, + const INT bandwidth_qmf_slot, + const INT no_qmf_channels, + const INT sbr_qmf_1st_band + ); + +void FDKsbrEnc_fastTransientDetect( + const HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const FIXP_DBL *const *Energies, + const int *const scaleEnergies, + const INT YBufferWriteOffset, + UCHAR *const tran_vector + ); + void FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, FIXP_DBL **Energies, @@ -124,6 +176,7 @@ FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, int FDKsbrEnc_InitSbrTransientDetector (HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, + UINT sbrSyntaxFlags, /* SBR syntax flags derived from AOT. */ INT frameSize, INT sampleFreq, sbrConfigurationPtr params, @@ -145,6 +198,6 @@ FDKsbrEnc_frameSplitter(FIXP_DBL **Energies, int YBufferSzShift, int nSfb, int timeStep, - int no_cols); - + int no_cols, + FIXP_DBL* tonality); #endif diff --git a/libSYS/include/FDK_audio.h b/libSYS/include/FDK_audio.h index 0660f4c..98ded3b 100644 --- a/libSYS/include/FDK_audio.h +++ b/libSYS/include/FDK_audio.h @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -134,13 +134,7 @@ typedef enum TT_MP4_LOAS = 10, /**< Audio Sync Stream. */ - TT_DRM = 12, /**< Digital Radio Mondial (DRM30/DRM+) bitstream format. */ - - TT_MP1_L1 = 16, /**< MPEG 1 Audio Layer 1 audio bitstream. */ - TT_MP1_L2 = 17, /**< MPEG 1 Audio Layer 2 audio bitstream. */ - TT_MP1_L3 = 18, /**< MPEG 1 Audio Layer 3 audio bitstream. */ - - TT_RSVD50 = 50 /**< */ + TT_DRM = 12 /**< Digital Radio Mondial (DRM30/DRM+) bitstream format. */ } TRANSPORT_TYPE; @@ -203,38 +197,22 @@ typedef enum AOT_SAOC = 43, /**< SAOC */ AOT_LD_MPEGS = 44, /**< Low Delay MPEG Surround */ - AOT_RSVD50 = 50, /**< Interim AOT for Rsvd50 */ - /* Pseudo AOTs */ - AOT_MP2_AAC_MAIN = 128, /**< Virtual AOT MP2 Main profile */ - AOT_MP2_AAC_LC = 129, /**< Virtual AOT MP2 Low Complexity profile */ - AOT_MP2_AAC_SSR = 130, /**< Virtual AOT MP2 Scalable Sampling Rate profile */ - - AOT_MP2_SBR = 132, /**< Virtual AOT MP2 Low Complexity Profile with SBR */ - - AOT_DAB = 134, /**< Virtual AOT for DAB (Layer2 with scalefactor CRC) */ - AOT_DABPLUS_AAC_LC = 135, /**< Virtual AOT for DAB plus AAC-LC */ - AOT_DABPLUS_SBR = 136, /**< Virtual AOT for DAB plus HE-AAC */ - AOT_DABPLUS_PS = 137, /**< Virtual AOT for DAB plus HE-AAC v2 */ - - AOT_PLAIN_MP1 = 140, /**< Virtual AOT for plain mp1 */ - AOT_PLAIN_MP2 = 141, /**< Virtual AOT for plain mp2 */ - AOT_PLAIN_MP3 = 142, /**< Virtual AOT for plain mp3 */ - AOT_DRM_AAC = 143, /**< Virtual AOT for DRM (ER-AAC-SCAL without SBR) */ AOT_DRM_SBR = 144, /**< Virtual AOT for DRM (ER-AAC-SCAL with SBR) */ - AOT_DRM_MPEG_PS = 145, /**< Virtual AOT for DRM (ER-AAC-SCAL with SBR and MPEG-PS) */ - AOT_DRM_SURROUND = 146, /**< Virtual AOT for DRM Surround (ER-AAC-SCAL (+SBR) +MPS) */ - - AOT_MP2_PS = 156, /**< Virtual AOT MP2 Low Complexity Profile with SBR and PS */ - - AOT_MPEGS_RESIDUALS = 256 /**< Virtual AOT for MPEG Surround residuals */ + AOT_DRM_MPEG_PS = 145 /**< Virtual AOT for DRM (ER-AAC-SCAL with SBR and MPEG-PS) */ } AUDIO_OBJECT_TYPE; +#define CAN_DO_PS(aot) \ + ((aot) == AOT_AAC_LC \ +|| (aot) == AOT_SBR \ +|| (aot) == AOT_PS \ +|| (aot) == AOT_ER_BSAC \ +|| (aot) == AOT_DRM_AAC) + #define IS_USAC(aot) \ - ((aot) == AOT_USAC \ -|| (aot) == AOT_RSVD50) + ((aot) == AOT_USAC) #define IS_LOWDELAY(aot) \ ((aot) == AOT_ER_AAC_LD \ diff --git a/libSYS/src/genericStds.cpp b/libSYS/src/genericStds.cpp index 47d62fc..89c422c 100644 --- a/libSYS/src/genericStds.cpp +++ b/libSYS/src/genericStds.cpp @@ -2,7 +2,7 @@ /* ----------------------------------------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -92,14 +92,14 @@ amm-info@iis.fraunhofer.de #define _CRT_SECURE_NO_WARNINGS -#include "genericStds.h" - #include <math.h> +#include "genericStds.h" + /* library info */ #define SYS_LIB_VL0 1 #define SYS_LIB_VL1 3 -#define SYS_LIB_VL2 6 +#define SYS_LIB_VL2 8 #define SYS_LIB_TITLE "System Integration Library" #ifdef __ANDROID__ #define SYS_LIB_BUILD_DATE "" |