Commit 698b536f authored by Dave Burke's avatar Dave Burke

Update to 2012_05_11 version.

Fixes:
- Don't throw error for invalid bitrate but limit to functional value
- More robust ASC parsing
- More robust handling of corrupt bitstreams
- Handle multiple raw access units

Change-Id: Ib49fe2545ff4185fe924126da702fe84ac5c2d87
parent 9bf37cc9
......@@ -42,7 +42,7 @@
#define DRC_PARAMETER_BITS ( 7 )
#define DRC_MAX_QUANT_STEPS ( 1<<DRC_PARAMETER_BITS )
#define DRC_MAX_QUANT_FACTOR ( DRC_MAX_QUANT_STEPS-1 )
#define DRC_PARAM_QUANT_STEP ( FL2FXCONST_DBL(1.0f/(float)DRC_MAX_QUANT_STEPS) )
#define DRC_PARAM_QUANT_STEP ( FL2FXCONST_DBL(1.0f/(float)DRC_MAX_QUANT_FACTOR) )
#define DRC_PARAM_SCALE ( 1 )
#define MAX_REFERENCE_LEVEL ( 127 )
......@@ -99,6 +99,7 @@ void aacDecoder_drcInitChannelData (
pDrcChData->bandTop[0] = (1024 >> 2) - 1;
pDrcChData->drcValue[0] = 0;
pDrcChData->drcInterpolationScheme = 0;
pDrcChData->drcDataType = UNKNOWN_PAYLOAD;
}
}
......@@ -130,7 +131,7 @@ AAC_DECODER_ERROR aacDecoder_drcSetParam (
if (self == NULL) {
return AAC_DEC_INVALID_HANDLE;
}
self->params.cut = (FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP>>DRC_PARAM_SCALE) * (INT)(value+1));
self->params.cut = (FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP>>DRC_PARAM_SCALE) * (INT)value);
break;
case DRC_BOOST_SCALE:
/* set boost factor */
......@@ -141,7 +142,7 @@ AAC_DECODER_ERROR aacDecoder_drcSetParam (
if (self == NULL) {
return AAC_DEC_INVALID_HANDLE;
}
self->params.boost = (FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP>>DRC_PARAM_SCALE) * (INT)(value+1));
self->params.boost = (FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP>>DRC_PARAM_SCALE) * (INT)value);
break;
case TARGET_REF_LEVEL:
if ( value > MAX_REFERENCE_LEVEL
......@@ -300,14 +301,13 @@ int aacDecoder_drcMarkPayload (
break;
case DVB_DRC_ANC_DATA:
bitCnt += 8;
/* check sync word */
if (FDKreadBits(bs, 8) == DVB_ANC_DATA_SYNC_BYTE)
{
int dmxLevelsPresent, compressionPresent;
int coarseGrainTcPresent, fineGrainTcPresent;
bitCnt+=8;
/* bs_info field */
FDKreadBits(bs, 8); /* mpeg_audio_type, dolby_surround_mode, presentation_mode */
bitCnt+=8;
......@@ -432,7 +432,7 @@ static int aacDecoder_drcParse (
}
/* Set DRC payload type */
pDrcBs->type = MPEG_DRC_EXT_DATA;
pDrcBs->channelData.drcDataType = MPEG_DRC_EXT_DATA;
return (bitCnt);
}
......@@ -515,23 +515,26 @@ static int aacDecoder_drcReadCompression (
if ( compressionOn ) {
/* A compression value is available so store the data just like MPEG DRC data */
pDrcBs->channelData.drcValue[0] = compressionValue;
pDrcBs->channelData.numBands = 1; /* one value for all bands */
pDrcBs->pceInstanceTag = -1; /* not present */
pDrcBs->progRefLevel = -1; /* not present */
pDrcBs->channelData.numBands = 1; /* One band ... */
pDrcBs->channelData.drcValue[0] = compressionValue; /* ... with one value ... */
pDrcBs->channelData.bandTop[0] = (1024 >> 2) - 1; /* ... comprising the whole spectrum. */
pDrcBs->pceInstanceTag = -1; /* Not present */
pDrcBs->progRefLevel = -1; /* Not present */
pDrcBs->channelData.drcDataType = DVB_DRC_ANC_DATA; /* Set DRC payload type to DVB. */
} else {
/* No compression value available */
/* CAUTION: It is not clearly defined by standard how to react in this situation. */
pDrcBs->channelData.drcValue[0] = 0x7F; /* 0dB */
pDrcBs->channelData.bandTop[0] = 0;
/* Turn down the compression value to aprox. 0dB */
pDrcBs->channelData.numBands = 1; /* One band ... */
pDrcBs->channelData.drcValue[0] = 0x80; /* ... with aprox. 0dB ... */
pDrcBs->channelData.bandTop[0] = (1024 >> 2) - 1; /* ... comprising the whole spectrum. */
pDrcBs->channelData.drcDataType = DVB_DRC_ANC_DATA; /* Set DRC payload type to DVB. */
/* If compression_on field is set to "0" the compression_value field shall be "0000 0000". */
if (compressionValue != 0) {
return 0;
}
}
/* Set DRC payload type now because the payload seems to be correct. */
pDrcBs->type = DVB_DRC_ANC_DATA;
}
/* Read timecodes if available just to get the right amount of bits. */
......@@ -617,7 +620,7 @@ static int aacDecoder_drcExtractAndMap (
CDrcPayload *pThreadBs = &threadBs[thread];
int numExclChns = 0;
switch (pThreadBs->type) {
switch ((AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType) {
default:
continue;
case MPEG_DRC_EXT_DATA:
......@@ -659,7 +662,7 @@ static int aacDecoder_drcExtractAndMap (
/* thread applies to this channel */
if ( (pThreadBs->type == MPEG_DRC_EXT_DATA)
if ( (pThreadBs->channelData.drcDataType == MPEG_DRC_EXT_DATA)
&& ( (numExcludedChns[thread] == 0)
|| (!(pThreadBs->excludedChnsMask & (1<<ch))) ) ) {
present++;
......@@ -678,6 +681,7 @@ static int aacDecoder_drcExtractAndMap (
{
CDrcPayload *pThreadBs = validThreadBs[thread];
INT exclMask = pThreadBs->excludedChnsMask;
AACDEC_DRC_PAYLOAD_TYPE drcPayloadType = (AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType;
int ch;
/* last progRefLevel transmitted is the one that is used
......@@ -692,9 +696,9 @@ static int aacDecoder_drcExtractAndMap (
int mapedChannel = channelMapping[ch];
if ( ((exclMask & (1<<mapedChannel)) == 0)
&& ( ( self->params.applyHeavyCompression && (pThreadBs->type == DVB_DRC_ANC_DATA))
|| (!self->params.applyHeavyCompression && (pThreadBs->type == MPEG_DRC_EXT_DATA)) )
) {
&& ( (drcPayloadType == MPEG_DRC_EXT_DATA)
|| ((drcPayloadType == DVB_DRC_ANC_DATA) && self->params.applyHeavyCompression)
) ) {
/* copy thread to channel */
pAacDecoderStaticChannelInfo[ch]->drcData = pThreadBs->channelData;
}
......@@ -781,10 +785,17 @@ void aacDecoder_drcApply (
UCHAR drcVal = pDrcChData->drcValue[band];
top = fixMin((int)( (pDrcChData->bandTop[band]+1)<<2 ), aacFrameSize);
if ( pParams->applyHeavyCompression ) {
fact_mantissa[band] = FL2FXCONST_DBL(0.5f);
fact_exponent[band] = 1;
if ( pParams->applyHeavyCompression
&& ((AACDEC_DRC_PAYLOAD_TYPE)pDrcChData->drcDataType == DVB_DRC_ANC_DATA) )
{
INT compressionFactorVal_e;
int valX = drcVal >> 4;
int valY = drcVal & 0x0F;
int valX, valY;
valX = drcVal >> 4;
valY = drcVal & 0x0F;
/* calculate the unscaled heavy compression factor.
compressionFactor = 48.164 - 6.0206*valX - 0.4014*valY dB
......@@ -801,11 +812,8 @@ void aacDecoder_drcApply (
fact_exponent[band] = DVB_COMPRESSION_SCALE - valX + compressionFactorVal_e;
}
else {
fact_mantissa[band] = FL2FXCONST_DBL(0.5f);
fact_exponent[band] = 1;
}
} else
if ((AACDEC_DRC_PAYLOAD_TYPE)pDrcChData->drcDataType == MPEG_DRC_EXT_DATA)
{
/* apply the scaled dynamic range control words to factor.
* if scaling drc_cut (or drc_boost), or control word drc_mantissa is 0
......@@ -824,10 +832,6 @@ void aacDecoder_drcApply (
3+DRC_PARAM_SCALE,
&fact_exponent[band] );
}
else {
fact_mantissa[band] = FL2FXCONST_DBL(0.5f);
fact_exponent[band] = 1;
}
}
fact_mantissa[band] = fMult(fact_mantissa[band], norm_mantissa);
......
......@@ -41,9 +41,9 @@
*/
typedef enum
{
UNKNOWN_PAYLOAD = 0,
MPEG_DRC_EXT_DATA,
DVB_DRC_ANC_DATA
UNKNOWN_PAYLOAD = 0,
MPEG_DRC_EXT_DATA = 1,
DVB_DRC_ANC_DATA = 2
} AACDEC_DRC_PAYLOAD_TYPE;
......@@ -54,12 +54,12 @@ typedef struct
USHORT bandTop[MAX_DRC_BANDS];
SHORT drcInterpolationScheme;
UCHAR drcValue[MAX_DRC_BANDS];
SCHAR drcDataType;
} CDrcChannelData;
typedef struct
{
AACDEC_DRC_PAYLOAD_TYPE type;
UINT excludedChnsMask;
SCHAR progRefLevel;
SCHAR pceInstanceTag;
......
......@@ -736,6 +736,9 @@ UINT Hcr_State_BODY_SIGN__SIGN(HANDLE_FDK_BITSTREAM bs, void *ptr)
/* search for a line (which was decoded in previous state) which is not zero. [This value will get a sign] */
while ( pResultBase[iQSC] == (FIXP_DBL)0 ) {
iQSC++; /* points to current value different from zero */
if (iQSC >= 1024) {
return BODY_SIGN__SIGN;
}
}
/* put sign together with line; if carryBit is zero, the sign is ok already; no write operation necessary in this case */
......
......@@ -34,7 +34,7 @@
enum
{
TNS_MAX_WINDOWS = 8, /* 8 */
TNS_MAXIMUM_ORDER = 12, /* 12 for AAC-LC and AAC-SSR. Set to 20 for AAC-Main (AOT 1). Some broken encoders also do order 20 for AAC-LC :( */
TNS_MAXIMUM_ORDER = 20, /* 12 for AAC-LC and AAC-SSR. Set to 20 for AAC-Main (AOT 1). Some broken encoders also do order 20 for AAC-LC :( */
TNS_MAXIMUM_FILTERS = 3
};
......
......@@ -345,6 +345,7 @@ static AAC_DECODER_ERROR CProgramConfigElement_Read (
HANDLE_FDK_BITSTREAM bs,
HANDLE_TRANSPORTDEC pTp,
CProgramConfig *pce,
UINT channelConfig,
UINT alignAnchor )
{
AAC_DECODER_ERROR error = AAC_DEC_OK;
......@@ -362,8 +363,15 @@ static AAC_DECODER_ERROR CProgramConfigElement_Read (
transportDec_CrcEndReg(pTp, crcReg);
if (!pce->isValid && tmpPce->NumChannels <= (6) && tmpPce->Profile == 1) {
/* store PCE data */
if ( CProgramConfig_IsValid(tmpPce)
&& ( (channelConfig == 6 && (tmpPce->NumChannels == 6))
|| (channelConfig == 5 && (tmpPce->NumChannels == 5))
|| (channelConfig == 0 && (tmpPce->NumChannels == pce->NumChannels)) )
&& (tmpPce->NumFrontChannelElements == 2)
&& (tmpPce->NumSideChannelElements == 0)
&& (tmpPce->NumBackChannelElements == 1)
&& (tmpPce->Profile == 1) )
{ /* Copy the complete PCE including metadata. */
FDKmemcpy(pce, tmpPce, sizeof(CProgramConfig));
}
......@@ -411,29 +419,18 @@ AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self,
INT readBits = aacDecoder_drcMarkPayload( self->hDrcInfo, hBs, MPEG_DRC_EXT_DATA );
if (readBits > *count)
{
FDKpushBack(hBs, readBits - *count);
{ /* Read too much. Something went wrong! */
error = AAC_DEC_PARSE_ERROR;
return error;
}
else
{
*count -= (readBits+7) & ~0x7;
}
*count -= readBits;
}
break;
case EXT_LDSAC_DATA:
case EXT_SAC_DATA:
/* Skip MPEG Surround Extension payload */
FDKpushFor(hBs, *count);
*count = 0;
break;
case EXT_SBR_DATA_CRC:
crcFlag = 1;
case EXT_SBR_DATA:
{
if (IS_CHANNEL_ELEMENT(previous_element)) {
SBR_ERROR sbrError;
CAacDecoder_SyncQmfMode(self);
......@@ -479,6 +476,8 @@ AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self,
self->frameOK = 0;
}
}
} else {
error = AAC_DEC_PARSE_ERROR;
}
break;
......@@ -523,14 +522,16 @@ AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self,
*count -= (dataElementLength<<3);
} else {
/* align = 0 */
FDKpushFor(hBs, (*count)<<3);
*count = 0;
error = AAC_DEC_PARSE_ERROR;
goto bail;
}
}
break;
case EXT_DATA_LENGTH:
{
if ( !fIsFillElement /* Makes no sens to have an additional length in a fill ... */
&& (self->flags & AC_ER) ) /* ... element because this extension payload type was ... */
{ /* ... created to circumvent the missing length in ER-Syntax. */
int bitCnt, len = FDKreadBits(hBs, 4);
*count -= 4;
......@@ -551,7 +552,9 @@ AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self,
/* Check NOTE 2: The extension_payload() included here must
not have extension_type == EXT_DATA_LENGTH. */
error = AAC_DEC_PARSE_ERROR;
} else {
goto bail;
}
else {
/* rewind and call myself again. */
FDKpushBack(hBs, 4);
......@@ -562,12 +565,13 @@ AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self,
&bitCnt,
previous_element,
elIndex,
0 );
1 ); /* Treat same as fill element */
*count -= len - bitCnt;
}
/* Note: the fall through in case the if statement above is not taken is intentional. */
break;
}
break;
case EXT_FIL:
......@@ -578,6 +582,16 @@ AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self,
break;
}
bail:
if ( (error != AAC_DEC_OK)
&& fIsFillElement )
{ /* Skip the remaining extension bytes */
FDKpushBiDirectional(hBs, *count);
*count = 0;
/* Patch error code because decoding can go on. */
error = AAC_DEC_OK;
/* Be sure that parsing errors have been stored. */
}
return error;
}
......@@ -750,7 +764,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
/* valid number of channels -> copy program config element (PCE) from ASC */
FDKmemcpy(&self->pce, &asc->m_progrConfigElement, sizeof(CProgramConfig));
/* Built element table */
el = CProgramConfig_GetElementTable(&asc->m_progrConfigElement, self->elements);
el = CProgramConfig_GetElementTable(&asc->m_progrConfigElement, self->elements, 7);
for (; el<7; el++) {
self->elements[el] = ID_NONE;
}
......@@ -1286,7 +1300,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
}
}
#if defined(PCM_POSTPROCESS_ENABLE) && defined(DVB_MIXDOWN_ENABLE) && defined(AACDEC_DVB_SUPPORT_ENABLE)
{
UCHAR *pDvbAncData = NULL;
AAC_DECODER_ERROR ancErr;
......@@ -1309,7 +1322,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
0 /* not mpeg2 */ );
}
}
#endif /* PCM_POSTPROCESS_ENABLE && DVB_MIXDOWN_ENABLE && AACDEC_DVB_SUPPORT_ENABLE */
break;
#ifdef TP_PCE_ENABLE
......@@ -1318,9 +1330,10 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
if ( CProgramConfigElement_Read( bs,
self->hInput,
pce,
self->streamInfo.channelConfig,
auStartAnchor ) )
{ /* Built element table */
int elIdx = CProgramConfig_GetElementTable(pce, self->elements);
int elIdx = CProgramConfig_GetElementTable(pce, self->elements, 7);
/* Reset the remaining tabs */
for ( ; elIdx<7; elIdx++) {
self->elements[elIdx] = ID_NONE;
......@@ -1368,7 +1381,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
if ( (bitCnt > 0) && (self->flags & AC_SBR_PRESENT) && (self->flags & (AC_USAC|AC_RSVD50|AC_ELD)) )
{
SBR_ERROR err;
SBR_ERROR err = SBRDEC_OK;
int elIdx, numChElements = el_cnt[ID_SCE] + el_cnt[ID_CPE];
for (elIdx = 0; elIdx < numChElements; elIdx += 1)
......@@ -1494,7 +1507,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
/* Update number of output channels */
self->streamInfo.numChannels = aacChannels;
#if defined(TP_PCE_ENABLE) && defined(PCM_POSTPROCESS_ENABLE) && defined(MPEG_PCE_MIXDOWN_ENABLE)
#ifdef TP_PCE_ENABLE
if (pceRead == 1 || CProgramConfig_IsValid(pce)) {
/* Set matrix mixdown infos if available from PCE. */
pcmDmx_SetMatrixMixdownFromPce ( self->hPcmUtils,
......@@ -1502,7 +1515,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
pce->MatrixMixdownIndex,
pce->PseudoSurroundEnable );
}
#endif
#endif
/* If there is no valid data to transfrom into time domain, return. */
if ( ! IS_OUTPUT_VALID(ErrorStatus) ) {
......
......@@ -48,7 +48,7 @@
/* Decoder library info */
#define AACDECODER_LIB_VL0 2
#define AACDECODER_LIB_VL1 4
#define AACDECODER_LIB_VL2 0
#define AACDECODER_LIB_VL2 1
#define AACDECODER_LIB_TITLE "AAC Decoder Lib"
#define AACDECODER_LIB_BUILD_DATE __DATE__
#define AACDECODER_LIB_BUILD_TIME __TIME__
......@@ -500,6 +500,8 @@ LINKSPEC_CPP HANDLE_AACDECODER aacDecoder_Open(TRANSPORT_TYPE transportFmt, UINT
return NULL;
}
transportDec_SetParam(pIn, TPDEC_PARAM_IGNORE_BUFFERFULLNESS, 1);
/* Allocate AAC decoder core struct. */
aacDec = CAacDecoder_Open(transportFmt);
......
......@@ -43,48 +43,61 @@
#define MIN_BUFSIZE_PER_EFF_CHAN 6144
static AAC_ENCODER_ERROR FDKaacEnc_InitCheckAncillary(INT bitRate,
INT framelength,
INT ancillaryRate,
INT *ancillaryBitsPerFrame,
INT sampleRate);
/**
* For calculating average bitrate of an access unit 32 bit data width is not sufficient
* in worst case. Therefore use scaling of the samplingrate parameter to keep complete information.
*/
typedef struct {
INT samplingRate;
UCHAR scalingFactor;
} SR_SCALING_TAB;
static const SR_SCALING_TAB samplingRateScalingTable[] =
INT FDKaacEnc_LimitBitrate(
HANDLE_TRANSPORTENC hTpEnc,
INT coreSamplingRate,
INT frameLength,
INT nChannels,
INT nChannelsEff,
INT bitRate,
INT averageBits,
INT *pAverageBitsPerFrame,
INT bitrateMode,
INT nSubFrames
)
{
{ 8000, 5 }, { 11025, 0 }, { 12000, 5 }, { 16000, 5 },
{ 22050, 1 }, { 24000, 5 }, { 32000, 5 }, { 44100, 2 },
{ 48000, 5 }, { 64000, 5 }, { 88200, 3 }, { 96000, 5 }
};
INT transportBits, prevBitRate, averageBitsPerFrame, shift = 0, iter=0;
/**
* Get maximal scaling factor without losing samplingrate accuracy.
*
* \param samplingRate Samplingrate to be used.
* \return scaling value.
*/
static int GetSrSf(const INT samplingRate)
{
int i, result = 0;
while ( (frameLength & ~((1<<(shift+1))-1)) == frameLength
&& (coreSamplingRate & ~((1<<(shift+1))-1)) == coreSamplingRate )
{
shift ++;
}
for (i=0; i<(int)(sizeof(samplingRateScalingTable)/sizeof(SR_SCALING_TAB)); i++) {
if ( samplingRateScalingTable[i].samplingRate == samplingRate ) {
result = samplingRateScalingTable[i].scalingFactor;
break;
do {
prevBitRate = bitRate;
averageBitsPerFrame = (bitRate*(frameLength>>shift)) / (coreSamplingRate>>shift) / nSubFrames;
if (pAverageBitsPerFrame != NULL) {
*pAverageBitsPerFrame = averageBitsPerFrame;
}
}
return result;
if (hTpEnc != NULL) {
transportBits = transportEnc_GetStaticBits(hTpEnc, averageBitsPerFrame);
} else {
/* Assume some worst case */
transportBits = 208;
}
bitRate = FDKmax(bitRate, ((((40 * nChannels) + transportBits + frameLength) * (coreSamplingRate)) / frameLength) );
FDK_ASSERT(bitRate >= 0);
bitRate = FDKmin(bitRate, ((nChannelsEff * MIN_BUFSIZE_PER_EFF_CHAN)*(coreSamplingRate>>shift)) / (frameLength>>shift)) ;
FDK_ASSERT(bitRate >= 0);
} while (prevBitRate != bitRate && iter++ < 3) ;
return bitRate;
}
#define MIN_BUFSIZE_PER_EFF_CHAN 6144
typedef struct
{
......@@ -349,16 +362,20 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize(HANDLE_AAC_ENC hAacEnc,
/* check bit rate */
/* check if bitRate is not too low or high */
averageBitsPerFrame = (config->bitRate*(config->framelength>>GetSrSf(config->sampleRate))) / (config->sampleRate>>GetSrSf(config->sampleRate)) / config->nSubFrames;
/* assume minimum static bits of 40 in each channel. */
if ( (averageBitsPerFrame <= ((40*config->nChannels) + transportEnc_GetStaticBits(hTpEnc, averageBitsPerFrame))) ||
( ((config->bitRate*(config->framelength>>GetSrSf(config->sampleRate)))) >
((FDKaacEnc_GetChannelModeConfiguration(config->channelMode)->nChannelsEff * MIN_BUFSIZE_PER_EFF_CHAN))*(config->sampleRate>>GetSrSf(config->sampleRate)) )
)
if (FDKaacEnc_LimitBitrate(
hTpEnc,
config->sampleRate,
config->framelength,
config->nChannels,
FDKaacEnc_GetChannelModeConfiguration(config->channelMode)->nChannelsEff,
config->bitRate,
config->averageBits,
&averageBitsPerFrame,
config->bitrateMode,
config->nSubFrames
) != config->bitRate )
{
return AAC_ENC_UNSUPPORTED_BITRATE;
return AAC_ENC_UNSUPPORTED_BITRATE;
}
if (config->syntaxFlags & AC_ER_VCB11) {
......
......@@ -159,6 +159,33 @@ typedef struct {
typedef struct AAC_ENC *HANDLE_AAC_ENC;
/**
* \brief Limit given bit rate to a valid value
* \param hTpEnc transport encoder handle
* \param coreSamplingRate the sample rate to be used for the AAC encoder
* \param frameLength the frameLength to be used for the AAC encoder
* \param nChannels number of total channels
* \param nChannelsEff number of effective channels
* \param bitRate the initial bit rate value for which the closest valid bit rate value is searched for
* \param averageBits average bits per frame for fixed framing. Set to -1 if not available.
* \param optional pointer where the current bits per frame are stored into.
* \param bitrateMode the current bit rate mode
* \param nSubFrames number of sub frames for super framing (not transport frames).
* \return a valid bit rate value as close as possible or identical to bitRate
*/
INT FDKaacEnc_LimitBitrate(
HANDLE_TRANSPORTENC hTpEnc,
INT coreSamplingRate,
INT frameLength,
INT nChannels,
INT nChannelsEff,
INT bitRate,
INT averageBits,
INT *pAverageBitsPerFrame,
INT bitrateMode,
INT nSubFrames
);
/*-----------------------------------------------------------------------------
functionname: FDKaacEnc_GetVBRBitrate
......
......@@ -388,6 +388,138 @@ AAC_ENCODER_ERROR aacEncDefaultConfig(HANDLE_AACENC_CONFIG hAacConfig,
return AAC_ENC_OK;
}
static
void aacEncDistributeSbrBits(CHANNEL_MAPPING *channelMapping, SBR_ELEMENT_INFO *sbrElInfo, INT bitRate)
{
INT codebits = bitRate;
int el;
/* Copy Element info */
for (el=0; el<channelMapping->nElements; el++) {
sbrElInfo[el].ChannelIndex[0] = channelMapping->elInfo[el].ChannelIndex[0];
sbrElInfo[el].ChannelIndex[1] = channelMapping->elInfo[el].ChannelIndex[1];
sbrElInfo[el].elType = channelMapping->elInfo[el].elType;
sbrElInfo[el].bitRate = (INT)(fMultNorm(channelMapping->elInfo[el].relativeBits, (FIXP_DBL)bitRate));
sbrElInfo[el].instanceTag = channelMapping->elInfo[el].instanceTag;
sbrElInfo[el].nChannelsInEl = channelMapping->elInfo[el].nChannelsInEl;
codebits -= sbrElInfo[el].bitRate;
}
sbrElInfo[0].bitRate += codebits;
}
static
INT aacEncoder_LimitBitrate(
const HANDLE_TRANSPORTENC hTpEnc,
const INT samplingRate,
const INT frameLength,
const INT nChannels,
const CHANNEL_MODE channelMode,
INT bitRate,
const INT nSubFrames,
const INT sbrActive,
const AUDIO_OBJECT_TYPE aot
)
{
INT coreSamplingRate;
CHANNEL_MAPPING cm;
FDKaacEnc_InitChannelMapping(channelMode, CH_ORDER_MPEG, &cm);
if (sbrActive) {
/* Assume SBR rate ratio of 2:1 */
coreSamplingRate = samplingRate / 2;
} else {
coreSamplingRate = samplingRate;
}
/* Consider bandwidth channel bit rate limit (see bandwidth.cpp: GetBandwidthEntry()) */
if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD) {
bitRate = FDKmin(360000*nChannels, bitRate);
bitRate = FDKmax(8000*nChannels, bitRate);
}
if (aot == AOT_AAC_LC || aot == AOT_SBR || aot == AOT_PS) {
bitRate = FDKmin(576000*nChannels, bitRate);
/*bitRate = FDKmax(0*nChannels, bitRate);*/
}
/* Limit bit rate in respect to the core coder */
bitRate = FDKaacEnc_LimitBitrate(
hTpEnc,
coreSamplingRate,
frameLength,
nChannels,
cm.nChannelsEff,
bitRate,
-1,
NULL,
-1,
nSubFrames
);
/* Limit bit rate in respect to available SBR modes if active */
if (sbrActive)
{
SBR_ELEMENT_INFO sbrElInfo[6];
INT sbrBitRate = 0;
int e, tooBig=-1;
FDK_ASSERT(cm.nElements <= (6));
/* Get bit rate for each SBR element */
aacEncDistributeSbrBits(&cm, sbrElInfo, bitRate);
for (e=0; e<cm.nElements; e++)
{
INT sbrElementBitRateIn, sbrBitRateOut;
if (cm.elInfo[e].elType != ID_SCE && cm.elInfo[e].elType != ID_CPE) {
continue;
}
sbrElementBitRateIn = sbrElInfo[e].bitRate;
sbrBitRateOut = sbrEncoder_LimitBitRate(sbrElementBitRateIn , cm.elInfo[e].nChannelsInEl, coreSamplingRate, aot);
if (sbrBitRateOut == 0) {
return 0;
}
if (sbrElementBitRateIn < sbrBitRateOut) {
FDK_ASSERT(tooBig != 1);
tooBig = 0;
if (e == 0) {
sbrBitRate = 0;
}
}
if (sbrElementBitRateIn > sbrBitRateOut) {
FDK_ASSERT(tooBig != 0);
tooBig = 1;
if (e == 0) {
sbrBitRate = 5000000;
}
}
if (tooBig != -1)
{
INT sbrBitRateLimit = (INT)fDivNorm((FIXP_DBL)sbrBitRateOut, cm.elInfo[e].relativeBits);
if (tooBig) {
sbrBitRate = fMin(sbrBitRate, sbrBitRateLimit-16);
FDK_ASSERT( (INT)fMultNorm(cm.elInfo[e].relativeBits, (FIXP_DBL)sbrBitRate) < sbrBitRateOut);
} else {
sbrBitRate = fMax(sbrBitRate, sbrBitRateLimit+16);
FDK_ASSERT( (INT)fMultNorm(cm.elInfo[e].relativeBits, (FIXP_DBL)sbrBitRate) >= sbrBitRateOut);
}
}
}
if (tooBig != -1) {
bitRate = sbrBitRate;
}
}
FDK_ASSERT(bitRate > 0);
return bitRate;
}
/*
* \brief Consistency check of given USER_PARAM struct and
* copy back configuration from public struct into internal
......@@ -482,6 +614,19 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder,
break;
}
/* We need the frame length to call aacEncoder_LimitBitrate() */
hAacConfig->bitRate = aacEncoder_LimitBitrate(
NULL,
hAacConfig->sampleRate,
hAacConfig->framelength,
hAacConfig->nChannels,
hAacConfig->channelMode,
config->userBitrate,
hAacConfig->nSubFrames,
isSbrActive(hAacConfig),
hAacConfig->audioObjectType
);
switch ( hAacConfig->audioObjectType ) {
case AOT_ER_AAC_LD:
case AOT_ER_AAC_ELD:
......@@ -605,7 +750,6 @@ static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder,
INT frameLength = hAacConfig->framelength;
if ( (InitFlags & AACENC_INIT_CONFIG) )
{
CHANNEL_MODE prevChMode = hAacConfig->channelMode;
......@@ -645,9 +789,7 @@ static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder,
INT sbrError;
SBR_ELEMENT_INFO sbrElInfo[(6)];
CHANNEL_MAPPING channelMapping;
int el;
INT codebits = hAacConfig->bitRate;
INT bitrateSc = CountLeadingBits(codebits);
AUDIO_OBJECT_TYPE aot = hAacConfig->audioObjectType;
if ( FDKaacEnc_InitChannelMapping(hAacConfig->channelMode,
......@@ -662,19 +804,7 @@ static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder,
return AACENC_INIT_ERROR;
}
/* Copy Element info */
for (el=0; el<channelMapping.nElements; el++) {
sbrElInfo[el].ChannelIndex[0] = channelMapping.elInfo[el].ChannelIndex[0];
sbrElInfo[el].ChannelIndex[1] = channelMapping.elInfo[el].ChannelIndex[1];
sbrElInfo[el].elType = channelMapping.elInfo[el].elType;
sbrElInfo[el].bitRate = (INT)(fMult(channelMapping.elInfo[el].relativeBits, (FIXP_DBL)(hAacConfig->bitRate<<bitrateSc))>>(bitrateSc));
sbrElInfo[el].instanceTag = channelMapping.elInfo[el].instanceTag;
sbrElInfo[el].nChannelsInEl = channelMapping.elInfo[el].nChannelsInEl;
sbrElInfo[el].bitRate = fMult(channelMapping.elInfo[el].relativeBits, (FIXP_DBL)hAacConfig->bitRate);
codebits -= sbrElInfo[el].bitRate;
}
sbrElInfo[0].bitRate += codebits;
aacEncDistributeSbrBits(&channelMapping, sbrElInfo, hAacConfig->bitRate);
UINT initFlag = 0;
initFlag += (InitFlags & AACENC_INIT_STATES) ? 1 : 0;
......
......@@ -60,7 +60,7 @@ typedef shouldBeUnion{
typedef struct{
INT_PCM* psyInputBuffer;
FIXP_DBL RESTRICT overlapAddBuffer[1024];
FIXP_DBL overlapAddBuffer[1024];
BLOCK_SWITCHING_CONTROL blockSwitchingControl; /* block switching */
FIXP_DBL sfbThresholdnm1[MAX_SFB]; /* FDKaacEnc_PreEchoControl */
......
......@@ -1314,23 +1314,30 @@ AAC_ENCODER_ERROR FDKaacEnc_FinalizeBitConsumption(CHANNEL_MAPPING *cm,
/* Now we can get the exact transport bit amount, and hopefully it is equal to the estimated value */
exactTpBits = transportEnc_GetStaticBits(hTpEnc, qcOut->totalBits);
while (exactTpBits != qcKernel->globHdrBits && (max_iter-- > 0))
{
INT diffBits = qcKernel->globHdrBits-exactTpBits;
if (diffBits >= 0) {
/* move bits from header to payload */
qcOut->totFillBits += diffBits;
qcOut->totalBits += diffBits;
qcOut->grantedDynBits += diffBits;
if (exactTpBits != qcKernel->globHdrBits) {
INT diffFillBits = 0;
/* Number of bits which can be moved to bitreservoir. */
INT bitsToBitres = qcKernel->globHdrBits - exactTpBits;
if (bitsToBitres>0) {
/* if bitreservoir can not take all bits, move ramaining bits to fillbits */
diffFillBits = FDKmax(0, bitsToBitres - (qcKernel->bitResTotMax-qcKernel->bitResTot));
}
else {
/* get missing bits from bitreservoir */
qcKernel->bitResTot += diffBits;
else if (bitsToBitres<0) {
/* if bits mus be taken from bitreservoir, reduce fillbits first. */
diffFillBits = (FDKmax(FDKmax(bitsToBitres, -qcKernel->bitResTot), -qcOut->totFillBits));
}
qcKernel->globHdrBits = exactTpBits;
exactTpBits = transportEnc_GetStaticBits(hTpEnc, qcOut->totalBits);
diffFillBits = (diffFillBits+7)&~7; /* assure previous alignment */
qcOut->totFillBits += diffFillBits;
qcOut->totalBits += diffFillBits;
qcOut->grantedDynBits += diffFillBits;
/* new header bits */
qcKernel->globHdrBits = transportEnc_GetStaticBits(hTpEnc, qcOut->totalBits);
}
FDK_ASSERT(exactTpBits == qcKernel->globHdrBits);
}
/* Save total fill bits and distribut to alignment and fill bits */
......
/*************************** Fraunhofer IIS FDK Tools **********************
(C) Copyright Fraunhofer IIS (2011)
All Rights Reserved
Please be advised that this software and/or program delivery is
Confidential Information of Fraunhofer and subject to and covered by the
Fraunhofer IIS Software Evaluation Agreement
between Google Inc. and Fraunhofer
effective and in full force since March 1, 2012.
You may use this software and/or program only under the terms and
conditions described in the above mentioned Fraunhofer IIS Software
Evaluation Agreement. Any other and/or further use requires a separate agreement.
$Id$
Author(s): Markus Lohwasser
Description: FDK Tools Hybrid Filterbank
This software and/or program is protected by copyright law and international
treaties. Any reproduction or distribution of this software and/or program,
or any portion of it, may result in severe civil and criminal penalties, and
will be prosecuted to the maximum extent possible under law.
******************************************************************************/
#ifndef __FDK_HYBRID_H
#define __FDK_HYBRID_H
#include "common_fix.h"
/*--------------- enums -------------------------------*/
/**
* Hybrid Filterband modes.
*/
typedef enum {
THREE_TO_TEN,
THREE_TO_TWELVE,
THREE_TO_SIXTEEN
} FDK_HYBRID_MODE;
/*--------------- structure definitions ---------------*/
typedef struct FDK_HYBRID_SETUP *HANDLE_FDK_HYBRID_SETUP;
typedef struct
{
FIXP_DBL *bufferLFReal[3]; /*!< LF real filter states. */
FIXP_DBL *bufferLFImag[3]; /*!< LF imag filter states. */
FIXP_DBL *bufferHFReal[13]; /*!< HF real delay lines. */
FIXP_DBL *bufferHFImag[13]; /*!< HF imag delay lines. */
INT bufferLFpos; /*!< Position to write incoming data into ringbuffer. */
INT bufferHFpos; /*!< Delay line positioning. */
INT nrBands; /*!< Number of QMF bands. */
INT cplxBands; /*!< Number of complex QMF bands.*/
UCHAR hfMode; /*!< Flag signalizes treatment of HF bands. */
FIXP_DBL *pLFmemory; /*!< Pointer to LF states buffer. */
FIXP_DBL *pHFmemory; /*!< Pointer to HF states buffer. */
UINT LFmemorySize; /*!< Size of LF states buffer. */
UINT HFmemorySize; /*!< Size of HF states buffer. */
HANDLE_FDK_HYBRID_SETUP pSetup; /*!< Pointer to filter setup. */
} FDK_ANA_HYB_FILTER;
typedef struct
{
INT nrBands; /*!< Number of QMF bands. */
INT cplxBands; /*!< Number of complex QMF bands.*/
HANDLE_FDK_HYBRID_SETUP pSetup; /*!< Pointer to filter setup. */
} FDK_SYN_HYB_FILTER;
typedef FDK_ANA_HYB_FILTER *HANDLE_FDK_ANA_HYB_FILTER;
typedef FDK_SYN_HYB_FILTER *HANDLE_FDK_SYN_HYB_FILTER;
/**
* \brief Create one instance of Hybrid Analyis Filterbank.
*
* \param hAnalysisHybFilter Pointer to an outlying allocated Hybrid Analysis Filterbank structure.
* \param pLFmemory Pointer to outlying buffer used LF filtering.
* \param LFmemorySize Size of pLFmemory in bytes.
* \param pHFmemory Pointer to outlying buffer used HF delay line.
* \param HFmemorySize Size of pLFmemory in bytes.
*
* \return 0 on success.
*/
INT FDKhybridAnalysisOpen(
HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter,
FIXP_DBL *const pLFmemory,
const UINT LFmemorySize,
FIXP_DBL *const pHFmemory,
const UINT HFmemorySize
);
/**
* \brief Initialize and configure Hybrdid Analysis Filterbank instance.
*
* \param hAnalysisHybFilter A Hybrid Analysis Filterbank handle.
* \param mode Select hybrid filter configuration.
* \param qmfBands Number of qmf bands to be processed.
* \param cplxBands Number of complex qmf bands to be processed.
* \param initStatesFlag Indicates whether the states buffer has to be cleared.
*
* \return 0 on success.
*/
INT FDKhybridAnalysisInit(
HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter,
const FDK_HYBRID_MODE mode,
const INT qmfBands,
const INT cplxBands,
const INT initStatesFlag
);
/**
* \brief Adjust Hybrdid Analysis Filterbank states.
*
* \param hAnalysisHybFilter A Hybrid Analysis Filterbank handle.
* \param scalingValue Scaling value to be applied on filter states.
*
* \return 0 on success.
*/
INT FDKhybridAnalysisScaleStates(
HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter,
const INT scalingValue
);
/**
* \brief Apply Hybrid Analysis Filterbank on Qmf input data.
*
* \param hAnalysisHybFilter A Hybrid Analysis Filterbank handle.
* \param pQmfReal Qmf input data.
* \param pQmfImag Qmf input data.
* \param pHybridReal Hybrid output data.
* \param pHybridImag Hybrid output data.
*
* \return 0 on success.
*/
INT FDKhybridAnalysisApply(
HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter,
const FIXP_DBL *const pQmfReal,
const FIXP_DBL *const pQmfImag,
FIXP_DBL *const pHybridReal,
FIXP_DBL *const pHybridImag
);
/**
* \brief Close a Hybrid Analysis Filterbank instance.
*
* \param hAnalysisHybFilter Pointer to a Hybrid Analysis Filterbank instance.
*
* \return 0 on success.
*/
INT FDKhybridAnalysisClose(
HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter
);
/**
* \brief Initialize and configure Hybrdid Synthesis Filterbank instance.
*
* \param hSynthesisHybFilter A Hybrid Synthesis Filterbank handle.
* \param mode Select hybrid filter configuration.
* \param qmfBands Number of qmf bands to be processed.
* \param cplxBands Number of complex qmf bands to be processed.
*
* \return 0 on success.
*/
INT FDKhybridSynthesisInit(
HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter,
const FDK_HYBRID_MODE mode,
const INT qmfBands,
const INT cplxBands
);
/**
* \brief Apply Hybrid Analysis Filterbank on Hybrid data.
*
* \param hSynthesisHybFilter A Hybrid Analysis Filterbandk handle.
* \param pHybridReal Hybrid input data.
* \param pHybridImag Hybrid input data.
* \param pQmfReal Qmf output data.
* \param pQmfImag Qmf output data.
*
* \return 0 on success.
*/
INT FDKhybridSynthesisApply(
HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter,
const FIXP_DBL *const pHybridReal,
const FIXP_DBL *const pHybridImag,
FIXP_DBL *const pQmfReal,
FIXP_DBL *const pQmfImag
);
#endif /* __FDK_HYBRID_H */
......@@ -43,12 +43,12 @@
inline INT fixnorm_D(LONG value)
{
INT result;
if (value < 0) {
value = ~value;
}
if (value == 0) {
return 0;
}
if (value < 0) {
value = ~value;
}
result = fixnormz_D(value);
return result - 1;
}
......
......@@ -206,6 +206,18 @@ FIXP_DBL fMultNorm(
INT *result_e
);
inline FIXP_DBL fMultNorm(FIXP_DBL f1, FIXP_DBL f2)
{
FIXP_DBL m;
INT e;
m = fMultNorm(f1, f2, &e);
m = scaleValueSaturate(m, e);
return m;
}
/**
* \brief Divide 2 FIXP_DBL values with normalization of input values.
* \param num numerator
......
......@@ -25,7 +25,7 @@
*******************************************************************************/
/*!
\file qmf.h
\brief Complex qmf analysis/synthesis $Revision: 36871 $
\brief Complex qmf analysis/synthesis $Revision: 37444 $
\author Markus Werner
*/
......
......@@ -7,6 +7,7 @@ LOCAL_SRC_FILES := \
FDK_bitbuffer.cpp \
FDK_core.cpp \
FDK_crc.cpp \
FDK_hybrid.cpp \
FDK_tools_rom.cpp \
FDK_trigFcts.cpp \
fft.cpp \
......
This diff is collapsed.
......@@ -21,7 +21,7 @@
*******************************************************************************/
/*!
\file dct.cpp
\brief DCT Implementations $Revision: 36871 $
\brief DCT Implementations $Revision: 37444 $
Library functions to calculate standard DCTs. This will most likely be replaced by hand-optimized
functions for the specific target processor.
......
......@@ -344,7 +344,7 @@ static inline void fft15(FIXP_DBL *pInput)
y[ 3 + iy] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ \
y[ 7 + iy] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */
static const FIXP_SPK fft16_w16[2] = { {{STC(0x7641af3d), STC(0x30fbc54d)}}, {{ STC(0x30fbc54d), STC(0x7641af3d)}} };
static const FIXP_STP fft16_w16[2] = { STCP(0x7641af3d, 0x30fbc54d), STCP(0x30fbc54d, 0x7641af3d) };
LNK_SECTION_CODE_L1
inline void fft_16(FIXP_DBL *RESTRICT x)
......@@ -527,10 +527,10 @@ inline void fft_16(FIXP_DBL *RESTRICT x)
}
#ifndef FUNCTION_fft_32
static const FIXP_SPK fft32_w32[6] =
static const FIXP_STP fft32_w32[6] =
{
{{ STC(0x7641af3d), STC(0x30fbc54d)}}, {{ STC(0x30fbc54d), STC(0x7641af3d)}}, {{ STC(0x7d8a5f40), STC(0x18f8b83c)}},
{{ STC(0x6a6d98a4), STC(0x471cece7)}}, {{ STC(0x471cece7), STC(0x6a6d98a4)}}, {{ STC(0x18f8b83c), STC(0x7d8a5f40)}}
STCP (0x7641af3d, 0x30fbc54d), STCP(0x30fbc54d, 0x7641af3d), STCP(0x7d8a5f40, 0x18f8b83c),
STCP (0x6a6d98a4, 0x471cece7), STCP(0x471cece7, 0x6a6d98a4), STCP(0x18f8b83c, 0x7d8a5f40)
};
LNK_SECTION_CODE_L1
......
......@@ -27,7 +27,7 @@
******************************************************************************/
/*!
\file
\brief Complex qmf analysis/synthesis, $Revision: 36871 $
\brief Complex qmf analysis/synthesis, $Revision: 37444 $
This module contains the qmf filterbank for analysis [ cplxAnalysisQmfFiltering() ] and
synthesis [ cplxSynthesisQmfFiltering() ]. It is a polyphase implementation of a complex
exponential modulated filter bank. The analysis part usually runs at half the sample rate
......
......@@ -162,7 +162,8 @@ int CProgramConfig_LookupElement(
* \return Total element count including all SCE, CPE and LFE.
*/
int CProgramConfig_GetElementTable( const CProgramConfig *pPce,
MP4_ELEMENT_ID table[] );
MP4_ELEMENT_ID table[],
const INT elListSize );
/**
* \brief Initialize a given AudioSpecificConfig structure.
......
......@@ -382,11 +382,19 @@ int CProgramConfig_LookupElement(
#ifdef TP_PCE_ENABLE
int CProgramConfig_GetElementTable(
const CProgramConfig *pPce,
MP4_ELEMENT_ID elList[]
MP4_ELEMENT_ID elList[],
const INT elListSize
)
{
int i, el = 0;
if ( elListSize
< pPce->NumFrontChannelElements + pPce->NumSideChannelElements + pPce->NumBackChannelElements + pPce->NumLfeChannelElements
)
{
return 0;
}
for (i=0; i < pPce->NumFrontChannelElements; i++)
{
elList[el++] = (pPce->FrontElementIsCpe[i]) ? ID_CPE : ID_SCE;
......@@ -619,94 +627,6 @@ bail:
#endif /* TP_ELD_ENABLE */
static
TRANSPORTDEC_ERROR AudioSpecificConfig_ExtensionParse(CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs, CSTpCallBacks *cb)
{
TP_ASC_EXTENSION_ID lastAscExt, ascExtId = ASCEXT_UNKOWN;
INT bitsAvailable = (INT)FDKgetValidBits(bs);
while (bitsAvailable >= 11)
{
lastAscExt = ascExtId;
ascExtId = (TP_ASC_EXTENSION_ID)FDKreadBits(bs, 11);
bitsAvailable -= 11;
switch (ascExtId) {
case ASCEXT_SBR: /* 0x2b7 */
if ( (self->m_extensionAudioObjectType != AOT_SBR) && (bitsAvailable >= 5) ) {
self->m_extensionAudioObjectType = getAOT(bs);
if ( (self->m_extensionAudioObjectType == AOT_SBR)
|| (self->m_extensionAudioObjectType == AOT_ER_BSAC) )
{ /* Get SBR extension configuration */
self->m_sbrPresentFlag = FDKreadBits(bs, 1);
bitsAvailable -= 1;
if ( self->m_sbrPresentFlag == 1 ) {
self->m_extensionSamplingFrequency = getSampleRate(bs, &self->m_extensionSamplingFrequencyIndex, 4);
if ((INT)self->m_extensionSamplingFrequency <= 0) {
return TRANSPORTDEC_PARSE_ERROR;
}
}
if ( self->m_extensionAudioObjectType == AOT_ER_BSAC ) {
self->m_extensionChannelConfiguration = FDKreadBits(bs, 4);
bitsAvailable -= 4;
}
}
/* Update counter because of variable length fields (AOT and sampling rate) */
bitsAvailable = (INT)FDKgetValidBits(bs);
}
break;
case ASCEXT_PS: /* 0x548 */
if ( (lastAscExt == ASCEXT_SBR)
&& (self->m_extensionAudioObjectType == AOT_SBR)
&& (bitsAvailable > 0) )
{ /* Get PS extension configuration */
self->m_psPresentFlag = FDKreadBits(bs, 1);
bitsAvailable -= 1;
}
break;
case ASCEXT_MPS: /* 0x76a */
if ( self->m_extensionAudioObjectType == AOT_MPEGS )
break;
case ASCEXT_LDMPS: /* 0x7cc */
if ( (ascExtId == ASCEXT_LDMPS)
&& (self->m_extensionAudioObjectType == AOT_LD_MPEGS) )
break;
if (bitsAvailable >= 1)
{
bitsAvailable -= 1;
if ( FDKreadBits(bs, 1) ) { /* self->m_mpsPresentFlag */
int sscLen = FDKreadBits(bs, 8);
bitsAvailable -= 8;
if (sscLen == 0xFF) {
sscLen += FDKreadBits(bs, 16);
bitsAvailable -= 16;
}
if (cb->cbSsc != NULL) {
cb->cbSsc(
cb->cbSscData,
bs,
self->m_aot,
self->m_samplingFrequency,
1,
sscLen
);
} else
FDKpushFor(bs, sscLen); /* Skip SSC to be able to read the next extension if there is one. */
bitsAvailable -= sscLen*8;
}
}
break;
default:
return TRANSPORTDEC_UNSUPPORTED_FORMAT;
}
}
return TRANSPORTDEC_OK;
}
/*
* API Functions
......@@ -857,9 +777,6 @@ TRANSPORTDEC_ERROR AudioSpecificConfig_Parse(
break;
}
if (fExplicitBackwardCompatible) {
ErrorStatus = AudioSpecificConfig_ExtensionParse(self, bs, cb);
}
return (ErrorStatus);
}
......
......@@ -315,9 +315,6 @@ TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs, CLa
else {
ErrorStatus = TRANSPORTDEC_PARSE_ERROR; //AAC_DEC_LATM_TIMEFRAMING;
}
if ((INT)FDKgetValidBits(bs) < totalPayloadBits) {
return TRANSPORTDEC_NOT_ENOUGH_BITS;
}
if (pLatmDemux->m_audioMuxLengthBytes > 0 && totalPayloadBits > pLatmDemux->m_audioMuxLengthBytes*8) {
return TRANSPORTDEC_PARSE_ERROR;
}
......
......@@ -85,6 +85,7 @@ struct TRANSPORTDEC
#define TPDEC_IGNORE_BUFFERFULLNESS 4
#define TPDEC_EARLY_CONFIG 8
#define TPDEC_LOST_FRAMES_PENDING 16
#define TPDEC_CONFIG_FOUND 32
C_ALLOC_MEM(Ram_TransportDecoder, TRANSPORTDEC, 1)
C_ALLOC_MEM(Ram_TransportDecoderBuffer, UCHAR, TRANSPORTDEC_INBUF_SIZE)
......@@ -177,11 +178,10 @@ TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, UCHAR *
}
}
break;
default:
case TT_MP4_RAW:
err = AudioSpecificConfig_Parse(&hTp->asc[layer], hBs, 1, &hTp->callbacks);
break;
default:
return TRANSPORTDEC_UNSUPPORTED_FORMAT;
}
if (err == TRANSPORTDEC_OK) {
int errC;
......@@ -192,6 +192,10 @@ TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, UCHAR *
}
}
if (err == TRANSPORTDEC_OK) {
hTp->flags |= TPDEC_CONFIG_FOUND;
}
return err;
}
......@@ -439,6 +443,14 @@ TRANSPORTDEC_ERROR synchronization(
totalBits = (INT)FDKgetValidBits(hBs);
if (totalBits <= 0) {
/* Return sync error, because this happens only in case of severly damaged bit streams.
Returning TRANSPORTDEC_NOT_ENOUGH_BITS here is very dangerous. */
/* numberOfRawDataBlocks must be always reset in case of sync errors. */
hTp->numberOfRawDataBlocks = 0;
goto bail;
}
fTraverseMoreFrames = (hTp->flags & (TPDEC_MINIMIZE_DELAY|TPDEC_EARLY_CONFIG)) && ! (hTp->flags & TPDEC_SYNCOK);
/* Set transport specific sync parameters */
......@@ -625,13 +637,15 @@ TRANSPORTDEC_ERROR synchronization(
if (err == TRANSPORTDEC_SYNC_ERROR) {
int bits;
FDK_ASSERT(hTp->numberOfRawDataBlocks == 0);
/* Enforce re-sync of transport headers. */
hTp->numberOfRawDataBlocks = 0;
/* Ensure that the bit amount lands and a multiple of TPDEC_SYNCSKIP */
bits = (bitsAvail + headerBits) % TPDEC_SYNCSKIP;
/* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead next time. */
FDKpushBiDirectional(hBs, -(headerBits - TPDEC_SYNCSKIP) + bits);
bitsAvail += headerBits - TPDEC_SYNCSKIP - bits;
headerBits = 0;
headerBits = 0;
}
/* Frame traversal */
......@@ -710,6 +724,7 @@ TRANSPORTDEC_ERROR synchronization(
err = TRANSPORTDEC_OK;
}
bail:
hTp->auLength[0] = rawDataBlockLength;
if (err == TRANSPORTDEC_OK) {
......@@ -852,7 +867,7 @@ TRANSPORTDEC_ERROR transportDec_ReadAccessUnit( const HANDLE_TRANSPORTDEC hTp, c
case TT_MP4_ADIF:
/* Read header if not already done */
if (!(hTp->flags & TPDEC_SYNCOK))
if (!(hTp->flags & TPDEC_CONFIG_FOUND))
{
CProgramConfig *pce;
......@@ -876,8 +891,7 @@ TRANSPORTDEC_ERROR transportDec_ReadAccessUnit( const HANDLE_TRANSPORTDEC hTp, c
errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[0]);
if (errC == 0) {
/* Misuse sync flag to parse header only once. */
hTp->flags |= TPDEC_SYNCOK;
hTp->flags |= TPDEC_CONFIG_FOUND;
} else {
err = TRANSPORTDEC_PARSE_ERROR;
goto bail;
......
......@@ -33,15 +33,6 @@
#include "FDK_bitstream.h"
#include "genericStds.h"
#define ASC_FLAG_EXT 0x0001
#define ASC_FLAG_SBR 0x0002
#define ASC_FLAG_SBRCRC 0x0004
#define ASC_FLAG_VCB11 0x0010
#define ASC_FLAG_RVLC 0x0020
#define ASC_FLAG_HCR 0x0040
#define ASC_FLAG_HCR 0x0040
#define PCE_MAX_ELEMENTS 8
/**
......@@ -353,7 +344,6 @@ int transportEnc_writeELDSpecificConfig(
HANDLE_FDK_BITSTREAM hBs,
CODER_CONFIG *config,
int epConfig,
int flags,
CSTpCallBacks *cb
)
{
......@@ -363,14 +353,14 @@ int transportEnc_writeELDSpecificConfig(
}
FDKwriteBits(hBs, (config->samplesPerFrame == 480) ? 1 : 0, 1);
FDKwriteBits(hBs, (flags & ASC_FLAG_VCB11) ? 1:0, 1);
FDKwriteBits(hBs, (flags & ASC_FLAG_RVLC ) ? 1:0, 1);
FDKwriteBits(hBs, (flags & ASC_FLAG_HCR ) ? 1:0, 1);
FDKwriteBits(hBs, (config->flags & CC_VCB11 ) ? 1:0, 1);
FDKwriteBits(hBs, (config->flags & CC_RVLC ) ? 1:0, 1);
FDKwriteBits(hBs, (config->flags & CC_HCR ) ? 1:0, 1);
FDKwriteBits(hBs, (flags & ASC_FLAG_SBR) ? 1:0, 1); /* SBR header flag */
if ( (flags & ASC_FLAG_SBR) ) {
FDKwriteBits(hBs, (config->flags & CC_SBR) ? 1:0, 1); /* SBR header flag */
if ( (config->flags & CC_SBR) ) {
FDKwriteBits(hBs, (config->samplingRate == config->extSamplingRate) ? 0:1, 1); /* Samplerate Flag */
FDKwriteBits(hBs, (flags &ASC_FLAG_SBRCRC) ? 1:0, 1); /* SBR CRC flag*/
FDKwriteBits(hBs, (config->flags & CC_SBRCRC) ? 1:0, 1); /* SBR CRC flag*/
if (cb->cbSbr != NULL) {
const PCE_CONFIGURATION *pPce;
......@@ -399,7 +389,7 @@ int transportEnc_writeASC (
CSTpCallBacks *cb
)
{
UINT flags = 0;
UINT extFlag = 0;
int err;
int epConfig = 0;
......@@ -416,14 +406,11 @@ int transportEnc_writeASC (
case AOT_ER_AAC_LD:
case AOT_ER_AAC_ELD:
case AOT_USAC:
flags |= ASC_FLAG_EXT;
extFlag = 1;
break;
default:
break;
}
if (config->flags & CC_SBR) {
flags |= ASC_FLAG_SBR;
}
if (config->extAOT == AOT_SBR || config->extAOT == AOT_PS)
writeAot(asc, config->extAOT);
......@@ -462,14 +449,14 @@ int transportEnc_writeASC (
case AOT_ER_TWIN_VQ:
case AOT_ER_BSAC:
case AOT_ER_AAC_LD:
err = transportEnc_writeGASpecificConfig(asc, config, (flags & ASC_FLAG_EXT) ? 1:0, alignAnchor);
err = transportEnc_writeGASpecificConfig(asc, config, extFlag, alignAnchor);
if (err)
return err;
break;
#endif /* TP_GA_ENABLE */
#ifdef TP_ELD_ENABLE
case AOT_ER_AAC_ELD:
err = transportEnc_writeELDSpecificConfig(asc, config, epConfig, flags, cb);
err = transportEnc_writeELDSpecificConfig(asc, config, epConfig, cb);
if (err)
return err;
break;
......
......@@ -25,7 +25,7 @@
*******************************************************************************/
/*!
\file
\brief Envelope extraction $Revision: 36841 $
\brief Envelope extraction $Revision: 38006 $
The functions provided by this module are mostly called by applySBR(). After it is
determined that there is valid SBR data, sbrGetHeaderData() might be called if the current
SBR data contains an \ref SBR_HEADER_ELEMENT as opposed to a \ref SBR_STANDARD_ELEMENT. This function
......@@ -167,6 +167,10 @@ initHeaderData (
/* One SBR timeslot corresponds to the amount of samples equal to the amount of analysis bands, divided by the timestep. */
hHeaderData->numberTimeSlots = (samplesPerFrame/numAnalysisBands) >> (hHeaderData->timeStep - 1);
if (hHeaderData->numberTimeSlots > (16)) {
sbrError = SBRDEC_UNSUPPORTED_CONFIG;
}
hHeaderData->numberOfAnalysisBands = numAnalysisBands;
bail:
......
......@@ -25,7 +25,7 @@
*******************************************************************************/
/*!
\file
\brief Sbr decoder $Revision: 36841 $
\brief Sbr decoder $Revision: 37646 $
This module provides the actual decoder implementation. The SBR data (side information) is already
decoded. Only three functions are provided:
......@@ -537,6 +537,9 @@ sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
maxShift = hSbrDec->sbrDrcChannel.nextFact_exp;
}
/* copy DRC data to right channel (with PS both channels use the same DRC gains) */
FDKmemcpy(&hSbrDecRight->sbrDrcChannel, &hSbrDec->sbrDrcChannel, sizeof(SBRDEC_DRC_CHANNEL));
for (i = 0; i < synQmf->no_col; i++) { /* ----- no_col loop ----- */
INT outScalefactorR, outScalefactorL;
......@@ -565,7 +568,7 @@ sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
sbrDecoder_drcApplySlot ( /* right channel */
&hSbrDec->sbrDrcChannel,
&hSbrDecRight->sbrDrcChannel,
rQmfReal,
rQmfImag,
i,
......
......@@ -26,7 +26,7 @@
/*!
\file
\brief Memory layout
$Revision: 36841 $
$Revision: 38012 $
This module declares all static and dynamic memory spaces
*/
......
......@@ -25,7 +25,7 @@
*******************************************************************************/
/*!
\file
\brief SBR decoder frontend $Revision: 36841 $
\brief SBR decoder frontend $Revision: 38029 $
This module provides a frontend to the SBR decoder. The function openSBR() is called for
initialization. The function sbrDecoder_Apply() is called for each frame. sbr_Apply() will call the
required functions to decode the raw SBR data (provided by env_extr.cpp), to decode the envelope data and noise floor levels [decodeSbrData()],
......@@ -79,7 +79,7 @@
/* Decoder library info */
#define SBRDECODER_LIB_VL0 2
#define SBRDECODER_LIB_VL1 1
#define SBRDECODER_LIB_VL2 0
#define SBRDECODER_LIB_VL2 1
#define SBRDECODER_LIB_TITLE "SBR Decoder"
#define SBRDECODER_LIB_BUILD_DATE __DATE__
#define SBRDECODER_LIB_BUILD_TIME __TIME__
......@@ -367,6 +367,7 @@ SBR_ERROR sbrDecoder_InitElement (
{
SBR_ERROR sbrError = SBRDEC_OK;
int chCnt=0;
int nSbrElementsStart = self->numSbrElements;
/* Check core codec AOT */
if (! sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (4)) {
......@@ -488,8 +489,13 @@ SBR_ERROR sbrDecoder_InitElement (
bail:
if (sbrError != SBRDEC_OK) {
/* Free the memory allocated for this element */
sbrDecoder_DestroyElement( self, elementIndex );
if (nSbrElementsStart < self->numSbrElements) {
/* Free the memory allocated for this element */
sbrDecoder_DestroyElement( self, elementIndex );
} else if (self->pSbrElement[elementIndex] != NULL) {
/* Set error flag to trigger concealment */
self->pSbrElement[elementIndex]->frameErrorFlag[self->pSbrElement[elementIndex]->useFrameSlot] = 1;;
}
}
return sbrError;
......@@ -933,7 +939,8 @@ SBR_ERROR sbrDecoder_Parse(
1);
}
if (headerStatus == HEADER_RESET) {
if (headerStatus == HEADER_RESET)
{
errorStatus = sbrDecoder_HeaderUpdate(
self,
hSbrHeader,
......@@ -1130,6 +1137,10 @@ sbrDecoder_DecodeElement (
self->flags
);
if (errorStatus != SBRDEC_OK) {
return errorStatus;
}
hSbrHeader->syncState = UPSAMPLING;
errorStatus = sbrDecoder_HeaderUpdate(
......@@ -1139,6 +1150,11 @@ sbrDecoder_DecodeElement (
pSbrChannel,
hSbrElement->nChannels
);
if (errorStatus != SBRDEC_OK) {
hSbrHeader->syncState = SBR_NOT_INITIALIZED;
return errorStatus;
}
}
/* reset */
......@@ -1296,6 +1312,11 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self,
psPossible = *psDecoded;
if (self->numSbrElements < 1) {
/* exit immediately to avoid access violations */
return SBRDEC_CREATE_ERROR;
}
/* Sanity check of allocated SBR elements. */
for (sbrElementNum=0; sbrElementNum<self->numSbrElements; sbrElementNum++) {
if (self->pSbrElement[sbrElementNum] == NULL) {
......
......@@ -212,6 +212,16 @@ INT sbrEncoder_Open(
INT supportPS
);
/**
* \brief get closest working bit rate to specified desired bit rate for a single SBR element
* \param bitRate the desired target bit rate
* \param numChannels the amount of audio channels
* \param coreSampleRate the sample rate of the core coder
* \param the current Audio Object Type
* \return closest working bit rate to bitRate value
*/
UINT sbrEncoder_LimitBitRate(UINT bitRate, UINT numChannels, UINT coreSampleRate, AUDIO_OBJECT_TYPE aot);
/**
* \brief Initialize SBR Encoder instance.
* \param phSbrEncoder Pointer to a SBR Encoder instance.
......
......@@ -16,7 +16,6 @@ LOCAL_SRC_FILES := \
env_est.cpp \
invf_est.cpp \
nf_est.cpp \
psenc_hybrid.cpp \
ps_main.cpp \
sbrenc_freq_sca.cpp \
sbr_misc.cpp \
......
......@@ -799,27 +799,6 @@ calculateSbrEnvelope (FIXP_DBL **RESTRICT YBufferLeft, /*! energy buffer left *
} /* i*/
}
/*
* Update QMF buffers
*/
static void FDKsbrEnc_updateRIBuffers(HANDLE_ENV_CHANNEL h_envChan)
{
int i;
/* rBufferWriteOffset ist always 0, do we need this ? */
for (i = 0; i < h_envChan->sbrExtractEnvelope.rBufferWriteOffset; i++) {
FIXP_DBL *temp;
temp = h_envChan->sbrExtractEnvelope.rBuffer[i];
h_envChan->sbrExtractEnvelope.rBuffer[i] = h_envChan->sbrExtractEnvelope.rBuffer[i + h_envChan->sbrExtractEnvelope.no_cols];
h_envChan->sbrExtractEnvelope.rBuffer[i + h_envChan->sbrExtractEnvelope.no_cols] = temp;
temp = h_envChan->sbrExtractEnvelope.iBuffer[i];
h_envChan->sbrExtractEnvelope.iBuffer[i] = h_envChan->sbrExtractEnvelope.iBuffer[i + h_envChan->sbrExtractEnvelope.no_cols];
h_envChan->sbrExtractEnvelope.iBuffer[i + h_envChan->sbrExtractEnvelope.no_cols] = temp;
}
}
/***************************************************************************/
/*!
......@@ -873,8 +852,8 @@ FDKsbrEnc_extractSbrEnvelope1 (
Precalculation of Tonality Quotas COEFF Transform OK
*/
FDKsbrEnc_CalculateTonalityQuotas(&hEnvChan->TonCorr,
sbrExtrEnv->rBuffer+ sbrExtrEnv->rBufferWriteOffset,
sbrExtrEnv->iBuffer+ sbrExtrEnv->rBufferWriteOffset,
sbrExtrEnv->rBuffer,
sbrExtrEnv->iBuffer,
h_con->freqBandTable[HI][h_con->nSfb[HI]],
hEnvChan->qmfScale);
......@@ -914,8 +893,6 @@ FDKsbrEnc_extractSbrEnvelope1 (
sbrExtrEnv->no_cols);
FDKsbrEnc_updateRIBuffers(hEnvChan);
}
/***************************************************************************/
......@@ -1741,12 +1718,11 @@ FDKsbrEnc_InitExtractSbrEnvelope (HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut,
{
hSbrCut->YBufferWriteOffset = tran_off*time_step;
}
hSbrCut->rBufferWriteOffset = 0;
hSbrCut->rBufferReadOffset = 0;
YBufferLength = hSbrCut->YBufferWriteOffset + no_cols;
rBufferLength = hSbrCut->rBufferWriteOffset + no_cols;
rBufferLength = no_cols;
hSbrCut->pre_transient_info[0] = 0;
hSbrCut->pre_transient_info[1] = 0;
......@@ -1824,8 +1800,8 @@ FDKsbrEnc_deleteExtractSbrEnvelope (HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut)
INT
FDKsbrEnc_GetEnvEstDelay(HANDLE_SBR_EXTRACT_ENVELOPE hSbr)
{
return hSbr->no_rows*((hSbr->YBufferWriteOffset)*2 + /* mult 2 because nrg's are grouped half */
hSbr->rBufferWriteOffset - hSbr->rBufferReadOffset ); /* in reference hold half spec and calc nrg's on overlapped spec */
return hSbr->no_rows*((hSbr->YBufferWriteOffset)*2 /* mult 2 because nrg's are grouped half */
- hSbr->rBufferReadOffset ); /* in reference hold half spec and calc nrg's on overlapped spec */
}
......
......@@ -25,7 +25,7 @@
****************************************************************************/
/*!
\file
\brief Envelope estimation structs and prototypes $Revision: 36847 $
\brief Envelope estimation structs and prototypes $Revision: 37142 $
*/
#ifndef __ENV_EST_H
#define __ENV_EST_H
......@@ -56,7 +56,6 @@ typedef struct
int YBufferWriteOffset;
int YBufferSzShift;
int rBufferReadOffset;
int rBufferWriteOffset;
int no_cols;
int no_rows;
......
......@@ -202,8 +202,7 @@ static const UINT opdDeltaTime_Code[] =
static const INT psBands[] =
{
PS_BANDS_COARSE,
PS_BANDS_MID,
PS_BANDS_FINE
PS_BANDS_MID
};
static INT getNoBands(PS_RESOLUTION mode)
......
......@@ -28,6 +28,17 @@
#ifndef PS_CONST_H
#define PS_CONST_H
#define MAX_PS_CHANNELS ( 2 )
#define HYBRID_MAX_QMF_BANDS ( 3 )
#define HYBRID_FILTER_LENGTH ( 13 )
#define HYBRID_FILTER_DELAY ( (HYBRID_FILTER_LENGTH-1)/2 )
#define HYBRID_FRAMESIZE ( QMF_MAX_TIME_SLOTS )
#define HYBRID_READ_OFFSET ( 10 )
#define MAX_HYBRID_BANDS ( (QMF_CHANNELS-HYBRID_MAX_QMF_BANDS+10) )
typedef enum {
PS_RES_COARSE = 0,
PS_RES_MID = 1,
......@@ -37,8 +48,7 @@ typedef enum {
typedef enum {
PS_BANDS_COARSE = 10,
PS_BANDS_MID = 20,
PS_BANDS_FINE = 34,
PS_MAX_BANDS = PS_BANDS_FINE
PS_MAX_BANDS = PS_BANDS_MID
} PS_BANDS;
typedef enum {
......@@ -62,4 +72,14 @@ typedef enum {
} PS_CONSTS;
typedef enum {
PSENC_OK = 0x0000, /*!< No error happened. All fine. */
PSENC_INVALID_HANDLE = 0x0020, /*!< Handle passed to function call was invalid. */
PSENC_MEMORY_ERROR = 0x0021, /*!< Memory allocation failed. */
PSENC_INIT_ERROR = 0x0040, /*!< General initialization error. */
PSENC_ENCODE_ERROR = 0x0060 /*!< The encoding process was interrupted by an unexpected error. */
} FDK_PSENC_ERROR;
#endif
This diff is collapsed.
......@@ -27,7 +27,7 @@
******************************************************************************/
/*!
\file
\brief PS parameter extraction, encoding functions $Revision: 36847 $
\brief PS parameter extraction, encoding functions $Revision: 37142 $
*/
#ifndef __INCLUDED_PS_ENCODE_H
......@@ -35,7 +35,7 @@
#include "ps_const.h"
#include "ps_bitenc.h"
#include "psenc_hybrid.h"
#define IID_SCALE_FT (64.f) /* maxVal in Quant tab is +/- 50 */
#define IID_SCALE 6 /* maxVal in Quant tab is +/- 50 */
......@@ -81,7 +81,7 @@ typedef struct T_PS_DATA {
typedef struct T_PS_ENCODE{
HANDLE_PS_DATA hPsData;
PS_DATA psData;
PS_BANDS psEncMode;
INT nQmfIidGroups;
......@@ -97,21 +97,29 @@ typedef struct T_PS_ENCODE{
typedef struct T_PS_ENCODE *HANDLE_PS_ENCODE;
typedef struct T_PS_CHANNEL_DATA *HANDLE_PS_CHANNEL_DATA;
HANDLE_ERROR_INFO FDKsbrEnc_CreatePSEncode(HANDLE_PS_ENCODE *phPsEncode);
HANDLE_ERROR_INFO FDKsbrEnc_InitPSEncode(HANDLE_PS_ENCODE hPsEncode, const PS_BANDS psEncMode, const FIXP_DBL iidQuantErrorThreshold);
HANDLE_ERROR_INFO FDKsbrEnc_DestroyPSEncode(HANDLE_PS_ENCODE *phPsEncode);
HANDLE_ERROR_INFO FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE hPsEncode,
HANDLE_PS_OUT hPsOut,
HANDLE_PS_CHANNEL_DATA hChanDatal,
HANDLE_PS_CHANNEL_DATA hChanDatar,
UCHAR *dynBandScale,
UINT maxEnvelopes,
const int sendHeader);
FDK_PSENC_ERROR FDKsbrEnc_CreatePSEncode(
HANDLE_PS_ENCODE *phPsEncode
);
FDK_PSENC_ERROR FDKsbrEnc_InitPSEncode(
HANDLE_PS_ENCODE hPsEncode,
const PS_BANDS psEncMode,
const FIXP_DBL iidQuantErrorThreshold
);
FDK_PSENC_ERROR FDKsbrEnc_DestroyPSEncode(
HANDLE_PS_ENCODE *phPsEncode
);
FDK_PSENC_ERROR FDKsbrEnc_PSEncode(
HANDLE_PS_ENCODE hPsEncode,
HANDLE_PS_OUT hPsOut,
UCHAR *dynBandScale,
UINT maxEnvelopes,
FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2],
const INT frameSize,
const INT sendHeader
);
#endif
This diff is collapsed.
......@@ -30,74 +30,49 @@
/* Includes ******************************************************************/
#include "sbr_def.h"
#include "psenc_hybrid.h"
#include "qmf.h"
#include "ps_encode.h"
#include "FDK_bitstream.h"
#include "FDK_hybrid.h"
/* Data Types ****************************************************************/
typedef enum {
PSENC_STEREO_BANDS_INVALID = 0,
PSENC_STEREO_BANDS_10 = 10,
PSENC_STEREO_BANDS_20 = 20,
PSENC_STEREO_BANDS_34 = 34
PSENC_STEREO_BANDS_10 = 10,
PSENC_STEREO_BANDS_20 = 20
} PSENC_STEREO_BANDS_CONFIG;
typedef enum {
PSENC_NENV_1 = 1,
PSENC_NENV_2 = 2,
PSENC_NENV_4 = 4,
PSENC_NENV_DEFAULT = PSENC_NENV_2,
PSENC_NENV_MAX = PSENC_NENV_4
} PSENC_NENV_CONFIG;
PSENC_NENV_1 = 1,
PSENC_NENV_2 = 2,
PSENC_NENV_4 = 4,
PSENC_NENV_DEFAULT = PSENC_NENV_2,
PSENC_NENV_MAX = PSENC_NENV_4
#define MAX_PS_CHANNELS ( 2 )
#define PSENC_QMF_BUFFER_LENGTH ( 48 )
} PSENC_NENV_CONFIG;
typedef struct {
UINT bitrateFrom; /* inclusive */
UINT bitrateTo; /* exclusive */
PSENC_STEREO_BANDS_CONFIG nStereoBands;
PSENC_NENV_CONFIG nEnvelopes;
LONG iidQuantErrorThreshold; /* quantization threshold to switch between coarse and fine iid quantization */
UINT bitrateFrom; /* inclusive */
UINT bitrateTo; /* exclusive */
PSENC_STEREO_BANDS_CONFIG nStereoBands;
PSENC_NENV_CONFIG nEnvelopes;
LONG iidQuantErrorThreshold; /* quantization threshold to switch between coarse and fine iid quantization */
} psTuningTable_t;
/* Function / Class Declarations *********************************************/
typedef struct T_PS_QMF_DATA
{
FIXP_QMF *rQmfData[PSENC_QMF_BUFFER_LENGTH];
FIXP_QMF *iQmfData[PSENC_QMF_BUFFER_LENGTH];
INT nCols;
INT nRows;
INT bufferReadOffset;
INT bufferReadOffsetHybrid;
INT bufferWriteOffset;
INT bufferLength;
} PS_QMF_DATA, *HANDLE_PS_QMF_DATA;
typedef struct T_PS_CHANNEL_DATA {
HANDLE_PS_QMF_DATA hPsQmfData;
int psQmfScale;
HANDLE_PS_HYBRID_DATA hHybData;
HANDLE_PS_HYBRID hHybAna;
INT psChannelDelay; /* delay in samples */
} PS_CHANNEL_DATA, *HANDLE_PS_CHANNEL_DATA;
typedef struct T_PARAMETRIC_STEREO {
HANDLE_PS_HYBRID_CONFIG hHybridConfig;
HANDLE_PS_CHANNEL_DATA hPsChannelData[MAX_PS_CHANNELS];
HANDLE_PS_ENCODE hPsEncode;
HANDLE_PS_OUT hPsOut[2];
PS_OUT psOut[2];
FIXP_QMF *qmfDelayReal[QMF_MAX_TIME_SLOTS>>1];
FIXP_QMF *qmfDelayImag[QMF_MAX_TIME_SLOTS>>1];
FIXP_QMF *qmfDelayRealRef;
FIXP_QMF *qmfDelayImagRef;
int qmfDelayScale;
FIXP_DBL __staticHybridData[HYBRID_READ_OFFSET][MAX_PS_CHANNELS][2][MAX_HYBRID_BANDS];
FIXP_DBL *pHybridData[HYBRID_READ_OFFSET+HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2];
FIXP_QMF qmfDelayLines[2][QMF_MAX_TIME_SLOTS>>1][QMF_CHANNELS];
int qmfDelayScale;
INT psDelay;
UINT maxEnvelopes;
......@@ -108,53 +83,126 @@ typedef struct T_PARAMETRIC_STEREO {
INT noQmfSlots;
INT noQmfBands;
} PARAMETRIC_STEREO;
FIXP_DBL __staticHybAnaStatesLF[MAX_PS_CHANNELS][2*HYBRID_FILTER_LENGTH*HYBRID_MAX_QMF_BANDS];
FIXP_DBL __staticHybAnaStatesHF[MAX_PS_CHANNELS][2*HYBRID_FILTER_DELAY*(QMF_CHANNELS-HYBRID_MAX_QMF_BANDS)];
FDK_ANA_HYB_FILTER fdkHybAnaFilter[MAX_PS_CHANNELS];
FDK_SYN_HYB_FILTER fdkHybSynFilter;
} PARAMETRIC_STEREO;
typedef struct T_PSENC_CONFIG {
INT frameSize;
INT qmfFilterMode;
INT sbrPsDelay;
PSENC_STEREO_BANDS_CONFIG nStereoBands;
PSENC_NENV_CONFIG maxEnvelopes;
FIXP_DBL iidQuantErrorThreshold;
INT frameSize;
INT qmfFilterMode;
INT sbrPsDelay;
PSENC_STEREO_BANDS_CONFIG nStereoBands;
PSENC_NENV_CONFIG maxEnvelopes;
FIXP_DBL iidQuantErrorThreshold;
} PSENC_CONFIG, *HANDLE_PSENC_CONFIG;
typedef struct T_PARAMETRIC_STEREO *HANDLE_PARAMETRIC_STEREO;
HANDLE_ERROR_INFO
PSEnc_Create(HANDLE_PARAMETRIC_STEREO *phParametricStereo);
HANDLE_ERROR_INFO
PSEnc_Init(HANDLE_PARAMETRIC_STEREO hParametricStereo,
HANDLE_PSENC_CONFIG hPsEncConfig,
INT noQmfSlots,
INT noQmfBands
,UCHAR *dynamic_RAM
);
HANDLE_ERROR_INFO
UpdatePSQmfData_second(HANDLE_PARAMETRIC_STEREO hParametricStereo);
HANDLE_ERROR_INFO
PSEnc_Destroy(HANDLE_PARAMETRIC_STEREO *hParametricStereo);
HANDLE_ERROR_INFO
FDKsbrEnc_PSEnc_ParametricStereoProcessing(HANDLE_PARAMETRIC_STEREO hParametricStereo,
FIXP_QMF **RESTRICT qmfRealData,
FIXP_QMF **RESTRICT qmfImagData,
INT qmfOffset,
INT_PCM *downsampledOutSignal,
HANDLE_QMF_FILTER_BANK sbrSynthQmf,
SCHAR *qmfScale,
const int sendHeader);
INT
FDKsbrEnc_PSEnc_WritePSData(HANDLE_PARAMETRIC_STEREO hParametricStereo, HANDLE_FDK_BITSTREAM hBitstream);
/**
* \brief Create a parametric stereo encoder instance.
*
* \param phParametricStereo A pointer to a parametric stereo handle to be allocated. Initialized on return.
*
* \return
* - PSENC_OK, on succes.
* - PSENC_INVALID_HANDLE, PSENC_MEMORY_ERROR, on failure.
*/
FDK_PSENC_ERROR PSEnc_Create(
HANDLE_PARAMETRIC_STEREO *phParametricStereo
);
/**
* \brief Initialize a parametric stereo encoder instance.
*
* \param hParametricStereo Meta Data handle.
* \param hPsEncConfig Filled parametric stereo configuration structure.
* \param noQmfSlots Number of slots within one audio frame.
* \param noQmfBands Number of QMF bands.
* \param dynamic_RAM Pointer to preallocated workbuffer.
*
* \return
* - PSENC_OK, on succes.
* - PSENC_INVALID_HANDLE, PSENC_INIT_ERROR, on failure.
*/
FDK_PSENC_ERROR PSEnc_Init(
HANDLE_PARAMETRIC_STEREO hParametricStereo,
const HANDLE_PSENC_CONFIG hPsEncConfig,
INT noQmfSlots,
INT noQmfBands
,UCHAR *dynamic_RAM
);
/**
* \brief Destroy parametric stereo encoder instance.
*
* Deallocate instance and free whole memory.
*
* \param phParametricStereo Pointer to the parametric stereo handle to be deallocated.
*
* \return
* - PSENC_OK, on succes.
* - PSENC_INVALID_HANDLE, on failure.
*/
FDK_PSENC_ERROR PSEnc_Destroy(
HANDLE_PARAMETRIC_STEREO *phParametricStereo
);
/**
* \brief Apply parametric stereo processing.
*
* \param hParametricStereo Meta Data handle.
* \param samples Pointer to 2 channel audio input signal.
* \param timeInStride, Stride factor of input buffer.
* \param hQmfAnalysis, Pointer to QMF analysis filterbanks.
* \param downmixedRealQmfData Pointer to real QMF buffer to be written to.
* \param downmixedImagQmfData Pointer to imag QMF buffer to be written to.
* \param downsampledOutSignal Pointer to buffer where to write downmixed timesignal.
* \param sbrSynthQmf Pointer to QMF synthesis filterbank.
* \param qmfScale Return scaling factor of the qmf data.
* \param sendHeader Signal whether to write header data.
*
* \return
* - PSENC_OK, on succes.
* - PSENC_INVALID_HANDLE, PSENC_ENCODE_ERROR, on failure.
*/
FDK_PSENC_ERROR FDKsbrEnc_PSEnc_ParametricStereoProcessing(
HANDLE_PARAMETRIC_STEREO hParametricStereo,
INT_PCM *samples[2],
UINT timeInStride,
QMF_FILTER_BANK **hQmfAnalysis,
FIXP_QMF **RESTRICT downmixedRealQmfData,
FIXP_QMF **RESTRICT downmixedImagQmfData,
INT_PCM *downsampledOutSignal,
HANDLE_QMF_FILTER_BANK sbrSynthQmf,
SCHAR *qmfScale,
const int sendHeader
);
/**
* \brief Write parametric stereo bitstream.
*
* Write ps_data() element to bitstream and return number of written bits.
* Returns number of written bits only, if hBitstream == NULL.
*
* \param hParametricStereo Meta Data handle.
* \param hBitstream Bitstream buffer handle.
*
* \return
* - number of written bits.
*/
INT FDKsbrEnc_PSEnc_WritePSData(
HANDLE_PARAMETRIC_STEREO hParametricStereo,
HANDLE_FDK_BITSTREAM hBitstream
);
#endif /* __INCLUDED_PS_MAIN_H */
This diff is collapsed.
/***************************** MPEG Audio Encoder ***************************
(C) Copyright Fraunhofer IIS (2004-2005)
All Rights Reserved
Please be advised that this software and/or program delivery is
Confidential Information of Fraunhofer and subject to and covered by the
Fraunhofer IIS Software Evaluation Agreement
between Google Inc. and Fraunhofer
effective and in full force since March 1, 2012.
You may use this software and/or program only under the terms and
conditions described in the above mentioned Fraunhofer IIS Software
Evaluation Agreement. Any other and/or further use requires a separate agreement.
$Id$
Initial author: M. Neuendorf, M. Multrus
contents/description: hypbrid filter bank (prototypes)
This software and/or program is protected by copyright law and international
treaties. Any reproduction or distribution of this software and/or program,
or any portion of it, may result in severe civil and criminal penalties, and
will be prosecuted to the maximum extent possible under law.
******************************************************************************/
#ifndef __hybrid_h
#define __hybrid_h
/* Includes ******************************************************************/
#include "sbr_def.h"
#include "ps_const.h"
#include "qmf.h"
/* Data Types ****************************************************************/
typedef enum {
HYBRID_2_REAL = 2,
HYBRID_4_CPLX = 4,
HYBRID_6_CPLX = 6,
HYBRID_8_CPLX = 8,
HYBRID_12_CPLX = 12
} HYBRID_RES;
#define MAX_HYBRID_RES (HYBRID_12_CPLX)
/* Defines *******************************************************************/
#define MAX_QMF_BANDS_IN_HYBRID (5)
#define MAX_IID_GROUPS (50) /* NO_IID_GROUPS_HI_RES */
#define HYBRID_FILTER_LENGTH ( 13 )
#define HYBRID_FRAMESIZE ( QMF_MAX_TIME_SLOTS )
#define HYBRID_WRITEOFFSET ( 10 )
#define HYBRID_NUM_BANDS ( 10 )
#define NO_QMF_BANDS_HYBRID_10 ( 3 )
#define NO_QMF_BANDS_HYBRID_20 ( 3 )
#define HYBRID_MAX_QMF_BANDS ( NO_QMF_BANDS_HYBRID_20 )
#define QMF_BUFFER_MOVE ( HYBRID_FILTER_LENGTH - 1 )
/* Data Types ****************************************************************/
typedef struct PS_HYBRID_CONFIG_tag {
PS_BANDS mode;
UINT noQmfBandsInHybrid;
INT aHybridResolution[MAX_QMF_BANDS_IN_HYBRID]; /* valid entries from 0 to noQmfBandsInHybrid */
} PS_HYBRID_CONFIG, *HANDLE_PS_HYBRID_CONFIG;
typedef struct PS_HYBRID_tag
{
PS_BANDS mode;
INT nQmfBands;
INT frameSizeInit;
INT frameSize;
INT pResolution[HYBRID_MAX_QMF_BANDS];
INT qmfBufferMove;
INT hybridFilterDelay;
FIXP_DBL *fft;
FIXP_QMF *pWorkReal; /**< Working arrays for Qmf samples. */
FIXP_QMF *pWorkImag;
FIXP_QMF mQmfBufferReal[HYBRID_MAX_QMF_BANDS][QMF_BUFFER_MOVE]; /**< Stores old Qmf samples. */
FIXP_QMF mQmfBufferImag[HYBRID_MAX_QMF_BANDS][QMF_BUFFER_MOVE];
FIXP_QMF *mTempReal[HYBRID_FRAMESIZE]; /**< Temporary matrices for filter bank output. */
FIXP_QMF *mTempImag[HYBRID_FRAMESIZE];
} PS_HYBRID;
typedef struct PS_HYBRID_DATA_tag {
INT frameSize;
INT nHybridBands;
INT nHybridQmfBands;
INT nHybridResolution [HYBRID_MAX_QMF_BANDS];
FIXP_QMF* rHybData [(HYBRID_FRAMESIZE + HYBRID_WRITEOFFSET)];
FIXP_QMF* iHybData [(HYBRID_FRAMESIZE + HYBRID_WRITEOFFSET)];
SCHAR sf_fixpHybrid;
INT hybDataReadOffset;
INT hybDataWriteOffset;
} PS_HYBRID_DATA;
typedef struct PS_HYBRID_DATA_tag *HANDLE_PS_HYBRID_DATA;
typedef struct PS_HYBRID_tag *HANDLE_PS_HYBRID;
/* Function Declarations *********************************************/
/*****************************************************************************/
/* **** FILTERBANK CONFIG **** */
HANDLE_ERROR_INFO FDKsbrEnc_CreateHybridConfig(HANDLE_PS_HYBRID_CONFIG *phHybConfig,
PS_BANDS mode);
/*****************************************************************************/
/* **** FILTERBANK DATA **** */
HANDLE_ERROR_INFO FDKsbrEnc_CreateHybridData(HANDLE_PS_HYBRID_DATA *phHybData,
INT ch);
HANDLE_ERROR_INFO FDKsbrEnc_InitHybridData(HANDLE_PS_HYBRID_DATA hHybData,
HANDLE_PS_HYBRID_CONFIG hHybConfig,
INT frameSize);
HANDLE_ERROR_INFO FDKsbrEnc_DestroyHybridData(HANDLE_PS_HYBRID_DATA* phHybData);
inline INT FDKsbrEnc_GetHybridFrameSize(HANDLE_PS_HYBRID_DATA h) {
return h->frameSize;
}
inline INT FDKsbrEnc_GetNumberHybridBands(HANDLE_PS_HYBRID_DATA h) {
return h->nHybridBands;
}
inline INT FDKsbrEnc_GetNumberHybridQmfBands(HANDLE_PS_HYBRID_DATA h) {
return h->nHybridQmfBands;
}
INT FDKsbrEnc_GetHybridResolution(HANDLE_PS_HYBRID_DATA h, INT qmfBand);
/*****************************************************************************/
/* **** FILTERBANK **** */
HANDLE_ERROR_INFO
FDKsbrEnc_CreateHybridFilterBank ( HANDLE_PS_HYBRID *phHybrid,
INT ch );
HANDLE_ERROR_INFO
FDKsbrEnc_InitHybridFilterBank ( HANDLE_PS_HYBRID hHybrid,
HANDLE_PS_HYBRID_CONFIG hHybConfig,
INT frameSize );
HANDLE_ERROR_INFO
FDKsbrEnc_DeleteHybridFilterBank ( HANDLE_PS_HYBRID* phHybrid );
HANDLE_ERROR_INFO
HybridAnalysis ( HANDLE_PS_HYBRID hHybrid,
FIXP_QMF *const * const mQmfReal,
FIXP_QMF *const * const mQmfImag,
SCHAR sf_fixpQmf,
FIXP_QMF **mHybridReal,
FIXP_QMF **mHybridImag,
SCHAR *sf_fixpHybrid);
INT
FDKsbrEnc_GetHybridFilterDelay(HANDLE_PS_HYBRID hHybrid);
#endif /*__hybrid_h*/
......@@ -25,7 +25,7 @@
*******************************************************************************/
/*!
\file
\brief Main SBR structs definitions $Revision: 36847 $
\brief Main SBR structs definitions $Revision: 37142 $
*/
#ifndef __SBR_H
......@@ -92,7 +92,6 @@ struct SBR_ENCODER
UCHAR* dynamicRam;
UCHAR* pSBRdynamic_RAM;
HANDLE_PSENC_CONFIG hPsEncConfig;
HANDLE_PARAMETRIC_STEREO hParametricStereo;
QMF_FILTER_BANK qmfSynthesisPS;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -40,7 +40,7 @@
/* Always increase verbosity of memory allocation in case of a debug built. DEBUG is defined globally in that case. */
#if defined(DEBUG) || defined(FDK_DEBUG)
#define MEMORY_MEASUREMENT
//#define MEMORY_MEASUREMENT
#endif
#ifndef M_PI
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment