123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- /* ***** 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 <stdio.h>
- #include <stdlib.h>
- #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;
- }
|