/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: sbr.c,v 1.3 2005/05/24 16:01:55 albertofloyd 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(USE_DEFAULT_STDLIB) || defined(ESP_PLATFORM) #include #include #else #include "hlxclib/stdlib.h" #endif #include "sbr.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) { printf("OOM in SBR, can't allocate %d bytes\n", sizeof(PSInfoSBR)); return ERR_AAC_SBR_INIT; } InitSBRState(psi); aacDecInfo->psInfoSBR = psi; return ERR_AAC_NONE; } int InitSBRPre(AACDecInfo *aacDecInfo, void **ptr, int *sz) { PSInfoSBR *psi; if (!aacDecInfo) return ERR_AAC_NULL_POINTER; /* allocate SBR state structure */ psi = (PSInfoSBR *)*ptr; *sz -= sizeof(PSInfoSBR); if (*sz < 0) { printf("OOM in SBR, can't allocate %d bytes\n", sizeof(PSInfoSBR)); return ERR_AAC_SBR_INIT; } InitSBRState(psi); *ptr = (void*)((char*)(*ptr) + sizeof(PSInfoSBR)); 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; /* 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) { UnpackSBRSingleChannel(&bsi, psi, chBase); } else if (aacDecInfo->prevBlockID == AAC_ID_CPE) { UnpackSBRChannelPair(&bsi, psi, chBase); } else { return ERR_AAC_SBR_BITSTREAM; } ByteAlignBitstream(&bsi); return ERR_AAC_NONE; } /************************************************************************************** * 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; /* 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 */ GenerateHighFreq(psi, sbrGrid, sbrFreq, sbrChan, ch); /* 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 */ AdjustHighFreq(psi, sbrHdr, sbrGrid, sbrFreq, sbrChan, ch); /* 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; }