Files
squeezelite-esp32/components/spotify/cspot/bell/libhelix-aac/sbr.c
Philippe G 898998efb0 big merge
2021-12-18 21:04:23 -08:00

432 lines
14 KiB
C

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