| 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;}
 |