AAC/SBR decoder improvements and bugfixes

* AAC-Decoder

   - Add support for AOT 20 (ER-AAC scalable) (base layer only)
   - Add support for AAC as used in Digital Radio Mondiale (DRM30/DRM+)
     Modified file(s):
        libAACdec/src/aacdecoder.cpp
        libAACdec/src/aacdecoder_lib.cpp
        libFDK/src/FDK_core.cpp
        libFDK/src/FDK_tools_rom.cpp
        libMpegTPDec/src/tpdec_asc.cpp
        libMpegTPDec/src/tpdec_lib.cpp
        libMpegTPDec/src/version
        libSBRdec/include/sbrdecoder.h
        libSBRdec/src/env_extr.h
        libSBRdec/src/sbrdecoder.cpp
     Added file(s):
        libMpegTPDec/src/tpdec_drm.cpp
        libMpegTPDec/src/tpdec_drm.h

   - Fix sanity check in HCR module that was performed at the wrong point in time.
     Modified file(s):
        libAACdec/src/aacdecoder_lib.cpp
        libAACdec/src/block.cpp

   - Extend core sampling rate support up to 96 kHz.
     Modified file(s):
        libAACdec/src/aac_rom.cpp
        libAACdec/src/aacdecoder.cpp
        libAACdec/src/aacdecoder_lib.cpp

   - Return correct audio output channel description according number of output
     channels.
     Modified file(s):
        libAACdec/src/aacdecoder_lib.cpp

   - Indroduce decoder intern output buffer. This change allows to use framework
     output buffer with the actual size of the deocder output channels.
     Modified file(s):
        libAACdec/include/aacdecoder_lib.h
        libAACdec/src/aacdecoder.h
        libAACdec/src/aacdecoder_lib.cpp

* SBR-Decoder

   - Increase robustness for erroneous input data.
   - Improve error concealment performance.
   - Fix handling of lowest sub-band for LD-SBR
     Modified file(s):
        libAACdec/src/aacdecoder.cpp
        libAACdec/src/aacdecoder_lib.cpp
        libSBRdec/src/env_calc.cpp
        libSBRdec/src/env_dec.cpp
        libSBRdec/src/env_extr.cpp
        libSBRdec/src/env_extr.h
        libSBRdec/src/sbr_dec.cpp
        libSBRdec/src/sbr_rom.cpp
        libSBRdec/src/sbr_rom.h
        libSBRdec/src/sbrdecoder.cpp

   - Add QMF delay compensation for ELD v2 streams decoded with the complex
     low delay filter-bank.
     Modified file(s):
        libSBRdec/src/sbr_dec.cpp
        libSBRdec/src/sbr_dec.h
        libSBRdec/src/sbrdecoder.cpp

   - Introduce a different handling of frames to be flushed
     dependent on whether there are delayed frames available or not.
     Modified file(s):
        libSBRdec/src/sbr_ram.h
        libSBRdec/src/sbrdecoder.cpp

   - Calculate the correct number of samples for dual-mono copy in case of no
     available PS data.
     Modified file(s):
        libSBRdec/src/sbrdecoder.cpp

* SYS-Library

   - Change include order of genericStds.h to prevent conflict with definitions
     which are also used in math.h.
     Modified file(s):
        libSYS/src/genericStds.cpp

Change-Id: I3ecffbad85f39b056213107955cfadbeb3f4b6e1
This commit is contained in:
Jean-Michel Trivi 2016-04-08 12:05:12 -07:00
parent 46ba3676b8
commit 203e3f28fb
26 changed files with 1237 additions and 142 deletions

Binary file not shown.

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -378,6 +378,7 @@ typedef enum {
not exist. */ not exist. */
AAC_DEC_NEED_TO_RESTART = 0x200B, /*!< The decoder needs to be restarted, since the requiered configuration change cannot be AAC_DEC_NEED_TO_RESTART = 0x200B, /*!< The decoder needs to be restarted, since the requiered configuration change cannot be
performed. */ performed. */
AAC_DEC_OUTPUT_BUFFER_TOO_SMALL = 0x200C, /*!< The provided output buffer is too small. */
aac_dec_init_error_end = 0x2FFF, aac_dec_init_error_end = 0x2FFF,
/* Decode errors. Output buffer is valid but concealed. */ /* Decode errors. Output buffer is valid but concealed. */

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 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 */ /* 49 scfbands */
static const SHORT sfb_48_1024[50] = { 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] = static const SHORT sfb_48_960[50] =
{ {
@ -358,9 +417,9 @@ static const SHORT sfb_24_480[31] =
const SFB_INFO sfbOffsetTables[5][16] = const SFB_INFO sfbOffsetTables[5][16] =
{ {
{ {
{ NULL, NULL, 0, 0 }, { sfb_96_1024, sfb_96_128, 41, 12 },
{ NULL, NULL, 0, 0 }, { sfb_96_1024, sfb_96_128, 41, 12 },
{ NULL, NULL, 0, 0 }, { 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_48_1024, sfb_48_128, 49, 14 }, { sfb_48_1024, sfb_48_128, 49, 14 },
{ sfb_32_1024, sfb_48_128, 51, 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 },
{ sfb_8_1024, sfb_8_128, 40, 15 }, { sfb_8_1024, sfb_8_128, 40, 15 },
}, { }, {
{ NULL, NULL, 0, 0 }, { sfb_96_960, sfb_96_120, 40, 12 },
{ NULL, NULL, 0, 0 }, { sfb_96_960, sfb_96_120, 40, 12 },
{ NULL, NULL, 0, 0 }, { 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_48_960, sfb_48_120, 49, 14 }, { sfb_48_960, sfb_48_120, 49, 14 },
{ sfb_32_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 }, { sfb_48_512, NULL, 36, 0 },
{ NULL, NULL, 0, 0 }, { sfb_48_512, NULL, 36, 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 }, { 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 },
{ sfb_24_512, NULL, 31, 0 }, { sfb_24_512, NULL, 31, 0 },
}, { }, {
{ NULL, NULL, 0, 0 }, { sfb_48_480, NULL, 35, 0 },
{ NULL, NULL, 0, 0 }, { sfb_48_480, NULL, 35, 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 }, { sfb_32_480, NULL, 37, 0 },

View File

@ -157,6 +157,7 @@ amm-info@iis.fraunhofer.de
#include "conceal.h" #include "conceal.h"
#include "FDK_crc.h"
void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self) void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self)
@ -537,8 +538,9 @@ AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self,
previous_element, previous_element,
elIndex, elIndex,
self->flags & AC_INDEP ); self->flags & AC_INDEP );
/* Enable SBR for implicit SBR signalling. */ /* Enable SBR for implicit SBR signalling but only if no severe error happend. */
if (sbrError == SBRDEC_OK) { if ( (sbrError == SBRDEC_OK)
|| (sbrError == SBRDEC_PARSE_ERROR) ) {
self->sbrEnabled = 1; self->sbrEnabled = 1;
} }
} else { } else {
@ -553,7 +555,7 @@ AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self,
FDKpushBiDirectional(hBs, *count); FDKpushBiDirectional(hBs, *count);
*count = 0; *count = 0;
} else { } 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) { if (sbrError != SBRDEC_OK) {
self->frameOK = 0; self->frameOK = 0;
} }
@ -832,12 +834,18 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
switch (asc->m_aot) { switch (asc->m_aot) {
case AOT_AAC_LC: case AOT_AAC_LC:
self->streamInfo.profile = 1; 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_SBR:
case AOT_PS: case AOT_PS:
case AOT_ER_AAC_LD: case AOT_ER_AAC_LD:
case AOT_ER_AAC_ELD: case AOT_ER_AAC_ELD:
case AOT_DRM_AAC:
break; break;
default: default:
@ -957,11 +965,20 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
if (asc->m_aot == AOT_ER_AAC_ELD) { if (asc->m_aot == AOT_ER_AAC_ELD) {
self->flags |= AC_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_sbrCrcFlag) ? AC_SBRCRC : 0;
self->flags |= (asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) ? AC_LD_MPS : 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_aot == AOT_ER_AAC_LD) ? AC_LD : 0;
self->flags |= (asc->m_epConfig >= 0) ? AC_ER : 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) { if (asc->m_sbrPresentFlag) {
@ -1147,6 +1164,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
/* Check sampling frequency */ /* Check sampling frequency */
switch ( self->streamInfo.aacSampleRate ) { switch ( self->streamInfo.aacSampleRate ) {
case 96000:
case 88200:
case 64000:
case 16000: case 16000:
case 12000: case 12000:
case 11025: case 11025:
@ -1475,7 +1495,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
/* get the remaining bits of this frame */ /* get the remaining bits of this frame */
bitCnt = transportDec_GetAuBitsRemaining(self->hInput, 0); 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; SBR_ERROR err = SBRDEC_OK;
int elIdx, numChElements = el_cnt[ID_SCE] + el_cnt[ID_CPE]; int elIdx, numChElements = el_cnt[ID_SCE] + el_cnt[ID_CPE];
@ -1513,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)) ) if ( ! (self->flags & (AC_USAC|AC_RSVD50|AC_DRM)) )
{ {
while ( bitCnt > 7 ) { while ( bitCnt > 7 ) {

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -226,6 +226,8 @@ struct AAC_DECODER_INSTANCE {
FIXP_DBL extGain[1]; /*!< Gain that must be applied to the output signal. */ FIXP_DBL extGain[1]; /*!< Gain that must be applied to the output signal. */
UINT extGainDelay; /*!< Delay that must be accounted for extGain. */ UINT extGainDelay; /*!< Delay that must be accounted for extGain. */
INT_PCM pcmOutputBuffer[(8)*(2048)];
}; };

View File

@ -110,7 +110,7 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */ /* Decoder library info */
#define AACDECODER_LIB_VL0 2 #define AACDECODER_LIB_VL0 2
#define AACDECODER_LIB_VL1 5 #define AACDECODER_LIB_VL1 5
#define AACDECODER_LIB_VL2 11 #define AACDECODER_LIB_VL2 17
#define AACDECODER_LIB_TITLE "AAC Decoder Lib" #define AACDECODER_LIB_TITLE "AAC Decoder Lib"
#ifdef __ANDROID__ #ifdef __ANDROID__
#define AACDECODER_LIB_BUILD_DATE "" #define AACDECODER_LIB_BUILD_DATE ""
@ -181,8 +181,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_ConfigRaw (
break; break;
} }
/* if baselayer is OK we continue decoding */ /* if baselayer is OK we continue decoding */
if(layer >= 1){ if(layer >= 1){
self->nrOfLayers = layer; self->nrOfLayers = layer;
err = AAC_DEC_OK;
} }
break; break;
} }
@ -785,8 +786,8 @@ static INT aacDecoder_EstimateNumberOfLostFrames(HANDLE_AACDECODER self)
LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
HANDLE_AACDECODER self, HANDLE_AACDECODER self,
INT_PCM *pTimeData, INT_PCM *pTimeData_extern,
const INT timeDataSize, const INT timeDataSize_extern,
const UINT flags) const UINT flags)
{ {
AAC_DECODER_ERROR ErrorStatus; AAC_DECODER_ERROR ErrorStatus;
@ -796,12 +797,17 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
HANDLE_FDK_BITSTREAM hBs; HANDLE_FDK_BITSTREAM hBs;
int fTpInterruption = 0; /* Transport originated interruption detection. */ int fTpInterruption = 0; /* Transport originated interruption detection. */
int fTpConceal = 0; /* Transport originated concealment. */ int fTpConceal = 0; /* Transport originated concealment. */
INT_PCM *pTimeData = NULL;
INT timeDataSize = 0;
if (self == NULL) { if (self == NULL) {
return AAC_DEC_INVALID_HANDLE; return AAC_DEC_INVALID_HANDLE;
} }
pTimeData = self->pcmOutputBuffer;
timeDataSize = sizeof(self->pcmOutputBuffer)/sizeof(*self->pcmOutputBuffer);
if (flags & AACDEC_INTR) { if (flags & AACDEC_INTR) {
self->streamInfo.numLostAccessUnits = 0; self->streamInfo.numLostAccessUnits = 0;
} }
@ -918,7 +924,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
if (self->sbrEnabled) if (self->sbrEnabled)
{ {
SBR_ERROR sbrError = SBRDEC_OK; 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 */ /* set params */
sbrDecoder_SetParam ( self->hSbrDecoder, sbrDecoder_SetParam ( self->hSbrDecoder,
@ -978,10 +985,10 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
if (self->psPossible) { if (self->psPossible) {
self->flags |= AC_PS_PRESENT; self->flags |= AC_PS_PRESENT;
self->channelType[0] = ACT_FRONT; }
self->channelType[1] = ACT_FRONT; for (chIdx = numCoreChannel; chIdx < self->streamInfo.numChannels; chIdx+=1) {
self->channelIndices[0] = 0; self->channelType[chIdx] = ACT_FRONT;
self->channelIndices[1] = 1; self->channelIndices[chIdx] = chIdx;
} }
} }
} }
@ -1006,7 +1013,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
self->channelOutputMapping, self->channelOutputMapping,
(self->limiterEnableCurr) ? &pcmLimiterScale : NULL (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 /* 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. */ * settings are not know to produce a predictable behavior and thus maybe produce strange output. */
ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
@ -1051,6 +1059,19 @@ bail:
/* Update Statistics */ /* Update Statistics */
aacDecoder_UpdateBitStreamCounters(&self->streamInfo, hBs, nBits, ErrorStatus); 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; return ErrorStatus;
} }
@ -1120,6 +1141,7 @@ LINKSPEC_CPP INT aacDecoder_GetLibInfo ( LIB_INFO *info )
/* Set flags */ /* Set flags */
info->flags = 0 info->flags = 0
| CAPF_AAC_LC | CAPF_AAC_LC
| CAPF_ER_AAC_SCAL
| CAPF_AAC_VCB11 | CAPF_AAC_VCB11
| CAPF_AAC_HCR | CAPF_AAC_HCR
| CAPF_AAC_RVLC | CAPF_AAC_RVLC
@ -1130,6 +1152,7 @@ LINKSPEC_CPP INT aacDecoder_GetLibInfo ( LIB_INFO *info )
| CAPF_AAC_MPEG4 | CAPF_AAC_MPEG4
| CAPF_AAC_DRM_BSFORMAT
| CAPF_AAC_1024 | CAPF_AAC_1024
| CAPF_AAC_960 | CAPF_AAC_960

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -324,11 +324,11 @@ AAC_DECODER_ERROR CBlock_ReadSectionData(HANDLE_FDK_BITSTREAM bs,
if (flags & AC_ER_HCR) { if (flags & AC_ER_HCR) {
/* HCR input (long) -- collecting sideinfo (for HCR-_long_ only) */ /* HCR input (long) -- collecting sideinfo (for HCR-_long_ only) */
pNumLinesInSec[numLinesInSecIdx] = BandOffsets[top] - BandOffsets[band];
numLinesInSecIdx++;
if (numLinesInSecIdx >= MAX_SFB_HCR) { if (numLinesInSecIdx >= MAX_SFB_HCR) {
return AAC_DEC_PARSE_ERROR; return AAC_DEC_PARSE_ERROR;
} }
pNumLinesInSec[numLinesInSecIdx] = BandOffsets[top] - BandOffsets[band];
numLinesInSecIdx++;
if ( if (
(sect_cb == BOOKSCL) ) (sect_cb == BOOKSCL) )
{ {

View File

@ -93,7 +93,7 @@ amm-info@iis.fraunhofer.de
/* FDK tools library info */ /* FDK tools library info */
#define FDK_TOOLS_LIB_VL0 2 #define FDK_TOOLS_LIB_VL0 2
#define FDK_TOOLS_LIB_VL1 3 #define FDK_TOOLS_LIB_VL1 3
#define FDK_TOOLS_LIB_VL2 5 #define FDK_TOOLS_LIB_VL2 6
#define FDK_TOOLS_LIB_TITLE "FDK Tools" #define FDK_TOOLS_LIB_TITLE "FDK Tools"
#ifdef __ANDROID__ #ifdef __ANDROID__
#define FDK_TOOLS_LIB_BUILD_DATE "" #define FDK_TOOLS_LIB_BUILD_DATE ""

View File

@ -2236,7 +2236,7 @@ static const rbd_id_t el_aac_cpe1_epc1[] = {
ics_info, ics_info,
ms, ms,
ltp_data_present, ltp_data_present,
ltp_data, /* ltp_data, */
global_gain, global_gain,
section_data, section_data,
scale_factor_data, scale_factor_data,
@ -2247,7 +2247,7 @@ static const rbd_id_t el_aac_cpe1_epc1[] = {
next_channel, next_channel,
ltp_data_present, ltp_data_present,
ltp_data, /* ltp_data, */
global_gain, global_gain,
section_data, section_data,
scale_factor_data, scale_factor_data,
@ -2290,7 +2290,178 @@ static const element_list_t node_aac_cpe_epc1 = {
{ &node_aac_cpe0_epc1, &node_aac_cpe1_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 * AOT = 39
@ -2405,6 +2576,19 @@ const element_list_t * getBitstreamElementList(AUDIO_OBJECT_TYPE aot, SCHAR epCo
return &node_aac_cpe_epc1; return &node_aac_cpe_epc1;
} }
break; 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: case AOT_ER_AAC_ELD:
if (nChannels == 1) { if (nChannels == 1) {
if (epConfig <= 0) if (epConfig <= 0)
@ -2417,6 +2601,16 @@ const element_list_t * getBitstreamElementList(AUDIO_OBJECT_TYPE aot, SCHAR epCo
else else
return &node_eld_cpe_epc1; return &node_eld_cpe_epc1;
} }
case AOT_DRM_AAC:
case AOT_DRM_SBR:
case AOT_DRM_MPEG_PS:
FDK_ASSERT(epConfig == 1);
if (nChannels == 1) {
return &node_drm_sce;
} else {
return &node_drm_cpe;
}
break;
default: default:
break; break;
} }

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -1126,6 +1126,8 @@ TRANSPORTDEC_ERROR EldSpecificConfig_Parse(
if ( 0 != ld_sbr_header(asc, hBs, cb) ) { if ( 0 != ld_sbr_header(asc, hBs, cb) ) {
return TRANSPORTDEC_PARSE_ERROR; return TRANSPORTDEC_PARSE_ERROR;
} }
} else {
return TRANSPORTDEC_UNSUPPORTED_FORMAT;
} }
} }
esc->m_useLdQmfTimeAlign = 0; esc->m_useLdQmfTimeAlign = 0;
@ -1146,7 +1148,7 @@ TRANSPORTDEC_ERROR EldSpecificConfig_Parse(
switch (eldExtType) { switch (eldExtType) {
default: default:
for(cnt=0; cnt<len; cnt++) { for(cnt=0; cnt<eldExtLen; cnt++) {
FDKreadBits(hBs, 8 ); FDKreadBits(hBs, 8 );
} }
break; break;
@ -1372,4 +1374,133 @@ TRANSPORTDEC_ERROR AudioSpecificConfig_Parse(
return (ErrorStatus); 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);
}

View File

@ -0,0 +1,146 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
of the MPEG specifications.
Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
individually for the purpose of encoding or decoding bit streams in products that are compliant with
the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
software may already be covered under those patent licenses when it is used for those licensed purposes only.
Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
applications information and documentation.
2. COPYRIGHT LICENSE
Redistribution and use in source and binary forms, with or without modification, are permitted without
payment of copyright license fees provided that you satisfy the following conditions:
You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
your modifications thereto in source code form.
You must retain the complete text of this software license in the documentation and/or other materials
provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
modifications thereto to recipients of copies in binary form.
The name of Fraunhofer may not be used to endorse or promote products derived from this library without
prior written permission.
You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
software or your modifications thereto.
Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
and the date of any change. For modified versions of the FDK AAC Codec, the term
"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
3. NO PATENT LICENSE
NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
respect to this software.
You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
by appropriate patent licenses.
4. DISCLAIMER
This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
or business interruption, however caused and on any theory of liability, whether in contract, strict
liability, or tort (including negligence), arising in any way out of the use of this software, even if
advised of the possibility of such damage.
5. CONTACT INFORMATION
Fraunhofer Institute for Integrated Circuits IIS
Attention: Audio and Multimedia Departments - FDK AAC LL
Am Wolfsmantel 33
91058 Erlangen, Germany
www.iis.fraunhofer.de/amm
amm-info@iis.fraunhofer.de
----------------------------------------------------------------------------------------------------------- */
/***************************** MPEG-4 AAC Decoder **************************
Author(s): Christian Griebel
Description: DRM transport stuff
******************************************************************************/
#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);
}

View File

@ -0,0 +1,194 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
of the MPEG specifications.
Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
individually for the purpose of encoding or decoding bit streams in products that are compliant with
the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
software may already be covered under those patent licenses when it is used for those licensed purposes only.
Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
applications information and documentation.
2. COPYRIGHT LICENSE
Redistribution and use in source and binary forms, with or without modification, are permitted without
payment of copyright license fees provided that you satisfy the following conditions:
You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
your modifications thereto in source code form.
You must retain the complete text of this software license in the documentation and/or other materials
provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
modifications thereto to recipients of copies in binary form.
The name of Fraunhofer may not be used to endorse or promote products derived from this library without
prior written permission.
You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
software or your modifications thereto.
Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
and the date of any change. For modified versions of the FDK AAC Codec, the term
"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
3. NO PATENT LICENSE
NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
respect to this software.
You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
by appropriate patent licenses.
4. DISCLAIMER
This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
or business interruption, however caused and on any theory of liability, whether in contract, strict
liability, or tort (including negligence), arising in any way out of the use of this software, even if
advised of the possibility of such damage.
5. CONTACT INFORMATION
Fraunhofer Institute for Integrated Circuits IIS
Attention: Audio and Multimedia Departments - FDK AAC LL
Am Wolfsmantel 33
91058 Erlangen, Germany
www.iis.fraunhofer.de/amm
amm-info@iis.fraunhofer.de
----------------------------------------------------------------------------------------------------------- */
/***************************** MPEG-4 AAC Decoder **************************
Author(s): Josef Hoepfl
Description: DRM interface
******************************************************************************/
#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 */

View File

@ -102,6 +102,7 @@ amm-info@iis.fraunhofer.de
#include "tpdec_latm.h" #include "tpdec_latm.h"
#include "tpdec_drm.h"
#define MODULE_NAME "transportDec" #define MODULE_NAME "transportDec"
@ -113,6 +114,7 @@ typedef union {
CLatmDemux latm; CLatmDemux latm;
STRUCT_DRM drm;
} transportdec_parser_t; } transportdec_parser_t;
@ -182,6 +184,9 @@ HANDLE_TRANSPORTDEC transportDec_Open( const TRANSPORT_TYPE transportFmt, const
hInput->numberOfRawDataBlocks = 0; hInput->numberOfRawDataBlocks = 0;
break; break;
case TT_DRM:
drmRead_CrcInit(&hInput->parser.drm);
break;
case TT_MP4_LATM_MCP0: case TT_MP4_LATM_MCP0:
case TT_MP4_LATM_MCP1: case TT_MP4_LATM_MCP1:
@ -253,6 +258,18 @@ TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, UCHAR *
} }
} }
break; 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) { if (err == TRANSPORTDEC_OK && fConfigFound) {
@ -1083,6 +1100,7 @@ TRANSPORTDEC_ERROR transportDec_ReadAccessUnit( const HANDLE_TRANSPORTDEC hTp, c
break; break;
case TT_MP4_RAW: case TT_MP4_RAW:
case TT_DRM:
/* One Access Unit was filled into buffer. /* One Access Unit was filled into buffer.
So get the length out of the buffer. */ So get the length out of the buffer. */
hTp->auLength[layer] = FDKgetValidBits(hBs); hTp->auLength[layer] = FDKgetValidBits(hBs);
@ -1283,6 +1301,7 @@ TRANSPORTDEC_ERROR transportDec_GetLibInfo( LIB_INFO *info )
| CAPF_LATM | CAPF_LATM
| CAPF_LOAS | CAPF_LOAS
| CAPF_RAWPACKETS | CAPF_RAWPACKETS
| CAPF_DRM
; ;
return TRANSPORTDEC_OK; /* FDKERR_NOERROR; */ return TRANSPORTDEC_OK; /* FDKERR_NOERROR; */
@ -1294,6 +1313,8 @@ int transportDec_CrcStartReg(HANDLE_TRANSPORTDEC pTp, INT mBits)
switch (pTp->transportFmt) { switch (pTp->transportFmt) {
case TT_MP4_ADTS: case TT_MP4_ADTS:
return adtsRead_CrcStartReg(&pTp->parser.adts, &pTp->bitStream[0], mBits); return adtsRead_CrcStartReg(&pTp->parser.adts, &pTp->bitStream[0], mBits);
case TT_DRM:
return drmRead_CrcStartReg(&pTp->parser.drm, &pTp->bitStream[0], mBits);
default: default:
return 0; return 0;
} }
@ -1305,6 +1326,9 @@ void transportDec_CrcEndReg(HANDLE_TRANSPORTDEC pTp, INT reg)
case TT_MP4_ADTS: case TT_MP4_ADTS:
adtsRead_CrcEndReg(&pTp->parser.adts, &pTp->bitStream[0], reg); adtsRead_CrcEndReg(&pTp->parser.adts, &pTp->bitStream[0], reg);
break; break;
case TT_DRM:
drmRead_CrcEndReg(&pTp->parser.drm, &pTp->bitStream[0], reg);
break;
default: default:
break; break;
} }
@ -1321,6 +1345,9 @@ TRANSPORTDEC_ERROR transportDec_CrcCheck(HANDLE_TRANSPORTDEC pTp)
transportDec_AdjustEndOfAccessUnit(pTp); transportDec_AdjustEndOfAccessUnit(pTp);
} }
return adtsRead_CrcCheck(&pTp->parser.adts); return adtsRead_CrcCheck(&pTp->parser.adts);
case TT_DRM:
return drmRead_CrcCheck(&pTp->parser.drm);
break;
default: default:
return TRANSPORTDEC_OK; return TRANSPORTDEC_OK;
} }

View File

@ -2,7 +2,7 @@
/* library info */ /* library info */
#define TP_LIB_VL0 2 #define TP_LIB_VL0 2
#define TP_LIB_VL1 3 #define TP_LIB_VL1 3
#define TP_LIB_VL2 5 #define TP_LIB_VL2 7
#define TP_LIB_TITLE "MPEG Transport" #define TP_LIB_TITLE "MPEG Transport"
#ifdef __ANDROID__ #ifdef __ANDROID__
#define TP_LIB_BUILD_DATE "" #define TP_LIB_BUILD_DATE ""

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 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 * 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 * 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. * 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 self SBR decoder handle.
* \param hBs Bit stream handle as data source. * \param hBs Bit stream handle as data source.

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -151,13 +151,13 @@ typedef struct
} }
ENV_CALC_NRGS; ENV_CALC_NRGS;
/*static*/ void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer,
SCHAR *filtBuffer_e, SCHAR *filtBuffer_e,
FIXP_DBL *NrgGain, FIXP_DBL *NrgGain,
SCHAR *NrgGain_e, SCHAR *NrgGain_e,
int subbands); int subbands);
/*static*/ void calcNrgPerSubband(FIXP_DBL **analysBufferReal, static void calcNrgPerSubband(FIXP_DBL **analysBufferReal,
FIXP_DBL **analysBufferImag, FIXP_DBL **analysBufferImag,
int lowSubband, int highSubband, int lowSubband, int highSubband,
int start_pos, int next_pos, int start_pos, int next_pos,
@ -165,7 +165,7 @@ ENV_CALC_NRGS;
FIXP_DBL *nrgEst, FIXP_DBL *nrgEst,
SCHAR *nrgEst_e ); SCHAR *nrgEst_e );
/*static*/ void calcNrgPerSfb(FIXP_DBL **analysBufferReal, static void calcNrgPerSfb(FIXP_DBL **analysBufferReal,
FIXP_DBL **analysBufferImag, FIXP_DBL **analysBufferImag,
int nSfb, int nSfb,
UCHAR *freqBandTable, UCHAR *freqBandTable,
@ -174,13 +174,13 @@ ENV_CALC_NRGS;
FIXP_DBL *nrg_est, FIXP_DBL *nrg_est,
SCHAR *nrg_est_e ); 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, FIXP_DBL tmpNoise, SCHAR tmpNoise_e,
UCHAR sinePresentFlag, UCHAR sinePresentFlag,
UCHAR sineMapped, UCHAR sineMapped,
int noNoiseFlag); int noNoiseFlag);
/*static*/ void calcAvgGain(ENV_CALC_NRGS* nrgs, static void calcAvgGain(ENV_CALC_NRGS* nrgs,
int lowSubband, int lowSubband,
int highSubband, int highSubband,
FIXP_DBL *sumRef_m, FIXP_DBL *sumRef_m,
@ -188,7 +188,7 @@ ENV_CALC_NRGS;
FIXP_DBL *ptrAvgGain_m, FIXP_DBL *ptrAvgGain_m,
SCHAR *ptrAvgGain_e); SCHAR *ptrAvgGain_e);
/*static*/ void adjustTimeSlotLC(FIXP_DBL *ptrReal, static void adjustTimeSlot_EldGrid(FIXP_DBL *ptrReal,
ENV_CALC_NRGS* nrgs, ENV_CALC_NRGS* nrgs,
UCHAR *ptrHarmIndex, UCHAR *ptrHarmIndex,
int lowSubbands, int lowSubbands,
@ -196,8 +196,17 @@ ENV_CALC_NRGS;
int scale_change, int scale_change,
int noNoiseFlag, int noNoiseFlag,
int *ptrPhaseIndex, int *ptrPhaseIndex,
int fCldfb); int scale_diff_low);
/*static*/ void adjustTimeSlotHQ(FIXP_DBL *ptrReal,
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, FIXP_DBL *ptrImag,
HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env,
ENV_CALC_NRGS* nrgs, ENV_CALC_NRGS* nrgs,
@ -224,7 +233,7 @@ ENV_CALC_NRGS;
Additionally, the flags in harmFlagsPrev are being updated by this function Additionally, the flags in harmFlagsPrev are being updated by this function
for the next frame. 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 */ int nSfb, /*!< Number of bands in the table */
UCHAR *addHarmonics, /*!< vector with 1 flag per sfb */ UCHAR *addHarmonics, /*!< vector with 1 flag per sfb */
int *harmFlagsPrev, /*!< Packed 'addHarmonics' */ int *harmFlagsPrev, /*!< Packed 'addHarmonics' */
@ -990,7 +999,6 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling
/* Prevent the smoothing filter from running on constant levels */ /* Prevent the smoothing filter from running on constant levels */
if (j-start_pos < smooth_length) if (j-start_pos < smooth_length)
smooth_ratio = FDK_sbrDecoder_sbr_smoothFilter[j-start_pos]; smooth_ratio = FDK_sbrDecoder_sbr_smoothFilter[j-start_pos];
else else
smooth_ratio = FL2FXCONST_SGL(0.0f); smooth_ratio = FL2FXCONST_SGL(0.0f);
@ -1007,7 +1015,8 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling
} }
else else
{ {
adjustTimeSlotLC(&analysBufferReal[j][lowSubband], if (flags & SBRDEC_ELD_GRID) {
adjustTimeSlot_EldGrid(&analysBufferReal[j][lowSubband],
pNrgs, pNrgs,
&h_sbr_cal_env->harmIndex, &h_sbr_cal_env->harmIndex,
lowSubband, lowSubband,
@ -1015,7 +1024,18 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling
scale_change, scale_change,
noNoiseFlag, noNoiseFlag,
&h_sbr_cal_env->phaseIndex, &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 } // for
@ -1176,7 +1196,7 @@ resetSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv) /*!< pointer to env
can be performed. can be performed.
This function is called once for each envelope before adjusting. 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 */ SCHAR *filtBuffer_e, /*!< exponents of bufferd gains */
FIXP_DBL *nrgGain, /*!< gains for current envelope */ FIXP_DBL *nrgGain, /*!< gains for current envelope */
SCHAR *nrgGain_e, /*!< exponents of 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. 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 */ FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */
int lowSubband, /*!< Begin of the SBR frequency range */ int lowSubband, /*!< Begin of the SBR frequency range */
int highSubband, /*!< High end 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. 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 */ FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */
int nSfb, /*!< Number of scale factor bands */ int nSfb, /*!< Number of scale factor bands */
UCHAR *freqBandTable, /*!< First Subband for each Sfb */ 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. 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) */ SCHAR nrgRef_e, /*!< Reference Energy according to envelope data (exponent) */
ENV_CALC_NRGS* nrgs, ENV_CALC_NRGS* nrgs,
int i, 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 The result is used as a relative limit for all gains within the
current "limiter band" (a certain frequency range). 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 lowSubband, /*!< Begin of the limiter band */
int highSubband, /*!< High end of the limiter band */ int highSubband, /*!< High end of the limiter band */
FIXP_DBL *ptrSumRef, FIXP_DBL *ptrSumRef,
@ -1728,21 +1748,101 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output
*ptrSumRef_e = sumRef_e; *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 \brief Amplify one timeslot of the signal with the calculated gains
and add the noisefloor. 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, ENV_CALC_NRGS* nrgs,
UCHAR *ptrHarmIndex, /*!< Harmonic index */ UCHAR *ptrHarmIndex, /*!< Harmonic index */
int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */
int noSubbands, /*!< Number of QMF subbands */ int noSubbands, /*!< Number of QMF subbands */
int scale_change, /*!< Number of bits to shift adjusted samples */ int scale_change, /*!< Number of bits to shift adjusted samples */
int noNoiseFlag, /*!< Flag to suppress noise addition */ int noNoiseFlag, /*!< Flag to suppress noise addition */
int *ptrPhaseIndex, /*!< Start index to random number array */ int *ptrPhaseIndex) /*!< Start index to random number array */
int fCldfb) /*!< CLDFB 80 flag */
{ {
FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */ FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */
FIXP_DBL *pNoiseLevel = nrgs->noiseLevel; /*!< Noise levels 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); sineLevelNext = (noSubbands > 1) ? pSineLevel[0] : FL2FXCONST_DBL(0.0f);
if (sineLevel!=FL2FXCONST_DBL(0.0f)) tone_count++; if (sineLevel!=FL2FXCONST_DBL(0.0f)) tone_count++;
else if (!noNoiseFlag) else if (!noNoiseFlag)
/* Add noisefloor to the amplified signal */ /* Add noisefloor to the amplified signal */
signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4); 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)) { if (!(harmIndex&0x1)) {
/* harmIndex 0,2 */ /* harmIndex 0,2 */
@ -1933,8 +2002,9 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output
*ptrHarmIndex = (harmIndex + 1) & 3; *ptrHarmIndex = (harmIndex + 1) & 3;
*ptrPhaseIndex = index & (SBR_NF_NO_RANDOM_VAL - 1); *ptrPhaseIndex = index & (SBR_NF_NO_RANDOM_VAL - 1);
} }
void adjustTimeSlotHQ(FIXP_DBL *RESTRICT ptrReal, /*!< Subband samples to be adjusted, real part */ static void adjustTimeSlotHQ(
FIXP_DBL *RESTRICT ptrImag, /*!< Subband samples to be adjusted, imag part */ 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, HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env,
ENV_CALC_NRGS* nrgs, ENV_CALC_NRGS* nrgs,
int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ 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]; UCHAR workLimiterBandTable[MAX_FREQ_COEFFS / 2 + MAX_NUM_PATCHES + 1];
int patchBorders[MAX_NUM_PATCHES + 1]; int patchBorders[MAX_NUM_PATCHES + 1];
int kx, k2; int kx, k2;
FIXP_DBL temp;
int lowSubband = freqBandTable[0]; int lowSubband = freqBandTable[0];
int highSubband = freqBandTable[noFreqBands]; int highSubband = freqBandTable[noFreqBands];
@ -2169,13 +2238,32 @@ ResetLimiterBands ( UCHAR *limiterBandTable, /*!< Resulting band borders in QM
while (hiLimIndex <= tempNoLim) { while (hiLimIndex <= tempNoLim) {
FIXP_DBL div_m, oct_m, temp;
INT div_e = 0, oct_e = 0, temp_e = 0;
k2 = workLimiterBandTable[hiLimIndex] + lowSubband; k2 = workLimiterBandTable[hiLimIndex] + lowSubband;
kx = workLimiterBandTable[loLimIndex] + lowSubband; kx = workLimiterBandTable[loLimIndex] + lowSubband;
temp = FX_SGL2FX_DBL(FDK_getNumOctavesDiv8(kx,k2)); /* Number of octaves */ div_m = fDivNorm(k2, kx, &div_e);
temp = fMult(temp, FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[limiterBands]);
/* 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]) { if (workLimiterBandTable[hiLimIndex] == workLimiterBandTable[loLimIndex]) {
workLimiterBandTable[hiLimIndex] = highSubband; workLimiterBandTable[hiLimIndex] = highSubband;
nBands--; nBands--;

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -369,7 +369,7 @@ leanSbrConcealment(HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control d
FIXP_SGL step; /* speed of fade */ FIXP_SGL step; /* speed of fade */
int i; int i;
int currentStartPos = h_prev_data->stopPos - hHeaderData->numberTimeSlots; int currentStartPos = FDKmax(0, h_prev_data->stopPos - hHeaderData->numberTimeSlots);
int currentStopPos = hHeaderData->numberTimeSlots; int currentStopPos = hHeaderData->numberTimeSlots;

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -327,7 +327,7 @@ sbrGetHeaderData (HANDLE_SBR_HEADER_DATA hHeaderData,
} }
/* Look for new settings. IEC 14496-3, 4.6.18.3.1 */ /* 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.startFreq != pBsData->startFreq ||
lastHeader.stopFreq != pBsData->stopFreq || lastHeader.stopFreq != pBsData->stopFreq ||
lastHeader.freqScale != pBsData->freqScale || lastHeader.freqScale != pBsData->freqScale ||

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -125,6 +125,7 @@ amm-info@iis.fraunhofer.de
typedef enum typedef enum
{ {
HEADER_NOT_PRESENT, HEADER_NOT_PRESENT,
HEADER_ERROR,
HEADER_OK, HEADER_OK,
HEADER_RESET HEADER_RESET
} }
@ -132,10 +133,10 @@ SBR_HEADER_STATUS;
typedef enum typedef enum
{ {
SBR_NOT_INITIALIZED, SBR_NOT_INITIALIZED = 0,
UPSAMPLING, UPSAMPLING = 1,
SBR_HEADER, SBR_HEADER = 2,
SBR_ACTIVE SBR_ACTIVE = 3
} }
SBR_SYNC_STATE; 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_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_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_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_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_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. */ #define SBRDEC_FORCE_RESET 32768 /* Flag is used to force a reset of all elements in use. */

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -225,7 +225,14 @@ static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< hand
} }
if (resetAnaQmf) { 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->AnalysiscQMF,
hSbrDec->anaQmfStates, hSbrDec->anaQmfStates,
hSbrDec->AnalysiscQMF.no_col, hSbrDec->AnalysiscQMF.no_col,
@ -234,13 +241,22 @@ static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< hand
hSbrDec->AnalysiscQMF.no_channels, hSbrDec->AnalysiscQMF.no_channels,
anaQmfFlags | QMF_FLAG_KEEP_STATES anaQmfFlags | QMF_FLAG_KEEP_STATES
); );
if (qmfErr != 0) { if (qmfErr != 0) {
FDK_ASSERT(0); /* Restore old configuration of analysis QMF */
FDKmemcpy(&hSbrDec->AnalysiscQMF, &prvAnaQmf, sizeof(QMF_FILTER_BANK));
} }
} }
if (resetSynQmf) { 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->SynthesisQMF,
hSbrDec->pSynQmfStates, hSbrDec->pSynQmfStates,
hSbrDec->SynthesisQMF.no_col, hSbrDec->SynthesisQMF.no_col,
@ -251,7 +267,8 @@ static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< hand
); );
if (qmfErr != 0) { 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 */ HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */
const int applyProcessing, /*!< Flag for SBR operation */ const int applyProcessing, /*!< Flag for SBR operation */
HANDLE_PS_DEC h_ps_d, HANDLE_PS_DEC h_ps_d,
const UINT flags const UINT flags,
const int codecFrameSize
) )
{ {
int i, slot, reserve; int i, slot, reserve;
@ -348,6 +366,33 @@ sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
if (flags & SBRDEC_ELD_GRID) { if (flags & SBRDEC_ELD_GRID) {
/* Choose the right low delay filter bank */ /* Choose the right low delay filter bank */
changeQmfType( hSbrDec, (flags & SBRDEC_LD_MPS_QMF) ? 1 : 0 ); 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; int qmfErr;
/* Adapted QMF analysis post-twiddles for down-sampled HQ SBR */ /* 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 ( qmfErr = qmfInitAnalysisFilterBank (
&hs->AnalysiscQMF, &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 */ /* assign qmf time slots */
assignTimeSlots( &hSbrChannel->SbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, qmfFlags & QMF_FLAG_LP); assignTimeSlots( &hSbrChannel->SbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, qmfFlags & QMF_FLAG_LP);

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -118,6 +118,9 @@ typedef struct
FIXP_DBL * WorkBuffer1; FIXP_DBL * WorkBuffer1;
FIXP_DBL * WorkBuffer2; FIXP_DBL * WorkBuffer2;
/* Delayed time input signal needed to align CLDFD with LD-MPS QMF. */
INT_PCM coreDelayBuf[(96)];
/* QMF filter states */ /* QMF filter states */
FIXP_QAS anaQmfStates[(320)]; FIXP_QAS anaQmfStates[(320)];
FIXP_QSS * pSynQmfStates; 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 */ HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */
const int applyProcessing, /*!< Flag for SBR operation */ const int applyProcessing, /*!< Flag for SBR operation */
HANDLE_PS_DEC h_ps_d, HANDLE_PS_DEC h_ps_d,
const UINT flags const UINT flags,
const int codecFrameSize
); );

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -135,6 +135,7 @@ struct SBR_DECODER_INSTANCE
USHORT codecFrameSize; USHORT codecFrameSize;
UCHAR synDownsampleFac; UCHAR synDownsampleFac;
UCHAR numDelayFrames; /* The current number of additional delay frames used for processing. */ 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; UINT flags;

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -189,6 +189,15 @@ const FIXP_SGL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[4] =
FL2FXCONST_SGL(3.0f / 4.0f) 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 */ /*! Ratio of old gains and noise levels for the first 4 timeslots of an envelope */
const FIXP_SGL FDK_sbrDecoder_sbr_smoothFilter[4] = { const FIXP_SGL FDK_sbrDecoder_sbr_smoothFilter[4] = {
FL2FXCONST_SGL(0.66666666666666f), FL2FXCONST_SGL(0.66666666666666f),

View File

@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. All rights reserved.
1. INTRODUCTION 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 FIXP_SGL FDK_sbrDecoder_sbr_limGains_m[4];
extern const UCHAR FDK_sbrDecoder_sbr_limGains_e[4]; extern const UCHAR FDK_sbrDecoder_sbr_limGains_e[4];
extern const FIXP_SGL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[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_smoothFilter[4];
extern const FIXP_SGL FDK_sbrDecoder_sbr_randomPhase[SBR_NF_NO_RANDOM_VAL][2]; extern const FIXP_SGL FDK_sbrDecoder_sbr_randomPhase[SBR_NF_NO_RANDOM_VAL][2];
extern const FIXP_SGL harmonicPhaseX [2][4]; extern const FIXP_SGL harmonicPhaseX [2][4];

View File

@ -128,6 +128,7 @@ amm-info@iis.fraunhofer.de
#include "lpp_tran.h" #include "lpp_tran.h"
#include "transcendent.h" #include "transcendent.h"
#include "FDK_crc.h"
#include "sbrdec_drc.h" #include "sbrdec_drc.h"
@ -137,7 +138,7 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */ /* Decoder library info */
#define SBRDECODER_LIB_VL0 2 #define SBRDECODER_LIB_VL0 2
#define SBRDECODER_LIB_VL1 2 #define SBRDECODER_LIB_VL1 2
#define SBRDECODER_LIB_VL2 7 #define SBRDECODER_LIB_VL2 12
#define SBRDECODER_LIB_TITLE "SBR Decoder" #define SBRDECODER_LIB_TITLE "SBR Decoder"
#ifdef __ANDROID__ #ifdef __ANDROID__
#define SBRDECODER_LIB_BUILD_DATE "" #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; 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. \brief Reset SBR decoder.
@ -391,6 +419,7 @@ int sbrDecoder_isCoreCodecValid(AUDIO_OBJECT_TYPE coreCodec)
case AOT_PS: case AOT_PS:
case AOT_ER_AAC_SCAL: case AOT_ER_AAC_SCAL:
case AOT_ER_AAC_ELD: case AOT_ER_AAC_ELD:
case AOT_DRM_AAC:
return 1; return 1;
default: default:
return 0; return 0;
@ -463,6 +492,8 @@ SBR_ERROR sbrDecoder_InitElement (
self->flags = 0; self->flags = 0;
self->flags |= (coreCodec == AOT_ER_AAC_ELD) ? SBRDEC_ELD_GRID : 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 */ /* Init SBR elements */
{ {
@ -928,24 +959,73 @@ SBR_ERROR sbrDecoder_Parse(
) )
{ {
SBR_DECODER_ELEMENT *hSbrElement; SBR_DECODER_ELEMENT *hSbrElement;
HANDLE_SBR_HEADER_DATA hSbrHeader; HANDLE_SBR_HEADER_DATA hSbrHeader = NULL;
HANDLE_SBR_CHANNEL *pSbrChannel; HANDLE_SBR_CHANNEL *pSbrChannel;
SBR_FRAME_DATA *hFrameDataLeft; SBR_FRAME_DATA *hFrameDataLeft;
SBR_FRAME_DATA *hFrameDataRight; SBR_FRAME_DATA *hFrameDataRight;
SBR_ERROR errorStatus = SBRDEC_OK; SBR_ERROR errorStatus = SBRDEC_OK;
SBR_SYNC_STATE initialSyncState;
SBR_HEADER_STATUS headerStatus = HEADER_NOT_PRESENT; SBR_HEADER_STATUS headerStatus = HEADER_NOT_PRESENT;
INT startPos; INT startPos;
INT CRCLen = 0; 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 stereo;
int fDoDecodeSbrData = 1; int fDoDecodeSbrData = 1;
int lastSlot, lastHdrSlot = 0, thisHdrSlot; 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 */ /* Remember start position of SBR element */
startPos = FDKgetValidBits(hBs); startPos = FDKgetValidBits(hBs);
@ -970,7 +1050,6 @@ SBR_ERROR sbrDecoder_Parse(
hFrameDataLeft = &self->pSbrElement[elementIndex]->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; hFrameDataLeft = &self->pSbrElement[elementIndex]->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
hFrameDataRight = &self->pSbrElement[elementIndex]->pSbrChannel[1]->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 */ /* reset PS flag; will be set after PS was found */
self->flags &= ~SBRDEC_PS_DECODED; self->flags &= ~SBRDEC_PS_DECODED;
@ -1006,12 +1085,19 @@ SBR_ERROR sbrDecoder_Parse(
*/ */
if (fDoDecodeSbrData) if (fDoDecodeSbrData)
{ {
if (crcFlag == 1) { if (crcFlag) {
switch (self->coreCodec) { switch (self->coreCodec) {
case AOT_ER_AAC_ELD: case AOT_ER_AAC_ELD:
FDKpushFor (hBs, 10); FDKpushFor (hBs, 10);
/* check sbrcrc later: we don't know the payload length now */ /* check sbrcrc later: we don't know the payload length now */
break; 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: default:
CRCLen = bsPayLen - 10; /* change: 0 => i */ CRCLen = bsPayLen - 10; /* change: 0 => i */
if (CRCLen < 0) { if (CRCLen < 0) {
@ -1056,6 +1142,7 @@ SBR_ERROR sbrDecoder_Parse(
hSbrHeader->syncState = SBR_HEADER; hSbrHeader->syncState = SBR_HEADER;
} else { } else {
hSbrHeader->syncState = SBR_NOT_INITIALIZED; hSbrHeader->syncState = SBR_NOT_INITIALIZED;
headerStatus = HEADER_ERROR;
} }
} }
@ -1105,7 +1192,7 @@ SBR_ERROR sbrDecoder_Parse(
valBits = (INT)FDKgetValidBits(hBs); valBits = (INT)FDKgetValidBits(hBs);
} }
if ( crcFlag == 1 ) { if ( crcFlag ) {
switch (self->coreCodec) { switch (self->coreCodec) {
case AOT_ER_AAC_ELD: case AOT_ER_AAC_ELD:
{ {
@ -1117,6 +1204,14 @@ SBR_ERROR sbrDecoder_Parse(
FDKpushFor(hBs, crcLen); FDKpushFor(hBs, crcLen);
} }
break; break;
case AOT_DRM_AAC:
/* End CRC region */
FDKcrcEndReg(&crcInfo, hBs, crcReg);
/* Check CRC */
if ((FDKcrcGetCRC(&crcInfo)^0xFF) != drmSbrCrc) {
fDoDecodeSbrData = 0;
}
break;
default: default:
break; break;
} }
@ -1167,8 +1262,25 @@ SBR_ERROR sbrDecoder_Parse(
} }
bail: 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 */ /* Use the old header for this frame */
hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = lastHdrSlot; hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = lastHdrSlot;
} else { } else {
@ -1229,12 +1341,21 @@ sbrDecoder_DecodeElement (
int numElementChannels = hSbrElement->nChannels; /* Number of channels of the current SBR element */ int numElementChannels = hSbrElement->nChannels; /* Number of channels of the current SBR element */
if (self->flags & SBRDEC_FLUSH) { if (self->flags & SBRDEC_FLUSH) {
/* Move frame pointer to the next slot which is up to be decoded/applied next */ if ( self->numFlushedFrames > self->numDelayFrames ) {
hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1); int hdrIdx;
/* Update header and frame data pointer because they have already been set */ /* No valid SBR payload available, hence switch to upsampling (in all headers) */
hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]]; for (hdrIdx = 0; hdrIdx < ((1)+1); hdrIdx += 1) {
hFrameDataLeft = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; self->sbrHeader[elementIndex][hdrIdx].syncState = UPSAMPLING;
hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; }
}
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 */ /* Update the header error flag */
@ -1354,7 +1475,8 @@ sbrDecoder_DecodeElement (
&pSbrChannel[0]->prevFrameData, &pSbrChannel[0]->prevFrameData,
(hSbrHeader->syncState == SBR_ACTIVE), (hSbrHeader->syncState == SBR_ACTIVE),
h_ps_d, h_ps_d,
self->flags self->flags,
codecFrameSize
); );
if (stereo) { if (stereo) {
@ -1371,7 +1493,8 @@ sbrDecoder_DecodeElement (
&pSbrChannel[1]->prevFrameData, &pSbrChannel[1]->prevFrameData,
(hSbrHeader->syncState == SBR_ACTIVE), (hSbrHeader->syncState == SBR_ACTIVE),
NULL, NULL,
self->flags self->flags,
codecFrameSize
); );
} }
@ -1387,20 +1510,21 @@ sbrDecoder_DecodeElement (
if ( !(self->flags & SBRDEC_PS_DECODED) ) { 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. */ /* 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. */ /* So copy left channel to right channel. */
int copyFrameSize = codecFrameSize * 2 / self->synDownsampleFac;
if (interleaved) { if (interleaved) {
INT_PCM *ptr; INT_PCM *ptr;
INT i; INT i;
FDK_ASSERT(strideOut == 2); FDK_ASSERT(strideOut == 2);
ptr = timeData; 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. */ 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;
tmp = *ptr++; *ptr++ = tmp; tmp = *ptr++; *ptr++ = tmp;
} }
} else { } 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. */ *numOutChannels = 2; /* Output minimum two channels when PS is enabled. */
@ -1464,14 +1588,23 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self,
self->flags &= ~SBRDEC_PS_DECODED; 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 */ /* Loop over SBR elements */
for (sbrElementNum = 0; sbrElementNum<self->numSbrElements; sbrElementNum++) for (sbrElementNum = 0; sbrElementNum<self->numSbrElements; sbrElementNum++)
{ {
int numElementChan; int numElementChan;
if (psPossible && self->pSbrElement[sbrElementNum]->pSbrChannel[1] == NULL) { if (psPossible && self->pSbrElement[sbrElementNum]->pSbrChannel[1] == NULL) {
errorStatus = SBRDEC_UNSUPPORTED_CONFIG; /* Disable PS and try decoding SBR mono. */
goto bail; psPossible = 0;
} }
numElementChan = (self->pSbrElement[sbrElementNum]->elementID == ID_CPE) ? 2 : 1; numElementChan = (self->pSbrElement[sbrElementNum]->elementID == ID_CPE) ? 2 : 1;
@ -1579,6 +1712,7 @@ INT sbrDecoder_GetLibInfo( LIB_INFO *info )
| CAPF_SBR_HQ | CAPF_SBR_HQ
| CAPF_SBR_LP | CAPF_SBR_LP
| CAPF_SBR_PS_MPEG | CAPF_SBR_PS_MPEG
| CAPF_SBR_DRM_BS
| CAPF_SBR_CONCEALMENT | CAPF_SBR_CONCEALMENT
| CAPF_SBR_DRC | CAPF_SBR_DRC
; ;
@ -1607,6 +1741,9 @@ UINT sbrDecoder_GetDelay( const HANDLE_SBRDECODER self )
/* Low delay SBR: */ /* Low delay SBR: */
{ {
outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 32 : 64; /* QMF synthesis */ outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 32 : 64; /* QMF synthesis */
if (flags & SBRDEC_LD_MPS_QMF) {
outputDelay += 32;
}
} }
} }
else if (!IS_USAC(self->coreCodec)) { else if (!IS_USAC(self->coreCodec)) {

View File

@ -92,14 +92,14 @@ amm-info@iis.fraunhofer.de
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#include "genericStds.h"
#include <math.h> #include <math.h>
#include "genericStds.h"
/* library info */ /* library info */
#define SYS_LIB_VL0 1 #define SYS_LIB_VL0 1
#define SYS_LIB_VL1 3 #define SYS_LIB_VL1 3
#define SYS_LIB_VL2 7 #define SYS_LIB_VL2 8
#define SYS_LIB_TITLE "System Integration Library" #define SYS_LIB_TITLE "System Integration Library"
#ifdef __ANDROID__ #ifdef __ANDROID__
#define SYS_LIB_BUILD_DATE "" #define SYS_LIB_BUILD_DATE ""