aboutsummaryrefslogtreecommitdiffstats
path: root/fdk-aac/libAACdec/src/rvlc.cpp
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2019-11-11 11:38:02 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2019-11-11 11:38:02 +0100
commit0e5af65c467b2423a0b857ae3ad98c91acc1e190 (patch)
treed07f69550d8886271e44fe79c4dcfb299cafbd38 /fdk-aac/libAACdec/src/rvlc.cpp
parentefe406d9724f959c8bc2a31802559ca6d41fd897 (diff)
downloadODR-AudioEnc-0e5af65c467b2423a0b857ae3ad98c91acc1e190.tar.gz
ODR-AudioEnc-0e5af65c467b2423a0b857ae3ad98c91acc1e190.tar.bz2
ODR-AudioEnc-0e5af65c467b2423a0b857ae3ad98c91acc1e190.zip
Include patched FDK-AAC in the repository
The initial idea was to get the DAB+ patch into upstream, but since that follows the android source releases, there is no place for a custom DAB+ patch there. So instead of having to maintain a patched fdk-aac that has to have the same .so version as the distribution package on which it is installed, we prefer having a separate fdk-aac-dab library to avoid collision. At that point, there's no reason to keep fdk-aac in a separate repository, as odr-audioenc is the only tool that needs DAB+ encoding support. Including it here simplifies installation, and makes it consistent with toolame-dab, also shipped in this repository. DAB+ decoding support (needed by ODR-SourceCompanion, dablin, etisnoop, welle.io and others) can be done using upstream FDK-AAC.
Diffstat (limited to 'fdk-aac/libAACdec/src/rvlc.cpp')
-rw-r--r--fdk-aac/libAACdec/src/rvlc.cpp1217
1 files changed, 1217 insertions, 0 deletions
diff --git a/fdk-aac/libAACdec/src/rvlc.cpp b/fdk-aac/libAACdec/src/rvlc.cpp
new file mode 100644
index 0000000..b7a9be1
--- /dev/null
+++ b/fdk-aac/libAACdec/src/rvlc.cpp
@@ -0,0 +1,1217 @@
+/* -----------------------------------------------------------------------------
+Software License for The Fraunhofer FDK AAC Codec Library for Android
+
+© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+Forschung e.V. All rights reserved.
+
+ 1. INTRODUCTION
+The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
+that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
+scheme for digital audio. This FDK AAC Codec software is intended to be used on
+a wide variety of Android devices.
+
+AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
+general perceptual audio codecs. AAC-ELD is considered the best-performing
+full-bandwidth communications codec by independent studies and is widely
+deployed. AAC has been standardized by ISO and IEC as part of the MPEG
+specifications.
+
+Patent licenses for necessary patent claims for the FDK AAC Codec (including
+those of Fraunhofer) may be obtained through Via Licensing
+(www.vialicensing.com) or through the respective patent owners individually for
+the purpose of encoding or decoding bit streams in products that are compliant
+with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
+Android devices already license these patent claims through Via Licensing or
+directly from the patent owners, and therefore FDK AAC Codec software may
+already be covered under those patent licenses when it is used for those
+licensed purposes only.
+
+Commercially-licensed AAC software libraries, including floating-point versions
+with enhanced sound quality, are also available from Fraunhofer. Users are
+encouraged to check the Fraunhofer website for additional applications
+information and documentation.
+
+2. COPYRIGHT LICENSE
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted without payment of copyright license fees provided that you
+satisfy the following conditions:
+
+You must retain the complete text of this software license in redistributions of
+the FDK AAC Codec or your modifications thereto in source code form.
+
+You must retain the complete text of this software license in the documentation
+and/or other materials provided with redistributions of the FDK AAC Codec or
+your modifications thereto in binary form. You must make available free of
+charge copies of the complete source code of the FDK AAC Codec and your
+modifications thereto to recipients of copies in binary form.
+
+The name of Fraunhofer may not be used to endorse or promote products derived
+from this library without prior written permission.
+
+You may not charge copyright license fees for anyone to use, copy or distribute
+the FDK AAC Codec software or your modifications thereto.
+
+Your modified versions of the FDK AAC Codec must carry prominent notices stating
+that you changed the software and the date of any change. For modified versions
+of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
+must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
+AAC Codec Library for Android."
+
+3. NO PATENT LICENSE
+
+NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
+limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
+Fraunhofer provides no warranty of patent non-infringement with respect to this
+software.
+
+You may use this FDK AAC Codec software or modifications thereto only for
+purposes that are authorized by appropriate patent licenses.
+
+4. DISCLAIMER
+
+This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
+holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+including but not limited to the implied warranties of merchantability and
+fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
+or consequential damages, including but not limited to procurement of substitute
+goods or services; loss of use, data, or profits, or business interruption,
+however caused and on any theory of liability, whether in contract, strict
+liability, or tort (including negligence), arising in any way out of the use of
+this software, even if advised of the possibility of such damage.
+
+5. CONTACT INFORMATION
+
+Fraunhofer Institute for Integrated Circuits IIS
+Attention: Audio and Multimedia Departments - FDK AAC LL
+Am Wolfsmantel 33
+91058 Erlangen, Germany
+
+www.iis.fraunhofer.de/amm
+amm-info@iis.fraunhofer.de
+----------------------------------------------------------------------------- */
+
+/**************************** AAC decoder library ******************************
+
+ Author(s):
+
+ Description:
+
+*******************************************************************************/
+
+/*!
+ \file
+ \brief RVLC Decoder
+ \author Robert Weidner
+*/
+
+#include "rvlc.h"
+
+#include "block.h"
+
+#include "aac_rom.h"
+#include "rvlcbit.h"
+#include "rvlcconceal.h"
+#include "aacdec_hcr.h"
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcInit
+
+ description: init RVLC by data from channelinfo, which was decoded
+previously and set up pointers
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - pointer channel info structure
+ - pointer bitstream structure
+-----------------------------------------------------------------------------------------------
+ return: -
+--------------------------------------------------------------------------------------------
+*/
+
+static void rvlcInit(CErRvlcInfo *pRvlc,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ HANDLE_FDK_BITSTREAM bs) {
+ /* RVLC common initialization part 2 of 2 */
+ SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc;
+ SHORT *pScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd;
+ SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd;
+ SHORT *pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor;
+ int bnds;
+
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcIntensityUsed = 0;
+
+ pRvlc->numDecodedEscapeWordsEsc = 0;
+ pRvlc->numDecodedEscapeWordsFwd = 0;
+ pRvlc->numDecodedEscapeWordsBwd = 0;
+
+ pRvlc->intensity_used = 0;
+ pRvlc->errorLogRvlc = 0;
+
+ pRvlc->conceal_max = CONCEAL_MAX_INIT;
+ pRvlc->conceal_min = CONCEAL_MIN_INIT;
+
+ pRvlc->conceal_max_esc = CONCEAL_MAX_INIT;
+ pRvlc->conceal_min_esc = CONCEAL_MIN_INIT;
+
+ pRvlc->pHuffTreeRvlcEscape = aHuffTreeRvlcEscape;
+ pRvlc->pHuffTreeRvlCodewds = aHuffTreeRvlCodewds;
+
+ /* init scf arrays (for savety (in case of there are only zero codebooks)) */
+ for (bnds = 0; bnds < RVLC_MAX_SFB; bnds++) {
+ pScfFwd[bnds] = 0;
+ pScfBwd[bnds] = 0;
+ pScfEsc[bnds] = 0;
+ pScaleFactor[bnds] = 0;
+ }
+
+ /* set base bitstream ptr to the RVL-coded part (start of RVLC data (ESC 2))
+ */
+ FDKsyncCache(bs);
+ pRvlc->bsAnchor = (INT)FDKgetValidBits(bs);
+
+ pRvlc->bitstreamIndexRvlFwd =
+ 0; /* first bit within RVL coded block as start address for forward
+ decoding */
+ pRvlc->bitstreamIndexRvlBwd =
+ pRvlc->length_of_rvlc_sf - 1; /* last bit within RVL coded block as start
+ address for backward decoding */
+
+ /* skip RVLC-bitstream-part -- pointing now to escapes (if present) or to TNS
+ * data (if present) */
+ FDKpushFor(bs, pRvlc->length_of_rvlc_sf);
+
+ if (pRvlc->sf_escapes_present != 0) {
+ /* locate internal bitstream ptr at escapes (which is the second part) */
+ FDKsyncCache(bs);
+ pRvlc->bitstreamIndexEsc = pRvlc->bsAnchor - (INT)FDKgetValidBits(bs);
+
+ /* skip escapeRVLC-bitstream-part -- pointing to TNS data (if present) to
+ * make decoder continue */
+ /* decoding of RVLC should work despite this second pushFor during
+ * initialization because */
+ /* bitstream initialization is valid for both ESC2 data parts (RVL-coded
+ * values and ESC-coded values) */
+ FDKpushFor(bs, pRvlc->length_of_rvlc_escapes);
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcCheckIntensityCb
+
+ description: Check if a intensity codebook is used in the current channel.
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - pointer channel info structure
+-----------------------------------------------------------------------------------------------
+ output: - intensity_used: 0 no intensity codebook is used
+ 1 intensity codebook is used
+-----------------------------------------------------------------------------------------------
+ return: -
+--------------------------------------------------------------------------------------------
+*/
+
+static void rvlcCheckIntensityCb(
+ CErRvlcInfo *pRvlc, CAacDecoderChannelInfo *pAacDecoderChannelInfo) {
+ int group, band, bnds;
+
+ pRvlc->intensity_used = 0;
+
+ for (group = 0; group < pRvlc->numWindowGroups; group++) {
+ for (band = 0; band < pRvlc->maxSfbTransmitted; band++) {
+ bnds = 16 * group + band;
+ if ((pAacDecoderChannelInfo->pDynData->aCodeBook[bnds] ==
+ INTENSITY_HCB) ||
+ (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds] ==
+ INTENSITY_HCB2)) {
+ pRvlc->intensity_used = 1;
+ break;
+ }
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcDecodeEscapeWord
+
+ description: Decode a huffman coded RVLC Escape-word. This value is part
+of a DPCM coded scalefactor.
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+-----------------------------------------------------------------------------------------------
+ return: - a single RVLC-Escape value which had to be applied to a
+DPCM value (which has a absolute value of 7)
+--------------------------------------------------------------------------------------------
+*/
+
+static SCHAR rvlcDecodeEscapeWord(CErRvlcInfo *pRvlc, HANDLE_FDK_BITSTREAM bs) {
+ int i;
+ SCHAR value;
+ UCHAR carryBit;
+ UINT treeNode;
+ UINT branchValue;
+ UINT branchNode;
+
+ INT *pBitstreamIndexEsc;
+ const UINT *pEscTree;
+
+ pEscTree = pRvlc->pHuffTreeRvlcEscape;
+ pBitstreamIndexEsc = &(pRvlc->bitstreamIndexEsc);
+ treeNode = *pEscTree; /* init at starting node */
+
+ for (i = MAX_LEN_RVLC_ESCAPE_WORD - 1; i >= 0; i--) {
+ carryBit =
+ rvlcReadBitFromBitstream(bs, /* get next bit */
+ pRvlc->bsAnchor, pBitstreamIndexEsc, FWD);
+
+ CarryBitToBranchValue(carryBit, /* huffman decoding, do a single step in
+ huffman decoding tree */
+ treeNode, &branchValue, &branchNode);
+
+ if ((branchNode & TEST_BIT_10) ==
+ TEST_BIT_10) { /* test bit 10 ; if set --> a RVLC-escape-word is
+ completely decoded */
+ value = (SCHAR)branchNode & CLR_BIT_10;
+ pRvlc->length_of_rvlc_escapes -= (MAX_LEN_RVLC_ESCAPE_WORD - i);
+
+ if (pRvlc->length_of_rvlc_escapes < 0) {
+ pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID;
+ value = -1;
+ }
+
+ return value;
+ } else {
+ treeNode = *(
+ pEscTree +
+ branchValue); /* update treeNode for further step in decoding tree */
+ }
+ }
+
+ pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID;
+
+ return -1; /* should not be reached */
+}
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcDecodeEscapes
+
+ description: Decodes all huffman coded RVLC Escape Words.
+ Here a difference to the pseudo-code-implementation from
+standard can be found. A while loop (and not two nested for loops) is used for
+two reasons:
+
+ 1. The plain huffman encoded escapes are decoded before the
+RVL-coded scalefactors. Therefore the escapes are present in the second step
+ when decoding the RVL-coded-scalefactor values in forward
+and backward direction.
+
+ When the RVL-coded scalefactors are decoded and there a
+escape is needed, then it is just taken out of the array in ascending order.
+
+ 2. It's faster.
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - handle to FDK bitstream
+-----------------------------------------------------------------------------------------------
+ return: - 0 ok the decoded escapes seem to be valid
+ - 1 error there was a error detected during decoding escapes
+ --> all escapes are invalid
+--------------------------------------------------------------------------------------------
+*/
+
+static void rvlcDecodeEscapes(CErRvlcInfo *pRvlc, SHORT *pEsc,
+ HANDLE_FDK_BITSTREAM bs) {
+ SCHAR escWord;
+ SCHAR escCnt = 0;
+ SHORT *pEscBitCntSum;
+
+ pEscBitCntSum = &(pRvlc->length_of_rvlc_escapes);
+
+ /* Decode all RVLC-Escape words with a plain Huffman-Decoder */
+ while (*pEscBitCntSum > 0) {
+ escWord = rvlcDecodeEscapeWord(pRvlc, bs);
+
+ if (escWord >= 0) {
+ pEsc[escCnt] = escWord;
+ escCnt++;
+ } else {
+ pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID;
+ pRvlc->numDecodedEscapeWordsEsc = escCnt;
+
+ return;
+ }
+ } /* all RVLC escapes decoded */
+
+ pRvlc->numDecodedEscapeWordsEsc = escCnt;
+}
+
+/*---------------------------------------------------------------------------------------------
+ function: decodeRVLCodeword
+
+ description: Decodes a RVL-coded dpcm-word (-part).
+-----------------------------------------------------------------------------------------------
+ input: - FDK bitstream handle
+ - pointer rvlc structure
+-----------------------------------------------------------------------------------------------
+ return: - a dpcm value which is within range [0,1,..,14] in case of
+no errors. The offset of 7 must be subtracted to get a valid dpcm scalefactor
+value. In case of errors a forbidden codeword is detected --> returning -1
+--------------------------------------------------------------------------------------------
+*/
+
+SCHAR decodeRVLCodeword(HANDLE_FDK_BITSTREAM bs, CErRvlcInfo *pRvlc) {
+ int i;
+ SCHAR value;
+ UCHAR carryBit;
+ UINT branchValue;
+ UINT branchNode;
+
+ const UINT *pRvlCodeTree = pRvlc->pHuffTreeRvlCodewds;
+ UCHAR direction = pRvlc->direction;
+ INT *pBitstrIndxRvl = pRvlc->pBitstrIndxRvl_RVL;
+ UINT treeNode = *pRvlCodeTree;
+
+ for (i = MAX_LEN_RVLC_CODE_WORD - 1; i >= 0; i--) {
+ carryBit =
+ rvlcReadBitFromBitstream(bs, /* get next bit */
+ pRvlc->bsAnchor, pBitstrIndxRvl, direction);
+
+ CarryBitToBranchValue(carryBit, /* huffman decoding, do a single step in
+ huffman decoding tree */
+ treeNode, &branchValue, &branchNode);
+
+ if ((branchNode & TEST_BIT_10) ==
+ TEST_BIT_10) { /* test bit 10 ; if set --> a
+ RVLC-codeword is completely decoded
+ */
+ value = (SCHAR)(branchNode & CLR_BIT_10);
+ *pRvlc->pRvlBitCnt_RVL -= (MAX_LEN_RVLC_CODE_WORD - i);
+
+ /* check available bits for decoding */
+ if (*pRvlc->pRvlBitCnt_RVL < 0) {
+ if (direction == FWD) {
+ pRvlc->errorLogRvlc |= RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_FWD;
+ } else {
+ pRvlc->errorLogRvlc |= RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_BWD;
+ }
+ value = -1; /* signalize an error in return value, because too many bits
+ was decoded */
+ }
+
+ /* check max value of dpcm value */
+ if (value > MAX_ALLOWED_DPCM_INDEX) {
+ if (direction == FWD) {
+ pRvlc->errorLogRvlc |= RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD;
+ } else {
+ pRvlc->errorLogRvlc |= RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD;
+ }
+ value = -1; /* signalize an error in return value, because a forbidden
+ cw was detected*/
+ }
+
+ return value; /* return a dpcm value with offset +7 or an error status */
+ } else {
+ treeNode = *(
+ pRvlCodeTree +
+ branchValue); /* update treeNode for further step in decoding tree */
+ }
+ }
+
+ return -1;
+}
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcDecodeForward
+
+ description: Decode RVL-coded codewords in forward direction.
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - pointer channel info structure
+ - handle to FDK bitstream
+-----------------------------------------------------------------------------------------------
+ return: -
+--------------------------------------------------------------------------------------------
+*/
+
+static void rvlcDecodeForward(CErRvlcInfo *pRvlc,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ HANDLE_FDK_BITSTREAM bs) {
+ int band = 0;
+ int group = 0;
+ int bnds = 0;
+
+ SHORT dpcm;
+
+ SHORT factor =
+ pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET;
+ SHORT position = -SF_OFFSET;
+ SHORT noisenrg = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain -
+ SF_OFFSET - 90 - 256;
+
+ SHORT *pScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd;
+ SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc;
+ UCHAR *pEscFwdCnt = &(pRvlc->numDecodedEscapeWordsFwd);
+
+ pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_fwd);
+ pRvlc->pBitstrIndxRvl_RVL = &(pRvlc->bitstreamIndexRvlFwd);
+
+ *pEscFwdCnt = 0;
+ pRvlc->direction = FWD;
+ pRvlc->noise_used = 0;
+ pRvlc->sf_used = 0;
+ pRvlc->lastScf = 0;
+ pRvlc->lastNrg = 0;
+ pRvlc->lastIs = 0;
+
+ rvlcCheckIntensityCb(pRvlc, pAacDecoderChannelInfo);
+
+ /* main loop fwd long */
+ for (group = 0; group < pRvlc->numWindowGroups; group++) {
+ for (band = 0; band < pRvlc->maxSfbTransmitted; band++) {
+ bnds = 16 * group + band;
+
+ switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
+ case ZERO_HCB:
+ pScfFwd[bnds] = 0;
+ break;
+
+ case INTENSITY_HCB2:
+ case INTENSITY_HCB:
+ /* store dpcm_is_position */
+ dpcm = decodeRVLCodeword(bs, pRvlc);
+ if (dpcm < 0) {
+ pRvlc->conceal_max = bnds;
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pRvlc->conceal_max = bnds;
+ return;
+ } else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc++;
+ } else {
+ dpcm += *pScfEsc++;
+ }
+ (*pEscFwdCnt)++;
+ if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) {
+ pRvlc->conceal_max_esc = bnds;
+ }
+ }
+ }
+ position += dpcm;
+ pScfFwd[bnds] = position;
+ pRvlc->lastIs = position;
+ break;
+
+ case NOISE_HCB:
+ if (pRvlc->noise_used == 0) {
+ pRvlc->noise_used = 1;
+ pRvlc->first_noise_band = bnds;
+ noisenrg += pRvlc->dpcm_noise_nrg;
+ pScfFwd[bnds] = 100 + noisenrg;
+ pRvlc->lastNrg = noisenrg;
+ } else {
+ dpcm = decodeRVLCodeword(bs, pRvlc);
+ if (dpcm < 0) {
+ pRvlc->conceal_max = bnds;
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pRvlc->conceal_max = bnds;
+ return;
+ } else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc++;
+ } else {
+ dpcm += *pScfEsc++;
+ }
+ (*pEscFwdCnt)++;
+ if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) {
+ pRvlc->conceal_max_esc = bnds;
+ }
+ }
+ }
+ noisenrg += dpcm;
+ pScfFwd[bnds] = 100 + noisenrg;
+ pRvlc->lastNrg = noisenrg;
+ }
+ pAacDecoderChannelInfo->data.aac.PnsData.pnsUsed[bnds] = 1;
+ break;
+
+ default:
+ pRvlc->sf_used = 1;
+ dpcm = decodeRVLCodeword(bs, pRvlc);
+ if (dpcm < 0) {
+ pRvlc->conceal_max = bnds;
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pRvlc->conceal_max = bnds;
+ return;
+ } else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc++;
+ } else {
+ dpcm += *pScfEsc++;
+ }
+ (*pEscFwdCnt)++;
+ if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) {
+ pRvlc->conceal_max_esc = bnds;
+ }
+ }
+ }
+ factor += dpcm;
+ pScfFwd[bnds] = factor;
+ pRvlc->lastScf = factor;
+ break;
+ }
+ }
+ }
+
+ /* postfetch fwd long */
+ if (pRvlc->intensity_used) {
+ dpcm = decodeRVLCodeword(bs, pRvlc); /* dpcm_is_last_position */
+ if (dpcm < 0) {
+ pRvlc->conceal_max = bnds;
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pRvlc->conceal_max = bnds;
+ return;
+ } else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc++;
+ } else {
+ dpcm += *pScfEsc++;
+ }
+ (*pEscFwdCnt)++;
+ if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) {
+ pRvlc->conceal_max_esc = bnds;
+ }
+ }
+ }
+ pRvlc->dpcm_is_last_position = dpcm;
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcDecodeBackward
+
+ description: Decode RVL-coded codewords in backward direction.
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - pointer channel info structure
+ - handle FDK bitstream
+-----------------------------------------------------------------------------------------------
+ return: -
+--------------------------------------------------------------------------------------------
+*/
+
+static void rvlcDecodeBackward(CErRvlcInfo *pRvlc,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ HANDLE_FDK_BITSTREAM bs) {
+ SHORT band, group, dpcm, offset;
+ SHORT bnds = pRvlc->maxSfbTransmitted - 1;
+
+ SHORT factor = pRvlc->rev_global_gain - SF_OFFSET;
+ SHORT position = pRvlc->dpcm_is_last_position - SF_OFFSET;
+ SHORT noisenrg = pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position -
+ SF_OFFSET - 90 - 256;
+
+ SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd;
+ SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc;
+ UCHAR *pEscEscCnt = &(pRvlc->numDecodedEscapeWordsEsc);
+ UCHAR *pEscBwdCnt = &(pRvlc->numDecodedEscapeWordsBwd);
+
+ pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_bwd);
+ pRvlc->pBitstrIndxRvl_RVL = &(pRvlc->bitstreamIndexRvlBwd);
+
+ *pEscBwdCnt = 0;
+ pRvlc->direction = BWD;
+ pScfEsc += *pEscEscCnt - 1; /* set pScfEsc to last entry */
+ pRvlc->firstScf = 0;
+ pRvlc->firstNrg = 0;
+ pRvlc->firstIs = 0;
+
+ /* prefetch long BWD */
+ if (pRvlc->intensity_used) {
+ dpcm = decodeRVLCodeword(bs, pRvlc); /* dpcm_is_last_position */
+ if (dpcm < 0) {
+ pRvlc->dpcm_is_last_position = 0;
+ pRvlc->conceal_min = bnds;
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pRvlc->conceal_min = bnds;
+ return;
+ } else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc--;
+ } else {
+ dpcm += *pScfEsc--;
+ }
+ (*pEscBwdCnt)++;
+ if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) {
+ pRvlc->conceal_min_esc = bnds;
+ }
+ }
+ }
+ pRvlc->dpcm_is_last_position = dpcm;
+ }
+
+ /* main loop long BWD */
+ for (group = pRvlc->numWindowGroups - 1; group >= 0; group--) {
+ for (band = pRvlc->maxSfbTransmitted - 1; band >= 0; band--) {
+ bnds = 16 * group + band;
+ if ((band == 0) && (pRvlc->numWindowGroups != 1))
+ offset = 16 - pRvlc->maxSfbTransmitted + 1;
+ else
+ offset = 1;
+
+ switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
+ case ZERO_HCB:
+ pScfBwd[bnds] = 0;
+ break;
+
+ case INTENSITY_HCB2:
+ case INTENSITY_HCB:
+ /* store dpcm_is_position */
+ dpcm = decodeRVLCodeword(bs, pRvlc);
+ if (dpcm < 0) {
+ pScfBwd[bnds] = position;
+ pRvlc->conceal_min = fMax(0, bnds - offset);
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pScfBwd[bnds] = position;
+ pRvlc->conceal_min = fMax(0, bnds - offset);
+ return;
+ } else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc--;
+ } else {
+ dpcm += *pScfEsc--;
+ }
+ (*pEscBwdCnt)++;
+ if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) {
+ pRvlc->conceal_min_esc = fMax(0, bnds - offset);
+ }
+ }
+ }
+ pScfBwd[bnds] = position;
+ position -= dpcm;
+ pRvlc->firstIs = position;
+ break;
+
+ case NOISE_HCB:
+ if (bnds == pRvlc->first_noise_band) {
+ pScfBwd[bnds] =
+ pRvlc->dpcm_noise_nrg +
+ pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain -
+ SF_OFFSET - 90 - 256;
+ pRvlc->firstNrg = pScfBwd[bnds];
+ } else {
+ dpcm = decodeRVLCodeword(bs, pRvlc);
+ if (dpcm < 0) {
+ pScfBwd[bnds] = noisenrg;
+ pRvlc->conceal_min = fMax(0, bnds - offset);
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pScfBwd[bnds] = noisenrg;
+ pRvlc->conceal_min = fMax(0, bnds - offset);
+ return;
+ } else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc--;
+ } else {
+ dpcm += *pScfEsc--;
+ }
+ (*pEscBwdCnt)++;
+ if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) {
+ pRvlc->conceal_min_esc = fMax(0, bnds - offset);
+ }
+ }
+ }
+ pScfBwd[bnds] = noisenrg;
+ noisenrg -= dpcm;
+ pRvlc->firstNrg = noisenrg;
+ }
+ break;
+
+ default:
+ dpcm = decodeRVLCodeword(bs, pRvlc);
+ if (dpcm < 0) {
+ pScfBwd[bnds] = factor;
+ pRvlc->conceal_min = fMax(0, bnds - offset);
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pScfBwd[bnds] = factor;
+ pRvlc->conceal_min = fMax(0, bnds - offset);
+ return;
+ } else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc--;
+ } else {
+ dpcm += *pScfEsc--;
+ }
+ (*pEscBwdCnt)++;
+ if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) {
+ pRvlc->conceal_min_esc = fMax(0, bnds - offset);
+ }
+ }
+ }
+ pScfBwd[bnds] = factor;
+ factor -= dpcm;
+ pRvlc->firstScf = factor;
+ break;
+ }
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcFinalErrorDetection
+
+ description: Call RVLC concealment if error was detected in decoding
+process
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - pointer channel info structure
+-----------------------------------------------------------------------------------------------
+ return: -
+--------------------------------------------------------------------------------------------
+*/
+
+static void rvlcFinalErrorDetection(
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo) {
+ CErRvlcInfo *pRvlc =
+ &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
+ UCHAR ErrorStatusComplete = 0;
+ UCHAR ErrorStatusLengthFwd = 0;
+ UCHAR ErrorStatusLengthBwd = 0;
+ UCHAR ErrorStatusLengthEscapes = 0;
+ UCHAR ErrorStatusFirstScf = 0;
+ UCHAR ErrorStatusLastScf = 0;
+ UCHAR ErrorStatusFirstNrg = 0;
+ UCHAR ErrorStatusLastNrg = 0;
+ UCHAR ErrorStatusFirstIs = 0;
+ UCHAR ErrorStatusLastIs = 0;
+ UCHAR ErrorStatusForbiddenCwFwd = 0;
+ UCHAR ErrorStatusForbiddenCwBwd = 0;
+ UCHAR ErrorStatusNumEscapesFwd = 0;
+ UCHAR ErrorStatusNumEscapesBwd = 0;
+ UCHAR ConcealStatus = 1;
+ UCHAR currentBlockType; /* short: 0, not short: 1*/
+
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 1;
+
+ /* invalid escape words, bit counter unequal zero, forbidden codeword detected
+ */
+ if (pRvlc->errorLogRvlc & RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD)
+ ErrorStatusForbiddenCwFwd = 1;
+
+ if (pRvlc->errorLogRvlc & RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD)
+ ErrorStatusForbiddenCwBwd = 1;
+
+ /* bit counter forward unequal zero */
+ if (pRvlc->length_of_rvlc_sf_fwd) ErrorStatusLengthFwd = 1;
+
+ /* bit counter backward unequal zero */
+ if (pRvlc->length_of_rvlc_sf_bwd) ErrorStatusLengthBwd = 1;
+
+ /* bit counter escape sequences unequal zero */
+ if (pRvlc->sf_escapes_present)
+ if (pRvlc->length_of_rvlc_escapes) ErrorStatusLengthEscapes = 1;
+
+ if (pRvlc->sf_used) {
+ /* first decoded scf does not match to global gain in backward direction */
+ if (pRvlc->firstScf !=
+ (pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET))
+ ErrorStatusFirstScf = 1;
+
+ /* last decoded scf does not match to rev global gain in forward direction
+ */
+ if (pRvlc->lastScf != (pRvlc->rev_global_gain - SF_OFFSET))
+ ErrorStatusLastScf = 1;
+ }
+
+ if (pRvlc->noise_used) {
+ /* first decoded nrg does not match to dpcm_noise_nrg in backward direction
+ */
+ if (pRvlc->firstNrg !=
+ (pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain +
+ pRvlc->dpcm_noise_nrg - SF_OFFSET - 90 - 256))
+ ErrorStatusFirstNrg = 1;
+
+ /* last decoded nrg does not match to dpcm_noise_last_position in forward
+ * direction */
+ if (pRvlc->lastNrg !=
+ (pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - SF_OFFSET -
+ 90 - 256))
+ ErrorStatusLastNrg = 1;
+ }
+
+ if (pRvlc->intensity_used) {
+ /* first decoded is position does not match in backward direction */
+ if (pRvlc->firstIs != (-SF_OFFSET)) ErrorStatusFirstIs = 1;
+
+ /* last decoded is position does not match in forward direction */
+ if (pRvlc->lastIs != (pRvlc->dpcm_is_last_position - SF_OFFSET))
+ ErrorStatusLastIs = 1;
+ }
+
+ /* decoded escapes and used escapes in forward direction do not fit */
+ if ((pRvlc->numDecodedEscapeWordsFwd != pRvlc->numDecodedEscapeWordsEsc) &&
+ (pRvlc->conceal_max == CONCEAL_MAX_INIT)) {
+ ErrorStatusNumEscapesFwd = 1;
+ }
+
+ /* decoded escapes and used escapes in backward direction do not fit */
+ if ((pRvlc->numDecodedEscapeWordsBwd != pRvlc->numDecodedEscapeWordsEsc) &&
+ (pRvlc->conceal_min == CONCEAL_MIN_INIT)) {
+ ErrorStatusNumEscapesBwd = 1;
+ }
+
+ if (ErrorStatusLengthEscapes ||
+ (((pRvlc->conceal_max == CONCEAL_MAX_INIT) &&
+ (pRvlc->numDecodedEscapeWordsFwd != pRvlc->numDecodedEscapeWordsEsc) &&
+ (ErrorStatusLastScf || ErrorStatusLastNrg || ErrorStatusLastIs))
+
+ &&
+
+ ((pRvlc->conceal_min == CONCEAL_MIN_INIT) &&
+ (pRvlc->numDecodedEscapeWordsBwd != pRvlc->numDecodedEscapeWordsEsc) &&
+ (ErrorStatusFirstScf || ErrorStatusFirstNrg || ErrorStatusFirstIs))) ||
+ ((pRvlc->conceal_max == CONCEAL_MAX_INIT) &&
+ ((pRvlc->rev_global_gain - SF_OFFSET - pRvlc->lastScf) < -15)) ||
+ ((pRvlc->conceal_min == CONCEAL_MIN_INIT) &&
+ ((pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET -
+ pRvlc->firstScf) < -15))) {
+ if ((pRvlc->conceal_max == CONCEAL_MAX_INIT) ||
+ (pRvlc->conceal_min == CONCEAL_MIN_INIT)) {
+ pRvlc->conceal_max = 0;
+ pRvlc->conceal_min = fMax(
+ 0, (pRvlc->numWindowGroups - 1) * 16 + pRvlc->maxSfbTransmitted - 1);
+ } else {
+ pRvlc->conceal_max = fMin(pRvlc->conceal_max, pRvlc->conceal_max_esc);
+ pRvlc->conceal_min = fMax(pRvlc->conceal_min, pRvlc->conceal_min_esc);
+ }
+ }
+
+ ErrorStatusComplete = ErrorStatusLastScf || ErrorStatusFirstScf ||
+ ErrorStatusLastNrg || ErrorStatusFirstNrg ||
+ ErrorStatusLastIs || ErrorStatusFirstIs ||
+ ErrorStatusForbiddenCwFwd ||
+ ErrorStatusForbiddenCwBwd || ErrorStatusLengthFwd ||
+ ErrorStatusLengthBwd || ErrorStatusLengthEscapes ||
+ ErrorStatusNumEscapesFwd || ErrorStatusNumEscapesBwd;
+
+ currentBlockType =
+ (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) ? 0
+ : 1;
+
+ if (!ErrorStatusComplete) {
+ int band;
+ int group;
+ int bnds;
+ int lastSfbIndex;
+
+ lastSfbIndex = (pRvlc->numWindowGroups > 1) ? 16 : 64;
+
+ for (group = 0; group < pRvlc->numWindowGroups; group++) {
+ for (band = 0; band < pRvlc->maxSfbTransmitted; band++) {
+ bnds = 16 * group + band;
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] =
+ pAacDecoderStaticChannelInfo->concealmentInfo
+ .aRvlcPreviousScaleFactor[bnds] =
+ pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
+ }
+ }
+
+ for (group = 0; group < pRvlc->numWindowGroups; group++) {
+ for (band = 0; band < pRvlc->maxSfbTransmitted; band++) {
+ bnds = 16 * group + band;
+ pAacDecoderStaticChannelInfo->concealmentInfo
+ .aRvlcPreviousCodebook[bnds] =
+ pAacDecoderChannelInfo->pDynData->aCodeBook[bnds];
+ }
+ for (; band < lastSfbIndex; band++) {
+ bnds = 16 * group + band;
+ FDK_ASSERT(bnds >= 0 && bnds < RVLC_MAX_SFB);
+ pAacDecoderStaticChannelInfo->concealmentInfo
+ .aRvlcPreviousCodebook[bnds] = ZERO_HCB;
+ }
+ }
+ } else {
+ int band;
+ int group;
+
+ /* A single bit error was detected in decoding of dpcm values. It also could
+ be an error with more bits in decoding of escapes and dpcm values whereby
+ an illegal codeword followed not directly after the corrupted bits but
+ just after decoding some more (wrong) scalefactors. Use the smaller
+ scalefactor from forward decoding, backward decoding and previous frame.
+ */
+ if (((pRvlc->conceal_min != CONCEAL_MIN_INIT) ||
+ (pRvlc->conceal_max != CONCEAL_MAX_INIT)) &&
+ (pRvlc->conceal_min <= pRvlc->conceal_max) &&
+ (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType ==
+ currentBlockType) &&
+ pAacDecoderStaticChannelInfo->concealmentInfo
+ .rvlcPreviousScaleFactorOK &&
+ pRvlc->sf_concealment && ConcealStatus) {
+ BidirectionalEstimation_UseScfOfPrevFrameAsReference(
+ pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo);
+ ConcealStatus = 0;
+ }
+
+ /* A single bit error was detected in decoding of dpcm values. It also could
+ be an error with more bits in decoding of escapes and dpcm values whereby
+ an illegal codeword followed not directly after the corrupted bits but
+ just after decoding some more (wrong) scalefactors. Use the smaller
+ scalefactor from forward and backward decoding. */
+ if ((pRvlc->conceal_min <= pRvlc->conceal_max) &&
+ ((pRvlc->conceal_min != CONCEAL_MIN_INIT) ||
+ (pRvlc->conceal_max != CONCEAL_MAX_INIT)) &&
+ !(pAacDecoderStaticChannelInfo->concealmentInfo
+ .rvlcPreviousScaleFactorOK &&
+ pRvlc->sf_concealment &&
+ (pAacDecoderStaticChannelInfo->concealmentInfo
+ .rvlcPreviousBlockType == currentBlockType)) &&
+ ConcealStatus) {
+ BidirectionalEstimation_UseLowerScfOfCurrentFrame(pAacDecoderChannelInfo);
+ ConcealStatus = 0;
+ }
+
+ /* No errors were detected in decoding of escapes and dpcm values however
+ the first and last value of a group (is,nrg,sf) is incorrect */
+ if ((pRvlc->conceal_min <= pRvlc->conceal_max) &&
+ ((ErrorStatusLastScf && ErrorStatusFirstScf) ||
+ (ErrorStatusLastNrg && ErrorStatusFirstNrg) ||
+ (ErrorStatusLastIs && ErrorStatusFirstIs)) &&
+ !(ErrorStatusForbiddenCwFwd || ErrorStatusForbiddenCwBwd ||
+ ErrorStatusLengthEscapes) &&
+ ConcealStatus) {
+ StatisticalEstimation(pAacDecoderChannelInfo);
+ ConcealStatus = 0;
+ }
+
+ /* A error with more bits in decoding of escapes and dpcm values was
+ detected. Use the smaller scalefactor from forward decoding, backward
+ decoding and previous frame. */
+ if ((pRvlc->conceal_min <= pRvlc->conceal_max) &&
+ pAacDecoderStaticChannelInfo->concealmentInfo
+ .rvlcPreviousScaleFactorOK &&
+ pRvlc->sf_concealment &&
+ (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType ==
+ currentBlockType) &&
+ ConcealStatus) {
+ PredictiveInterpolation(pAacDecoderChannelInfo,
+ pAacDecoderStaticChannelInfo);
+ ConcealStatus = 0;
+ }
+
+ /* Call frame concealment, because no better strategy was found. Setting the
+ scalefactors to zero is done for debugging purposes */
+ if (ConcealStatus) {
+ for (group = 0; group < pRvlc->numWindowGroups; group++) {
+ for (band = 0; band < pRvlc->maxSfbTransmitted; band++) {
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[16 * group + band] = 0;
+ }
+ }
+ pAacDecoderChannelInfo->pDynData->specificTo.aac
+ .rvlcCurrentScaleFactorOK = 0;
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ function: CRvlc_Read
+
+ description: Read RVLC ESC1 data (side info) from bitstream.
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - pointer channel info structure
+ - pointer bitstream structure
+-----------------------------------------------------------------------------------------------
+ return: -
+--------------------------------------------------------------------------------------------
+*/
+
+void CRvlc_Read(CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ HANDLE_FDK_BITSTREAM bs) {
+ CErRvlcInfo *pRvlc =
+ &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
+
+ int group, band;
+
+ /* RVLC long specific initialization Init part 1 of 2 */
+ pRvlc->numWindowGroups = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo);
+ pRvlc->maxSfbTransmitted =
+ GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+ pRvlc->noise_used = 0; /* noise detection */
+ pRvlc->dpcm_noise_nrg = 0; /* only for debugging */
+ pRvlc->dpcm_noise_last_position = 0; /* only for debugging */
+ pRvlc->length_of_rvlc_escapes =
+ -1; /* default value is used for error detection and concealment */
+
+ /* read only error sensitivity class 1 data (ESC 1 - data) */
+ pRvlc->sf_concealment = FDKreadBits(bs, 1); /* #1 */
+ pRvlc->rev_global_gain = FDKreadBits(bs, 8); /* #2 */
+
+ if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) {
+ pRvlc->length_of_rvlc_sf = FDKreadBits(bs, 11); /* #3 */
+ } else {
+ pRvlc->length_of_rvlc_sf = FDKreadBits(bs, 9); /* #3 */
+ }
+
+ /* check if noise codebook is used */
+ for (group = 0; group < pRvlc->numWindowGroups; group++) {
+ for (band = 0; band < pRvlc->maxSfbTransmitted; band++) {
+ if (pAacDecoderChannelInfo->pDynData->aCodeBook[16 * group + band] ==
+ NOISE_HCB) {
+ pRvlc->noise_used = 1;
+ break;
+ }
+ }
+ }
+
+ if (pRvlc->noise_used)
+ pRvlc->dpcm_noise_nrg = FDKreadBits(bs, 9); /* #4 PNS */
+
+ pRvlc->sf_escapes_present = FDKreadBits(bs, 1); /* #5 */
+
+ if (pRvlc->sf_escapes_present) {
+ pRvlc->length_of_rvlc_escapes = FDKreadBits(bs, 8); /* #6 */
+ }
+
+ if (pRvlc->noise_used) {
+ pRvlc->dpcm_noise_last_position = FDKreadBits(bs, 9); /* #7 PNS */
+ pRvlc->length_of_rvlc_sf -= 9;
+ }
+
+ pRvlc->length_of_rvlc_sf_fwd = pRvlc->length_of_rvlc_sf;
+ pRvlc->length_of_rvlc_sf_bwd = pRvlc->length_of_rvlc_sf;
+}
+
+/*---------------------------------------------------------------------------------------------
+ function: CRvlc_Decode
+
+ description: Decode rvlc data
+ The function reads both the escape sequences and the
+scalefactors in forward and backward direction. If an error occured during
+decoding process which can not be concealed with the rvlc concealment frame
+concealment will be initiated. Then the element "rvlcCurrentScaleFactorOK" in
+the decoder channel info is set to 0 otherwise it is set to 1.
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - pointer channel info structure
+ - pointer to persistent channel info structure
+ - pointer bitstream structure
+-----------------------------------------------------------------------------------------------
+ return: ErrorStatus = AAC_DEC_OK
+--------------------------------------------------------------------------------------------
+*/
+
+void CRvlc_Decode(CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
+ HANDLE_FDK_BITSTREAM bs) {
+ CErRvlcInfo *pRvlc =
+ &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
+ INT bitCntOffst;
+ INT saveBitCnt;
+
+ rvlcInit(pRvlc, pAacDecoderChannelInfo, bs);
+
+ /* save bitstream position */
+ saveBitCnt = (INT)FDKgetValidBits(bs);
+
+ if (pRvlc->sf_escapes_present)
+ rvlcDecodeEscapes(
+ pRvlc, pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc, bs);
+
+ rvlcDecodeForward(pRvlc, pAacDecoderChannelInfo, bs);
+ rvlcDecodeBackward(pRvlc, pAacDecoderChannelInfo, bs);
+ rvlcFinalErrorDetection(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo);
+
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcIntensityUsed =
+ pRvlc->intensity_used;
+ pAacDecoderChannelInfo->data.aac.PnsData.PnsActive = pRvlc->noise_used;
+
+ /* restore bitstream position */
+ bitCntOffst = (INT)FDKgetValidBits(bs) - saveBitCnt;
+ if (bitCntOffst) {
+ FDKpushBiDirectional(bs, bitCntOffst);
+ }
+}
+
+void CRvlc_ElementCheck(
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
+ const UINT flags, const INT elChannels) {
+ int ch;
+
+ /* Required for MPS residuals. */
+ if (pAacDecoderStaticChannelInfo == NULL) {
+ return;
+ }
+
+ /* RVLC specific sanity checks */
+ if ((flags & AC_ER_RVLC) && (elChannels == 2)) { /* to be reviewed */
+ if (((pAacDecoderChannelInfo[0]
+ ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) ||
+ (pAacDecoderChannelInfo[1]
+ ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0)) &&
+ pAacDecoderChannelInfo[0]->pComData->jointStereoData.MsMaskPresent) {
+ pAacDecoderChannelInfo[0]
+ ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0;
+ pAacDecoderChannelInfo[1]
+ ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0;
+ }
+
+ if ((pAacDecoderChannelInfo[0]
+ ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) &&
+ (pAacDecoderChannelInfo[1]
+ ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 1) &&
+ (pAacDecoderChannelInfo[1]
+ ->pDynData->specificTo.aac.rvlcIntensityUsed == 1)) {
+ pAacDecoderChannelInfo[1]
+ ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0;
+ }
+ }
+
+ for (ch = 0; ch < elChannels; ch++) {
+ pAacDecoderStaticChannelInfo[ch]->concealmentInfo.rvlcPreviousBlockType =
+ (GetWindowSequence(&pAacDecoderChannelInfo[ch]->icsInfo) == BLOCK_SHORT)
+ ? 0
+ : 1;
+ if (flags & AC_ER_RVLC) {
+ pAacDecoderStaticChannelInfo[ch]
+ ->concealmentInfo.rvlcPreviousScaleFactorOK =
+ pAacDecoderChannelInfo[ch]
+ ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK;
+ } else {
+ pAacDecoderStaticChannelInfo[ch]
+ ->concealmentInfo.rvlcPreviousScaleFactorOK = 0;
+ }
+ }
+}