545 files changed, 230976 insertions, 0 deletions
diff --git a/audio_codec/libfaad/helixaac/sbr.c b/audio_codec/libfaad/helixaac/sbr.c new file mode 100644 index 0000000..fcf1fe4 --- a/dev/null +++ b/audio_codec/libfaad/helixaac/sbr.c @@ -0,0 +1,433 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Source last modified: $Id: sbr.c,v 1.4 2008/01/15 21:20:31 ehyche Exp $ + * + * Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, + * are subject to the current version of the RealNetworks Public + * Source License (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the current version of the RealNetworks Community + * Source License (the "RCSL") available at + * http://www.helixcommunity.org/content/rcsl, in which case the RCSL + * will apply. You may also obtain the license terms directly from + * RealNetworks. You may not use this file except in compliance with + * the RPSL or, if you have a valid RCSL with RealNetworks applicable + * to this file, the RCSL. Please see the applicable RPSL or RCSL for + * the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the + * portions it created. + * + * This file, and the files included with this file, is distributed + * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS + * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET + * ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point HE-AAC decoder + * Jon Recker (jrecker@real.com) + * February 2005 + * + * sbr.c - top level functions for SBR + **************************************************************************************/ + +#if defined(REAL_FORMAT_SDK) +#include "rm_memory_shim.h" +#define malloc hx_realformatsdk_malloc +#define free hx_realformatsdk_free +#endif /* #if defined(REAL_FORMAT_SDK) */ + +#include "sbr.h" +#include <stdio.h> + +/************************************************************************************** + * Function: InitSBRState + * + * Description: initialize PSInfoSBR struct at start of stream or after flush + * + * Inputs: valid AACDecInfo struct + * + * Outputs: PSInfoSBR struct with proper initial state + * + * Return: none + **************************************************************************************/ +static void InitSBRState(PSInfoSBR *psi) +{ + int i, ch; + unsigned char *c; + + if (!psi) { + return; + } + + /* clear SBR state structure */ + c = (unsigned char *)psi; + for (i = 0; i < (int)sizeof(PSInfoSBR); i++) { + *c++ = 0; + } + + /* initialize non-zero state variables */ + for (ch = 0; ch < AAC_MAX_NCHANS; ch++) { + psi->sbrChan[ch].reset = 1; + psi->sbrChan[ch].laPrev = -1; + } +} + +/************************************************************************************** + * Function: InitSBR + * + * Description: initialize SBR decoder + * + * Inputs: valid AACDecInfo struct + * + * Outputs: PSInfoSBR struct to hold SBR state information + * + * Return: 0 if successful, error code (< 0) if error + * + * Note: memory allocation for SBR is only done here + **************************************************************************************/ +int InitSBR(AACDecInfo *aacDecInfo) +{ + PSInfoSBR *psi; + + if (!aacDecInfo) { + return ERR_AAC_NULL_POINTER; + } + /* allocate SBR state structure */ + psi = (PSInfoSBR *)malloc(sizeof(PSInfoSBR)); + if (!psi) { + return ERR_AAC_SBR_INIT; + } + + InitSBRState(psi); + + aacDecInfo->psInfoSBR = psi; + return ERR_AAC_NONE; +} + +/************************************************************************************** + * Function: FreeSBR + * + * Description: free SBR decoder + * + * Inputs: valid AACDecInfo struct + * + * Outputs: none + * + * Return: none + * + * Note: memory deallocation for SBR is only done here + **************************************************************************************/ +void FreeSBR(AACDecInfo *aacDecInfo) +{ + if (aacDecInfo && aacDecInfo->psInfoSBR) { + free(aacDecInfo->psInfoSBR); + } + + return; +} + +/************************************************************************************** + * Function: DecodeSBRBitstream + * + * Description: decode sideband information for SBR + * + * Inputs: valid AACDecInfo struct + * fill buffer with SBR extension block + * number of bytes in fill buffer + * base output channel (range = [0, nChans-1]) + * + * Outputs: initialized state structs (SBRHdr, SBRGrid, SBRFreq, SBRChan) + * + * Return: 0 if successful, error code (< 0) if error + * + * Notes: SBR payload should be in aacDecInfo->fillBuf + * returns with no error if fill buffer is not an SBR extension block, + * or if current block is not a fill block (e.g. for LFE upsampling) + **************************************************************************************/ +int DecodeSBRBitstream(AACDecInfo *aacDecInfo, int chBase) +{ + int headerFlag; + BitStreamInfo bsi; + PSInfoSBR *psi; + int err = ERR_AAC_NONE; + /* validate pointers */ + if (!aacDecInfo || !aacDecInfo->psInfoSBR) { + return ERR_AAC_NULL_POINTER; + } + psi = (PSInfoSBR *)(aacDecInfo->psInfoSBR); + + if (aacDecInfo->currBlockID != AAC_ID_FIL || (aacDecInfo->fillExtType != EXT_SBR_DATA && aacDecInfo->fillExtType != EXT_SBR_DATA_CRC)) { + return ERR_AAC_NONE; + } + + SetBitstreamPointer(&bsi, aacDecInfo->fillCount, aacDecInfo->fillBuf); + if (GetBits(&bsi, 4) != (unsigned int)aacDecInfo->fillExtType) { + return ERR_AAC_SBR_BITSTREAM; + } + + if (aacDecInfo->fillExtType == EXT_SBR_DATA_CRC) { + psi->crcCheckWord = GetBits(&bsi, 10); + } + + headerFlag = GetBits(&bsi, 1); + if (headerFlag) { + /* get sample rate index for output sample rate (2x base rate) */ + psi->sampRateIdx = GetSampRateIdx(2 * aacDecInfo->sampRate); + if (psi->sampRateIdx < 0 || psi->sampRateIdx >= NUM_SAMPLE_RATES) { + return ERR_AAC_SBR_BITSTREAM; + } else if (psi->sampRateIdx >= NUM_SAMPLE_RATES_SBR) { + return ERR_AAC_SBR_SINGLERATE_UNSUPPORTED; + } + + /* reset flag = 1 if header values changed */ + if (UnpackSBRHeader(&bsi, &(psi->sbrHdr[chBase]))) { + psi->sbrChan[chBase].reset = 1; + } + + /* first valid SBR header should always trigger CalcFreqTables(), since psi->reset was set in InitSBR() */ + if (psi->sbrChan[chBase].reset) { + CalcFreqTables(&(psi->sbrHdr[chBase + 0]), &(psi->sbrFreq[chBase]), psi->sampRateIdx); + } + + /* copy and reset state to right channel for CPE */ + if (aacDecInfo->prevBlockID == AAC_ID_CPE) { + psi->sbrChan[chBase + 1].reset = psi->sbrChan[chBase + 0].reset; + } + } + + + /* if no header has been received, upsample only */ + if (psi->sbrHdr[chBase].count == 0) { + return ERR_AAC_NONE; + } + + if (aacDecInfo->prevBlockID == AAC_ID_SCE) { + err = UnpackSBRSingleChannel(&bsi, psi, chBase); + } else if (aacDecInfo->prevBlockID == AAC_ID_CPE) { + err = UnpackSBRChannelPair(&bsi, psi, chBase); + } else { + return ERR_AAC_SBR_BITSTREAM; + } + ByteAlignBitstream(&bsi); + + return err; +} + +/************************************************************************************** + * Function: DecodeSBRData + * + * Description: apply SBR to one frame of PCM data + * + * Inputs: 1024 samples of decoded 32-bit PCM, before SBR + * size of input PCM samples (must be 4 bytes) + * number of fraction bits in input PCM samples + * base output channel (range = [0, nChans-1]) + * initialized state structs (SBRHdr, SBRGrid, SBRFreq, SBRChan) + * + * Outputs: 2048 samples of decoded 16-bit PCM, after SBR + * + * Return: 0 if successful, error code (< 0) if error + **************************************************************************************/ +int DecodeSBRData(AACDecInfo *aacDecInfo, int chBase, short *outbuf) +{ + int k, l, ch, chBlock, qmfaBands, qmfsBands; + int upsampleOnly, gbIdx, gbMask; + int *inbuf; + short *outptr; + PSInfoSBR *psi; + SBRHeader *sbrHdr; + SBRGrid *sbrGrid; + SBRFreq *sbrFreq; + SBRChan *sbrChan; + int err = ERR_AAC_NONE; + + /* validate pointers */ + if (!aacDecInfo || !aacDecInfo->psInfoSBR) { + return ERR_AAC_NULL_POINTER; + } + psi = (PSInfoSBR *)(aacDecInfo->psInfoSBR); + + /* same header and freq tables for both channels in CPE */ + sbrHdr = &(psi->sbrHdr[chBase]); + sbrFreq = &(psi->sbrFreq[chBase]); + + /* upsample only if we haven't received an SBR header yet or if we have an LFE block */ + if (aacDecInfo->currBlockID == AAC_ID_LFE) { + chBlock = 1; + upsampleOnly = 1; + } else if (aacDecInfo->currBlockID == AAC_ID_FIL) { + if (aacDecInfo->prevBlockID == AAC_ID_SCE) { + chBlock = 1; + } else if (aacDecInfo->prevBlockID == AAC_ID_CPE) { + chBlock = 2; + } else { + return ERR_AAC_NONE; + } + + upsampleOnly = (sbrHdr->count == 0 ? 1 : 0); + if (aacDecInfo->fillExtType != EXT_SBR_DATA && aacDecInfo->fillExtType != EXT_SBR_DATA_CRC) { + return ERR_AAC_NONE; + } + } else { + /* ignore non-SBR blocks */ + return ERR_AAC_NONE; + } + + if (upsampleOnly) { + sbrFreq->kStart = 32; + sbrFreq->numQMFBands = 0; + } + + for (ch = 0; ch < chBlock; ch++) { + sbrGrid = &(psi->sbrGrid[chBase + ch]); + sbrChan = &(psi->sbrChan[chBase + ch]); + + if (aacDecInfo->rawSampleBuf[ch] == 0 || aacDecInfo->rawSampleBytes != 4) { + return ERR_AAC_SBR_PCM_FORMAT; + } + inbuf = (int *)aacDecInfo->rawSampleBuf[ch]; + outptr = outbuf + chBase + ch; + + /* restore delay buffers (could use ring buffer or keep in temp buffer for nChans == 1) */ + for (l = 0; l < HF_GEN; l++) { + for (k = 0; k < 64; k++) { + psi->XBuf[l][k][0] = psi->XBufDelay[chBase + ch][l][k][0]; + psi->XBuf[l][k][1] = psi->XBufDelay[chBase + ch][l][k][1]; + } + } + + /* step 1 - analysis QMF */ + qmfaBands = sbrFreq->kStart; + for (l = 0; l < 32; l++) { + gbMask = QMFAnalysis(inbuf + l * 32, psi->delayQMFA[chBase + ch], psi->XBuf[l + HF_GEN][0], + aacDecInfo->rawSampleFBits, &(psi->delayIdxQMFA[chBase + ch]), qmfaBands); + + gbIdx = ((l + HF_GEN) >> 5) & 0x01; + sbrChan->gbMask[gbIdx] |= gbMask; /* gbIdx = (0 if i < 32), (1 if i >= 32) */ + } + + if (upsampleOnly) { + /* no SBR - just run synthesis QMF to upsample by 2x */ + qmfsBands = 32; + for (l = 0; l < 32; l++) { + /* step 4 - synthesis QMF */ + QMFSynthesis(psi->XBuf[l + HF_ADJ][0], psi->delayQMFS[chBase + ch], &(psi->delayIdxQMFS[chBase + ch]), qmfsBands, outptr, aacDecInfo->nChans); + outptr += 64 * aacDecInfo->nChans; + } + } else { + /* if previous frame had lower SBR starting freq than current, zero out the synthesized QMF + * bands so they aren't used as sources for patching + * after patch generation, restore from delay buffer + * can only happen after header reset + */ + for (k = sbrFreq->kStartPrev; k < sbrFreq->kStart; k++) { + for (l = 0; l < sbrGrid->envTimeBorder[0] + HF_ADJ; l++) { + psi->XBuf[l][k][0] = 0; + psi->XBuf[l][k][1] = 0; + } + } + + /* step 2 - HF generation */ + err = GenerateHighFreq(psi, sbrGrid, sbrFreq, sbrChan, ch); + if (err) { + return err; + } + + /* restore SBR bands that were cleared before patch generation (time slots 0, 1 no longer needed) */ + for (k = sbrFreq->kStartPrev; k < sbrFreq->kStart; k++) { + for (l = HF_ADJ; l < sbrGrid->envTimeBorder[0] + HF_ADJ; l++) { + psi->XBuf[l][k][0] = psi->XBufDelay[chBase + ch][l][k][0]; + psi->XBuf[l][k][1] = psi->XBufDelay[chBase + ch][l][k][1]; + } + } + + /* step 3 - HF adjustment */ + err = AdjustHighFreq(psi, sbrHdr, sbrGrid, sbrFreq, sbrChan, ch); + if (err) { + return err; + } + + /* step 4 - synthesis QMF */ + qmfsBands = sbrFreq->kStartPrev + sbrFreq->numQMFBandsPrev; + for (l = 0; l < sbrGrid->envTimeBorder[0]; l++) { + /* if new envelope starts mid-frame, use old settings until start of first envelope in this frame */ + QMFSynthesis(psi->XBuf[l + HF_ADJ][0], psi->delayQMFS[chBase + ch], &(psi->delayIdxQMFS[chBase + ch]), qmfsBands, outptr, aacDecInfo->nChans); + outptr += 64 * aacDecInfo->nChans; + } + + qmfsBands = sbrFreq->kStart + sbrFreq->numQMFBands; + for (; l < 32; l++) { + /* use new settings for rest of frame (usually the entire frame, unless the first envelope starts mid-frame) */ + QMFSynthesis(psi->XBuf[l + HF_ADJ][0], psi->delayQMFS[chBase + ch], &(psi->delayIdxQMFS[chBase + ch]), qmfsBands, outptr, aacDecInfo->nChans); + outptr += 64 * aacDecInfo->nChans; + } + } + + /* save delay */ + for (l = 0; l < HF_GEN; l++) { + for (k = 0; k < 64; k++) { + psi->XBufDelay[chBase + ch][l][k][0] = psi->XBuf[l + 32][k][0]; + psi->XBufDelay[chBase + ch][l][k][1] = psi->XBuf[l + 32][k][1]; + } + } + sbrChan->gbMask[0] = sbrChan->gbMask[1]; + sbrChan->gbMask[1] = 0; + + if (sbrHdr->count > 0) { + sbrChan->reset = 0; + } + } + sbrFreq->kStartPrev = sbrFreq->kStart; + sbrFreq->numQMFBandsPrev = sbrFreq->numQMFBands; + + if (aacDecInfo->nChans > 0 && (chBase + ch) == aacDecInfo->nChans) { + psi->frameCount++; + } + + return ERR_AAC_NONE; +} + +/************************************************************************************** + * Function: FlushCodecSBR + * + * Description: flush internal SBR codec state (after seeking, for example) + * + * Inputs: valid AACDecInfo struct + * + * Outputs: updated state variables for SBR + * + * Return: 0 if successful, error code (< 0) if error + * + * Notes: SBR is heavily dependent on state from previous frames + * (e.g. delta coded scalefactors, previous envelope boundaries, etc.) + * On flush, we reset everything as if SBR had just been initialized + * for the first time. This triggers "upsample-only" mode until + * the first valid SBR header is received. Then SBR starts as usual. + **************************************************************************************/ +int FlushCodecSBR(AACDecInfo *aacDecInfo) +{ + PSInfoSBR *psi; + + /* validate pointers */ + if (!aacDecInfo || !aacDecInfo->psInfoSBR) { + return ERR_AAC_NULL_POINTER; + } + psi = (PSInfoSBR *)(aacDecInfo->psInfoSBR); + + InitSBRState(psi); + + return 0; +} |