mirror of
https://github.com/mstorsjo/fdk-aac.git
synced 2025-02-16 19:30:34 +01:00
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
This commit is contained in:
parent
9bf37cc971
commit
698b536f3b
@ -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;
|
||||
|
||||
for (i=0; i<(int)(sizeof(samplingRateScalingTable)/sizeof(SR_SCALING_TAB)); i++) {
|
||||
if ( samplingRateScalingTable[i].samplingRate == samplingRate ) {
|
||||
result = samplingRateScalingTable[i].scalingFactor;
|
||||
break;
|
||||
}
|
||||
while ( (frameLength & ~((1<<(shift+1))-1)) == frameLength
|
||||
&& (coreSamplingRate & ~((1<<(shift+1))-1)) == coreSamplingRate )
|
||||
{
|
||||
shift ++;
|
||||
}
|
||||
return result;
|
||||
|
||||
do {
|
||||
prevBitRate = bitRate;
|
||||
averageBitsPerFrame = (bitRate*(frameLength>>shift)) / (coreSamplingRate>>shift) / nSubFrames;
|
||||
|
||||
if (pAverageBitsPerFrame != NULL) {
|
||||
*pAverageBitsPerFrame = averageBitsPerFrame;
|
||||
}
|
||||
|
||||
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 */
|
||||
|
211
libFDK/include/FDK_hybrid.h
Normal file
211
libFDK/include/FDK_hybrid.h
Normal file
@ -0,0 +1,211 @@
|
||||
/*************************** 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 \
|
||||
|
766
libFDK/src/FDK_hybrid.cpp
Normal file
766
libFDK/src/FDK_hybrid.cpp
Normal file
@ -0,0 +1,766 @@
|
||||
/*************************** 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.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "FDK_hybrid.h"
|
||||
|
||||
|
||||
#include "fft.h"
|
||||
|
||||
/*--------------- defines -----------------------------*/
|
||||
#define FFT_IDX_R(a) (2*a)
|
||||
#define FFT_IDX_I(a) (2*a+1)
|
||||
|
||||
#define HYB_COEF8_0 ( 0.00746082949812f )
|
||||
#define HYB_COEF8_1 ( 0.02270420949825f )
|
||||
#define HYB_COEF8_2 ( 0.04546865930473f )
|
||||
#define HYB_COEF8_3 ( 0.07266113929591f )
|
||||
#define HYB_COEF8_4 ( 0.09885108575264f )
|
||||
#define HYB_COEF8_5 ( 0.11793710567217f )
|
||||
#define HYB_COEF8_6 ( 0.12500000000000f )
|
||||
#define HYB_COEF8_7 ( HYB_COEF8_5 )
|
||||
#define HYB_COEF8_8 ( HYB_COEF8_4 )
|
||||
#define HYB_COEF8_9 ( HYB_COEF8_3 )
|
||||
#define HYB_COEF8_10 ( HYB_COEF8_2 )
|
||||
#define HYB_COEF8_11 ( HYB_COEF8_1 )
|
||||
#define HYB_COEF8_12 ( HYB_COEF8_0 )
|
||||
|
||||
|
||||
/*--------------- structure definitions ---------------*/
|
||||
|
||||
#if defined(ARCH_PREFER_MULT_32x16)
|
||||
#define FIXP_HTB FIXP_SGL /* SGL data type. */
|
||||
#define FIXP_HTP FIXP_SPK /* Packed SGL data type. */
|
||||
#define HTC(a) (FX_DBL2FXCONST_SGL(a)) /* Cast to SGL */
|
||||
#define FL2FXCONST_HTB FL2FXCONST_SGL
|
||||
#else
|
||||
#define FIXP_HTB FIXP_DBL /* SGL data type. */
|
||||
#define FIXP_HTP FIXP_DPK /* Packed DBL data type. */
|
||||
#define HTC(a) ((FIXP_DBL)(LONG)(a)) /* Cast to DBL */
|
||||
#define FL2FXCONST_HTB FL2FXCONST_DBL
|
||||
#endif
|
||||
|
||||
#define HTCP(real,imag) { { HTC(real), HTC(imag) } } /* How to arrange the packed values. */
|
||||
|
||||
|
||||
struct FDK_HYBRID_SETUP
|
||||
{
|
||||
UCHAR nrQmfBands; /*!< Number of QMF bands to be converted to hybrid. */
|
||||
UCHAR nHybBands[3]; /*!< Number of Hybrid bands generated by nrQmfBands. */
|
||||
SCHAR kHybrid[3]; /*!< Filter configuration of each QMF band. */
|
||||
UCHAR protoLen; /*!< Prototype filter length. */
|
||||
UCHAR filterDelay; /*!< Delay caused by hybrid filter. */
|
||||
const INT *pReadIdxTable; /*!< Helper table to access input data ringbuffer. */
|
||||
|
||||
};
|
||||
|
||||
/*--------------- constants ---------------------------*/
|
||||
static const INT ringbuffIdxTab[2*13] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
|
||||
|
||||
static const FDK_HYBRID_SETUP setup_3_16 = { 3, { 8, 4, 4}, { 8, 4, 4}, 13, (13-1)/2, ringbuffIdxTab};
|
||||
static const FDK_HYBRID_SETUP setup_3_12 = { 3, { 8, 2, 2}, { 8, 2, 2}, 13, (13-1)/2, ringbuffIdxTab};
|
||||
static const FDK_HYBRID_SETUP setup_3_10 = { 3, { 6, 2, 2}, { -8, -2, 2}, 13, (13-1)/2, ringbuffIdxTab};
|
||||
|
||||
|
||||
static const FIXP_HTP HybFilterCoef8[] = {
|
||||
HTCP(0x10000000, 0x00000000), HTCP(0x0df26407, 0xfa391882), HTCP(0xff532109, 0x00acdef7), HTCP(0x08f26d36, 0xf70d92ca),
|
||||
HTCP(0xfee34b5f, 0x02af570f), HTCP(0x038f276e, 0xf7684793), HTCP(0x00000000, 0x05d1eac2), HTCP(0x00000000, 0x05d1eac2),
|
||||
HTCP(0x038f276e, 0x0897b86d), HTCP(0xfee34b5f, 0xfd50a8f1), HTCP(0x08f26d36, 0x08f26d36), HTCP(0xff532109, 0xff532109),
|
||||
HTCP(0x0df26407, 0x05c6e77e)
|
||||
};
|
||||
|
||||
static const FIXP_HTB HybFilterCoef2[13] = {
|
||||
FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB( 0.01899487526049f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB(-0.07293139167538f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB( 0.30596630545168f),
|
||||
FL2FXCONST_HTB( 0.50000000000000f), FL2FXCONST_HTB( 0.30596630545168f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB(-0.07293139167538f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB( 0.01899487526049f),
|
||||
FL2FXCONST_HTB( 0.00000000000000f)
|
||||
};
|
||||
|
||||
static const FIXP_HTB HybFilterCoef4[13] = {
|
||||
FL2FXCONST_HTB(-0.00305151927305f), FL2FXCONST_HTB(-0.00794862316203f), FL2FXCONST_HTB( 0.0f), FL2FXCONST_HTB( 0.04318924038756f), FL2FXCONST_HTB( 0.12542448210445f), FL2FXCONST_HTB( 0.21227807049160f),
|
||||
FL2FXCONST_HTB( 0.25f), FL2FXCONST_HTB( 0.21227807049160f), FL2FXCONST_HTB( 0.12542448210445f), FL2FXCONST_HTB( 0.04318924038756f), FL2FXCONST_HTB( 0.0f), FL2FXCONST_HTB(-0.00794862316203f),
|
||||
FL2FXCONST_HTB(-0.00305151927305f)
|
||||
};
|
||||
|
||||
/*--------------- function declarations ---------------*/
|
||||
static INT kChannelFiltering(
|
||||
const FIXP_DBL *const pQmfReal,
|
||||
const FIXP_DBL *const pQmfImag,
|
||||
const INT *const pReadIdx,
|
||||
FIXP_DBL *const mHybridReal,
|
||||
FIXP_DBL *const mHybridImag,
|
||||
const SCHAR hybridConfig
|
||||
);
|
||||
|
||||
|
||||
/*--------------- function definitions ----------------*/
|
||||
|
||||
INT FDKhybridAnalysisOpen(
|
||||
HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter,
|
||||
FIXP_DBL *const pLFmemory,
|
||||
const UINT LFmemorySize,
|
||||
FIXP_DBL *const pHFmemory,
|
||||
const UINT HFmemorySize
|
||||
)
|
||||
{
|
||||
INT err = 0;
|
||||
|
||||
/* Save pointer to extern memory. */
|
||||
hAnalysisHybFilter->pLFmemory = pLFmemory;
|
||||
hAnalysisHybFilter->LFmemorySize = LFmemorySize;
|
||||
|
||||
hAnalysisHybFilter->pHFmemory = pHFmemory;
|
||||
hAnalysisHybFilter->HFmemorySize = HFmemorySize;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
INT FDKhybridAnalysisInit(
|
||||
HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter,
|
||||
const FDK_HYBRID_MODE mode,
|
||||
const INT qmfBands,
|
||||
const INT cplxBands,
|
||||
const INT initStatesFlag
|
||||
)
|
||||
{
|
||||
int k;
|
||||
INT err = 0;
|
||||
FIXP_DBL *pMem = NULL;
|
||||
HANDLE_FDK_HYBRID_SETUP setup = NULL;
|
||||
|
||||
switch (mode) {
|
||||
case THREE_TO_TEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_10; break;
|
||||
case THREE_TO_TWELVE: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_12; break;
|
||||
case THREE_TO_SIXTEEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_16; break;
|
||||
default: err = -1; goto bail;
|
||||
}
|
||||
|
||||
/* Initialize handle. */
|
||||
hAnalysisHybFilter->pSetup = setup;
|
||||
hAnalysisHybFilter->bufferLFpos = setup->protoLen-1;
|
||||
hAnalysisHybFilter->bufferHFpos = 0;
|
||||
hAnalysisHybFilter->nrBands = qmfBands;
|
||||
hAnalysisHybFilter->cplxBands = cplxBands;
|
||||
hAnalysisHybFilter->hfMode = 0;
|
||||
|
||||
/* Check available memory. */
|
||||
if ( ((2*setup->nrQmfBands*setup->protoLen*sizeof(FIXP_DBL)) > hAnalysisHybFilter->LFmemorySize)
|
||||
|| ((setup->filterDelay*((qmfBands-setup->nrQmfBands)+(cplxBands-setup->nrQmfBands))*sizeof(FIXP_DBL)) > hAnalysisHybFilter->HFmemorySize) )
|
||||
{
|
||||
err = -2;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Distribut LF memory. */
|
||||
pMem = hAnalysisHybFilter->pLFmemory;
|
||||
for (k=0; k<setup->nrQmfBands; k++) {
|
||||
hAnalysisHybFilter->bufferLFReal[k] = pMem; pMem += setup->protoLen;
|
||||
hAnalysisHybFilter->bufferLFImag[k] = pMem; pMem += setup->protoLen;
|
||||
}
|
||||
|
||||
/* Distribut HF memory. */
|
||||
pMem = hAnalysisHybFilter->pHFmemory;
|
||||
for (k=0; k<setup->filterDelay; k++) {
|
||||
hAnalysisHybFilter->bufferHFReal[k] = pMem; pMem += (qmfBands-setup->nrQmfBands);
|
||||
hAnalysisHybFilter->bufferHFImag[k] = pMem; pMem += (cplxBands-setup->nrQmfBands);
|
||||
}
|
||||
|
||||
if (initStatesFlag) {
|
||||
/* Clear LF buffer */
|
||||
for (k=0; k<setup->nrQmfBands; k++) {
|
||||
FDKmemclear(hAnalysisHybFilter->bufferLFReal[k], setup->protoLen*sizeof(FIXP_DBL));
|
||||
FDKmemclear(hAnalysisHybFilter->bufferLFImag[k], setup->protoLen*sizeof(FIXP_DBL));
|
||||
}
|
||||
|
||||
if (qmfBands > setup->nrQmfBands) {
|
||||
/* Clear HF buffer */
|
||||
for (k=0; k<setup->filterDelay; k++) {
|
||||
FDKmemclear(hAnalysisHybFilter->bufferHFReal[k], (qmfBands-setup->nrQmfBands)*sizeof(FIXP_DBL));
|
||||
FDKmemclear(hAnalysisHybFilter->bufferHFImag[k], (cplxBands-setup->nrQmfBands)*sizeof(FIXP_DBL));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
INT FDKhybridAnalysisScaleStates(
|
||||
HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter,
|
||||
const INT scalingValue
|
||||
)
|
||||
{
|
||||
INT err = 0;
|
||||
|
||||
if (hAnalysisHybFilter==NULL) {
|
||||
err = 1; /* invalid handle */
|
||||
}
|
||||
else {
|
||||
int k;
|
||||
HANDLE_FDK_HYBRID_SETUP setup = hAnalysisHybFilter->pSetup;
|
||||
|
||||
/* Scale LF buffer */
|
||||
for (k=0; k<setup->nrQmfBands; k++) {
|
||||
scaleValues(hAnalysisHybFilter->bufferLFReal[k], setup->protoLen, scalingValue);
|
||||
scaleValues(hAnalysisHybFilter->bufferLFImag[k], setup->protoLen, scalingValue);
|
||||
}
|
||||
if (hAnalysisHybFilter->nrBands > setup->nrQmfBands) {
|
||||
/* Scale HF buffer */
|
||||
for (k=0; k<setup->filterDelay; k++) {
|
||||
scaleValues(hAnalysisHybFilter->bufferHFReal[k], (hAnalysisHybFilter->nrBands-setup->nrQmfBands), scalingValue);
|
||||
scaleValues(hAnalysisHybFilter->bufferHFImag[k], (hAnalysisHybFilter->cplxBands-setup->nrQmfBands), scalingValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int k, hybOffset = 0;
|
||||
INT err = 0;
|
||||
const int nrQmfBandsLF = hAnalysisHybFilter->pSetup->nrQmfBands; /* number of QMF bands to be converted to hybrid */
|
||||
|
||||
const int writIndex = hAnalysisHybFilter->bufferLFpos;
|
||||
int readIndex = hAnalysisHybFilter->bufferLFpos;
|
||||
|
||||
if (++readIndex>=hAnalysisHybFilter->pSetup->protoLen) readIndex = 0;
|
||||
const INT* pBufferLFreadIdx = &hAnalysisHybFilter->pSetup->pReadIdxTable[readIndex];
|
||||
|
||||
/*
|
||||
* LF buffer.
|
||||
*/
|
||||
for (k=0; k<nrQmfBandsLF; k++) {
|
||||
/* New input sample. */
|
||||
hAnalysisHybFilter->bufferLFReal[k][writIndex] = pQmfReal[k];
|
||||
hAnalysisHybFilter->bufferLFImag[k][writIndex] = pQmfImag[k];
|
||||
|
||||
/* Perform hybrid filtering. */
|
||||
kChannelFiltering(
|
||||
hAnalysisHybFilter->bufferLFReal[k],
|
||||
hAnalysisHybFilter->bufferLFImag[k],
|
||||
pBufferLFreadIdx,
|
||||
pHybridReal+hybOffset,
|
||||
pHybridImag+hybOffset,
|
||||
hAnalysisHybFilter->pSetup->kHybrid[k]);
|
||||
|
||||
hybOffset += hAnalysisHybFilter->pSetup->nHybBands[k];
|
||||
}
|
||||
|
||||
hAnalysisHybFilter->bufferLFpos = readIndex; /* Index where to write next input sample. */
|
||||
|
||||
if (hAnalysisHybFilter->nrBands > nrQmfBandsLF) {
|
||||
/*
|
||||
* HF buffer.
|
||||
*/
|
||||
if (hAnalysisHybFilter->hfMode!=0) {
|
||||
/* HF delay compensation was applied outside. */
|
||||
FDKmemcpy(pHybridReal+hybOffset, &pQmfReal[nrQmfBandsLF], (hAnalysisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL));
|
||||
FDKmemcpy(pHybridImag+hybOffset, &pQmfImag[nrQmfBandsLF], (hAnalysisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL));
|
||||
}
|
||||
else {
|
||||
/* HF delay compensation, filterlength/2. */
|
||||
FDKmemcpy(pHybridReal+hybOffset, hAnalysisHybFilter->bufferHFReal[hAnalysisHybFilter->bufferHFpos], (hAnalysisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL));
|
||||
FDKmemcpy(pHybridImag+hybOffset, hAnalysisHybFilter->bufferHFImag[hAnalysisHybFilter->bufferHFpos], (hAnalysisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL));
|
||||
|
||||
FDKmemcpy(hAnalysisHybFilter->bufferHFReal[hAnalysisHybFilter->bufferHFpos], &pQmfReal[nrQmfBandsLF], (hAnalysisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL));
|
||||
FDKmemcpy(hAnalysisHybFilter->bufferHFImag[hAnalysisHybFilter->bufferHFpos], &pQmfImag[nrQmfBandsLF], (hAnalysisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL));
|
||||
|
||||
if (++hAnalysisHybFilter->bufferHFpos>=hAnalysisHybFilter->pSetup->filterDelay) hAnalysisHybFilter->bufferHFpos = 0;
|
||||
}
|
||||
} /* process HF part*/
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
INT FDKhybridAnalysisClose(
|
||||
HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter
|
||||
)
|
||||
{
|
||||
INT err = 0;
|
||||
|
||||
if (hAnalysisHybFilter != NULL) {
|
||||
hAnalysisHybFilter->pLFmemory = NULL;
|
||||
hAnalysisHybFilter->pHFmemory = NULL;
|
||||
hAnalysisHybFilter->LFmemorySize = 0;
|
||||
hAnalysisHybFilter->HFmemorySize = 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
INT FDKhybridSynthesisInit(
|
||||
HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter,
|
||||
const FDK_HYBRID_MODE mode,
|
||||
const INT qmfBands,
|
||||
const INT cplxBands
|
||||
)
|
||||
{
|
||||
INT err = 0;
|
||||
HANDLE_FDK_HYBRID_SETUP setup = NULL;
|
||||
|
||||
switch (mode) {
|
||||
case THREE_TO_TEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_10; break;
|
||||
case THREE_TO_TWELVE: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_12; break;
|
||||
case THREE_TO_SIXTEEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_16; break;
|
||||
default: err = -1; goto bail;
|
||||
}
|
||||
|
||||
hSynthesisHybFilter->pSetup = setup;
|
||||
hSynthesisHybFilter->nrBands = qmfBands;
|
||||
hSynthesisHybFilter->cplxBands = cplxBands;
|
||||
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
)
|
||||
{
|
||||
int k, n, hybOffset=0;
|
||||
INT err = 0;
|
||||
const INT nrQmfBandsLF = hSynthesisHybFilter->pSetup->nrQmfBands;
|
||||
|
||||
/*
|
||||
* LF buffer.
|
||||
*/
|
||||
for (k=0; k<nrQmfBandsLF; k++) {
|
||||
const int nHybBands = hSynthesisHybFilter->pSetup->nHybBands[k];
|
||||
|
||||
FIXP_DBL accu1 = FL2FXCONST_DBL(0.f);
|
||||
FIXP_DBL accu2 = FL2FXCONST_DBL(0.f);
|
||||
|
||||
/* Perform hybrid filtering. */
|
||||
for (n=0; n<nHybBands; n++) {
|
||||
accu1 += pHybridReal[hybOffset+n];
|
||||
accu2 += pHybridImag[hybOffset+n];
|
||||
}
|
||||
pQmfReal[k] = accu1;
|
||||
pQmfImag[k] = accu2;
|
||||
|
||||
hybOffset += nHybBands;
|
||||
}
|
||||
|
||||
if (hSynthesisHybFilter->nrBands > nrQmfBandsLF) {
|
||||
/*
|
||||
* HF buffer.
|
||||
*/
|
||||
FDKmemcpy(&pQmfReal[nrQmfBandsLF], &pHybridReal[hybOffset], (hSynthesisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL));
|
||||
FDKmemcpy(&pQmfImag[nrQmfBandsLF], &pHybridImag[hybOffset], (hSynthesisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* **** FILTERBANK **** */
|
||||
|
||||
/*
|
||||
2 channel filter
|
||||
Filter Coefs:
|
||||
0.0,
|
||||
0.01899487526049,
|
||||
0.0,
|
||||
-0.07293139167538,
|
||||
0.0,
|
||||
0.30596630545168,
|
||||
0.5,
|
||||
0.30596630545168,
|
||||
0.0,
|
||||
-0.07293139167538,
|
||||
0.0,
|
||||
0.01899487526049,
|
||||
0.0
|
||||
|
||||
|
||||
Filter design:
|
||||
h[q,n] = g[n] * cos(2pi/2 * q * (n-6) ); n = 0..12, q = 0,1;
|
||||
|
||||
-> h[0,n] = g[n] * 1;
|
||||
-> h[1,n] = g[n] * pow(-1,n);
|
||||
*/
|
||||
static void dualChannelFiltering(
|
||||
const FIXP_DBL *const pQmfReal,
|
||||
const FIXP_DBL *const pQmfImag,
|
||||
const INT *const pReadIdx,
|
||||
FIXP_DBL *const mHybridReal,
|
||||
FIXP_DBL *const mHybridImag,
|
||||
const INT invert
|
||||
)
|
||||
{
|
||||
const FIXP_HTB *p = HybFilterCoef2;
|
||||
|
||||
FIXP_DBL r1, r6;
|
||||
FIXP_DBL i1, i6;
|
||||
|
||||
/* symmetric filter coefficients */
|
||||
r1 = fMultDiv2(p[1], pQmfReal[pReadIdx[1]]) + fMultDiv2(p[1], pQmfReal[pReadIdx[11]]) ;
|
||||
i1 = fMultDiv2(p[1], pQmfImag[pReadIdx[1]]) + fMultDiv2(p[1], pQmfImag[pReadIdx[11]]) ;
|
||||
r1 += fMultDiv2(p[3], pQmfReal[pReadIdx[3]]) + fMultDiv2(p[3], pQmfReal[pReadIdx[ 9]]) ;
|
||||
i1 += fMultDiv2(p[3], pQmfImag[pReadIdx[3]]) + fMultDiv2(p[3], pQmfImag[pReadIdx[ 9]]) ;
|
||||
r1 += fMultDiv2(p[5], pQmfReal[pReadIdx[5]]) + fMultDiv2(p[5], pQmfReal[pReadIdx[ 7]]) ;
|
||||
i1 += fMultDiv2(p[5], pQmfImag[pReadIdx[5]]) + fMultDiv2(p[5], pQmfImag[pReadIdx[ 7]]) ;
|
||||
r6 = fMultDiv2(p[6], pQmfReal[pReadIdx[6]]) ;
|
||||
i6 = fMultDiv2(p[6], pQmfImag[pReadIdx[6]]) ;
|
||||
|
||||
if (invert) {
|
||||
mHybridReal[1] = (r1 + r6) << 1;
|
||||
mHybridImag[1] = (i1 + i6) << 1;
|
||||
|
||||
mHybridReal[0] = (r6 - r1) << 1;
|
||||
mHybridImag[0] = (i6 - i1) << 1;
|
||||
}
|
||||
else {
|
||||
mHybridReal[0] = (r1 + r6) << 1;
|
||||
mHybridImag[0] = (i1 + i6) << 1;
|
||||
|
||||
mHybridReal[1] = (r6 - r1) << 1;
|
||||
mHybridImag[1] = (i6 - i1) << 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void fourChannelFiltering(
|
||||
const FIXP_DBL *const pQmfReal,
|
||||
const FIXP_DBL *const pQmfImag,
|
||||
const INT *const pReadIdx,
|
||||
FIXP_DBL *const mHybridReal,
|
||||
FIXP_DBL *const mHybridImag,
|
||||
const INT invert
|
||||
)
|
||||
{
|
||||
const FIXP_HTB *p = HybFilterCoef4;
|
||||
|
||||
FIXP_DBL fft[8];
|
||||
|
||||
static const FIXP_DBL cr[13] = {
|
||||
FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( -1.f),
|
||||
FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL( 0.70710678118655f),
|
||||
FL2FXCONST_DBL( 1.f),
|
||||
FL2FXCONST_DBL( 0.70710678118655f), FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL(-0.70710678118655f),
|
||||
FL2FXCONST_DBL( -1.f), FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( 0.f)
|
||||
};
|
||||
static const FIXP_DBL ci[13] = {
|
||||
FL2FXCONST_DBL( -1.f), FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( 0.f),
|
||||
FL2FXCONST_DBL( 0.70710678118655f), FL2FXCONST_DBL( 1.f), FL2FXCONST_DBL( 0.70710678118655f),
|
||||
FL2FXCONST_DBL( 0.f),
|
||||
FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( -1.f), FL2FXCONST_DBL(-0.70710678118655f),
|
||||
FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL( 0.70710678118655f), FL2FXCONST_DBL( 1.f)
|
||||
};
|
||||
|
||||
|
||||
/* FIR filter. */
|
||||
/* pre twiddeling with pre-twiddling coefficients c[n] */
|
||||
/* multiplication with filter coefficients p[n] */
|
||||
/* hint: (a + ib)*(c + id) = (a*c - b*d) + i(a*d + b*c) */
|
||||
/* write to fft coefficient n' */
|
||||
fft[FFT_IDX_R(0)] = ( fMult(p[10], ( fMultSub(fMultDiv2(cr[ 2], pQmfReal[pReadIdx[ 2]]), ci[ 2], pQmfImag[pReadIdx[ 2]]))) +
|
||||
fMult(p[ 6], ( fMultSub(fMultDiv2(cr[ 6], pQmfReal[pReadIdx[ 6]]), ci[ 6], pQmfImag[pReadIdx[ 6]]))) +
|
||||
fMult(p[ 2], ( fMultSub(fMultDiv2(cr[10], pQmfReal[pReadIdx[10]]), ci[10], pQmfImag[pReadIdx[10]]))) );
|
||||
fft[FFT_IDX_I(0)] = ( fMult(p[10], ( fMultAdd(fMultDiv2(ci[ 2], pQmfReal[pReadIdx[ 2]]), cr[ 2], pQmfImag[pReadIdx[ 2]]))) +
|
||||
fMult(p[ 6], ( fMultAdd(fMultDiv2(ci[ 6], pQmfReal[pReadIdx[ 6]]), cr[ 6], pQmfImag[pReadIdx[ 6]]))) +
|
||||
fMult(p[ 2], ( fMultAdd(fMultDiv2(ci[10], pQmfReal[pReadIdx[10]]), cr[10], pQmfImag[pReadIdx[10]]))) );
|
||||
|
||||
/* twiddle dee dum */
|
||||
fft[FFT_IDX_R(1)] = ( fMult(p[ 9], ( fMultSub(fMultDiv2(cr[ 3], pQmfReal[pReadIdx[ 3]]), ci[ 3], pQmfImag[pReadIdx[ 3]]))) +
|
||||
fMult(p[ 5], ( fMultSub(fMultDiv2(cr[ 7], pQmfReal[pReadIdx[ 7]]), ci[ 7], pQmfImag[pReadIdx[ 7]]))) +
|
||||
fMult(p[ 1], ( fMultSub(fMultDiv2(cr[11], pQmfReal[pReadIdx[11]]), ci[11], pQmfImag[pReadIdx[11]]))) );
|
||||
fft[FFT_IDX_I(1)] = ( fMult(p[ 9], ( fMultAdd(fMultDiv2(ci[ 3], pQmfReal[pReadIdx[ 3]]), cr[ 3], pQmfImag[pReadIdx[ 3]]))) +
|
||||
fMult(p[ 5], ( fMultAdd(fMultDiv2(ci[ 7], pQmfReal[pReadIdx[ 7]]), cr[ 7], pQmfImag[pReadIdx[ 7]]))) +
|
||||
fMult(p[ 1], ( fMultAdd(fMultDiv2(ci[11], pQmfReal[pReadIdx[11]]), cr[11], pQmfImag[pReadIdx[11]]))) );
|
||||
|
||||
/* twiddle dee dee */
|
||||
fft[FFT_IDX_R(2)] = ( fMult(p[12], ( fMultSub(fMultDiv2(cr[ 0], pQmfReal[pReadIdx[ 0]]), ci[ 0], pQmfImag[pReadIdx[ 0]]))) +
|
||||
fMult(p[ 8], ( fMultSub(fMultDiv2(cr[ 4], pQmfReal[pReadIdx[ 4]]), ci[ 4], pQmfImag[pReadIdx[ 4]]))) +
|
||||
fMult(p[ 4], ( fMultSub(fMultDiv2(cr[ 8], pQmfReal[pReadIdx[ 8]]), ci[ 8], pQmfImag[pReadIdx[ 8]]))) +
|
||||
fMult(p[ 0], ( fMultSub(fMultDiv2(cr[12], pQmfReal[pReadIdx[12]]), ci[12], pQmfImag[pReadIdx[12]]))) );
|
||||
fft[FFT_IDX_I(2)] = ( fMult(p[12], ( fMultAdd(fMultDiv2(ci[ 0], pQmfReal[pReadIdx[ 0]]), cr[ 0], pQmfImag[pReadIdx[ 0]]))) +
|
||||
fMult(p[ 8], ( fMultAdd(fMultDiv2(ci[ 4], pQmfReal[pReadIdx[ 4]]), cr[ 4], pQmfImag[pReadIdx[ 4]]))) +
|
||||
fMult(p[ 4], ( fMultAdd(fMultDiv2(ci[ 8], pQmfReal[pReadIdx[ 8]]), cr[ 8], pQmfImag[pReadIdx[ 8]]))) +
|
||||
fMult(p[ 0], ( fMultAdd(fMultDiv2(ci[12], pQmfReal[pReadIdx[12]]), cr[12], pQmfImag[pReadIdx[12]]))) );
|
||||
|
||||
fft[FFT_IDX_R(3)] = ( fMult(p[11], ( fMultSub(fMultDiv2(cr[ 1], pQmfReal[pReadIdx[ 1]]), ci[ 1], pQmfImag[pReadIdx[ 1]]))) +
|
||||
fMult(p[ 7], ( fMultSub(fMultDiv2(cr[ 5], pQmfReal[pReadIdx[ 5]]), ci[ 5], pQmfImag[pReadIdx[ 5]]))) +
|
||||
fMult(p[ 3], ( fMultSub(fMultDiv2(cr[ 9], pQmfReal[pReadIdx[ 9]]), ci[ 9], pQmfImag[pReadIdx[ 9]]))) );
|
||||
fft[FFT_IDX_I(3)] = ( fMult(p[11], ( fMultAdd(fMultDiv2(ci[ 1], pQmfReal[pReadIdx[ 1]]), cr[ 1], pQmfImag[pReadIdx[ 1]]))) +
|
||||
fMult(p[ 7], ( fMultAdd(fMultDiv2(ci[ 5], pQmfReal[pReadIdx[ 5]]), cr[ 5], pQmfImag[pReadIdx[ 5]]))) +
|
||||
fMult(p[ 3], ( fMultAdd(fMultDiv2(ci[ 9], pQmfReal[pReadIdx[ 9]]), cr[ 9], pQmfImag[pReadIdx[ 9]]))) );
|
||||
|
||||
/* fft modulation */
|
||||
/* here: fast manual fft modulation for a fft of length M=4 */
|
||||
/* fft_4{x[n]} = x[0]*exp(-i*2*pi/4*m*0) + x[1]*exp(-i*2*pi/4*m*1) +
|
||||
x[2]*exp(-i*2*pi/4*m*2) + x[3]*exp(-i*2*pi/4*m*3) */
|
||||
|
||||
/*
|
||||
fft bin m=0:
|
||||
X[0, n] = x[0] + x[1] + x[2] + x[3]
|
||||
*/
|
||||
mHybridReal[0] = fft[FFT_IDX_R(0)] + fft[FFT_IDX_R(1)] + fft[FFT_IDX_R(2)] + fft[FFT_IDX_R(3)];
|
||||
mHybridImag[0] = fft[FFT_IDX_I(0)] + fft[FFT_IDX_I(1)] + fft[FFT_IDX_I(2)] + fft[FFT_IDX_I(3)];
|
||||
|
||||
/*
|
||||
fft bin m=1:
|
||||
X[1, n] = x[0] - i*x[1] - x[2] + i*x[3]
|
||||
*/
|
||||
mHybridReal[1] = fft[FFT_IDX_R(0)] + fft[FFT_IDX_I(1)] - fft[FFT_IDX_R(2)] - fft[FFT_IDX_I(3)];
|
||||
mHybridImag[1] = fft[FFT_IDX_I(0)] - fft[FFT_IDX_R(1)] - fft[FFT_IDX_I(2)] + fft[FFT_IDX_R(3)];
|
||||
|
||||
/*
|
||||
fft bin m=2:
|
||||
X[2, n] = x[0] - x[1] + x[2] - x[3]
|
||||
*/
|
||||
mHybridReal[2] = fft[FFT_IDX_R(0)] - fft[FFT_IDX_R(1)] + fft[FFT_IDX_R(2)] - fft[FFT_IDX_R(3)];
|
||||
mHybridImag[2] = fft[FFT_IDX_I(0)] - fft[FFT_IDX_I(1)] + fft[FFT_IDX_I(2)] - fft[FFT_IDX_I(3)];
|
||||
|
||||
/*
|
||||
fft bin m=3:
|
||||
X[3, n] = x[0] + j*x[1] - x[2] - j*x[3]
|
||||
*/
|
||||
mHybridReal[3] = fft[FFT_IDX_R(0)] - fft[FFT_IDX_I(1)] - fft[FFT_IDX_R(2)] + fft[FFT_IDX_I(3)];
|
||||
mHybridImag[3] = fft[FFT_IDX_I(0)] + fft[FFT_IDX_R(1)] - fft[FFT_IDX_I(2)] - fft[FFT_IDX_R(3)];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
8 channel filter
|
||||
|
||||
Implementation using a FFT of length 8
|
||||
|
||||
prototype filter coefficients:
|
||||
0.00746082949812 0.02270420949825 0.04546865930473 0.07266113929591 0.09885108575264 0.11793710567217
|
||||
0.125
|
||||
0.11793710567217 0.09885108575264 0.07266113929591 0.04546865930473 0.02270420949825 0.00746082949812
|
||||
|
||||
Filter design:
|
||||
N = 13; Q = 8;
|
||||
h[q,n] = g[n] * exp(j * 2 * pi / Q * (q + .5) * (n - 6)); n = 0..(N-1), q = 0..(Q-1);
|
||||
|
||||
Time Signal: x[t];
|
||||
Filter Bank Output
|
||||
y[q,t] = conv(x[t],h[q,t]) = conv(h[q,t],x[t]) = sum(x[k] * h[q, t - k] ) = sum(h[q, k] * x[t - k] ); k = 0..(N-1);
|
||||
|
||||
y[q,t] = x[t - 12]*h[q, 12] + x[t - 11]*h[q, 11] + x[t - 10]*h[q, 10] + x[t - 9]*h[q, 9]
|
||||
+ x[t - 8]*h[q, 8] + x[t - 7]*h[q, 7]
|
||||
+ x[t - 6]*h[q, 6]
|
||||
+ x[t - 5]*h[q, 5] + x[t - 4]*h[q, 4]
|
||||
+ x[t - 3]*h[q, 3] + x[t - 2]*h[q, 2] + x[t - 1]*h[q, 1] + x[t - 0]*h[q, 0];
|
||||
|
||||
h'[q, n] = h[q,(N-1)-n] = g[n] * exp(j * 2 * pi / Q * (q + .5) * (6 - n)); n = 0..(N-1), q = 0..(Q-1);
|
||||
|
||||
y[q,t] = x[t - 12]*h'[q, 0] + x[t - 11]*h'[q, 1] + x[t - 10]*h'[q, 2] + x[t - 9]*h'[q, 3]
|
||||
+ x[t - 8]*h'[q, 4] + x[t - 7]*h'[q, 5]
|
||||
+ x[t - 6]*h'[q, 6]
|
||||
+ x[t - 5]*h'[q, 7] + x[t - 4]*h'[q, 8]
|
||||
+ x[t - 3]*h'[q, 9] + x[t - 2]*h'[q, 10] + x[t - 1]*h'[q, 11] + x[t - 0]*h'[q, 12];
|
||||
|
||||
Try to split off FFT Modulation Term:
|
||||
FFT(x[t], q) = sum(x[t+k]*exp(-j*2*pi/N *q * k))
|
||||
c m
|
||||
Step 1: h'[q,n] = g[n] * ( exp(j * 2 * pi / 8 * .5 * (6 - n)) ) * ( exp (j * 2 * pi / 8 * q * (6 - n)) );
|
||||
|
||||
h'[q,n] = g[n] *c[n] * m[q,n]; (see above)
|
||||
c[n] = exp( j * 2 * pi / 8 * .5 * (6 - n) );
|
||||
m[q,n] = exp( j * 2 * pi / 8 * q * (6 - n) );
|
||||
|
||||
y[q,t] = x[t - 0]*g[0]*c[0]*m[q,0] + x[t - 1]*g[1]*c[ 1]*m[q, 1] + ...
|
||||
... + x[t - 12]*g[2]*c[12]*m[q,12];
|
||||
|
||||
|
|
||||
n m *exp(-j*2*pi) | n' fft
|
||||
-------------------------------------------------------------------------------------------------------------------------
|
||||
0 exp( j * 2 * pi / 8 * q * 6) -> exp(-j * 2 * pi / 8 * q * 2) | 2 exp(-j * 2 * pi / 8 * q * 0)
|
||||
1 exp( j * 2 * pi / 8 * q * 5) -> exp(-j * 2 * pi / 8 * q * 3) | 3 exp(-j * 2 * pi / 8 * q * 1)
|
||||
2 exp( j * 2 * pi / 8 * q * 4) -> exp(-j * 2 * pi / 8 * q * 4) | 4 exp(-j * 2 * pi / 8 * q * 2)
|
||||
3 exp( j * 2 * pi / 8 * q * 3) -> exp(-j * 2 * pi / 8 * q * 5) | 5 exp(-j * 2 * pi / 8 * q * 3)
|
||||
4 exp( j * 2 * pi / 8 * q * 2) -> exp(-j * 2 * pi / 8 * q * 6) | 6 exp(-j * 2 * pi / 8 * q * 4)
|
||||
5 exp( j * 2 * pi / 8 * q * 1) -> exp(-j * 2 * pi / 8 * q * 7) | 7 exp(-j * 2 * pi / 8 * q * 5)
|
||||
6 exp( j * 2 * pi / 8 * q * 0) | 0 exp(-j * 2 * pi / 8 * q * 6)
|
||||
7 exp(-j * 2 * pi / 8 * q * 1) | 1 exp(-j * 2 * pi / 8 * q * 7)
|
||||
8 exp(-j * 2 * pi / 8 * q * 2) | 2
|
||||
9 exp(-j * 2 * pi / 8 * q * 3) | 3
|
||||
10 exp(-j * 2 * pi / 8 * q * 4) | 4
|
||||
11 exp(-j * 2 * pi / 8 * q * 5) | 5
|
||||
12 exp(-j * 2 * pi / 8 * q * 6) | 6
|
||||
|
||||
|
||||
now use fft modulation coefficients
|
||||
m[6] = = fft[0]
|
||||
m[7] = = fft[1]
|
||||
m[8] = m[ 0] = fft[2]
|
||||
m[9] = m[ 1] = fft[3]
|
||||
m[10] = m[ 2] = fft[4]
|
||||
m[11] = m[ 3] = fft[5]
|
||||
m[12] = m[ 4] = fft[6]
|
||||
m[ 5] = fft[7]
|
||||
|
||||
y[q,t] = ( x[t- 6]*g[ 6]*c[ 6] ) * fft[q,0] +
|
||||
( x[t- 7]*g[ 7]*c[ 7] ) * fft[q,1] +
|
||||
( x[t- 0]*g[ 0]*c[ 0] + x[t- 8]*g[ 8]*c[ 8] ) * fft[q,2] +
|
||||
( x[t- 1]*g[ 1]*c[ 1] + x[t- 9]*g[ 9]*c[ 9] ) * fft[q,3] +
|
||||
( x[t- 2]*g[ 2]*c[ 2] + x[t-10]*g[10]*c[10] ) * fft[q,4] +
|
||||
( x[t- 3]*g[ 3]*c[ 3] + x[t-11]*g[11]*c[11] ) * fft[q,5] +
|
||||
( x[t- 4]*g[ 4]*c[ 4] + x[t-12]*g[12]*c[12] ) * fft[q,6] +
|
||||
( x[t- 5]*g[ 5]*c[ 5] ) * fft[q,7];
|
||||
|
||||
pre twiddle factors c[n] = exp(j * 2 * pi / 8 * .5 * (6 - n));
|
||||
n c] | n c[n] | n c[n]
|
||||
---------------------------------------------------------------------------------------------------
|
||||
0 exp( j * 6 * pi / 8) | 1 exp( j * 5 * pi / 8) | 2 exp( j * 4 * pi / 8)
|
||||
3 exp( j * 3 * pi / 8) | 4 exp( j * 2 * pi / 8) | 5 exp( j * 1 * pi / 8)
|
||||
6 exp( j * 0 * pi / 8) | 7 exp(-j * 1 * pi / 8) | 8 exp(-j * 2 * pi / 8)
|
||||
9 exp(-j * 3 * pi / 8) | 10 exp(-j * 4 * pi / 8) | 11 exp(-j * 5 * pi / 8)
|
||||
12 exp(-j * 6 * pi / 8) | |
|
||||
|
||||
*/
|
||||
static void eightChannelFiltering(
|
||||
const FIXP_DBL *const pQmfReal,
|
||||
const FIXP_DBL *const pQmfImag,
|
||||
const INT *const pReadIdx,
|
||||
FIXP_DBL *const mHybridReal,
|
||||
FIXP_DBL *const mHybridImag,
|
||||
const INT invert
|
||||
)
|
||||
{
|
||||
const FIXP_HTP *p = HybFilterCoef8;
|
||||
INT k, sc;
|
||||
|
||||
FIXP_DBL mfft[16+ALIGNMENT_DEFAULT];
|
||||
FIXP_DBL *pfft = (FIXP_DBL*)ALIGN_PTR(mfft);
|
||||
|
||||
FIXP_DBL accu1, accu2, accu3, accu4;
|
||||
|
||||
/* pre twiddeling */
|
||||
pfft[FFT_IDX_R(0)] = fMultDiv2(p[0].v.re, pQmfReal[pReadIdx[6]]);
|
||||
pfft[FFT_IDX_I(0)] = fMultDiv2(p[0].v.re, pQmfImag[pReadIdx[6]]);
|
||||
|
||||
cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[7]], pQmfImag[pReadIdx[7]], p[1]);
|
||||
pfft[FFT_IDX_R(1)] = accu1;
|
||||
pfft[FFT_IDX_I(1)] = accu2;
|
||||
|
||||
cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[0]], pQmfImag[pReadIdx[0]], p[2]);
|
||||
cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[8]], pQmfImag[pReadIdx[8]], p[3]);
|
||||
pfft[FFT_IDX_R(2)] = accu1 + accu3;
|
||||
pfft[FFT_IDX_I(2)] = accu2 + accu4;
|
||||
|
||||
cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[1]], pQmfImag[pReadIdx[1]], p[4]);
|
||||
cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[9]], pQmfImag[pReadIdx[9]], p[5]);
|
||||
pfft[FFT_IDX_R(3)] = accu1 + accu3;
|
||||
pfft[FFT_IDX_I(3)] = accu2 + accu4;
|
||||
|
||||
pfft[FFT_IDX_R(4)] = fMultDiv2(pQmfImag[pReadIdx[10]], p[7].v.im) - fMultDiv2(pQmfImag[pReadIdx[ 2]], p[6].v.im);
|
||||
pfft[FFT_IDX_I(4)] = fMultDiv2(pQmfReal[pReadIdx[ 2]], p[6].v.im) - fMultDiv2(pQmfReal[pReadIdx[10]], p[7].v.im);
|
||||
|
||||
cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[ 3]], pQmfImag[pReadIdx[ 3]], p[8]);
|
||||
cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[11]], pQmfImag[pReadIdx[11]], p[9]);
|
||||
pfft[FFT_IDX_R(5)] = accu1 + accu3;
|
||||
pfft[FFT_IDX_I(5)] = accu2 + accu4;
|
||||
|
||||
cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[ 4]], pQmfImag[pReadIdx[ 4]], p[10]);
|
||||
cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[12]], pQmfImag[pReadIdx[12]], p[11]);
|
||||
pfft[FFT_IDX_R(6)] = accu1 + accu3;
|
||||
pfft[FFT_IDX_I(6)] = accu2 + accu4;
|
||||
|
||||
cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[ 5]], pQmfImag[pReadIdx[ 5]], p[12]);
|
||||
pfft[FFT_IDX_R(7)] = accu1;
|
||||
pfft[FFT_IDX_I(7)] = accu2;
|
||||
|
||||
/* fft modulation */
|
||||
fft_8 (pfft);
|
||||
sc = 1 + 2;
|
||||
|
||||
if (invert) {
|
||||
mHybridReal[0] = pfft[FFT_IDX_R(7)] << sc;
|
||||
mHybridImag[0] = pfft[FFT_IDX_I(7)] << sc;
|
||||
mHybridReal[1] = pfft[FFT_IDX_R(0)] << sc;
|
||||
mHybridImag[1] = pfft[FFT_IDX_I(0)] << sc;
|
||||
|
||||
mHybridReal[2] = pfft[FFT_IDX_R(6)] << sc;
|
||||
mHybridImag[2] = pfft[FFT_IDX_I(6)] << sc;
|
||||
mHybridReal[3] = pfft[FFT_IDX_R(1)] << sc;
|
||||
mHybridImag[3] = pfft[FFT_IDX_I(1)] << sc;
|
||||
|
||||
mHybridReal[4] = pfft[FFT_IDX_R(2)] << sc;
|
||||
mHybridReal[4] += pfft[FFT_IDX_R(5)] << sc;
|
||||
mHybridImag[4] = pfft[FFT_IDX_I(2)] << sc;
|
||||
mHybridImag[4] += pfft[FFT_IDX_I(5)] << sc;
|
||||
|
||||
mHybridReal[5] = pfft[FFT_IDX_R(3)] << sc;
|
||||
mHybridReal[5] += pfft[FFT_IDX_R(4)] << sc;
|
||||
mHybridImag[5] = pfft[FFT_IDX_I(3)] << sc;
|
||||
mHybridImag[5] += pfft[FFT_IDX_I(4)] << sc;
|
||||
}
|
||||
else {
|
||||
for(k=0; k<8;k++ ) {
|
||||
mHybridReal[k] = pfft[FFT_IDX_R(k)] << sc;
|
||||
mHybridImag[k] = pfft[FFT_IDX_I(k)] << sc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static INT kChannelFiltering(
|
||||
const FIXP_DBL *const pQmfReal,
|
||||
const FIXP_DBL *const pQmfImag,
|
||||
const INT *const pReadIdx,
|
||||
FIXP_DBL *const mHybridReal,
|
||||
FIXP_DBL *const mHybridImag,
|
||||
const SCHAR hybridConfig
|
||||
)
|
||||
{
|
||||
INT err = 0;
|
||||
|
||||
switch (hybridConfig) {
|
||||
case 2:
|
||||
case -2:
|
||||
dualChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, mHybridImag, (hybridConfig<0) ? 1 : 0 );
|
||||
break;
|
||||
case 4:
|
||||
case -4:
|
||||
fourChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, mHybridImag, (hybridConfig<0) ? 1 : 0 );
|
||||
break;
|
||||
case 8:
|
||||
case -8:
|
||||
eightChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, mHybridImag, (hybridConfig<0) ? 1 : 0 );
|
||||
break;
|
||||
default:
|
||||
err = -1;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -27,7 +27,7 @@
|
||||
******************************************************************************/
|
||||
/*!
|
||||
\file
|
||||
\brief PS parameter extraction, encoding functions $Revision: 36847 $
|
||||
\brief PS parameter extraction, encoding functions $Revision: 37142 $
|
||||
*/
|
||||
|
||||
#include "ps_main.h"
|
||||
@ -43,7 +43,6 @@
|
||||
|
||||
#include "genericStds.h"
|
||||
|
||||
|
||||
inline void FDKsbrEnc_addFIXP_DBL(const FIXP_DBL *X, const FIXP_DBL *Y, FIXP_DBL *Z, INT n)
|
||||
{
|
||||
for (INT i=0; i<n; i++)
|
||||
@ -78,7 +77,6 @@ static const INT subband2parameter20[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES] =
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef enum {
|
||||
MAX_TIME_DIFF_FRAMES = 20,
|
||||
MAX_PS_NOHEADER_CNT = 10,
|
||||
@ -106,54 +104,17 @@ static const FIXP_DBL iccQuant[8] = {
|
||||
0x7fffffff, 0x77ef9d7f, 0x6babc97f, 0x4ceaf27f, 0x2f0ed3c0, 0x00000000, 0xb49ba601, 0x80000000
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
name: static HANDLE_ERROR_INFO CreatePSData()
|
||||
description: Creates struct (buffer) to store ps data
|
||||
returns: error code of type HANDLE_ERROR_INFO
|
||||
input: none
|
||||
output: - HANDLE_PS_DATA *hPsData: according handle
|
||||
*/
|
||||
static HANDLE_ERROR_INFO CreatePSData(HANDLE_PS_DATA *hPsData)
|
||||
static FDK_PSENC_ERROR InitPSData(
|
||||
HANDLE_PS_DATA hPsData
|
||||
)
|
||||
{
|
||||
HANDLE_ERROR_INFO error = noError;
|
||||
FDK_PSENC_ERROR error = PSENC_OK;
|
||||
|
||||
*hPsData = GetRam_PsData();
|
||||
if (*hPsData==NULL) {
|
||||
error = 1;
|
||||
goto bail;
|
||||
if(hPsData == NULL) {
|
||||
error = PSENC_INVALID_HANDLE;
|
||||
}
|
||||
FDKmemclear(*hPsData,sizeof(PS_DATA));
|
||||
|
||||
bail:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
name: static HANDLE_ERROR_INFO DestroyPSData()
|
||||
description: frees according data handle
|
||||
returns: error code of type HANDLE_ERROR_INFO
|
||||
input: - HANDLE_PS_DATA *hPsData
|
||||
output: none
|
||||
*/
|
||||
static HANDLE_ERROR_INFO DestroyPSData(HANDLE_PS_DATA *phPsData)
|
||||
{
|
||||
FreeRam_PsData(phPsData);
|
||||
|
||||
return noError;
|
||||
}
|
||||
|
||||
|
||||
static HANDLE_ERROR_INFO InitPSData(HANDLE_PS_DATA hPsData)
|
||||
{
|
||||
INT i, env;
|
||||
HANDLE_ERROR_INFO error = noError;
|
||||
|
||||
if(hPsData != NULL){
|
||||
|
||||
else {
|
||||
int i, env;
|
||||
FDKmemclear(hPsData,sizeof(PS_DATA));
|
||||
|
||||
for (i=0; i<PS_MAX_BANDS; i++) {
|
||||
@ -182,8 +143,6 @@ static HANDLE_ERROR_INFO InitPSData(HANDLE_PS_DATA hPsData)
|
||||
hPsData->iidTimeCnt = MAX_TIME_DIFF_FRAMES;
|
||||
hPsData->iccTimeCnt = MAX_TIME_DIFF_FRAMES;
|
||||
hPsData->noEnvCnt = MAX_NOENV_CNT;
|
||||
} else {
|
||||
error = ERROR(CDI, "Unable to write to hPsData.");
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -226,9 +185,6 @@ static INT getICCMode(const INT nBands,
|
||||
case PS_BANDS_MID:
|
||||
mode = PS_RES_MID;
|
||||
break;
|
||||
case PS_BANDS_FINE:
|
||||
mode = PS_RES_FINE;
|
||||
break;
|
||||
default:
|
||||
mode = 0;
|
||||
}
|
||||
@ -252,9 +208,6 @@ static INT getIIDMode(const INT nBands,
|
||||
case PS_BANDS_MID:
|
||||
mode = PS_RES_MID;
|
||||
break;
|
||||
case PS_BANDS_FINE:
|
||||
mode = PS_RES_FINE;
|
||||
break;
|
||||
default:
|
||||
mode = 0;
|
||||
break;
|
||||
@ -339,7 +292,6 @@ static void processIidData(PS_DATA *psData,
|
||||
INT loudnDiff = 0;
|
||||
INT iidTransmit = 0;
|
||||
|
||||
|
||||
bitsIidFreq = bitsIidTime = 0;
|
||||
|
||||
/* Quantize IID coefficients */
|
||||
@ -348,7 +300,6 @@ static void processIidData(PS_DATA *psData,
|
||||
errIIDFine += quantizeCoef(iid[env], psBands, iidQuantFine_fx, 15, 31, iidIdxFine[env]);
|
||||
}
|
||||
|
||||
|
||||
/* normalize error to number of envelopes, ps bands
|
||||
errIID /= psBands*nEnvelopes;
|
||||
errIIDFine /= psBands*nEnvelopes; */
|
||||
@ -638,8 +589,8 @@ static void calculateIID(FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS],
|
||||
*/
|
||||
FIXP_DBL IID = fMultDiv2( FL2FXCONST_DBL(LOG10_2_10/IID_SCALE_FT), (ldPwrL[env][i]-ldPwrR[env][i]) );
|
||||
|
||||
IID = fixMin( IID, (FIXP_DBL)(FL2FXCONST_DBL( 1.f)>>(LD_DATA_SHIFT+1)) );
|
||||
IID = fixMax( IID, (FIXP_DBL)(FL2FXCONST_DBL(-1.f)>>(LD_DATA_SHIFT+1)) );
|
||||
IID = fixMin( IID, (FIXP_DBL)(MAXVAL_DBL>>(LD_DATA_SHIFT+1)) );
|
||||
IID = fixMax( IID, (FIXP_DBL)(MINVAL_DBL>>(LD_DATA_SHIFT+1)) );
|
||||
iid[env][i] = IID << (LD_DATA_SHIFT+1);
|
||||
}
|
||||
}
|
||||
@ -664,9 +615,6 @@ static void calculateICC(FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS],
|
||||
case PS_BANDS_MID:
|
||||
border = 11;
|
||||
break;
|
||||
case PS_BANDS_FINE:
|
||||
border = 16;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -748,70 +696,74 @@ void FDKsbrEnc_initPsBandNrgScale(HANDLE_PS_ENCODE hPsEncode)
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE_ERROR_INFO FDKsbrEnc_CreatePSEncode(HANDLE_PS_ENCODE *phPsEncode){
|
||||
FDK_PSENC_ERROR FDKsbrEnc_CreatePSEncode(
|
||||
HANDLE_PS_ENCODE *phPsEncode
|
||||
)
|
||||
{
|
||||
FDK_PSENC_ERROR error = PSENC_OK;
|
||||
|
||||
HANDLE_ERROR_INFO error = noError;
|
||||
|
||||
HANDLE_PS_ENCODE hPsEncode = GetRam_PsEncode();
|
||||
FDKmemclear(hPsEncode,sizeof(PS_ENCODE));
|
||||
|
||||
if(error == noError){
|
||||
if(noError != (error = CreatePSData(&hPsEncode->hPsData))){
|
||||
error = handBack(error);
|
||||
}
|
||||
if (phPsEncode==NULL) {
|
||||
error = PSENC_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
*phPsEncode = hPsEncode;
|
||||
|
||||
else {
|
||||
HANDLE_PS_ENCODE hPsEncode = NULL;
|
||||
if (NULL==(hPsEncode = GetRam_PsEncode())) {
|
||||
error = PSENC_MEMORY_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
FDKmemclear(hPsEncode,sizeof(PS_ENCODE));
|
||||
*phPsEncode = hPsEncode; /* return allocated handle */
|
||||
}
|
||||
bail:
|
||||
return error;
|
||||
}
|
||||
|
||||
HANDLE_ERROR_INFO FDKsbrEnc_InitPSEncode(HANDLE_PS_ENCODE hPsEncode, const PS_BANDS psEncMode, const FIXP_DBL iidQuantErrorThreshold){
|
||||
FDK_PSENC_ERROR FDKsbrEnc_InitPSEncode(
|
||||
HANDLE_PS_ENCODE hPsEncode,
|
||||
const PS_BANDS psEncMode,
|
||||
const FIXP_DBL iidQuantErrorThreshold
|
||||
)
|
||||
{
|
||||
FDK_PSENC_ERROR error = PSENC_OK;
|
||||
|
||||
HANDLE_ERROR_INFO error = noError;
|
||||
|
||||
if(error == noError){
|
||||
if(noError != (InitPSData(hPsEncode->hPsData))){
|
||||
error = handBack(error);
|
||||
}
|
||||
if (NULL==hPsEncode) {
|
||||
error = PSENC_INVALID_HANDLE;
|
||||
}
|
||||
else {
|
||||
if (PSENC_OK != (InitPSData(&hPsEncode->psData))) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if(error == noError){
|
||||
switch(psEncMode){
|
||||
case PS_BANDS_COARSE:
|
||||
case PS_BANDS_MID:
|
||||
hPsEncode->nQmfIidGroups = QMF_GROUPS_LO_RES;
|
||||
hPsEncode->nSubQmfIidGroups = SUBQMF_GROUPS_LO_RES;
|
||||
FDKmemcpy(hPsEncode->iidGroupBorders, iidGroupBordersLoRes, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups + 1)*sizeof(INT));
|
||||
FDKmemcpy(hPsEncode->subband2parameterIndex, subband2parameter20, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) *sizeof(INT));
|
||||
FDKmemcpy(hPsEncode->iidGroupWidthLd, iidGroupWidthLdLoRes, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) *sizeof(UCHAR));
|
||||
break;
|
||||
case PS_BANDS_FINE:
|
||||
FDK_ASSERT(0); /* we don't support this mode! */
|
||||
|
||||
break;
|
||||
default:
|
||||
error = ERROR(CDI, "Invalid stereo band configuration.");
|
||||
break;
|
||||
case PS_BANDS_COARSE:
|
||||
case PS_BANDS_MID:
|
||||
hPsEncode->nQmfIidGroups = QMF_GROUPS_LO_RES;
|
||||
hPsEncode->nSubQmfIidGroups = SUBQMF_GROUPS_LO_RES;
|
||||
FDKmemcpy(hPsEncode->iidGroupBorders, iidGroupBordersLoRes, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups + 1)*sizeof(INT));
|
||||
FDKmemcpy(hPsEncode->subband2parameterIndex, subband2parameter20, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) *sizeof(INT));
|
||||
FDKmemcpy(hPsEncode->iidGroupWidthLd, iidGroupWidthLdLoRes, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) *sizeof(UCHAR));
|
||||
break;
|
||||
default:
|
||||
error = PSENC_INIT_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
if(error == noError){
|
||||
hPsEncode->psEncMode = psEncMode;
|
||||
hPsEncode->iidQuantErrorThreshold = iidQuantErrorThreshold;
|
||||
FDKsbrEnc_initPsBandNrgScale(hPsEncode);
|
||||
}
|
||||
|
||||
bail:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
HANDLE_ERROR_INFO FDKsbrEnc_DestroyPSEncode(HANDLE_PS_ENCODE *phPsEncode){
|
||||
FDK_PSENC_ERROR FDKsbrEnc_DestroyPSEncode(
|
||||
HANDLE_PS_ENCODE *phPsEncode
|
||||
)
|
||||
{
|
||||
FDK_PSENC_ERROR error = PSENC_OK;
|
||||
|
||||
HANDLE_ERROR_INFO error = noError;
|
||||
|
||||
if(error == noError){
|
||||
DestroyPSData(&(*phPsEncode)->hPsData);
|
||||
if (NULL !=phPsEncode) {
|
||||
FreeRam_PsEncode(phPsEncode);
|
||||
}
|
||||
|
||||
@ -825,44 +777,42 @@ typedef struct {
|
||||
FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS];
|
||||
FIXP_DBL pwrCr[PS_MAX_ENVELOPES][PS_MAX_BANDS];
|
||||
FIXP_DBL pwrCi[PS_MAX_ENVELOPES][PS_MAX_BANDS];
|
||||
|
||||
} PS_PWR_DATA;
|
||||
|
||||
HANDLE_ERROR_INFO FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE RESTRICT hPsEncode,
|
||||
HANDLE_PS_OUT RESTRICT hPsOut,
|
||||
HANDLE_PS_CHANNEL_DATA RESTRICT hChanDatal,
|
||||
HANDLE_PS_CHANNEL_DATA RESTRICT hChanDatar,
|
||||
UCHAR *RESTRICT dynBandScale,
|
||||
UINT maxEnvelopes,
|
||||
const int sendHeader)
|
||||
|
||||
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
|
||||
)
|
||||
{
|
||||
HANDLE_ERROR_INFO error = noError;
|
||||
HANDLE_PS_DATA hPsData = hPsEncode->hPsData;
|
||||
HANDLE_PS_HYBRID_DATA hHybDatal = hChanDatal->hHybData;
|
||||
HANDLE_PS_HYBRID_DATA hHybDatar = hChanDatar->hHybData;
|
||||
FIXP_QMF **RESTRICT lr = NULL, **RESTRICT li = NULL, **RESTRICT rr = NULL, **RESTRICT ri = NULL;
|
||||
FDK_PSENC_ERROR error = PSENC_OK;
|
||||
|
||||
HANDLE_PS_DATA hPsData = &hPsEncode->psData;
|
||||
FIXP_DBL iid [PS_MAX_ENVELOPES][PS_MAX_BANDS];
|
||||
FIXP_DBL icc [PS_MAX_ENVELOPES][PS_MAX_BANDS];
|
||||
int envBorder[PS_MAX_ENVELOPES+1];
|
||||
|
||||
int group, bin, border, col, subband, band;
|
||||
int group, bin, col, subband, band;
|
||||
int i = 0;
|
||||
|
||||
int env = 0;
|
||||
int psBands = (int) hPsEncode->psEncMode;
|
||||
int frameSize = FDKsbrEnc_GetHybridFrameSize(hHybDatal); /* same as FDKsbrEnc_GetHybridFrameSize(hHybDatar) */
|
||||
int nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups;
|
||||
int nEnvelopes = fixMin(maxEnvelopes, (UINT)PS_MAX_ENVELOPES);
|
||||
|
||||
C_ALLOC_SCRATCH_START(pwrData, PS_PWR_DATA, 1);
|
||||
|
||||
|
||||
for(env=0; env<nEnvelopes+1;env++) {
|
||||
envBorder[env] = fMultI(GetInvInt(nEnvelopes),frameSize*env);
|
||||
}
|
||||
|
||||
for(env=0; env<nEnvelopes;env++) {
|
||||
INT nHybridQmfOffset = 0;
|
||||
int descale = 0;
|
||||
|
||||
/* clear energy array */
|
||||
for (band=0; band<psBands; band++) {
|
||||
@ -872,10 +822,6 @@ HANDLE_ERROR_INFO FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE RESTRICT hPsEncode,
|
||||
/**** calculate energies and correlation ****/
|
||||
|
||||
/* start with hybrid data */
|
||||
lr = hHybDatal->rHybData; li = hHybDatal->iHybData;
|
||||
rr = hHybDatar->rHybData; ri = hHybDatar->iHybData;
|
||||
UCHAR switched = 0;
|
||||
|
||||
for (group=0; group < nIidGroups; group++) {
|
||||
/* Translate group to bin */
|
||||
bin = hPsEncode->subband2parameterIndex[group];
|
||||
@ -885,30 +831,21 @@ HANDLE_ERROR_INFO FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE RESTRICT hPsEncode,
|
||||
bin >>= 1;
|
||||
}
|
||||
|
||||
if (!switched && group == hPsEncode->nSubQmfIidGroups) {
|
||||
/* switch to qmf data */
|
||||
lr = hChanDatal->hPsQmfData->rQmfData; li = hChanDatal->hPsQmfData->iQmfData;
|
||||
rr = hChanDatar->hPsQmfData->rQmfData; ri = hChanDatar->hPsQmfData->iQmfData;
|
||||
/* calc offset between hybrid subsubbands and qmf bands */
|
||||
nHybridQmfOffset = FDKsbrEnc_GetNumberHybridQmfBands(hHybDatal) - FDKsbrEnc_GetNumberHybridBands(hHybDatal);
|
||||
switched = 1;
|
||||
}
|
||||
|
||||
/* determine group border */
|
||||
int bScale = 2*descale + hPsEncode->psBandNrgScale[bin];
|
||||
border = hPsEncode->iidGroupBorders[group+1];
|
||||
int bScale = hPsEncode->psBandNrgScale[bin];
|
||||
|
||||
FIXP_DBL pwrL_env_bin = pwrData->pwrL[env][bin];
|
||||
FIXP_DBL pwrR_env_bin = pwrData->pwrR[env][bin];
|
||||
FIXP_DBL pwrCr_env_bin = pwrData->pwrCr[env][bin];
|
||||
FIXP_DBL pwrCi_env_bin = pwrData->pwrCi[env][bin];
|
||||
|
||||
int scale = (int)dynBandScale[bin];
|
||||
for (col=envBorder[env]; col<envBorder[env+1]; col++) {
|
||||
for (subband = hPsEncode->iidGroupBorders[group]; subband < border; subband++) {
|
||||
FIXP_QMF l_real = (lr[col][subband + nHybridQmfOffset]) << scale;
|
||||
FIXP_QMF l_imag = (li[col][subband + nHybridQmfOffset]) << scale;
|
||||
FIXP_QMF r_real = (rr[col][subband + nHybridQmfOffset]) << scale;
|
||||
FIXP_QMF r_imag = (ri[col][subband + nHybridQmfOffset]) << scale;
|
||||
for (subband = hPsEncode->iidGroupBorders[group]; subband < hPsEncode->iidGroupBorders[group+1]; subband++) {
|
||||
FIXP_QMF l_real = (hybridData[col][0][0][subband]) << scale;
|
||||
FIXP_QMF l_imag = (hybridData[col][0][1][subband]) << scale;
|
||||
FIXP_QMF r_real = (hybridData[col][1][0][subband]) << scale;
|
||||
FIXP_QMF r_imag = (hybridData[col][1][1][subband]) << scale;
|
||||
|
||||
pwrL_env_bin += (fPow2Div2(l_real) + fPow2Div2(l_imag)) >> bScale;
|
||||
pwrR_env_bin += (fPow2Div2(r_real) + fPow2Div2(r_imag)) >> bScale;
|
||||
@ -931,13 +868,10 @@ HANDLE_ERROR_INFO FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE RESTRICT hPsEncode,
|
||||
|
||||
} /* nEnvelopes */
|
||||
|
||||
|
||||
/* calculate iid and icc */
|
||||
calculateIID(pwrData->ldPwrL, pwrData->ldPwrR, iid, nEnvelopes, psBands);
|
||||
calculateICC(pwrData->ldPwrL, pwrData->ldPwrR, pwrData->pwrCr, pwrData->pwrCi, icc, nEnvelopes, psBands);
|
||||
|
||||
|
||||
|
||||
/*** Envelope Reduction ***/
|
||||
while (envelopeReducible(iid,icc,psBands,nEnvelopes)) {
|
||||
int e=0;
|
||||
@ -1001,7 +935,6 @@ HANDLE_ERROR_INFO FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE RESTRICT hPsEncode,
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (nEnvelopes>0) {
|
||||
|
||||
hPsOut->enableIID = hPsData->iidEnable;
|
||||
@ -1060,7 +993,6 @@ HANDLE_ERROR_INFO FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE RESTRICT hPsEncode,
|
||||
}
|
||||
} /* Envelope > 0 */
|
||||
|
||||
|
||||
C_ALLOC_SCRATCH_END(pwrData, PS_PWR_DATA, 1)
|
||||
|
||||
return error;
|
||||
|
@ -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);
|
||||
FDK_PSENC_ERROR FDKsbrEnc_CreatePSEncode(
|
||||
HANDLE_PS_ENCODE *phPsEncode
|
||||
);
|
||||
|
||||
HANDLE_ERROR_INFO FDKsbrEnc_InitPSEncode(HANDLE_PS_ENCODE hPsEncode, const PS_BANDS psEncMode, const FIXP_DBL iidQuantErrorThreshold);
|
||||
FDK_PSENC_ERROR FDKsbrEnc_InitPSEncode(
|
||||
HANDLE_PS_ENCODE hPsEncode,
|
||||
const PS_BANDS psEncMode,
|
||||
const FIXP_DBL iidQuantErrorThreshold
|
||||
);
|
||||
|
||||
HANDLE_ERROR_INFO FDKsbrEnc_DestroyPSEncode(HANDLE_PS_ENCODE *phPsEncode);
|
||||
FDK_PSENC_ERROR 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_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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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_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;
|
||||
|
||||
#define MAX_PS_CHANNELS ( 2 )
|
||||
#define PSENC_QMF_BUFFER_LENGTH ( 48 )
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
/**
|
||||
* \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
|
||||
);
|
||||
|
||||
|
||||
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);
|
||||
/**
|
||||
* \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
|
||||
);
|
||||
|
||||
INT
|
||||
FDKsbrEnc_PSEnc_WritePSData(HANDLE_PARAMETRIC_STEREO hParametricStereo, HANDLE_FDK_BITSTREAM hBitstream);
|
||||
|
||||
/**
|
||||
* \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 */
|
||||
|
@ -1,836 +0,0 @@
|
||||
/***************************** 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: hybrid analysis filter bank
|
||||
|
||||
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.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "psenc_hybrid.h"
|
||||
|
||||
|
||||
/* Includes ******************************************************************/
|
||||
|
||||
#include "psenc_hybrid.h"
|
||||
#include "sbr_ram.h"
|
||||
|
||||
#include "fft.h"
|
||||
|
||||
#include "genericStds.h"
|
||||
|
||||
/* Defines *******************************************************************/
|
||||
|
||||
#define HYBRID_SCALE 4
|
||||
|
||||
/*//#define FAST_FILTER2
|
||||
#define FAST_FILTER4
|
||||
#define FAST_FILTER8
|
||||
#define FAST_FILTER12
|
||||
*/
|
||||
#define HYBRID_INVERSE_ORDER ( 0x0F000000 )
|
||||
#define HYBRID_INVERSE_MASK ( ~HYBRID_INVERSE_ORDER )
|
||||
|
||||
//#define REAL ( 0 )
|
||||
//#define CPLX ( 1 )
|
||||
|
||||
#define cos0Pi FL2FXCONST_DBL( 1.f)
|
||||
#define sin0Pi FL2FXCONST_DBL( 0.f)
|
||||
#define cos1Pi FL2FXCONST_DBL(-1.f)
|
||||
#define sin1Pi FL2FXCONST_DBL( 0.f)
|
||||
#define cos1Pi_2 FL2FXCONST_DBL( 0.f)
|
||||
#define sin1Pi_2 FL2FXCONST_DBL( 1.f)
|
||||
#define cos1Pi_3 FL2FXCONST_DBL( 0.5f)
|
||||
#define sin1Pi_3 FL2FXCONST_DBL( 0.86602540378444f)
|
||||
|
||||
#define cos0Pi_4 cos0Pi
|
||||
#define cos1Pi_4 FL2FXCONST_DBL(0.70710678118655f)
|
||||
#define cos2Pi_4 cos1Pi_2
|
||||
#define cos3Pi_4 (-cos1Pi_4)
|
||||
#define cos4Pi_4 (-cos0Pi_4)
|
||||
#define cos5Pi_4 cos3Pi_4
|
||||
#define cos6Pi_4 cos2Pi_4
|
||||
|
||||
#define sin0Pi_4 sin0Pi
|
||||
#define sin1Pi_4 FL2FXCONST_DBL(0.70710678118655f)
|
||||
#define sin2Pi_4 sin1Pi_2
|
||||
#define sin3Pi_4 sin1Pi_4
|
||||
#define sin4Pi_4 sin0Pi_4
|
||||
#define sin5Pi_4 (-sin3Pi_4)
|
||||
#define sin6Pi_4 (-sin2Pi_4)
|
||||
|
||||
#define cos0Pi_8 cos0Pi
|
||||
#define cos1Pi_8 FL2FXCONST_DBL(0.92387953251129f)
|
||||
#define cos2Pi_8 cos1Pi_4
|
||||
#define cos3Pi_8 FL2FXCONST_DBL(0.38268343236509f)
|
||||
#define cos4Pi_8 cos2Pi_4
|
||||
#define cos5Pi_8 (-cos3Pi_8)
|
||||
#define cos6Pi_8 (-cos2Pi_8)
|
||||
|
||||
#define sin0Pi_8 sin0Pi
|
||||
#define sin1Pi_8 cos3Pi_8
|
||||
#define sin2Pi_8 sin1Pi_4
|
||||
#define sin3Pi_8 cos1Pi_8
|
||||
#define sin4Pi_8 sin2Pi_4
|
||||
#define sin5Pi_8 sin3Pi_8
|
||||
#define sin6Pi_8 sin1Pi_4
|
||||
|
||||
#define cos0Pi_12 cos0Pi
|
||||
#define cos1Pi_12 FL2FXCONST_DBL(0.96592582628906f)
|
||||
#define cos2Pi_12 FL2FXCONST_DBL(0.86602540378444f)
|
||||
#define cos3Pi_12 cos1Pi_4
|
||||
#define cos4Pi_12 cos1Pi_3
|
||||
#define cos5Pi_12 FL2FXCONST_DBL(0.25881904510252f)
|
||||
#define cos6Pi_12 cos1Pi_2
|
||||
|
||||
#define sin0Pi_12 sin0Pi
|
||||
#define sin1Pi_12 cos5Pi_12
|
||||
#define sin2Pi_12 cos4Pi_12
|
||||
#define sin3Pi_12 sin1Pi_4
|
||||
#define sin4Pi_12 sin1Pi_3
|
||||
#define sin5Pi_12 cos1Pi_12
|
||||
#define sin6Pi_12 sin1Pi_2
|
||||
|
||||
#define FFT_IDX_R(a) (2*a)
|
||||
#define FFT_IDX_I(a) (2*a+1)
|
||||
|
||||
|
||||
/* Constants *****************************************************************/
|
||||
|
||||
/* static const UINT noQmfBandsInHybrid34 = 5; */
|
||||
|
||||
static const INT aHybridResolution10[] = { HYBRID_6_CPLX,
|
||||
HYBRID_2_REAL | HYBRID_INVERSE_ORDER,
|
||||
HYBRID_2_REAL };
|
||||
|
||||
static const INT aHybridResolution20[] = { HYBRID_6_CPLX,
|
||||
HYBRID_2_REAL | HYBRID_INVERSE_ORDER,
|
||||
HYBRID_2_REAL };
|
||||
|
||||
/*static const INT aHybridResolution34[] = { HYBRID_12_CPLX,
|
||||
HYBRID_8_CPLX,
|
||||
HYBRID_4_CPLX,
|
||||
HYBRID_4_CPLX,
|
||||
HYBRID_4_CPLX };*/
|
||||
|
||||
static const FIXP_DBL p8_13_20[HYBRID_FILTER_LENGTH] =
|
||||
{
|
||||
FL2FXCONST_DBL(0.00746082949812f), FL2FXCONST_DBL(0.02270420949825f), FL2FXCONST_DBL(0.04546865930473f), FL2FXCONST_DBL(0.07266113929591f),
|
||||
FL2FXCONST_DBL(0.09885108575264f), FL2FXCONST_DBL(0.11793710567217f), FL2FXCONST_DBL(0.125f ), FL2FXCONST_DBL(0.11793710567217f),
|
||||
FL2FXCONST_DBL(0.09885108575264f), FL2FXCONST_DBL(0.07266113929591f), FL2FXCONST_DBL(0.04546865930473f), FL2FXCONST_DBL(0.02270420949825f),
|
||||
FL2FXCONST_DBL(0.00746082949812f)
|
||||
};
|
||||
|
||||
static const FIXP_DBL p2_13_20[HYBRID_FILTER_LENGTH] =
|
||||
{
|
||||
FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL( 0.01899487526049f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(-0.07293139167538f),
|
||||
FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL( 0.30596630545168f), FL2FXCONST_DBL(0.5f), FL2FXCONST_DBL( 0.30596630545168f),
|
||||
FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(-0.07293139167538f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL( 0.01899487526049f),
|
||||
FL2FXCONST_DBL(0.0f)
|
||||
};
|
||||
|
||||
|
||||
/*static const float p12_13_34[HYBRID_FILTER_LENGTH] =
|
||||
{
|
||||
0.04081179924692, 0.03812810994926, 0.05144908135699, 0.06399831151592,
|
||||
0.07428313801106, 0.08100347892914, 0.08333333333333, 0.08100347892914,
|
||||
0.07428313801106, 0.06399831151592, 0.05144908135699, 0.03812810994926,
|
||||
0.04081179924692
|
||||
};
|
||||
|
||||
static const float p8_13_34[HYBRID_FILTER_LENGTH] =
|
||||
{
|
||||
0.01565675600122, 0.03752716391991, 0.05417891378782, 0.08417044116767,
|
||||
0.10307344158036, 0.12222452249753, 0.12500000000000, 0.12222452249753,
|
||||
0.10307344158036, 0.08417044116767, 0.05417891378782, 0.03752716391991,
|
||||
0.01565675600122
|
||||
};
|
||||
|
||||
static const float p4_13_34[HYBRID_FILTER_LENGTH] =
|
||||
{
|
||||
-0.05908211155639, -0.04871498374946, 0.0, 0.07778723915851,
|
||||
0.16486303567403, 0.23279856662996, 0.25, 0.23279856662996,
|
||||
0.16486303567403, 0.07778723915851, 0.0, -0.04871498374946,
|
||||
-0.05908211155639
|
||||
};*/
|
||||
|
||||
|
||||
/* Function / Class Implementation *******************************************/
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* **** FILTERBANK CONFIG **** */
|
||||
|
||||
HANDLE_ERROR_INFO FDKsbrEnc_CreateHybridConfig(HANDLE_PS_HYBRID_CONFIG *phHybConfig,
|
||||
PS_BANDS mode)
|
||||
{
|
||||
HANDLE_ERROR_INFO error = noError;
|
||||
HANDLE_PS_HYBRID_CONFIG h = NULL;
|
||||
UINT k = 0;
|
||||
|
||||
if (error == noError) {
|
||||
h = *phHybConfig; /* Simplify your life */
|
||||
h->mode = mode;
|
||||
|
||||
switch (mode) {
|
||||
case PS_BANDS_MID:
|
||||
h->noQmfBandsInHybrid = NO_QMF_BANDS_HYBRID_20;
|
||||
for (k=0; k<h->noQmfBandsInHybrid; k++) {
|
||||
h->aHybridResolution[k] = aHybridResolution20[k];
|
||||
}
|
||||
break;
|
||||
|
||||
case PS_BANDS_FINE:
|
||||
/*h->noQmfBandsInHybrid = noQmfBandsInHybrid34;
|
||||
for (k=0; k<h->noQmfBandsInHybrid; k++) {
|
||||
h->aHybridResolution[k] = aHybridResolution34[k];
|
||||
}*/
|
||||
FDK_ASSERT(0); /* we don't support! */
|
||||
break;
|
||||
|
||||
case PS_BANDS_COARSE:
|
||||
h->noQmfBandsInHybrid = NO_QMF_BANDS_HYBRID_10;
|
||||
for (k=0; k<h->noQmfBandsInHybrid; k++) {
|
||||
h->aHybridResolution[k] = aHybridResolution10[k];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error = ERROR(CDI, "Invalid hybrid filter bank configuration.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* **** FILTERBANK DATA **** */
|
||||
|
||||
HANDLE_ERROR_INFO FDKsbrEnc_CreateHybridData(HANDLE_PS_HYBRID_DATA *phHybData,
|
||||
INT ch)
|
||||
{
|
||||
HANDLE_ERROR_INFO error = noError;
|
||||
int k;
|
||||
|
||||
HANDLE_PS_HYBRID_DATA hHybData = GetRam_HybData(ch);
|
||||
if (hHybData==NULL) {
|
||||
error = 1;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
FDKmemclear(hHybData, sizeof(PS_HYBRID_DATA));
|
||||
|
||||
hHybData->rHybData[0] = GetRam_PsRhyb(ch);
|
||||
hHybData->iHybData[0] = GetRam_PsIhyb(ch);
|
||||
if ( (hHybData->rHybData[0]==NULL) || (hHybData->iHybData[0]==NULL) ) {
|
||||
error = 1;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (k=1; k<(HYBRID_FRAMESIZE+HYBRID_WRITEOFFSET); k++) {
|
||||
hHybData->rHybData[k] = hHybData->rHybData[0] + (k*HYBRID_NUM_BANDS);
|
||||
hHybData->iHybData[k] = hHybData->iHybData[0] + (k*HYBRID_NUM_BANDS);
|
||||
}
|
||||
|
||||
bail:
|
||||
*phHybData = hHybData;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
HANDLE_ERROR_INFO FDKsbrEnc_InitHybridData(HANDLE_PS_HYBRID_DATA hHybData,
|
||||
HANDLE_PS_HYBRID_CONFIG hHybConfig,
|
||||
INT frameSize)
|
||||
{
|
||||
HANDLE_ERROR_INFO error = noError;
|
||||
INT nHybridBands = 0;
|
||||
INT k = 0;
|
||||
INT noBands = 0;
|
||||
const INT *hybridRes = NULL;
|
||||
|
||||
if (hHybConfig != NULL) {
|
||||
noBands = hHybConfig->noQmfBandsInHybrid;
|
||||
hybridRes = hHybConfig->aHybridResolution;
|
||||
}
|
||||
|
||||
for (k=0; k<noBands; k++) {
|
||||
nHybridBands += (hybridRes[k] & HYBRID_INVERSE_MASK);
|
||||
}
|
||||
FDK_ASSERT (HYBRID_NUM_BANDS>=nHybridBands);
|
||||
|
||||
hHybData->hybDataReadOffset = HYBRID_DATA_READ_OFFSET;
|
||||
hHybData->hybDataWriteOffset = HYBRID_WRITEOFFSET;
|
||||
|
||||
for (k=0; k<(HYBRID_FRAMESIZE+HYBRID_WRITEOFFSET); k++) {
|
||||
FDKmemclear(hHybData->rHybData[k], sizeof(FIXP_QMF)*HYBRID_NUM_BANDS);
|
||||
FDKmemclear(hHybData->iHybData[k], sizeof(FIXP_QMF)*HYBRID_NUM_BANDS);
|
||||
}
|
||||
|
||||
hHybData->frameSize = frameSize;
|
||||
hHybData->nHybridBands = nHybridBands;
|
||||
hHybData->nHybridQmfBands = noBands;
|
||||
|
||||
/* store hybrid resoltion in hybrid data handle */
|
||||
FDK_ASSERT (HYBRID_MAX_QMF_BANDS>=hHybData->nHybridQmfBands);
|
||||
for(k = 0; k<hHybData->nHybridQmfBands; k++){
|
||||
hHybData->nHybridResolution[k] = (hybridRes[k] & HYBRID_INVERSE_MASK);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
HANDLE_ERROR_INFO FDKsbrEnc_DestroyHybridData(HANDLE_PS_HYBRID_DATA* phHybData)
|
||||
{
|
||||
HANDLE_PS_HYBRID_DATA hHybData = *phHybData;
|
||||
|
||||
if (hHybData!=NULL) {
|
||||
FreeRam_PsRhyb(&hHybData->rHybData[0]);
|
||||
FreeRam_PsIhyb(&hHybData->iHybData[0]);
|
||||
FreeRam_HybData(phHybData);
|
||||
}
|
||||
|
||||
return noError;
|
||||
}
|
||||
|
||||
/*** Access functions ***/
|
||||
|
||||
/* return hybrid band resolution of qmf band 'qmfBand' */
|
||||
INT FDKsbrEnc_GetHybridResolution(HANDLE_PS_HYBRID_DATA h, INT qmfBand){
|
||||
|
||||
INT nHybridResolution = 0;
|
||||
|
||||
if(h->nHybridResolution){
|
||||
nHybridResolution = h->nHybridResolution[qmfBand];
|
||||
}
|
||||
|
||||
return nHybridResolution;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* **** FILTERBANK **** */
|
||||
|
||||
/*
|
||||
2 channel filter
|
||||
Filter Coefs:
|
||||
0.0,
|
||||
0.01899487526049,
|
||||
0.0,
|
||||
-0.07293139167538,
|
||||
0.0,
|
||||
0.30596630545168,
|
||||
0.5,
|
||||
0.30596630545168,
|
||||
0.0,
|
||||
-0.07293139167538,
|
||||
0.0,
|
||||
0.01899487526049,
|
||||
0.0
|
||||
|
||||
|
||||
Filter design:
|
||||
h[q,n] = g[n] * cos(2pi/2 * q * (n-6) ); n = 0..12, q = 0,1;
|
||||
|
||||
-> h[0,n] = g[n] * 1;
|
||||
-> h[1,n] = g[n] * pow(-1,n);
|
||||
|
||||
*/
|
||||
|
||||
static void dualChannelFiltering(const FIXP_QMF *RESTRICT pQmfReal,
|
||||
const FIXP_QMF *RESTRICT pQmfImag,
|
||||
FIXP_QMF **RESTRICT mHybridReal,
|
||||
FIXP_QMF **RESTRICT mHybridImag,
|
||||
INT nSamples)
|
||||
{
|
||||
INT i;
|
||||
|
||||
for(i = 0; i < nSamples; i++) {
|
||||
FIXP_DBL r1, r3, r5, r6;
|
||||
FIXP_DBL i1, i3, i5, i6;
|
||||
|
||||
/* symmetric filter coefficients
|
||||
scaleValue same as used in eightChannelFiltering (HYBRID_SCALE = 4)
|
||||
*/
|
||||
r1 = fMultDiv2(p2_13_20[1], (FIXP_QMF)((pQmfReal[1+i]>>1) + (pQmfReal[11+i]>>1)) ) >> 2;
|
||||
r3 = fMultDiv2(p2_13_20[3], (FIXP_QMF)((pQmfReal[3+i]>>1) + (pQmfReal[ 9+i]>>1)) ) >> 2;
|
||||
r5 = fMultDiv2(p2_13_20[5], (FIXP_QMF)((pQmfReal[5+i]>>1) + (pQmfReal[ 7+i]>>1)) ) >> 2;
|
||||
r6 = fMultDiv2(p2_13_20[6], (FIXP_QMF) (pQmfReal[6+i]>>1) ) >> 2;
|
||||
|
||||
i1 = fMultDiv2(p2_13_20[1], (FIXP_QMF)((pQmfImag[1+i]>>1) + (pQmfImag[11+i]>>1)) ) >> 2;
|
||||
i3 = fMultDiv2(p2_13_20[3], (FIXP_QMF)((pQmfImag[3+i]>>1) + (pQmfImag[ 9+i]>>1)) ) >> 2;
|
||||
i5 = fMultDiv2(p2_13_20[5], (FIXP_QMF)((pQmfImag[5+i]>>1) + (pQmfImag[ 7+i]>>1)) ) >> 2;
|
||||
i6 = fMultDiv2(p2_13_20[6], (FIXP_QMF) (pQmfImag[6+i]>>1) ) >> 2;
|
||||
|
||||
mHybridReal[i][0] = FX_DBL2FX_QMF(r1 + r3 + r5 + r6);
|
||||
mHybridImag[i][0] = FX_DBL2FX_QMF(i1 + i3 + i5 + i6);
|
||||
|
||||
mHybridReal[i][1] = FX_DBL2FX_QMF(- r1 - r3 - r5 + r6);
|
||||
mHybridImag[i][1] = FX_DBL2FX_QMF(- i1 - i3 - i5 + i6);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
8 channel filter
|
||||
|
||||
Implementation using a FFT of length 8
|
||||
|
||||
prototype filter coefficients:
|
||||
0.00746082949812 0.02270420949825 0.04546865930473 0.07266113929591 0.09885108575264 0.11793710567217
|
||||
0.125
|
||||
0.11793710567217 0.09885108575264 0.07266113929591 0.04546865930473 0.02270420949825 0.00746082949812
|
||||
|
||||
Filter design:
|
||||
N = 13; Q = 8;
|
||||
h[q,n] = g[n] * exp(j * 2 * pi / Q * (q + .5) * (n - 6)); n = 0..(N-1), q = 0..(Q-1);
|
||||
|
||||
Time Signal: x[t];
|
||||
Filter Bank Output
|
||||
y[q,t] = conv(x[t],h[q,t]) = conv(h[q,t],x[t]) = sum(x[k] * h[q, t - k] ) = sum(h[q, k] * x[t - k] ); k = 0..(N-1);
|
||||
|
||||
y[q,t] = x[t - 12]*h[q, 12] + x[t - 11]*h[q, 11] + x[t - 10]*h[q, 10] + x[t - 9]*h[q, 9]
|
||||
+ x[t - 8]*h[q, 8] + x[t - 7]*h[q, 7]
|
||||
+ x[t - 6]*h[q, 6]
|
||||
+ x[t - 5]*h[q, 5] + x[t - 4]*h[q, 4]
|
||||
+ x[t - 3]*h[q, 3] + x[t - 2]*h[q, 2] + x[t - 1]*h[q, 1] + x[t - 0]*h[q, 0];
|
||||
|
||||
h'[q, n] = h[q,(N-1)-n] = g[n] * exp(j * 2 * pi / Q * (q + .5) * (6 - n)); n = 0..(N-1), q = 0..(Q-1);
|
||||
|
||||
y[q,t] = x[t - 12]*h'[q, 0] + x[t - 11]*h'[q, 1] + x[t - 10]*h'[q, 2] + x[t - 9]*h'[q, 3]
|
||||
+ x[t - 8]*h'[q, 4] + x[t - 7]*h'[q, 5]
|
||||
+ x[t - 6]*h'[q, 6]
|
||||
+ x[t - 5]*h'[q, 7] + x[t - 4]*h'[q, 8]
|
||||
+ x[t - 3]*h'[q, 9] + x[t - 2]*h'[q, 10] + x[t - 1]*h'[q, 11] + x[t - 0]*h'[q, 12];
|
||||
|
||||
Try to split off FFT Modulation Term:
|
||||
FFT(x[t], q) = sum(x[t+k]*exp(-j*2*pi/N *q * k))
|
||||
c m
|
||||
Step 1: h'[q,n] = g[n] * ( exp(j * 2 * pi / 8 * .5 * (6 - n)) ) * ( exp (j * 2 * pi / 8 * q * (6 - n)) );
|
||||
|
||||
h'[q,n] = g[n] *c[n] * m[q,n]; (see above)
|
||||
c[n] = exp( j * 2 * pi / 8 * .5 * (6 - n) );
|
||||
m[q,n] = exp( j * 2 * pi / 8 * q * (6 - n) );
|
||||
|
||||
y[q,t] = x[t - 0]*g[0]*c[0]*m[q,0] + x[t - 1]*g[1]*c[ 1]*m[q, 1] + ...
|
||||
... + x[t - 12]*g[2]*c[12]*m[q,12];
|
||||
|
||||
|
|
||||
n m *exp(-j*2*pi) | n' fft
|
||||
-------------------------------------------------------------------------------------------------------------------------
|
||||
0 exp( j * 2 * pi / 8 * q * 6) -> exp(-j * 2 * pi / 8 * q * 2) | 2 exp(-j * 2 * pi / 8 * q * 0)
|
||||
1 exp( j * 2 * pi / 8 * q * 5) -> exp(-j * 2 * pi / 8 * q * 3) | 3 exp(-j * 2 * pi / 8 * q * 1)
|
||||
2 exp( j * 2 * pi / 8 * q * 4) -> exp(-j * 2 * pi / 8 * q * 4) | 4 exp(-j * 2 * pi / 8 * q * 2)
|
||||
3 exp( j * 2 * pi / 8 * q * 3) -> exp(-j * 2 * pi / 8 * q * 5) | 5 exp(-j * 2 * pi / 8 * q * 3)
|
||||
4 exp( j * 2 * pi / 8 * q * 2) -> exp(-j * 2 * pi / 8 * q * 6) | 6 exp(-j * 2 * pi / 8 * q * 4)
|
||||
5 exp( j * 2 * pi / 8 * q * 1) -> exp(-j * 2 * pi / 8 * q * 7) | 7 exp(-j * 2 * pi / 8 * q * 5)
|
||||
6 exp( j * 2 * pi / 8 * q * 0) | 0 exp(-j * 2 * pi / 8 * q * 6)
|
||||
7 exp(-j * 2 * pi / 8 * q * 1) | 1 exp(-j * 2 * pi / 8 * q * 7)
|
||||
8 exp(-j * 2 * pi / 8 * q * 2) | 2
|
||||
9 exp(-j * 2 * pi / 8 * q * 3) | 3
|
||||
10 exp(-j * 2 * pi / 8 * q * 4) | 4
|
||||
11 exp(-j * 2 * pi / 8 * q * 5) | 5
|
||||
12 exp(-j * 2 * pi / 8 * q * 6) | 6
|
||||
|
||||
|
||||
now use fft modulation coefficients
|
||||
m[6] = = fft[0]
|
||||
m[7] = = fft[1]
|
||||
m[8] = m[ 0] = fft[2]
|
||||
m[9] = m[ 1] = fft[3]
|
||||
m[10] = m[ 2] = fft[4]
|
||||
m[11] = m[ 3] = fft[5]
|
||||
m[12] = m[ 4] = fft[6]
|
||||
m[ 5] = fft[7]
|
||||
|
||||
y[q,t] = ( x[t- 6]*g[ 6]*c[ 6] ) * fft[q,0] +
|
||||
( x[t- 7]*g[ 7]*c[ 7] ) * fft[q,1] +
|
||||
( x[t- 0]*g[ 0]*c[ 0] + x[t- 8]*g[ 8]*c[ 8] ) * fft[q,2] +
|
||||
( x[t- 1]*g[ 1]*c[ 1] + x[t- 9]*g[ 9]*c[ 9] ) * fft[q,3] +
|
||||
( x[t- 2]*g[ 2]*c[ 2] + x[t-10]*g[10]*c[10] ) * fft[q,4] +
|
||||
( x[t- 3]*g[ 3]*c[ 3] + x[t-11]*g[11]*c[11] ) * fft[q,5] +
|
||||
( x[t- 4]*g[ 4]*c[ 4] + x[t-12]*g[12]*c[12] ) * fft[q,6] +
|
||||
( x[t- 5]*g[ 5]*c[ 5] ) * fft[q,7];
|
||||
|
||||
pre twiddle factors c[n] = exp(j * 2 * pi / 8 * .5 * (6 - n));
|
||||
n c] | n c[n] | n c[n]
|
||||
---------------------------------------------------------------------------------------------------
|
||||
0 exp( j * 6 * pi / 8) | 1 exp( j * 5 * pi / 8) | 2 exp( j * 4 * pi / 8)
|
||||
3 exp( j * 3 * pi / 8) | 4 exp( j * 2 * pi / 8) | 5 exp( j * 1 * pi / 8)
|
||||
6 exp( j * 0 * pi / 8) | 7 exp(-j * 1 * pi / 8) | 8 exp(-j * 2 * pi / 8)
|
||||
9 exp(-j * 3 * pi / 8) | 10 exp(-j * 4 * pi / 8) | 11 exp(-j * 5 * pi / 8)
|
||||
12 exp(-j * 6 * pi / 8) | |
|
||||
|
||||
*/
|
||||
|
||||
static const FIXP_DBL cr[13] =
|
||||
{ cos6Pi_8, cos5Pi_8, cos4Pi_8,
|
||||
cos3Pi_8, cos2Pi_8, cos1Pi_8,
|
||||
cos0Pi_8,
|
||||
cos1Pi_8, cos2Pi_8, cos3Pi_8,
|
||||
cos4Pi_8, cos5Pi_8, cos6Pi_8
|
||||
};
|
||||
|
||||
static const FIXP_DBL ci[13] =
|
||||
{
|
||||
sin6Pi_8, sin5Pi_8, sin4Pi_8,
|
||||
sin3Pi_8, sin2Pi_8, sin1Pi_8,
|
||||
sin0Pi_8,
|
||||
-sin1Pi_8, -sin2Pi_8, -sin3Pi_8,
|
||||
-sin4Pi_8, -sin5Pi_8, -sin6Pi_8
|
||||
};
|
||||
|
||||
|
||||
static void eightChannelFiltering(const FIXP_QMF *pQmfReal,
|
||||
const FIXP_QMF *pQmfImag,
|
||||
FIXP_DBL *fft,
|
||||
FIXP_QMF **mHybridReal,
|
||||
FIXP_QMF **mHybridImag,
|
||||
INT nSamples,
|
||||
const FIXP_DBL *p)
|
||||
{
|
||||
INT i, bin;
|
||||
for(i = 0; i < nSamples; i++) {
|
||||
/* pre twiddeling
|
||||
scaling 4 = 2 (fMultDiv2) + 2 (dit_fft) scaling (HYBRID_SCALE = 4)
|
||||
*/
|
||||
fft[FFT_IDX_R(0)] = fMultDiv2(p[6], fMultSubDiv2(fMultDiv2(cr[6], pQmfReal[6+i]), ci[6], pQmfImag[6+i]));
|
||||
fft[FFT_IDX_I(0)] = fMultDiv2(p[6], fMultAddDiv2(fMultDiv2(ci[6], pQmfReal[6+i]), cr[6], pQmfImag[6+i]));
|
||||
|
||||
fft[FFT_IDX_R(1)] = fMultDiv2(p[7], fMultSubDiv2(fMultDiv2(cr[7], pQmfReal[7+i]), ci[7], pQmfImag[7+i]));
|
||||
fft[FFT_IDX_I(1)] = fMultDiv2(p[7], fMultAddDiv2(fMultDiv2(ci[7], pQmfReal[7+i]), cr[7], pQmfImag[7+i]));
|
||||
|
||||
fft[FFT_IDX_R(2)] = ( fMultDiv2(p[ 0], fMultSubDiv2(fMultDiv2(cr[0], pQmfReal[ 0+i]), ci[0], pQmfImag[ 0+i]))+
|
||||
fMultDiv2(p[ 8], fMultSubDiv2(fMultDiv2(cr[8], pQmfReal[ 8+i]), ci[8], pQmfImag[ 8+i])) );
|
||||
fft[FFT_IDX_I(2)] = ( fMultDiv2(p[ 0], fMultAddDiv2(fMultDiv2(ci[0], pQmfReal[ 0+i]), cr[0], pQmfImag[ 0+i]))+
|
||||
fMultDiv2(p[ 8], fMultAddDiv2(fMultDiv2(ci[8], pQmfReal[ 8+i]), cr[8], pQmfImag[ 8+i])) );
|
||||
|
||||
fft[FFT_IDX_R(3)] = ( fMultDiv2(p[ 1], fMultSubDiv2(fMultDiv2(cr[1], pQmfReal[ 1+i]), ci[1], pQmfImag[ 1+i]))+
|
||||
fMultDiv2(p[ 9], fMultSubDiv2(fMultDiv2(cr[9], pQmfReal[ 9+i]), ci[9], pQmfImag[ 9+i])) );
|
||||
fft[FFT_IDX_I(3)] = ( fMultDiv2(p[ 1], fMultAddDiv2(fMultDiv2(ci[1], pQmfReal[ 1+i]), cr[1], pQmfImag[ 1+i]))+
|
||||
fMultDiv2(p[ 9], fMultAddDiv2(fMultDiv2(ci[9], pQmfReal[ 9+i]), cr[9], pQmfImag[ 9+i])) );
|
||||
|
||||
fft[FFT_IDX_R(4)] = ( fMultDiv2(p[ 2], fMultSubDiv2( fMultDiv2(cr[2], pQmfReal[ 2+i]), ci[2], pQmfImag[ 2+i]))+
|
||||
fMultDiv2(p[10], fMultSubDiv2(fMultDiv2(cr[10], pQmfReal[10+i]), ci[10], pQmfImag[10+i])) );
|
||||
fft[FFT_IDX_I(4)] = ( fMultDiv2(p[ 2], fMultAddDiv2( fMultDiv2(ci[2], pQmfReal[ 2+i]), cr[2], pQmfImag[ 2+i]))+
|
||||
fMultDiv2(p[10], fMultAddDiv2(fMultDiv2(ci[10], pQmfReal[10+i]), cr[10], pQmfImag[10+i])) );
|
||||
|
||||
fft[FFT_IDX_R(5)] = ( fMultDiv2(p[ 3], fMultSubDiv2( fMultDiv2(cr[3], pQmfReal[ 3+i]), ci[3], pQmfImag[ 3+i]))+
|
||||
fMultDiv2(p[11], fMultSubDiv2(fMultDiv2(cr[11], pQmfReal[11+i]), ci[11], pQmfImag[11+i])) );
|
||||
fft[FFT_IDX_I(5)] = ( fMultDiv2(p[ 3], fMultAddDiv2( fMultDiv2(ci[3], pQmfReal[ 3+i]), cr[3], pQmfImag[ 3+i]))+
|
||||
fMultDiv2(p[11], fMultAddDiv2(fMultDiv2(ci[11], pQmfReal[11+i]), cr[11], pQmfImag[11+i])) );
|
||||
|
||||
fft[FFT_IDX_R(6)] = ( fMultDiv2(p[ 4], fMultSubDiv2( fMultDiv2(cr[4], pQmfReal[ 4+i]), ci[4], pQmfImag[ 4+i]))+
|
||||
fMultDiv2(p[12], fMultSubDiv2(fMultDiv2(cr[12], pQmfReal[12+i]), ci[12], pQmfImag[12+i])) );
|
||||
fft[FFT_IDX_I(6)] = ( fMultDiv2(p[ 4], fMultAddDiv2( fMultDiv2(ci[4], pQmfReal[ 4+i]), cr[4], pQmfImag[ 4+i]))+
|
||||
fMultDiv2(p[12], fMultAddDiv2(fMultDiv2(ci[12], pQmfReal[12+i]), cr[12], pQmfImag[12+i])) );
|
||||
|
||||
fft[FFT_IDX_R(7)] = fMultDiv2(p[5], fMultSubDiv2(fMultDiv2(cr[5], pQmfReal[5+i]), ci[5], pQmfImag[5+i]));
|
||||
fft[FFT_IDX_I(7)] = fMultDiv2(p[5], fMultAddDiv2(fMultDiv2(ci[5], pQmfReal[5+i]), cr[5], pQmfImag[5+i]));
|
||||
|
||||
/* fft modulation */
|
||||
fft_8(fft);
|
||||
|
||||
/* resort fft data INTo output array*/
|
||||
for(bin=0; bin<8;bin++ ) {
|
||||
mHybridReal[i][bin] = FX_DBL2FX_QMF(fft[FFT_IDX_R(bin)]);
|
||||
mHybridImag[i][bin] = FX_DBL2FX_QMF(fft[FFT_IDX_I(bin)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
HybridAnalysis
|
||||
******************************************************************************/
|
||||
|
||||
HANDLE_ERROR_INFO
|
||||
HybridAnalysis ( HANDLE_PS_HYBRID hHybrid, /*!< Handle to HYBRID struct. */
|
||||
FIXP_QMF *const *const mQmfReal, /*!< The real part of the QMF-matrix. */
|
||||
FIXP_QMF *const *const mQmfImag, /*!< The imaginary part of the QMF-matrix. */
|
||||
SCHAR sf_fixpQmf, /*!< Qmf scale factor */
|
||||
FIXP_QMF **mHybridReal, /*!< The real part of the hybrid-matrix. */
|
||||
FIXP_QMF **mHybridImag, /*!< The imaginary part of the hybrid-matrix. */
|
||||
SCHAR *sf_fixpHybrid) /*!< Hybrid scale factor */
|
||||
{
|
||||
HANDLE_ERROR_INFO error = noError;
|
||||
INT n, band;
|
||||
INT hybridRes;
|
||||
INT chOffset = 0;
|
||||
/* INT usedStereoBands = hHybrid->mode; */ /*!< indicates which 8 band filter to use */
|
||||
INT frameSize = hHybrid->frameSize;
|
||||
INT hybridFilterDelay = hHybrid->hybridFilterDelay;
|
||||
|
||||
for(band = 0; band < hHybrid->nQmfBands; band++) { /* loop all qmf bands */
|
||||
|
||||
if(error == noError){
|
||||
hybridRes = hHybrid->pResolution[band];
|
||||
|
||||
/* Create working buffer. */
|
||||
/* Copy stored samples to working buffer. */
|
||||
FDKmemcpy(hHybrid->pWorkReal, hHybrid->mQmfBufferReal[band],
|
||||
hHybrid->qmfBufferMove * sizeof(FIXP_QMF));
|
||||
FDKmemcpy(hHybrid->pWorkImag, hHybrid->mQmfBufferImag[band],
|
||||
hHybrid->qmfBufferMove * sizeof(FIXP_QMF));
|
||||
|
||||
/* Append new samples to working buffer. */
|
||||
for(n = 0; n < frameSize; n++) {
|
||||
hHybrid->pWorkReal [hHybrid->qmfBufferMove + n] = mQmfReal [n + hybridFilterDelay] [band];
|
||||
hHybrid->pWorkImag [hHybrid->qmfBufferMove + n] = mQmfImag [n + hybridFilterDelay] [band];
|
||||
}
|
||||
|
||||
/* Store samples for next frame. */
|
||||
FDKmemcpy(hHybrid->mQmfBufferReal[band], hHybrid->pWorkReal + frameSize,
|
||||
hHybrid->qmfBufferMove * sizeof(FIXP_QMF));
|
||||
FDKmemcpy(hHybrid->mQmfBufferImag[band], hHybrid->pWorkImag + frameSize,
|
||||
hHybrid->qmfBufferMove * sizeof(FIXP_QMF));
|
||||
|
||||
|
||||
switch(hybridRes) {
|
||||
case HYBRID_2_REAL:
|
||||
dualChannelFiltering( hHybrid->pWorkReal,
|
||||
hHybrid->pWorkImag,
|
||||
hHybrid->mTempReal,
|
||||
hHybrid->mTempImag,
|
||||
frameSize);
|
||||
|
||||
/* copy data to output buffer */
|
||||
for(n = 0; n < frameSize; n++) {
|
||||
FDKmemcpy(&mHybridReal[n][chOffset], hHybrid->mTempReal[n],
|
||||
(INT)(hybridRes & HYBRID_INVERSE_MASK)*sizeof(FIXP_QMF));
|
||||
FDKmemcpy(&mHybridImag[n][chOffset], hHybrid->mTempImag[n],
|
||||
(INT)(hybridRes & HYBRID_INVERSE_MASK)*sizeof(FIXP_QMF));
|
||||
}
|
||||
break;
|
||||
|
||||
case HYBRID_2_REAL | HYBRID_INVERSE_ORDER:
|
||||
dualChannelFiltering( hHybrid->pWorkReal,
|
||||
hHybrid->pWorkImag,
|
||||
hHybrid->mTempReal,
|
||||
hHybrid->mTempImag,
|
||||
frameSize);
|
||||
|
||||
/* copy and resort data */
|
||||
for ( n = 0; n < frameSize; n++ )
|
||||
{
|
||||
mHybridReal[n][chOffset + 0] = hHybrid->mTempReal[n][1] ;
|
||||
mHybridReal[n][chOffset + 1] = hHybrid->mTempReal[n][0] ;
|
||||
mHybridImag[n][chOffset + 0] = hHybrid->mTempImag[n][1] ;
|
||||
mHybridImag[n][chOffset + 1] = hHybrid->mTempImag[n][0] ;
|
||||
}
|
||||
break;
|
||||
|
||||
case HYBRID_6_CPLX:
|
||||
eightChannelFiltering( hHybrid->pWorkReal,
|
||||
hHybrid->pWorkImag,
|
||||
hHybrid->fft,
|
||||
hHybrid->mTempReal,
|
||||
hHybrid->mTempImag,
|
||||
frameSize,
|
||||
/*(usedStereoBands==PS_BANDS_FINE)?p8_13_34:*/p8_13_20);
|
||||
|
||||
/* do the shuffle */
|
||||
for ( n = 0; n < frameSize; n++ )
|
||||
{
|
||||
/* add data ... */
|
||||
hHybrid->mTempReal[n][2] += hHybrid->mTempReal[n][5];
|
||||
hHybrid->mTempImag[n][2] += hHybrid->mTempImag[n][5];
|
||||
hHybrid->mTempReal[n][3] += hHybrid->mTempReal[n][4];
|
||||
hHybrid->mTempImag[n][3] += hHybrid->mTempImag[n][4];
|
||||
|
||||
/* shuffle and copy to output buffer */
|
||||
mHybridReal[n][chOffset + 0] = hHybrid->mTempReal[n][6] ;
|
||||
mHybridReal[n][chOffset + 1] = hHybrid->mTempReal[n][7] ;
|
||||
mHybridReal[n][chOffset + 2] = hHybrid->mTempReal[n][0] ;
|
||||
mHybridReal[n][chOffset + 3] = hHybrid->mTempReal[n][1] ;
|
||||
mHybridReal[n][chOffset + 4] = hHybrid->mTempReal[n][2] ;
|
||||
mHybridReal[n][chOffset + 5] = hHybrid->mTempReal[n][3] ;
|
||||
|
||||
mHybridImag[n][chOffset + 0] = hHybrid->mTempImag[n][6] ;
|
||||
mHybridImag[n][chOffset + 1] = hHybrid->mTempImag[n][7] ;
|
||||
mHybridImag[n][chOffset + 2] = hHybrid->mTempImag[n][0] ;
|
||||
mHybridImag[n][chOffset + 3] = hHybrid->mTempImag[n][1] ;
|
||||
mHybridImag[n][chOffset + 4] = hHybrid->mTempImag[n][2] ;
|
||||
mHybridImag[n][chOffset + 5] = hHybrid->mTempImag[n][3] ;
|
||||
}
|
||||
break;
|
||||
|
||||
case HYBRID_8_CPLX:
|
||||
eightChannelFiltering( hHybrid->pWorkReal,
|
||||
hHybrid->pWorkImag,
|
||||
hHybrid->fft,
|
||||
hHybrid->mTempReal,
|
||||
hHybrid->mTempImag,
|
||||
frameSize,
|
||||
/*(usedStereoBands==PS_BANDS_FINE)?p8_13_34:*/p8_13_20);
|
||||
|
||||
/* copy data to output buffer */
|
||||
for(n = 0; n < frameSize; n++) {
|
||||
FDKmemcpy(&mHybridReal[n][chOffset], hHybrid->mTempReal[n],
|
||||
(INT)(hybridRes & HYBRID_INVERSE_MASK)*sizeof(FIXP_QMF));
|
||||
FDKmemcpy(&mHybridImag[n][chOffset], hHybrid->mTempImag[n],
|
||||
(INT)(hybridRes & HYBRID_INVERSE_MASK)*sizeof(FIXP_QMF));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error = ERROR(CDI, "Invalid filter bank configuration.");
|
||||
break;
|
||||
}
|
||||
/* prepare next run by incresing chOffset */
|
||||
chOffset += hybridRes & HYBRID_INVERSE_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
*sf_fixpHybrid = sf_fixpQmf + HYBRID_SCALE;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
FDKsbrEnc_CreateHybridFilterBank
|
||||
******************************************************************************/
|
||||
HANDLE_ERROR_INFO
|
||||
FDKsbrEnc_CreateHybridFilterBank ( HANDLE_PS_HYBRID *phHybrid, /*!< Pointer to handle to HYBRID struct. */
|
||||
INT ch) /*!< Current channel */
|
||||
{
|
||||
HANDLE_ERROR_INFO error = noError;
|
||||
INT i;
|
||||
HANDLE_PS_HYBRID hs = GetRam_PsHybrid(ch); /* allocate memory */
|
||||
if (hs==NULL) {
|
||||
error = 1;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
hs->fft = GetRam_PsHybFFT();
|
||||
|
||||
/* alloc working memory */
|
||||
hs->pWorkReal = GetRam_PsHybWkReal();
|
||||
hs->pWorkImag = GetRam_PsHybWkImag();
|
||||
|
||||
if ( (hs->fft==NULL) || (hs->pWorkReal==NULL) || (hs->pWorkImag==NULL) ) {
|
||||
error = 1;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Allocate buffers */
|
||||
for (i = 0; i < HYBRID_FRAMESIZE; i++) {
|
||||
hs->mTempReal[i] = GetRam_PsMtmpReal(i);
|
||||
hs->mTempImag[i] = GetRam_PsMtmpImag(i);
|
||||
if ( (hs->mTempReal[i]==NULL) || (hs->mTempImag[i]==NULL) ) {
|
||||
error = 1;
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
bail:
|
||||
*phHybrid = hs;
|
||||
return error;
|
||||
}
|
||||
|
||||
HANDLE_ERROR_INFO
|
||||
FDKsbrEnc_InitHybridFilterBank ( HANDLE_PS_HYBRID hs, /*!< Handle to HYBRID struct. */
|
||||
HANDLE_PS_HYBRID_CONFIG hHybConfig, /*!< Configuration hanlde for filter bank */
|
||||
INT frameSize) /*!< Number of QMF slots */
|
||||
{
|
||||
HANDLE_ERROR_INFO error = noError;
|
||||
INT i;
|
||||
INT maxNoChannels = HYBRID_12_CPLX, noBands;
|
||||
PS_BANDS mode;
|
||||
const INT *RESTRICT pResolution;
|
||||
|
||||
/* filter bank configuration */
|
||||
mode = hHybConfig->mode;
|
||||
noBands = hHybConfig->noQmfBandsInHybrid;
|
||||
pResolution = hHybConfig->aHybridResolution;
|
||||
|
||||
/* assign resolution, check for valid values */
|
||||
for (i = 0; i < noBands; i++) {
|
||||
if(error == noError){
|
||||
if( pResolution[i] != HYBRID_12_CPLX &&
|
||||
pResolution[i] != HYBRID_8_CPLX &&
|
||||
pResolution[i] != HYBRID_6_CPLX &&
|
||||
pResolution[i] != HYBRID_2_REAL &&
|
||||
pResolution[i] != (HYBRID_2_REAL | HYBRID_INVERSE_ORDER) &&
|
||||
pResolution[i] != HYBRID_4_CPLX ){
|
||||
error = ERROR(CDI, "Invalid filter bank resolution");
|
||||
}
|
||||
}
|
||||
hs->pResolution[i] = pResolution[i];
|
||||
if((pResolution[i] & HYBRID_INVERSE_MASK) > maxNoChannels){
|
||||
maxNoChannels = pResolution[i] & HYBRID_INVERSE_MASK;
|
||||
}
|
||||
}
|
||||
FDK_ASSERT (MAX_HYBRID_RES>=maxNoChannels); /* check size of mTempReal/Imag */
|
||||
|
||||
/* assign parameters */
|
||||
hs->mode = mode;
|
||||
hs->nQmfBands = noBands;
|
||||
hs->frameSize = frameSize;
|
||||
hs->frameSizeInit = frameSize;
|
||||
hs->qmfBufferMove = HYBRID_FILTER_LENGTH - 1;
|
||||
hs->hybridFilterDelay = HYBRID_FILTER_LENGTH/2;
|
||||
|
||||
FDK_ASSERT (HYBRID_FRAMESIZE>=hs->frameSize);
|
||||
FDK_ASSERT (QMF_BUFFER_MOVE>=hs->qmfBufferMove);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************//**
|
||||
FDKsbrEnc_DeleteHybridFilterBank
|
||||
******************************************************************************/
|
||||
|
||||
HANDLE_ERROR_INFO
|
||||
FDKsbrEnc_DeleteHybridFilterBank ( HANDLE_PS_HYBRID* phHybrid ) /*!< Pointer to handle to HYBRID struct. */
|
||||
{
|
||||
int i;
|
||||
HANDLE_PS_HYBRID hHybrid = *phHybrid;
|
||||
|
||||
if (hHybrid!=NULL) {
|
||||
if (hHybrid->fft)
|
||||
FreeRam_PsHybFFT(&hHybrid->fft);
|
||||
if (hHybrid->pWorkReal)
|
||||
FreeRam_PsHybWkReal(&hHybrid->pWorkReal);
|
||||
if (hHybrid->pWorkImag)
|
||||
FreeRam_PsHybWkImag(&hHybrid->pWorkImag);
|
||||
|
||||
for (i = 0; i < HYBRID_FRAMESIZE; i++) {
|
||||
if (hHybrid->mTempReal[i])
|
||||
FreeRam_PsMtmpReal(&hHybrid->mTempReal[i]);
|
||||
if (hHybrid->mTempImag[i])
|
||||
FreeRam_PsMtmpImag(&hHybrid->mTempImag[i]);
|
||||
}
|
||||
|
||||
FreeRam_PsHybrid(phHybrid);
|
||||
}
|
||||
|
||||
return noError;
|
||||
}
|
||||
|
||||
/*** Access functions ***/
|
||||
INT FDKsbrEnc_GetHybridFilterDelay(HANDLE_PS_HYBRID hHybrid){
|
||||
|
||||
return hHybrid->hybridFilterDelay;
|
||||
}
|
||||
|
@ -1,182 +0,0 @@
|
||||
/***************************** 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;
|
||||
|
||||
|
@ -37,7 +37,6 @@
|
||||
#include "qmf.h"
|
||||
|
||||
#include "ps_main.h"
|
||||
#include "psenc_hybrid.h"
|
||||
|
||||
#define SBRENCODER_LIB_VL0 3
|
||||
#define SBRENCODER_LIB_VL1 2
|
||||
@ -101,33 +100,79 @@
|
||||
\return Index to the appropriate table
|
||||
|
||||
****************************************************************************/
|
||||
#define DISTANCE_CEIL_VALUE 5000000
|
||||
static INT
|
||||
getSbrTuningTableIndex(UINT bitrate, /*! the total bitrate in bits/sec */
|
||||
UINT numChannels,/*! the number of channels for the core coder */
|
||||
UINT sampleRate, /*! the sampling rate of the core coder */
|
||||
AUDIO_OBJECT_TYPE core
|
||||
AUDIO_OBJECT_TYPE core,
|
||||
UINT *pBitRateClosest
|
||||
)
|
||||
{
|
||||
int i, paramSetTop;
|
||||
int i, paramSetTop, bitRateClosestLowerIndex=-1, bitRateClosestUpperIndex=-1, found = 0;
|
||||
UINT bitRateClosestUpper = 0, bitRateClosestLower=DISTANCE_CEIL_VALUE;
|
||||
|
||||
FDK_ASSERT(SBRENC_TUNING_SIZE == sizeof(sbrTuningTable)/sizeof(sbrTuningTable[0]));
|
||||
|
||||
if (core == AOT_ER_AAC_ELD) {
|
||||
paramSetTop = SBRENC_TUNING_SIZE;
|
||||
i = 126;
|
||||
i = SBRENC_AACLC_TUNING_SIZE;
|
||||
} else {
|
||||
paramSetTop = 126;
|
||||
paramSetTop = SBRENC_AACLC_TUNING_SIZE;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
for (; i < paramSetTop ; i++) {
|
||||
if (numChannels == sbrTuningTable [i].numChannels) {
|
||||
if ((sampleRate == sbrTuningTable [i].sampleRate) &&
|
||||
(bitrate >= sbrTuningTable [i].bitrateFrom) &&
|
||||
if ( numChannels == sbrTuningTable [i].numChannels
|
||||
&& sampleRate == sbrTuningTable [i].sampleRate )
|
||||
{
|
||||
found = 1;
|
||||
if ((bitrate >= sbrTuningTable [i].bitrateFrom) &&
|
||||
(bitrate < sbrTuningTable [i].bitrateTo)) {
|
||||
bitRateClosestLower = bitrate;
|
||||
bitRateClosestUpper = bitrate;
|
||||
//FDKprintf("entry %d\n", i);
|
||||
return i ;
|
||||
} else {
|
||||
if ( sbrTuningTable [i].bitrateFrom > bitrate ) {
|
||||
if (sbrTuningTable [i].bitrateFrom < bitRateClosestLower) {
|
||||
bitRateClosestLower = sbrTuningTable [i].bitrateFrom;
|
||||
bitRateClosestLowerIndex = i;
|
||||
}
|
||||
}
|
||||
if ( sbrTuningTable [i].bitrateTo <= bitrate ) {
|
||||
if (sbrTuningTable [i].bitrateTo > bitRateClosestUpper) {
|
||||
bitRateClosestUpper = sbrTuningTable [i].bitrateTo-1;
|
||||
bitRateClosestUpperIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pBitRateClosest != NULL)
|
||||
{
|
||||
/* Is there was at least one matching tuning entry found then pick the least distance bit rate */
|
||||
if (found)
|
||||
{
|
||||
int distanceUpper=DISTANCE_CEIL_VALUE, distanceLower=DISTANCE_CEIL_VALUE;
|
||||
if (bitRateClosestLowerIndex >= 0) {
|
||||
distanceLower = sbrTuningTable [bitRateClosestLowerIndex].bitrateFrom - bitrate;
|
||||
}
|
||||
if (bitRateClosestUpperIndex >= 0) {
|
||||
distanceUpper = bitrate - sbrTuningTable [bitRateClosestUpperIndex].bitrateTo;
|
||||
}
|
||||
if ( distanceUpper < distanceLower )
|
||||
{
|
||||
*pBitRateClosest = bitRateClosestUpper;
|
||||
} else {
|
||||
*pBitRateClosest = bitRateClosestLower;
|
||||
}
|
||||
} else {
|
||||
*pBitRateClosest = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return INVALID_TABLE_IDX;
|
||||
}
|
||||
|
||||
@ -141,14 +186,46 @@ getSbrTuningTableIndex(UINT bitrate, /*! the total bitrate in bits/sec */
|
||||
|
||||
****************************************************************************/
|
||||
static INT
|
||||
getPsTuningTableIndex(UINT bitrate){
|
||||
getPsTuningTableIndex(UINT bitrate, UINT *pBitRateClosest){
|
||||
|
||||
INT i, paramSets = sizeof (psTuningTable) / sizeof (psTuningTable [0]);
|
||||
int bitRateClosestLowerIndex=-1, bitRateClosestUpperIndex=-1;
|
||||
UINT bitRateClosestUpper = 0, bitRateClosestLower=DISTANCE_CEIL_VALUE;
|
||||
|
||||
for (i = 0 ; i < paramSets ; i++) {
|
||||
if ((bitrate >= psTuningTable [i].bitrateFrom) &&
|
||||
(bitrate < psTuningTable [i].bitrateTo)) {
|
||||
return i ;
|
||||
} else {
|
||||
if ( psTuningTable [i].bitrateFrom > bitrate ) {
|
||||
if (psTuningTable [i].bitrateFrom < bitRateClosestLower) {
|
||||
bitRateClosestLower = psTuningTable [i].bitrateFrom;
|
||||
bitRateClosestLowerIndex = i;
|
||||
}
|
||||
}
|
||||
if ( psTuningTable [i].bitrateTo <= bitrate ) {
|
||||
if (psTuningTable [i].bitrateTo > bitRateClosestUpper) {
|
||||
bitRateClosestUpper = psTuningTable [i].bitrateTo-1;
|
||||
bitRateClosestUpperIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pBitRateClosest != NULL)
|
||||
{
|
||||
int distanceUpper=DISTANCE_CEIL_VALUE, distanceLower=DISTANCE_CEIL_VALUE;
|
||||
if (bitRateClosestLowerIndex >= 0) {
|
||||
distanceLower = sbrTuningTable [bitRateClosestLowerIndex].bitrateFrom - bitrate;
|
||||
}
|
||||
if (bitRateClosestUpperIndex >= 0) {
|
||||
distanceUpper = bitrate - sbrTuningTable [bitRateClosestUpperIndex].bitrateTo;
|
||||
}
|
||||
if ( distanceUpper < distanceLower )
|
||||
{
|
||||
*pBitRateClosest = bitRateClosestUpper;
|
||||
} else {
|
||||
*pBitRateClosest = bitRateClosestLower;
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,7 +274,7 @@ FDKsbrEnc_IsSbrSettingAvail (UINT bitrate, /*! the total bitrate in bit
|
||||
|
||||
/* try DOWN_SMPL_FAC of the input sampling rate */
|
||||
sampleRateCore = sampleRateInput/DOWN_SMPL_FAC;
|
||||
idx = getSbrTuningTableIndex(bitrate, numOutputChannels, sampleRateCore, core);
|
||||
idx = getSbrTuningTableIndex(bitrate, numOutputChannels, sampleRateCore, core, NULL);
|
||||
|
||||
return (idx == INVALID_TABLE_IDX ? 0 : 1);
|
||||
}
|
||||
@ -257,7 +334,7 @@ FDKsbrEnc_AdjustSbrSettings (const sbrConfigurationPtr config, /*! output, modif
|
||||
}
|
||||
}
|
||||
|
||||
idx = getSbrTuningTableIndex(bitRate,numChannels,fsCore, core);
|
||||
idx = getSbrTuningTableIndex(bitRate,numChannels,fsCore, core, NULL);
|
||||
|
||||
if (idx != INVALID_TABLE_IDX) {
|
||||
config->startFreq = sbrTuningTable[idx].startFreq ;
|
||||
@ -492,8 +569,6 @@ void sbrEncoder_Close (HANDLE_SBR_ENCODER *phSbrEncoder)
|
||||
|
||||
}
|
||||
|
||||
if (hSbrEncoder->hPsEncConfig)
|
||||
FreeRam_PsEncConf(&hSbrEncoder->hPsEncConfig);
|
||||
if (hSbrEncoder->hParametricStereo)
|
||||
PSEnc_Destroy(&hSbrEncoder->hParametricStereo);
|
||||
if (hSbrEncoder->qmfSynthesisPS.FilterStates)
|
||||
@ -801,8 +876,8 @@ FDKsbrEnc_EnvEncodeFrame(HANDLE_SBR_ENCODER hEnvEncoder,
|
||||
|
||||
|
||||
/* Obtain pointers to QMF buffers. */
|
||||
pQmfReal = sbrExtrEnv->rBuffer+sbrExtrEnv->rBufferWriteOffset;
|
||||
pQmfImag = sbrExtrEnv->iBuffer+sbrExtrEnv->rBufferWriteOffset;
|
||||
pQmfReal = sbrExtrEnv->rBuffer;
|
||||
pQmfImag = sbrExtrEnv->iBuffer;
|
||||
|
||||
qmfAnalysisFiltering( hSbrElement->hQmfAnalysis[ch],
|
||||
pQmfReal,
|
||||
@ -822,33 +897,8 @@ FDKsbrEnc_EnvEncodeFrame(HANDLE_SBR_ENCODER hEnvEncoder,
|
||||
/*
|
||||
Parametric Stereo processing
|
||||
*/
|
||||
if(hSbrElement->elInfo.fParametricStereo)
|
||||
if (hSbrElement->elInfo.fParametricStereo)
|
||||
{
|
||||
int psCh;
|
||||
|
||||
/* Parametric Stereo QMF buffer preprocessing: copy previous qmf data down */
|
||||
UpdatePSQmfData_second(hEnvEncoder->hParametricStereo);
|
||||
|
||||
for (psCh = 0; psCh<2; psCh ++)
|
||||
{
|
||||
C_ALLOC_SCRATCH_START(qmfWorkBuffer, FIXP_DBL, QMF_CHANNELS*2);
|
||||
HANDLE_PS_QMF_DATA hPsQmfData = hEnvEncoder->hParametricStereo->hPsChannelData[psCh]->hPsQmfData;
|
||||
QMF_SCALE_FACTOR tmpScale;
|
||||
|
||||
|
||||
qmfAnalysisFiltering( hSbrElement->hQmfAnalysis[psCh],
|
||||
hPsQmfData->rQmfData + hPsQmfData->bufferWriteOffset,
|
||||
hPsQmfData->iQmfData + hPsQmfData->bufferWriteOffset,
|
||||
&tmpScale,
|
||||
samples + hSbrElement->elInfo.ChannelIndex[psCh],
|
||||
timeInStride,
|
||||
qmfWorkBuffer );
|
||||
|
||||
C_ALLOC_SCRATCH_END(qmfWorkBuffer, FIXP_DBL, QMF_CHANNELS*2);
|
||||
|
||||
hEnvEncoder->hParametricStereo->hPsChannelData[psCh]->psQmfScale = -tmpScale.lb_scale;
|
||||
}
|
||||
|
||||
|
||||
/* Limit Parametric Stereo to one instance */
|
||||
FDK_ASSERT(ch == 0);
|
||||
@ -867,10 +917,13 @@ FDKsbrEnc_EnvEncodeFrame(HANDLE_SBR_ENCODER hEnvEncoder,
|
||||
o downmixed qmf data is written to sbrExtrEnv->rBuffer and sbrExtrEnv->iBuffer
|
||||
*/
|
||||
SCHAR qmfScale;
|
||||
INT_PCM* pSamples[2] = {samples + hSbrElement->elInfo.ChannelIndex[0],samples + hSbrElement->elInfo.ChannelIndex[1]};
|
||||
error = FDKsbrEnc_PSEnc_ParametricStereoProcessing( hEnvEncoder->hParametricStereo,
|
||||
pSamples,
|
||||
timeInStride,
|
||||
hSbrElement->hQmfAnalysis,
|
||||
sbrExtrEnv->rBuffer,
|
||||
sbrExtrEnv->iBuffer,
|
||||
sbrExtrEnv->rBufferWriteOffset,
|
||||
samples + hSbrElement->elInfo.ChannelIndex[ch],
|
||||
&hEnvEncoder->qmfSynthesisPS,
|
||||
&qmfScale,
|
||||
@ -1266,11 +1319,6 @@ INT sbrEncoder_Open(
|
||||
}
|
||||
|
||||
if (supportPS) {
|
||||
hSbrEncoder->hPsEncConfig = GetRam_PsEncConf();
|
||||
if (hSbrEncoder->hPsEncConfig==NULL) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (PSEnc_Create(&hSbrEncoder->hParametricStereo))
|
||||
{
|
||||
goto bail;
|
||||
@ -1582,6 +1630,32 @@ INT FDKsbrEnc_DelayCompensation (
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT sbrEncoder_LimitBitRate(UINT bitRate, UINT numChannels, UINT coreSampleRate, AUDIO_OBJECT_TYPE aot)
|
||||
{
|
||||
UINT newBitRate;
|
||||
INT index;
|
||||
|
||||
FDK_ASSERT(numChannels > 0 && numChannels <= 2);
|
||||
if (aot == AOT_PS) {
|
||||
if (numChannels == 2) {
|
||||
index = getPsTuningTableIndex(bitRate, &newBitRate);
|
||||
if (index == INVALID_TABLE_IDX) {
|
||||
bitRate = newBitRate;
|
||||
}
|
||||
/* Set numChannels to 1 because for PS we need a SBR SCE (mono) element. */
|
||||
numChannels = 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
index = getSbrTuningTableIndex(bitRate, numChannels, coreSampleRate, aot, &newBitRate);
|
||||
if (index != INVALID_TABLE_IDX) {
|
||||
newBitRate = bitRate;
|
||||
}
|
||||
|
||||
return newBitRate;
|
||||
}
|
||||
|
||||
|
||||
INT sbrEncoder_Init(
|
||||
HANDLE_SBR_ENCODER hSbrEncoder,
|
||||
@ -1894,22 +1968,23 @@ INT sbrEncoder_Init(
|
||||
/* initialize parametric stereo */
|
||||
if (usePs)
|
||||
{
|
||||
PSENC_CONFIG psEncConfig;
|
||||
FDK_ASSERT(hSbrEncoder->noElements == 1);
|
||||
INT psTuningTableIdx = getPsTuningTableIndex(elInfo[0].bitRate); //sbrConfig.codecSettings.bitRate);
|
||||
INT psTuningTableIdx = getPsTuningTableIndex(elInfo[0].bitRate, NULL);
|
||||
|
||||
hSbrEncoder->hPsEncConfig->frameSize = *frameLength; //sbrConfig.sbrFrameSize;
|
||||
hSbrEncoder->hPsEncConfig->qmfFilterMode = 0;
|
||||
hSbrEncoder->hPsEncConfig->sbrPsDelay = 0;
|
||||
psEncConfig.frameSize = *frameLength; //sbrConfig.sbrFrameSize;
|
||||
psEncConfig.qmfFilterMode = 0;
|
||||
psEncConfig.sbrPsDelay = 0;
|
||||
|
||||
/* tuning parameters */
|
||||
if (psTuningTableIdx != INVALID_TABLE_IDX) {
|
||||
hSbrEncoder->hPsEncConfig->nStereoBands = psTuningTable[psTuningTableIdx].nStereoBands;
|
||||
hSbrEncoder->hPsEncConfig->maxEnvelopes = psTuningTable[psTuningTableIdx].nEnvelopes;
|
||||
hSbrEncoder->hPsEncConfig->iidQuantErrorThreshold = (FIXP_DBL)psTuningTable[psTuningTableIdx].iidQuantErrorThreshold;
|
||||
psEncConfig.nStereoBands = psTuningTable[psTuningTableIdx].nStereoBands;
|
||||
psEncConfig.maxEnvelopes = psTuningTable[psTuningTableIdx].nEnvelopes;
|
||||
psEncConfig.iidQuantErrorThreshold = (FIXP_DBL)psTuningTable[psTuningTableIdx].iidQuantErrorThreshold;
|
||||
|
||||
/* calculation is not quite linear, increased number of envelopes causes more bits */
|
||||
/* assume avg. 50 bits per frame for 10 stereo bands / 1 envelope configuration */
|
||||
hSbrEncoder->estimateBitrate += ( (((*sampleRate) * 5 * hSbrEncoder->hPsEncConfig->nStereoBands * hSbrEncoder->hPsEncConfig->maxEnvelopes) / hSbrEncoder->frameSize));
|
||||
hSbrEncoder->estimateBitrate += ( (((*sampleRate) * 5 * psEncConfig.nStereoBands * psEncConfig.maxEnvelopes) / hSbrEncoder->frameSize));
|
||||
|
||||
} else {
|
||||
error = ERROR(CDI, "Invalid ps tuning table index.");
|
||||
@ -1926,10 +2001,10 @@ INT sbrEncoder_Init(
|
||||
|
||||
if(errorInfo == noError){
|
||||
/* update delay */
|
||||
hSbrEncoder->hPsEncConfig->sbrPsDelay = FDKsbrEnc_GetEnvEstDelay(&hSbrEncoder->sbrElement[0]->sbrChannel[0]->hEnvChannel.sbrExtractEnvelope);
|
||||
psEncConfig.sbrPsDelay = FDKsbrEnc_GetEnvEstDelay(&hSbrEncoder->sbrElement[0]->sbrChannel[0]->hEnvChannel.sbrExtractEnvelope);
|
||||
|
||||
if(noError != (errorInfo = PSEnc_Init( hSbrEncoder->hParametricStereo,
|
||||
hSbrEncoder->hPsEncConfig,
|
||||
&psEncConfig,
|
||||
hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfSlots,
|
||||
hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands
|
||||
,hSbrEncoder->dynamicRam
|
||||
|
@ -26,7 +26,7 @@
|
||||
/*!
|
||||
\file
|
||||
\brief Memory layout
|
||||
$Revision: 36847 $
|
||||
$Revision: 37142 $
|
||||
|
||||
This module declares all static and dynamic memory spaces
|
||||
*/
|
||||
@ -114,39 +114,10 @@ C_ALLOC_MEM2 (Ram_Sbr_guideVectorOrig, FIXP_DBL, (MAX_NO_OF_ESTIMATES*MAX_FREQ_C
|
||||
*/
|
||||
C_AALLOC_MEM_L(Ram_PsQmfStatesSynthesis, FIXP_DBL, QMF_FILTER_LENGTH/2, SECT_DATA_L1)
|
||||
|
||||
C_ALLOC_MEM (Ram_PsEnvRBuffer, FIXP_DBL, QMF_MAX_TIME_SLOTS*QMF_CHANNELS/2)
|
||||
C_ALLOC_MEM (Ram_PsEnvIBuffer, FIXP_DBL, QMF_MAX_TIME_SLOTS*QMF_CHANNELS/2)
|
||||
C_ALLOC_MEM2 (Ram_PsChData, PS_CHANNEL_DATA, 1, MAX_PS_CHANNELS)
|
||||
C_ALLOC_MEM (Ram_PsEncConf, PSENC_CONFIG, 1)
|
||||
C_ALLOC_MEM_L (Ram_PsEncode, PS_ENCODE, 1, SECT_DATA_L1)
|
||||
C_ALLOC_MEM (Ram_PsData, PS_DATA, 1)
|
||||
C_ALLOC_MEM (Ram_ParamStereo, PARAMETRIC_STEREO, 1)
|
||||
C_ALLOC_MEM2 (Ram_PsOut, PS_OUT, 1, 2)
|
||||
|
||||
|
||||
/* QMF data
|
||||
*/
|
||||
C_ALLOC_MEM (Ram_PsQmfNewSamples, FIXP_DBL, QMF_CHANNELS)
|
||||
|
||||
C_ALLOC_MEM2 (Ram_PsQmfData, PS_QMF_DATA, 1, MAX_PS_CHANNELS)
|
||||
|
||||
/* HYBRID data
|
||||
*/
|
||||
C_AALLOC_MEM (Ram_PsHybFFT, FIXP_DBL, 16)
|
||||
|
||||
C_ALLOC_MEM2(Ram_HybData, PS_HYBRID_DATA, 1, MAX_PS_CHANNELS)
|
||||
C_ALLOC_MEM2(Ram_PsHybrid, PS_HYBRID, 1, MAX_PS_CHANNELS)
|
||||
C_ALLOC_MEM (Ram_PsHybConfig, PS_HYBRID_CONFIG, 1)
|
||||
|
||||
C_ALLOC_MEM2(Ram_PsRhyb, FIXP_QMF, ((HYBRID_FRAMESIZE+HYBRID_WRITEOFFSET)*HYBRID_NUM_BANDS), MAX_PS_CHANNELS)
|
||||
C_ALLOC_MEM2(Ram_PsIhyb, FIXP_QMF, ((HYBRID_FRAMESIZE+HYBRID_WRITEOFFSET)*HYBRID_NUM_BANDS), MAX_PS_CHANNELS)
|
||||
|
||||
C_ALLOC_MEM (Ram_PsHybWkReal, FIXP_QMF, (HYBRID_FRAMESIZE + QMF_BUFFER_MOVE))
|
||||
C_ALLOC_MEM (Ram_PsHybWkImag, FIXP_QMF, (HYBRID_FRAMESIZE + QMF_BUFFER_MOVE))
|
||||
|
||||
C_ALLOC_MEM2(Ram_PsMtmpReal, FIXP_QMF, (MAX_HYBRID_RES), HYBRID_FRAMESIZE)
|
||||
C_ALLOC_MEM2(Ram_PsMtmpImag, FIXP_QMF, (MAX_HYBRID_RES), HYBRID_FRAMESIZE)
|
||||
|
||||
|
||||
/* @} */
|
||||
|
||||
@ -175,38 +146,11 @@ C_ALLOC_MEM2(Ram_PsMtmpImag, FIXP_QMF, (MAX_HYBRID_RES), HYBRID_FRAMESIZE)
|
||||
/* The SBR encoder uses a single channel overlapping buffer set (always n=0), but PS does not. */
|
||||
FIXP_DBL* GetRam_Sbr_envRBuffer (int n, UCHAR* dynamic_RAM) {
|
||||
FDK_ASSERT(dynamic_RAM!=0);
|
||||
return ((FIXP_DBL*) (dynamic_RAM + OFFSET_QMF + (n*ENV_R_BUFF_BYTE*2) ));
|
||||
return ((FIXP_DBL*) (dynamic_RAM + OFFSET_QMF + (n*(ENV_R_BUFF_BYTE+ENV_I_BUFF_BYTE)) ));
|
||||
}
|
||||
FIXP_DBL* GetRam_Sbr_envIBuffer (int n, UCHAR* dynamic_RAM) {
|
||||
FDK_ASSERT(dynamic_RAM!=0);
|
||||
//return ((FIXP_DBL*) (dynamic_RAM + OFFSET_QMF + (MAX_NUM_CHANNELS*ENV_R_BUFF_BYTE) + n*ENV_I_BUFF_BYTE));
|
||||
return ((FIXP_DBL*) (dynamic_RAM + OFFSET_QMF + (ENV_R_BUFF_BYTE) + (n*ENV_I_BUFF_BYTE*2)));
|
||||
}
|
||||
|
||||
/* reuse QMF buffer in PS module. We Require space to hold 2 channels. */
|
||||
C_ALLOC_MEM2(Ram_PsRqmf, FIXP_QMF, ((PSENC_QMF_BUFFER_LENGTH-QMF_MAX_TIME_SLOTS)*(QMF_CHANNELS)), MAX_PS_CHANNELS)
|
||||
C_ALLOC_MEM2(Ram_PsIqmf, FIXP_QMF, ((PSENC_QMF_BUFFER_LENGTH-QMF_MAX_TIME_SLOTS)*(QMF_CHANNELS)), MAX_PS_CHANNELS)
|
||||
|
||||
FIXP_QMF* FDKsbrEnc_SliceRam_PsRqmf(FIXP_DBL* rQmfData, UCHAR* dynamic_RAM, int ch, int i, int qmfSlots)
|
||||
{
|
||||
FDK_ASSERT(dynamic_RAM!=0);
|
||||
if (i<HYBRID_READ_OFFSET)
|
||||
return rQmfData + (i*(QMF_CHANNELS));
|
||||
else if ((i<(HYBRID_READ_OFFSET+qmfSlots)))
|
||||
return GetRam_Sbr_envRBuffer(ch, dynamic_RAM) + ( (i-(HYBRID_READ_OFFSET))*(QMF_CHANNELS) );
|
||||
else
|
||||
return rQmfData + ((i-qmfSlots)*(QMF_CHANNELS));
|
||||
}
|
||||
|
||||
FIXP_QMF* FDKsbrEnc_SliceRam_PsIqmf(FIXP_DBL* iQmfData, UCHAR* dynamic_RAM, int ch, int i, int qmfSlots)
|
||||
{
|
||||
FDK_ASSERT(dynamic_RAM!=0);
|
||||
if (i<HYBRID_READ_OFFSET)
|
||||
return iQmfData + (i*(QMF_CHANNELS));
|
||||
else if ((i<(HYBRID_READ_OFFSET+qmfSlots)))
|
||||
return GetRam_Sbr_envIBuffer(ch, dynamic_RAM) + ( (i-(HYBRID_READ_OFFSET))*(QMF_CHANNELS) );
|
||||
else
|
||||
return iQmfData + ((i-qmfSlots)*(QMF_CHANNELS));
|
||||
return ((FIXP_DBL*) (dynamic_RAM + OFFSET_QMF + (ENV_R_BUFF_BYTE) + (n*(ENV_R_BUFF_BYTE+ENV_I_BUFF_BYTE))));
|
||||
}
|
||||
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
/*!
|
||||
\file
|
||||
\brief Memory layout
|
||||
$Revision: 36847 $
|
||||
$Revision: 37142 $
|
||||
*/
|
||||
#ifndef __SBR_RAM_H
|
||||
#define __SBR_RAM_H
|
||||
@ -44,10 +44,10 @@ $Revision: 36847 $
|
||||
|
||||
#define ENV_TRANSIENTS_BYTE ( (sizeof(FIXP_DBL)*(MAX_NUM_CHANNELS*3*QMF_MAX_TIME_SLOTS)) )
|
||||
|
||||
#define ENV_R_BUFF_BYTE ( (sizeof(FIXP_DBL)*((QMF_MAX_TIME_SLOTS) * QMF_CHANNELS)) )
|
||||
#define ENV_I_BUFF_BYTE ( (sizeof(FIXP_DBL)*((QMF_MAX_TIME_SLOTS) * QMF_CHANNELS)) )
|
||||
#define ENV_R_BUFF_BYTE ( (sizeof(FIXP_DBL)*((QMF_MAX_TIME_SLOTS) * MAX_HYBRID_BANDS)) )
|
||||
#define ENV_I_BUFF_BYTE ( (sizeof(FIXP_DBL)*((QMF_MAX_TIME_SLOTS) * MAX_HYBRID_BANDS)) )
|
||||
#define Y_BUF_CH_BYTE ( (2*sizeof(FIXP_DBL)*((QMF_MAX_TIME_SLOTS) * MAX_HYBRID_BANDS)) )
|
||||
|
||||
#define Y_BUF_CH_BYTE ( (sizeof(FIXP_DBL)*QMF_MAX_TIME_SLOTS * QMF_CHANNELS) )
|
||||
|
||||
#define ENV_R_BUF_PS_BYTE ( (sizeof(FIXP_DBL)*QMF_MAX_TIME_SLOTS * QMF_CHANNELS / 2) )
|
||||
#define ENV_I_BUF_PS_BYTE ( (sizeof(FIXP_DBL)*QMF_MAX_TIME_SLOTS * QMF_CHANNELS / 2) )
|
||||
@ -60,27 +60,24 @@ $Revision: 36847 $
|
||||
/* Workbuffer RAM - Allocation */
|
||||
/*
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
| OFFSET_NRG | OFFSET_QMF |
|
||||
| OFFSET_QMF | OFFSET_NRG |
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--------------------------------------------------
|
||||
| 0.5 * | |
|
||||
| sbr_envYBuffer_size | sbr_envRBuffer |
|
||||
| | sbr_envIBuffer |
|
||||
--------------------------------------------------
|
||||
------------------------- -------------------------
|
||||
| | 0.5 * |
|
||||
| sbr_envRBuffer | sbr_envYBuffer_size |
|
||||
| sbr_envIBuffer | |
|
||||
------------------------- -------------------------
|
||||
|
||||
*/
|
||||
#define BUF_NRG_SIZE ( (MAX_NUM_CHANNELS * Y_2_BUF_BYTE) )
|
||||
|
||||
#define OFFSET_NRG ( 0 )
|
||||
#define OFFSET_QMF ( OFFSET_NRG + BUF_NRG_SIZE )
|
||||
|
||||
/* if common dynamic memory used in AAC-core and SBR, find out maximal size of
|
||||
SCR buffer (see XX in figure above) */
|
||||
/* Only PS required holding 2 channel QMF data. AAC_WK_BUF_SIZE_0 must fit into this buffer. */
|
||||
#define BUF_QMF_SIZE ( 2*(ENV_R_BUFF_BYTE + ENV_I_BUFF_BYTE) )
|
||||
#define BUF_QMF_SIZE (ENV_R_BUFF_BYTE + ENV_I_BUFF_BYTE)
|
||||
|
||||
/* Size of the shareable memory region than can be reused */
|
||||
#define SBR_ENC_DYN_RAM_SIZE ( BUF_NRG_SIZE + BUF_QMF_SIZE )
|
||||
#define SBR_ENC_DYN_RAM_SIZE ( BUF_QMF_SIZE + BUF_NRG_SIZE )
|
||||
|
||||
#define OFFSET_QMF ( 0 )
|
||||
#define OFFSET_NRG ( OFFSET_QMF + BUF_QMF_SIZE )
|
||||
|
||||
|
||||
/*
|
||||
*****************************************************************************************************
|
||||
@ -117,53 +114,14 @@ $Revision: 36847 $
|
||||
H_ALLOC_MEM(Ram_Sbr_guideVectorOrig, FIXP_DBL)
|
||||
|
||||
|
||||
H_ALLOC_MEM(Ram_PsEnvRBuffer, FIXP_QMF)
|
||||
H_ALLOC_MEM(Ram_PsEnvIBuffer, FIXP_QMF)
|
||||
|
||||
H_ALLOC_MEM(Ram_PsQmfStatesSynthesis, FIXP_DBL)
|
||||
H_ALLOC_MEM(Ram_PsQmfNewSamples, FIXP_DBL)
|
||||
|
||||
H_ALLOC_MEM(Ram_PsEncConf, PSENC_CONFIG)
|
||||
H_ALLOC_MEM(Ram_PsEncode, PS_ENCODE)
|
||||
H_ALLOC_MEM(Ram_PsData, PS_DATA)
|
||||
|
||||
#define HYBRID_READ_OFFSET ( 10 )
|
||||
#define HYBRID_WRITE_OFFSET ( ((32)>>1)-6 )
|
||||
|
||||
#define HYBRID_DATA_READ_OFFSET ( 0 )
|
||||
#define QMF_READ_OFFSET ( 0 )
|
||||
|
||||
H_ALLOC_MEM(Ram_PsRqmf, FIXP_DBL)
|
||||
H_ALLOC_MEM(Ram_PsIqmf, FIXP_DBL)
|
||||
FIXP_DBL* FDKsbrEnc_SliceRam_PsRqmf (FIXP_DBL* rQmfData, UCHAR* dynamic_RAM, int n, int i, int qmfSlots);
|
||||
FIXP_DBL* FDKsbrEnc_SliceRam_PsIqmf (FIXP_DBL* iQmfData, UCHAR* dynamic_RAM, int n, int i, int qmfSlots);
|
||||
|
||||
H_ALLOC_MEM(Ram_PsQmfData, PS_QMF_DATA)
|
||||
H_ALLOC_MEM(Ram_PsChData, PS_CHANNEL_DATA)
|
||||
|
||||
H_ALLOC_MEM(Ram_ParamStereo, PARAMETRIC_STEREO)
|
||||
H_ALLOC_MEM(Ram_PsOut, PS_OUT)
|
||||
|
||||
/* HYBRID */
|
||||
H_ALLOC_MEM(Ram_PsHybFFT, FIXP_DBL)
|
||||
|
||||
H_ALLOC_MEM(Ram_HybData, PS_HYBRID_DATA)
|
||||
H_ALLOC_MEM(Ram_PsRhyb, FIXP_DBL)
|
||||
H_ALLOC_MEM(Ram_PsIhyb, FIXP_DBL)
|
||||
|
||||
H_ALLOC_MEM(Ram_PsHybConfig, PS_HYBRID_CONFIG)
|
||||
H_ALLOC_MEM(Ram_PsHybrid, PS_HYBRID)
|
||||
|
||||
FIXP_DBL* psMqmfBufferRealInit (INT ch, INT i);
|
||||
FIXP_DBL* psMqmfBufferImagInit (INT ch, INT i);
|
||||
|
||||
|
||||
/* working buffer */
|
||||
H_ALLOC_MEM(Ram_PsHybWkReal, FIXP_DBL)
|
||||
H_ALLOC_MEM(Ram_PsHybWkImag, FIXP_DBL)
|
||||
|
||||
H_ALLOC_MEM(Ram_PsMtmpReal, FIXP_DBL)
|
||||
H_ALLOC_MEM(Ram_PsMtmpImag, FIXP_DBL)
|
||||
|
||||
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
/*!
|
||||
\file
|
||||
\brief Definition of constant tables
|
||||
$Revision: 36914 $
|
||||
$Revision: 37577 $
|
||||
|
||||
This module contains most of the constant data that can be stored in ROM.
|
||||
*/
|
||||
@ -623,8 +623,8 @@ const sbrTuningTable_t sbrTuningTable[SBRENC_TUNING_SIZE] =
|
||||
/* 22.05/44.1 kHz dual rate */
|
||||
{ 8000, 11369, 22050, 1, 1, 1, 1, 1, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 8 kbit/s */ /**changed (not changed !!)*/
|
||||
{ 11369, 16000, 22050, 1, 1, 0, 3, 3, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 12 kbit/s */
|
||||
{ 16000, 18000, 22050, 1, 1, 0, 4, 3, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s */
|
||||
{ 18000, 22000, 22050, 1, 1, 2, 5, 4, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */
|
||||
{ 16000, 18000, 22050, 1, 2, 4, 4, 3, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s */
|
||||
{ 18000, 22000, 22050, 1, 4, 4, 5, 5, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */
|
||||
{ 22000, 28000, 22050, 1, 4, 4, 6, 5, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 24 kbit/s */
|
||||
{ 28000, 36000, 22050, 1, 7, 8, 8, 8, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 32 kbit/s */
|
||||
{ 36000, 44000, 22050, 1, 9, 9, 9, 9, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 40 kbit/s */
|
||||
@ -634,8 +634,8 @@ const sbrTuningTable_t sbrTuningTable[SBRENC_TUNING_SIZE] =
|
||||
/* 24/48 kHz dual rate */
|
||||
{ 8000, 12000, 24000, 1, 1, 1, 1, 1, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 8 kbit/s */ /**changed (not changed !!)*/
|
||||
{ 12000, 16000, 24000, 1, 1, 0, 3, 3, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 12 kbit/s */
|
||||
{ 16000, 18000, 24000, 1, 1, 0, 4, 3, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s */
|
||||
{ 18000, 22000, 24000, 1, 1, 1, 4, 4, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */
|
||||
{ 16000, 18000, 24000, 1, 2, 4, 4, 3, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s */
|
||||
{ 18000, 22000, 24000, 1, 4, 4, 5, 5, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */
|
||||
{ 22000, 28000, 24000, 1, 4, 4, 6, 5, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 24 kbit/s */
|
||||
{ 28000, 36000, 24000, 1, 6, 8, 8, 8, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 32 kbit/s */
|
||||
{ 36000, 44000, 24000, 1, 8, 9, 9, 9, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 40 kbit/s */
|
||||
@ -643,7 +643,6 @@ const sbrTuningTable_t sbrTuningTable[SBRENC_TUNING_SIZE] =
|
||||
{ 52000, 64001, 24000, 1, 13,11,11,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 48 kbit/s */
|
||||
|
||||
/* 22.05/44.1 kHz dual rate */
|
||||
{ 16000, 24000, 22050, 2, 0, 0, 0, 0, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 20 kbit/s */
|
||||
{ 24000, 28000, 22050, 2, 3, 2, 5, 4, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 24 kbit/s */
|
||||
{ 28000, 32000, 22050, 2, 3, 2, 7, 6, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 28 kbit/s */
|
||||
{ 32000, 36000, 22050, 2, 5, 4, 7, 6, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 32 kbit/s */
|
||||
@ -655,7 +654,6 @@ const sbrTuningTable_t sbrTuningTable[SBRENC_TUNING_SIZE] =
|
||||
{ 82000,128001, 22050, 2, 13,12,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */
|
||||
|
||||
/* 24/48 kHz dual rate */
|
||||
{ 16000, 24000, 24000, 2, 0, 0, 0, 0, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 20 kbit/s */
|
||||
{ 24000, 28000, 24000, 2, 3, 3, 5, 5, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 24 kbit/s */
|
||||
{ 28000, 36000, 24000, 2, 5, 4, 7, 6, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 32 kbit/s */
|
||||
{ 36000, 44000, 24000, 2, 4, 8, 8, 8, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 40 kbit/s */
|
||||
@ -664,6 +662,8 @@ const sbrTuningTable_t sbrTuningTable[SBRENC_TUNING_SIZE] =
|
||||
{ 60000, 76000, 24000, 2, 11,12,10,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 64 kbit/s */
|
||||
{ 76000, 88000, 24000, 2, 12,13,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */
|
||||
{ 88000,128001, 24000, 2, 13,13,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 92 kbit/s */
|
||||
|
||||
|
||||
};
|
||||
|
||||
const psTuningTable_t psTuningTable[4] =
|
||||
|
@ -26,7 +26,7 @@
|
||||
/*!
|
||||
\file
|
||||
\brief Declaration of constant tables
|
||||
$Revision: 36847 $
|
||||
$Revision: 37577 $
|
||||
*/
|
||||
#ifndef __SBR_ROM_H
|
||||
#define __SBR_ROM_H
|
||||
@ -60,7 +60,11 @@ extern const UCHAR v_Huff_NoiseLevelL11T[63];
|
||||
extern const INT bookSbrNoiseBalanceC11T[25];
|
||||
extern const UCHAR bookSbrNoiseBalanceL11T[25];
|
||||
|
||||
#define SBRENC_TUNING_SIZE (126 + 37)
|
||||
#define SBRENC_AACLC_TUNING_SIZE 124
|
||||
#define SBRENC_AACELD_TUNING_SIZE 35
|
||||
#define SBRENC_AACELD2_TUNING_SIZE 31
|
||||
|
||||
#define SBRENC_TUNING_SIZE (SBRENC_AACLC_TUNING_SIZE + SBRENC_AACELD_TUNING_SIZE)
|
||||
|
||||
extern const sbrTuningTable_t sbrTuningTable[SBRENC_TUNING_SIZE];
|
||||
|
||||
|
@ -236,6 +236,7 @@ typedef enum {
|
||||
#define CC_IS_BASELAYER 0x00200000
|
||||
#define CC_PROTECTION 0x00400000
|
||||
#define CC_SBR 0x00800000
|
||||
#define CC_SBRCRC 0x00010000
|
||||
#define CC_RVLC 0x01000000
|
||||
#define CC_VCB11 0x02000000
|
||||
#define CC_HCR 0x04000000
|
||||
@ -284,6 +285,11 @@ typedef enum
|
||||
ID_LAST
|
||||
} MP4_ELEMENT_ID;
|
||||
|
||||
#define IS_CHANNEL_ELEMENT(elementId) \
|
||||
((elementId) == ID_SCE \
|
||||
|| (elementId) == ID_CPE \
|
||||
|| (elementId) == ID_LFE)
|
||||
|
||||
#define EXT_ID_BITS 4 /**< Size in bits of extension payload type tags. */
|
||||
|
||||
/** Extension payload types. */
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user