diff options
75 files changed, 2613 insertions, 830 deletions
@@ -1,31 +1,31 @@  LOCAL_PATH:= $(call my-dir)  include $(CLEAR_VARS) -aacdec_sources := $(wildcard $(LOCAL_PATH)/libAACdec/src/*.cpp) +aacdec_sources := $(sort $(wildcard $(LOCAL_PATH)/libAACdec/src/*.cpp))  aacdec_sources := $(aacdec_sources:$(LOCAL_PATH)/libAACdec/src/%=%) -aacenc_sources := $(wildcard $(LOCAL_PATH)/libAACenc/src/*.cpp) +aacenc_sources := $(sort $(wildcard $(LOCAL_PATH)/libAACenc/src/*.cpp))  aacenc_sources := $(aacenc_sources:$(LOCAL_PATH)/libAACenc/src/%=%) -pcmutils_sources := $(wildcard $(LOCAL_PATH)/libPCMutils/src/*.cpp) +pcmutils_sources := $(sort $(wildcard $(LOCAL_PATH)/libPCMutils/src/*.cpp))  pcmutils_sources := $(pcmutils_sources:$(LOCAL_PATH)/libPCMutils/src/%=%) -fdk_sources := $(wildcard $(LOCAL_PATH)/libFDK/src/*.cpp) +fdk_sources := $(sort $(wildcard $(LOCAL_PATH)/libFDK/src/*.cpp))  fdk_sources := $(fdk_sources:$(LOCAL_PATH)/libFDK/src/%=%) -sys_sources := $(wildcard $(LOCAL_PATH)/libSYS/src/*.cpp) +sys_sources := $(sort $(wildcard $(LOCAL_PATH)/libSYS/src/*.cpp))  sys_sources := $(sys_sources:$(LOCAL_PATH)/libSYS/src/%=%) -mpegtpdec_sources := $(wildcard $(LOCAL_PATH)/libMpegTPDec/src/*.cpp) +mpegtpdec_sources := $(sort $(wildcard $(LOCAL_PATH)/libMpegTPDec/src/*.cpp))  mpegtpdec_sources := $(mpegtpdec_sources:$(LOCAL_PATH)/libMpegTPDec/src/%=%) -mpegtpenc_sources := $(wildcard $(LOCAL_PATH)/libMpegTPEnc/src/*.cpp) +mpegtpenc_sources := $(sort $(wildcard $(LOCAL_PATH)/libMpegTPEnc/src/*.cpp))  mpegtpenc_sources := $(mpegtpenc_sources:$(LOCAL_PATH)/libMpegTPEnc/src/%=%) -sbrdec_sources := $(wildcard $(LOCAL_PATH)/libSBRdec/src/*.cpp) +sbrdec_sources := $(sort $(wildcard $(LOCAL_PATH)/libSBRdec/src/*.cpp))  sbrdec_sources := $(sbrdec_sources:$(LOCAL_PATH)/libSBRdec/src/%=%) -sbrenc_sources := $(wildcard $(LOCAL_PATH)/libSBRenc/src/*.cpp) +sbrenc_sources := $(sort $(wildcard $(LOCAL_PATH)/libSBRenc/src/*.cpp))  sbrenc_sources := $(sbrenc_sources:$(LOCAL_PATH)/libSBRenc/src/%=%)  LOCAL_SRC_FILES := \ 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/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 9d703cc..2965fa6 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) )          { 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 63563fd..2845177 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 464c013..90b19cf 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 ""  | 
