mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-09 13:07:03 +03:00
426 lines
14 KiB
C
426 lines
14 KiB
C
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Source last modified: $Id: decelmnt.c,v 1.1 2005/02/26 01:47:34 jrecker 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
|
|
*
|
|
* decelmnt.c - syntactic element decoding
|
|
**************************************************************************************/
|
|
|
|
#include "coder.h"
|
|
|
|
/**************************************************************************************
|
|
* Function: DecodeSingleChannelElement
|
|
*
|
|
* Description: decode one SCE
|
|
*
|
|
* Inputs: BitStreamInfo struct pointing to start of SCE (14496-3, table 4.4.4)
|
|
*
|
|
* Outputs: updated element instance tag
|
|
*
|
|
* Return: 0 if successful, -1 if error
|
|
*
|
|
* Notes: doesn't decode individual channel stream (part of DecodeNoiselessData)
|
|
**************************************************************************************/
|
|
static int DecodeSingleChannelElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
|
|
{
|
|
/* validate pointers */
|
|
if (!aacDecInfo || !aacDecInfo->psInfoBase)
|
|
return -1;
|
|
|
|
/* read instance tag */
|
|
aacDecInfo->currInstTag = GetBits(bsi, NUM_INST_TAG_BITS);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************************
|
|
* Function: DecodeChannelPairElement
|
|
*
|
|
* Description: decode one CPE
|
|
*
|
|
* Inputs: BitStreamInfo struct pointing to start of CPE (14496-3, table 4.4.5)
|
|
*
|
|
* Outputs: updated element instance tag
|
|
* updated commonWin
|
|
* updated ICS info, if commonWin == 1
|
|
* updated mid-side stereo info, if commonWin == 1
|
|
*
|
|
* Return: 0 if successful, -1 if error
|
|
*
|
|
* Notes: doesn't decode individual channel stream (part of DecodeNoiselessData)
|
|
**************************************************************************************/
|
|
static int DecodeChannelPairElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
|
|
{
|
|
int sfb, gp, maskOffset;
|
|
unsigned char currBit, *maskPtr;
|
|
PSInfoBase *psi;
|
|
ICSInfo *icsInfo;
|
|
|
|
/* validate pointers */
|
|
if (!aacDecInfo || !aacDecInfo->psInfoBase)
|
|
return -1;
|
|
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
|
|
icsInfo = psi->icsInfo;
|
|
|
|
/* read instance tag */
|
|
aacDecInfo->currInstTag = GetBits(bsi, NUM_INST_TAG_BITS);
|
|
|
|
/* read common window flag and mid-side info (if present)
|
|
* store msMask bits in psi->msMaskBits[] as follows:
|
|
* long blocks - pack bits for each SFB in range [0, maxSFB) starting with lsb of msMaskBits[0]
|
|
* short blocks - pack bits for each SFB in range [0, maxSFB), for each group [0, 7]
|
|
* msMaskPresent = 0 means no M/S coding
|
|
* = 1 means psi->msMaskBits contains 1 bit per SFB to toggle M/S coding
|
|
* = 2 means all SFB's are M/S coded (so psi->msMaskBits is not needed)
|
|
*/
|
|
psi->commonWin = GetBits(bsi, 1);
|
|
if (psi->commonWin) {
|
|
DecodeICSInfo(bsi, icsInfo, psi->sampRateIdx);
|
|
psi->msMaskPresent = GetBits(bsi, 2);
|
|
if (psi->msMaskPresent == 1) {
|
|
maskPtr = psi->msMaskBits;
|
|
*maskPtr = 0;
|
|
maskOffset = 0;
|
|
for (gp = 0; gp < icsInfo->numWinGroup; gp++) {
|
|
for (sfb = 0; sfb < icsInfo->maxSFB; sfb++) {
|
|
currBit = (unsigned char)GetBits(bsi, 1);
|
|
*maskPtr |= currBit << maskOffset;
|
|
if (++maskOffset == 8) {
|
|
maskPtr++;
|
|
*maskPtr = 0;
|
|
maskOffset = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************************
|
|
* Function: DecodeLFEChannelElement
|
|
*
|
|
* Description: decode one LFE
|
|
*
|
|
* Inputs: BitStreamInfo struct pointing to start of LFE (14496-3, table 4.4.9)
|
|
*
|
|
* Outputs: updated element instance tag
|
|
*
|
|
* Return: 0 if successful, -1 if error
|
|
*
|
|
* Notes: doesn't decode individual channel stream (part of DecodeNoiselessData)
|
|
**************************************************************************************/
|
|
static int DecodeLFEChannelElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
|
|
{
|
|
/* validate pointers */
|
|
if (!aacDecInfo || !aacDecInfo->psInfoBase)
|
|
return -1;
|
|
|
|
/* read instance tag */
|
|
aacDecInfo->currInstTag = GetBits(bsi, NUM_INST_TAG_BITS);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************************
|
|
* Function: DecodeDataStreamElement
|
|
*
|
|
* Description: decode one DSE
|
|
*
|
|
* Inputs: BitStreamInfo struct pointing to start of DSE (14496-3, table 4.4.10)
|
|
*
|
|
* Outputs: updated element instance tag
|
|
* filled in data stream buffer
|
|
*
|
|
* Return: 0 if successful, -1 if error
|
|
**************************************************************************************/
|
|
static int DecodeDataStreamElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
|
|
{
|
|
unsigned int byteAlign, dataCount;
|
|
unsigned char *dataBuf;
|
|
PSInfoBase *psi;
|
|
|
|
/* validate pointers */
|
|
if (!aacDecInfo || !aacDecInfo->psInfoBase)
|
|
return -1;
|
|
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
|
|
|
|
aacDecInfo->currInstTag = GetBits(bsi, NUM_INST_TAG_BITS);
|
|
byteAlign = GetBits(bsi, 1);
|
|
dataCount = GetBits(bsi, 8);
|
|
if (dataCount == 255)
|
|
dataCount += GetBits(bsi, 8);
|
|
|
|
if (byteAlign)
|
|
ByteAlignBitstream(bsi);
|
|
|
|
psi->dataCount = dataCount;
|
|
dataBuf = psi->dataBuf;
|
|
while (dataCount--)
|
|
*dataBuf++ = GetBits(bsi, 8);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************************
|
|
* Function: DecodeProgramConfigElement
|
|
*
|
|
* Description: decode one PCE
|
|
*
|
|
* Inputs: BitStreamInfo struct pointing to start of PCE (14496-3, table 4.4.2)
|
|
*
|
|
* Outputs: filled-in ProgConfigElement struct
|
|
* updated BitStreamInfo struct
|
|
*
|
|
* Return: 0 if successful, error code (< 0) if error
|
|
*
|
|
* Notes: #define KEEP_PCE_COMMENTS to save the comment field of the PCE
|
|
* (otherwise we just skip it in the bitstream, to save memory)
|
|
**************************************************************************************/
|
|
int DecodeProgramConfigElement(ProgConfigElement *pce, BitStreamInfo *bsi)
|
|
{
|
|
int i;
|
|
|
|
pce->elemInstTag = GetBits(bsi, 4);
|
|
pce->profile = GetBits(bsi, 2);
|
|
pce->sampRateIdx = GetBits(bsi, 4);
|
|
pce->numFCE = GetBits(bsi, 4);
|
|
pce->numSCE = GetBits(bsi, 4);
|
|
pce->numBCE = GetBits(bsi, 4);
|
|
pce->numLCE = GetBits(bsi, 2);
|
|
pce->numADE = GetBits(bsi, 3);
|
|
pce->numCCE = GetBits(bsi, 4);
|
|
|
|
pce->monoMixdown = GetBits(bsi, 1) << 4; /* present flag */
|
|
if (pce->monoMixdown)
|
|
pce->monoMixdown |= GetBits(bsi, 4); /* element number */
|
|
|
|
pce->stereoMixdown = GetBits(bsi, 1) << 4; /* present flag */
|
|
if (pce->stereoMixdown)
|
|
pce->stereoMixdown |= GetBits(bsi, 4); /* element number */
|
|
|
|
pce->matrixMixdown = GetBits(bsi, 1) << 4; /* present flag */
|
|
if (pce->matrixMixdown) {
|
|
pce->matrixMixdown |= GetBits(bsi, 2) << 1; /* index */
|
|
pce->matrixMixdown |= GetBits(bsi, 1); /* pseudo-surround enable */
|
|
}
|
|
|
|
for (i = 0; i < pce->numFCE; i++) {
|
|
pce->fce[i] = GetBits(bsi, 1) << 4; /* is_cpe flag */
|
|
pce->fce[i] |= GetBits(bsi, 4); /* tag select */
|
|
}
|
|
|
|
for (i = 0; i < pce->numSCE; i++) {
|
|
pce->sce[i] = GetBits(bsi, 1) << 4; /* is_cpe flag */
|
|
pce->sce[i] |= GetBits(bsi, 4); /* tag select */
|
|
}
|
|
|
|
for (i = 0; i < pce->numBCE; i++) {
|
|
pce->bce[i] = GetBits(bsi, 1) << 4; /* is_cpe flag */
|
|
pce->bce[i] |= GetBits(bsi, 4); /* tag select */
|
|
}
|
|
|
|
for (i = 0; i < pce->numLCE; i++)
|
|
pce->lce[i] = GetBits(bsi, 4); /* tag select */
|
|
|
|
for (i = 0; i < pce->numADE; i++)
|
|
pce->ade[i] = GetBits(bsi, 4); /* tag select */
|
|
|
|
for (i = 0; i < pce->numCCE; i++) {
|
|
pce->cce[i] = GetBits(bsi, 1) << 4; /* independent/dependent flag */
|
|
pce->cce[i] |= GetBits(bsi, 4); /* tag select */
|
|
}
|
|
|
|
|
|
ByteAlignBitstream(bsi);
|
|
|
|
#ifdef KEEP_PCE_COMMENTS
|
|
pce->commentBytes = GetBits(bsi, 8);
|
|
for (i = 0; i < pce->commentBytes; i++)
|
|
pce->commentField[i] = GetBits(bsi, 8);
|
|
#else
|
|
/* eat comment bytes and throw away */
|
|
i = GetBits(bsi, 8);
|
|
while (i--)
|
|
GetBits(bsi, 8);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************************
|
|
* Function: DecodeFillElement
|
|
*
|
|
* Description: decode one fill element
|
|
*
|
|
* Inputs: BitStreamInfo struct pointing to start of fill element
|
|
* (14496-3, table 4.4.11)
|
|
*
|
|
* Outputs: updated element instance tag
|
|
* unpacked extension payload
|
|
*
|
|
* Return: 0 if successful, -1 if error
|
|
**************************************************************************************/
|
|
static int DecodeFillElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
|
|
{
|
|
unsigned int fillCount;
|
|
unsigned char *fillBuf;
|
|
PSInfoBase *psi;
|
|
|
|
/* validate pointers */
|
|
if (!aacDecInfo || !aacDecInfo->psInfoBase)
|
|
return -1;
|
|
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
|
|
|
|
fillCount = GetBits(bsi, 4);
|
|
if (fillCount == 15)
|
|
fillCount += (GetBits(bsi, 8) - 1);
|
|
|
|
psi->fillCount = fillCount;
|
|
fillBuf = psi->fillBuf;
|
|
while (fillCount--)
|
|
*fillBuf++ = GetBits(bsi, 8);
|
|
|
|
aacDecInfo->currInstTag = -1; /* fill elements don't have instance tag */
|
|
aacDecInfo->fillExtType = 0;
|
|
|
|
#ifdef AAC_ENABLE_SBR
|
|
/* check for SBR
|
|
* aacDecInfo->sbrEnabled is sticky (reset each raw_data_block), so for multichannel
|
|
* need to verify that all SCE/CPE/ICCE have valid SBR fill element following, and
|
|
* must upsample by 2 for LFE
|
|
*/
|
|
if (psi->fillCount > 0) {
|
|
aacDecInfo->fillExtType = (int)((psi->fillBuf[0] >> 4) & 0x0f);
|
|
if (aacDecInfo->fillExtType == EXT_SBR_DATA || aacDecInfo->fillExtType == EXT_SBR_DATA_CRC)
|
|
aacDecInfo->sbrEnabled = 1;
|
|
}
|
|
#endif
|
|
|
|
aacDecInfo->fillBuf = psi->fillBuf;
|
|
aacDecInfo->fillCount = psi->fillCount;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************************
|
|
* Function: DecodeNextElement
|
|
*
|
|
* Description: decode next syntactic element in AAC frame
|
|
*
|
|
* Inputs: valid AACDecInfo struct
|
|
* double pointer to buffer containing next element
|
|
* pointer to bit offset
|
|
* pointer to number of valid bits remaining in buf
|
|
*
|
|
* Outputs: type of element decoded (aacDecInfo->currBlockID)
|
|
* type of element decoded last time (aacDecInfo->prevBlockID)
|
|
* updated aacDecInfo state, depending on which element was decoded
|
|
* updated buffer pointer
|
|
* updated bit offset
|
|
* updated number of available bits
|
|
*
|
|
* Return: 0 if successful, error code (< 0) if error
|
|
**************************************************************************************/
|
|
int DecodeNextElement(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail)
|
|
{
|
|
int err, bitsUsed;
|
|
PSInfoBase *psi;
|
|
BitStreamInfo bsi;
|
|
|
|
/* validate pointers */
|
|
if (!aacDecInfo || !aacDecInfo->psInfoBase)
|
|
return ERR_AAC_NULL_POINTER;
|
|
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
|
|
|
|
/* init bitstream reader */
|
|
SetBitstreamPointer(&bsi, (*bitsAvail + 7) >> 3, *buf);
|
|
GetBits(&bsi, *bitOffset);
|
|
|
|
/* read element ID (save last ID for SBR purposes) */
|
|
aacDecInfo->prevBlockID = aacDecInfo->currBlockID;
|
|
aacDecInfo->currBlockID = GetBits(&bsi, NUM_SYN_ID_BITS);
|
|
|
|
/* set defaults (could be overwritten by DecodeXXXElement(), depending on currBlockID) */
|
|
psi->commonWin = 0;
|
|
|
|
err = 0;
|
|
switch (aacDecInfo->currBlockID) {
|
|
case AAC_ID_SCE:
|
|
err = DecodeSingleChannelElement(aacDecInfo, &bsi);
|
|
break;
|
|
case AAC_ID_CPE:
|
|
err = DecodeChannelPairElement(aacDecInfo, &bsi);
|
|
break;
|
|
case AAC_ID_CCE:
|
|
/* TODO - implement CCE decoding */
|
|
break;
|
|
case AAC_ID_LFE:
|
|
err = DecodeLFEChannelElement(aacDecInfo, &bsi);
|
|
break;
|
|
case AAC_ID_DSE:
|
|
err = DecodeDataStreamElement(aacDecInfo, &bsi);
|
|
break;
|
|
case AAC_ID_PCE:
|
|
err = DecodeProgramConfigElement(psi->pce + 0, &bsi);
|
|
break;
|
|
case AAC_ID_FIL:
|
|
err = DecodeFillElement(aacDecInfo, &bsi);
|
|
break;
|
|
case AAC_ID_END:
|
|
break;
|
|
}
|
|
if (err)
|
|
return ERR_AAC_SYNTAX_ELEMENT;
|
|
|
|
/* update bitstream reader */
|
|
bitsUsed = CalcBitsUsed(&bsi, *buf, *bitOffset);
|
|
*buf += (bitsUsed + *bitOffset) >> 3;
|
|
*bitOffset = (bitsUsed + *bitOffset) & 0x07;
|
|
*bitsAvail -= bitsUsed;
|
|
|
|
if (*bitsAvail < 0)
|
|
return ERR_AAC_INDATA_UNDERFLOW;
|
|
|
|
return ERR_AAC_NONE;
|
|
}
|
|
|