aboutsummaryrefslogtreecommitdiffstats
path: root/fdk-aac/libAACdec/src/aacdec_hcr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fdk-aac/libAACdec/src/aacdec_hcr.cpp')
-rw-r--r--fdk-aac/libAACdec/src/aacdec_hcr.cpp1498
1 files changed, 1498 insertions, 0 deletions
diff --git a/fdk-aac/libAACdec/src/aacdec_hcr.cpp b/fdk-aac/libAACdec/src/aacdec_hcr.cpp
new file mode 100644
index 0000000..6114756
--- /dev/null
+++ b/fdk-aac/libAACdec/src/aacdec_hcr.cpp
@@ -0,0 +1,1498 @@
+/* -----------------------------------------------------------------------------
+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): Robert Weidner (DSP Solutions)
+
+ Description: HCR Decoder: HCR initialization, preprocess HCR sideinfo,
+ decode priority codewords (PCWs)
+
+*******************************************************************************/
+
+#include "aacdec_hcr.h"
+
+#include "aacdec_hcr_types.h"
+#include "aacdec_hcr_bit.h"
+#include "aacdec_hcrs.h"
+#include "aac_ram.h"
+#include "aac_rom.h"
+#include "channel.h"
+#include "block.h"
+
+#include "aacdecoder.h" /* for ID_CPE, ID_SCE ... */
+#include "FDK_bitstream.h"
+
+extern int mlFileChCurr;
+
+static void errDetectorInHcrSideinfoShrt(SCHAR cb, SHORT numLine,
+ UINT *errorWord);
+
+static void errDetectorInHcrLengths(SCHAR lengthOfLongestCodeword,
+ SHORT lengthOfReorderedSpectralData,
+ UINT *errorWord);
+
+static void HcrCalcNumCodeword(H_HCR_INFO pHcr);
+static void HcrSortCodebookAndNumCodewordInSection(H_HCR_INFO pHcr);
+static void HcrPrepareSegmentationGrid(H_HCR_INFO pHcr);
+static void HcrExtendedSectionInfo(H_HCR_INFO pHcr);
+
+static void DeriveNumberOfExtendedSortedSectionsInSets(
+ UINT numSegment, USHORT *pNumExtendedSortedCodewordInSection,
+ int numExtendedSortedCodewordInSectionIdx,
+ USHORT *pNumExtendedSortedSectionsInSets,
+ int numExtendedSortedSectionsInSetsIdx);
+
+static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor,
+ INT quantSpecCoef, INT *pLeftStartOfSegment,
+ SCHAR *pRemainingBitsInSegment,
+ int *pNumDecodedBits);
+
+static int DecodePCW_Sign(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor,
+ UINT codebookDim, const SCHAR *pQuantVal,
+ FIXP_DBL *pQuantSpecCoef, int *quantSpecCoefIdx,
+ INT *pLeftStartOfSegment,
+ SCHAR *pRemainingBitsInSegment, int *pNumDecodedBits);
+
+static const SCHAR *DecodePCW_Body(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor,
+ const UINT *pCurrentTree,
+ const SCHAR *pQuantValBase,
+ INT *pLeftStartOfSegment,
+ SCHAR *pRemainingBitsInSegment,
+ int *pNumDecodedBits);
+
+static void DecodePCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr);
+
+static void HcrReorderQuantizedSpectralCoefficients(
+ H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo);
+
+static UCHAR errDetectPcwSegmentation(SCHAR remainingBitsInSegment,
+ H_HCR_INFO pHcr, PCW_TYPE kind,
+ FIXP_DBL *qsc_base_of_cw,
+ UCHAR dimension);
+
+static void errDetectWithinSegmentationFinal(H_HCR_INFO pHcr);
+
+/*---------------------------------------------------------------------------------------------
+ description: Check if codebook and numSect are within allowed range
+(short only)
+--------------------------------------------------------------------------------------------
+*/
+static void errDetectorInHcrSideinfoShrt(SCHAR cb, SHORT numLine,
+ UINT *errorWord) {
+ if (cb < ZERO_HCB || cb >= MAX_CB_CHECK || cb == BOOKSCL) {
+ *errorWord |= CB_OUT_OF_RANGE_SHORT_BLOCK;
+ }
+ if (numLine < 0 || numLine > 1024) {
+ *errorWord |= LINE_IN_SECT_OUT_OF_RANGE_SHORT_BLOCK;
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: Check both HCR lengths
+--------------------------------------------------------------------------------------------
+*/
+static void errDetectorInHcrLengths(SCHAR lengthOfLongestCodeword,
+ SHORT lengthOfReorderedSpectralData,
+ UINT *errorWord) {
+ if (lengthOfReorderedSpectralData < lengthOfLongestCodeword) {
+ *errorWord |= HCR_SI_LENGTHS_FAILURE;
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: Decode (and adapt if necessary) the two HCR sideinfo
+components: 'reordered_spectral_data_length' and 'longest_codeword_length'
+--------------------------------------------------------------------------------------------
+*/
+
+void CHcr_Read(HANDLE_FDK_BITSTREAM bs,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const MP4_ELEMENT_ID globalHcrType) {
+ SHORT lengOfReorderedSpectralData;
+ SCHAR lengOfLongestCodeword;
+
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData =
+ 0;
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = 0;
+
+ /* ------- SI-Value No 1 ------- */
+ lengOfReorderedSpectralData = FDKreadBits(bs, 14) + ERROR_LORSD;
+ if (globalHcrType == ID_CPE) {
+ if ((lengOfReorderedSpectralData >= 0) &&
+ (lengOfReorderedSpectralData <= CPE_TOP_LENGTH)) {
+ pAacDecoderChannelInfo->pDynData->specificTo.aac
+ .lenOfReorderedSpectralData =
+ lengOfReorderedSpectralData; /* the decoded value is within range */
+ } else {
+ if (lengOfReorderedSpectralData > CPE_TOP_LENGTH) {
+ pAacDecoderChannelInfo->pDynData->specificTo.aac
+ .lenOfReorderedSpectralData =
+ CPE_TOP_LENGTH; /* use valid maximum */
+ }
+ }
+ } else if (globalHcrType == ID_SCE || globalHcrType == ID_LFE ||
+ globalHcrType == ID_CCE) {
+ if ((lengOfReorderedSpectralData >= 0) &&
+ (lengOfReorderedSpectralData <= SCE_TOP_LENGTH)) {
+ pAacDecoderChannelInfo->pDynData->specificTo.aac
+ .lenOfReorderedSpectralData =
+ lengOfReorderedSpectralData; /* the decoded value is within range */
+ } else {
+ if (lengOfReorderedSpectralData > SCE_TOP_LENGTH) {
+ pAacDecoderChannelInfo->pDynData->specificTo.aac
+ .lenOfReorderedSpectralData =
+ SCE_TOP_LENGTH; /* use valid maximum */
+ }
+ }
+ }
+
+ /* ------- SI-Value No 2 ------- */
+ lengOfLongestCodeword = FDKreadBits(bs, 6) + ERROR_LOLC;
+ if ((lengOfLongestCodeword >= 0) &&
+ (lengOfLongestCodeword <= LEN_OF_LONGEST_CW_TOP_LENGTH)) {
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword =
+ lengOfLongestCodeword; /* the decoded value is within range */
+ } else {
+ if (lengOfLongestCodeword > LEN_OF_LONGEST_CW_TOP_LENGTH) {
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword =
+ LEN_OF_LONGEST_CW_TOP_LENGTH; /* use valid maximum */
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: Set up HCR - must be called before every call to
+HcrDecoder(). For short block a sorting algorithm is applied to get the SI in
+the order that HCR could assemble the qsc's as if it is a long block.
+-----------------------------------------------------------------------------------------------
+ return: error log
+--------------------------------------------------------------------------------------------
+*/
+
+UINT HcrInit(H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ HANDLE_FDK_BITSTREAM bs) {
+ CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
+ SHORT *pNumLinesInSec;
+ UCHAR *pCodeBk;
+ SHORT numSection;
+ SCHAR cb;
+ int numLine;
+ int i;
+
+ pHcr->decInOut.lengthOfReorderedSpectralData =
+ pAacDecoderChannelInfo->pDynData->specificTo.aac
+ .lenOfReorderedSpectralData;
+ pHcr->decInOut.lengthOfLongestCodeword =
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword;
+ pHcr->decInOut.pQuantizedSpectralCoefficientsBase =
+ pAacDecoderChannelInfo->pSpectralCoefficient;
+ pHcr->decInOut.quantizedSpectralCoefficientsIdx = 0;
+ pHcr->decInOut.pCodebook =
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.aCodeBooks4Hcr;
+ pHcr->decInOut.pNumLineInSect =
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.aNumLineInSec4Hcr;
+ pHcr->decInOut.numSection =
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection;
+ pHcr->decInOut.errorLog = 0;
+ pHcr->nonPcwSideinfo.pResultBase =
+ SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
+
+ FDKsyncCache(bs);
+ pHcr->decInOut.bitstreamAnchor = (INT)FDKgetValidBits(bs);
+
+ if (!IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) /* short block */
+ {
+ SHORT band;
+ SHORT maxBand;
+ SCHAR group;
+ SCHAR winGroupLen;
+ SCHAR window;
+ SCHAR numUnitInBand;
+ SCHAR cntUnitInBand;
+ SCHAR groupWin;
+ SCHAR cb_prev;
+
+ UCHAR *pCodeBook;
+ const SHORT *BandOffsets;
+ SCHAR numOfGroups;
+
+ pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; /* in */
+ pNumLinesInSec = pHcr->decInOut.pNumLineInSect; /* out */
+ pCodeBk = pHcr->decInOut.pCodebook; /* out */
+ BandOffsets =
+ GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo); /* aux */
+ numOfGroups = GetWindowGroups(pIcsInfo);
+
+ numLine = 0;
+ numSection = 0;
+ cb = pCodeBook[0];
+ cb_prev = pCodeBook[0];
+
+ /* convert HCR-sideinfo into a unitwise manner: When the cb changes, a new
+ * section starts */
+
+ *pCodeBk++ = cb_prev;
+
+ maxBand = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+ for (band = 0; band < maxBand;
+ band++) { /* from low to high sfbs i.e. from low to high frequencies */
+ numUnitInBand =
+ ((BandOffsets[band + 1] - BandOffsets[band]) >>
+ FOUR_LOG_DIV_TWO_LOG); /* get the number of units in current sfb */
+ for (cntUnitInBand = numUnitInBand; cntUnitInBand != 0;
+ cntUnitInBand--) { /* for every unit in the band */
+ for (window = 0, group = 0; group < numOfGroups; group++) {
+ winGroupLen = (SCHAR)GetWindowGroupLength(
+ &pAacDecoderChannelInfo->icsInfo, group);
+ for (groupWin = winGroupLen; groupWin != 0; groupWin--, window++) {
+ cb = pCodeBook[group * 16 + band];
+ if (cb != cb_prev) {
+ errDetectorInHcrSideinfoShrt(cb, numLine,
+ &pHcr->decInOut.errorLog);
+ if (pHcr->decInOut.errorLog != 0) {
+ return (pHcr->decInOut.errorLog);
+ }
+ *pCodeBk++ = cb;
+ *pNumLinesInSec++ = numLine;
+ numSection++;
+
+ cb_prev = cb;
+ numLine = LINES_PER_UNIT;
+ } else {
+ numLine += LINES_PER_UNIT;
+ }
+ }
+ }
+ }
+ }
+
+ numSection++;
+
+ errDetectorInHcrSideinfoShrt(cb, numLine, &pHcr->decInOut.errorLog);
+ if (numSection <= 0 || numSection > 1024 / 2) {
+ pHcr->decInOut.errorLog |= NUM_SECT_OUT_OF_RANGE_SHORT_BLOCK;
+ }
+ errDetectorInHcrLengths(pHcr->decInOut.lengthOfLongestCodeword,
+ pHcr->decInOut.lengthOfReorderedSpectralData,
+ &pHcr->decInOut.errorLog);
+ if (pHcr->decInOut.errorLog != 0) {
+ return (pHcr->decInOut.errorLog);
+ }
+
+ *pCodeBk = cb;
+ *pNumLinesInSec = numLine;
+ pHcr->decInOut.numSection = numSection;
+
+ } else /* end short block prepare SI */
+ { /* long block */
+ errDetectorInHcrLengths(pHcr->decInOut.lengthOfLongestCodeword,
+ pHcr->decInOut.lengthOfReorderedSpectralData,
+ &pHcr->decInOut.errorLog);
+ numSection = pHcr->decInOut.numSection;
+ pNumLinesInSec = pHcr->decInOut.pNumLineInSect;
+ pCodeBk = pHcr->decInOut.pCodebook;
+ if (numSection <= 0 || numSection > 64) {
+ pHcr->decInOut.errorLog |= NUM_SECT_OUT_OF_RANGE_LONG_BLOCK;
+ numSection = 0;
+ }
+
+ for (i = numSection; i != 0; i--) {
+ cb = *pCodeBk++;
+
+ if (cb < ZERO_HCB || cb >= MAX_CB_CHECK || cb == BOOKSCL) {
+ pHcr->decInOut.errorLog |= CB_OUT_OF_RANGE_LONG_BLOCK;
+ }
+
+ numLine = *pNumLinesInSec++;
+ /* FDK_ASSERT(numLine > 0); */
+
+ if ((numLine <= 0) || (numLine > 1024)) {
+ pHcr->decInOut.errorLog |= LINE_IN_SECT_OUT_OF_RANGE_LONG_BLOCK;
+ }
+ }
+ if (pHcr->decInOut.errorLog != 0) {
+ return (pHcr->decInOut.errorLog);
+ }
+ }
+
+ pCodeBk = pHcr->decInOut.pCodebook;
+ for (i = 0; i < numSection; i++) {
+ if ((*pCodeBk == NOISE_HCB) || (*pCodeBk == INTENSITY_HCB2) ||
+ (*pCodeBk == INTENSITY_HCB)) {
+ *pCodeBk = 0;
+ }
+ pCodeBk++;
+ }
+
+ /* HCR-sideinfo-input is complete and seems to be valid */
+
+ return (pHcr->decInOut.errorLog);
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: This function decodes the codewords of the spectral
+coefficients from the bitstream according to the HCR algorithm and stores the
+quantized spectral coefficients in correct order in the output buffer.
+--------------------------------------------------------------------------------------------
+*/
+
+UINT HcrDecoder(H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ HANDLE_FDK_BITSTREAM bs) {
+ int pTmp1, pTmp2, pTmp3, pTmp4;
+ int pTmp5;
+
+ INT bitCntOffst;
+ INT saveBitCnt = (INT)FDKgetValidBits(bs); /* save bitstream position */
+
+ HcrCalcNumCodeword(pHcr);
+
+ HcrSortCodebookAndNumCodewordInSection(pHcr);
+
+ HcrPrepareSegmentationGrid(pHcr);
+
+ HcrExtendedSectionInfo(pHcr);
+
+ if ((pHcr->decInOut.errorLog & HCR_FATAL_PCW_ERROR_MASK) != 0) {
+ return (pHcr->decInOut.errorLog); /* sideinfo is massively corrupt, return
+ from HCR without having decoded
+ anything */
+ }
+
+ DeriveNumberOfExtendedSortedSectionsInSets(
+ pHcr->segmentInfo.numSegment,
+ pHcr->sectionInfo.pNumExtendedSortedCodewordInSection,
+ pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx,
+ pHcr->sectionInfo.pNumExtendedSortedSectionsInSets,
+ pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx);
+
+ /* store */
+ pTmp1 = pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx;
+ pTmp2 = pHcr->sectionInfo.extendedSortedCodebookIdx;
+ pTmp3 = pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx;
+ pTmp4 = pHcr->decInOut.quantizedSpectralCoefficientsIdx;
+ pTmp5 = pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx;
+
+ /* ------- decode meaningful PCWs ------ */
+ DecodePCWs(bs, pHcr);
+
+ if ((pHcr->decInOut.errorLog & HCR_FATAL_PCW_ERROR_MASK) == 0) {
+ /* ------ decode the non-PCWs -------- */
+ DecodeNonPCWs(bs, pHcr);
+ }
+
+ errDetectWithinSegmentationFinal(pHcr);
+
+ /* restore */
+ pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = pTmp1;
+ pHcr->sectionInfo.extendedSortedCodebookIdx = pTmp2;
+ pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = pTmp3;
+ pHcr->decInOut.quantizedSpectralCoefficientsIdx = pTmp4;
+ pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx = pTmp5;
+
+ HcrReorderQuantizedSpectralCoefficients(pHcr, pAacDecoderChannelInfo,
+ pSamplingRateInfo);
+
+ /* restore bitstream position */
+ bitCntOffst = (INT)FDKgetValidBits(bs) - saveBitCnt;
+ if (bitCntOffst) {
+ FDKpushBiDirectional(bs, bitCntOffst);
+ }
+
+ return (pHcr->decInOut.errorLog);
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: This function reorders the quantized spectral coefficients
+sectionwise for long- and short-blocks and compares to the LAV (Largest Absolute
+Value of the current codebook) -- a counter is incremented if there is an error
+ detected.
+ Additional for short-blocks a unit-based-deinterleaving is
+applied. Moreover (for short blocks) the scaling is derived (compare plain
+huffman decoder).
+--------------------------------------------------------------------------------------------
+*/
+
+static void HcrReorderQuantizedSpectralCoefficients(
+ H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo) {
+ INT qsc;
+ UINT abs_qsc;
+ UINT i, j;
+ USHORT numSpectralValuesInSection;
+ FIXP_DBL *pTeVa;
+ USHORT lavErrorCnt = 0;
+
+ UINT numSection = pHcr->decInOut.numSection;
+ SPECTRAL_PTR pQuantizedSpectralCoefficientsBase =
+ pHcr->decInOut.pQuantizedSpectralCoefficientsBase;
+ FIXP_DBL *pQuantizedSpectralCoefficients =
+ SPEC_LONG(pHcr->decInOut.pQuantizedSpectralCoefficientsBase);
+ const UCHAR *pCbDimShift = aDimCbShift;
+ const USHORT *pLargestAbsVal = aLargestAbsoluteValue;
+ UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook;
+ USHORT *pNumSortedCodewordInSection =
+ pHcr->sectionInfo.pNumSortedCodewordInSection;
+ USHORT *pReorderOffset = pHcr->sectionInfo.pReorderOffset;
+ FIXP_DBL pTempValues[1024];
+ FIXP_DBL *pBak = pTempValues;
+
+ FDKmemclear(pTempValues, 1024 * sizeof(FIXP_DBL));
+
+ /* long and short: check if decoded huffman-values (quantized spectral
+ * coefficients) are within range */
+ for (i = numSection; i != 0; i--) {
+ numSpectralValuesInSection = *pNumSortedCodewordInSection++
+ << pCbDimShift[*pSortedCodebook];
+ pTeVa = &pTempValues[*pReorderOffset++];
+ for (j = numSpectralValuesInSection; j != 0; j--) {
+ qsc = *pQuantizedSpectralCoefficients++;
+ abs_qsc = fAbs(qsc);
+ if (abs_qsc <= pLargestAbsVal[*pSortedCodebook]) {
+ *pTeVa++ = (FIXP_DBL)qsc; /* the qsc value is within range */
+ } else { /* line is too high .. */
+ if (abs_qsc ==
+ Q_VALUE_INVALID) { /* .. because of previous marking --> dont set
+ LAV flag (would be confusing), just copy out
+ the already marked value */
+ *pTeVa++ = (FIXP_DBL)qsc;
+ } else { /* .. because a too high value was decoded for this cb --> set
+ LAV flag */
+ *pTeVa++ = (FIXP_DBL)Q_VALUE_INVALID;
+ lavErrorCnt += 1;
+ }
+ }
+ }
+ pSortedCodebook++;
+ }
+
+ if (!IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) {
+ FIXP_DBL *pOut;
+ FIXP_DBL locMax;
+ FIXP_DBL tmp;
+ SCHAR groupoffset;
+ SCHAR group;
+ SCHAR band;
+ SCHAR groupwin;
+ SCHAR window;
+ SCHAR numWinGroup;
+ SHORT interm;
+ SCHAR numSfbTransm;
+ SCHAR winGroupLen;
+ SHORT index;
+ INT msb;
+ INT lsb;
+
+ SHORT *pScaleFacHcr = pAacDecoderChannelInfo->pDynData->aScaleFactor;
+ SHORT *pSfbSclHcr = pAacDecoderChannelInfo->pDynData->aSfbScale;
+ const SHORT *BandOffsets = GetScaleFactorBandOffsets(
+ &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
+
+ pBak = pTempValues;
+ /* deinterleave unitwise for short blocks */
+ for (window = 0; window < (8); window++) {
+ pOut = SPEC(pQuantizedSpectralCoefficientsBase, window,
+ pAacDecoderChannelInfo->granuleLength);
+ for (i = 0; i < (LINES_PER_UNIT_GROUP); i++) {
+ pTeVa = pBak + (window << FOUR_LOG_DIV_TWO_LOG) +
+ i * 32; /* distance of lines between unit groups has to be
+ constant for every framelength (32)! */
+ for (j = (LINES_PER_UNIT); j != 0; j--) {
+ *pOut++ = *pTeVa++;
+ }
+ }
+ }
+
+ /* short blocks only */
+ /* derive global scaling-value for every sfb and every window (as it is done
+ * in plain-huffman-decoder at short blocks) */
+ groupoffset = 0;
+
+ numWinGroup = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo);
+ numSfbTransm =
+ GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+
+ for (group = 0; group < numWinGroup; group++) {
+ winGroupLen =
+ GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo, group);
+ for (band = 0; band < numSfbTransm; band++) {
+ interm = group * 16 + band;
+ msb = pScaleFacHcr[interm] >> 2;
+ lsb = pScaleFacHcr[interm] & 3;
+ for (groupwin = 0; groupwin < winGroupLen; groupwin++) {
+ window = groupoffset + groupwin;
+ pBak = SPEC(pQuantizedSpectralCoefficientsBase, window,
+ pAacDecoderChannelInfo->granuleLength);
+ locMax = FL2FXCONST_DBL(0.0f);
+ for (index = BandOffsets[band]; index < BandOffsets[band + 1];
+ index += LINES_PER_UNIT) {
+ pTeVa = &pBak[index];
+ for (i = LINES_PER_UNIT; i != 0; i--) {
+ tmp = (*pTeVa < FL2FXCONST_DBL(0.0f)) ? -*pTeVa++ : *pTeVa++;
+ locMax = fixMax(tmp, locMax);
+ }
+ }
+ if (fixp_abs(locMax) > (FIXP_DBL)MAX_QUANTIZED_VALUE) {
+ locMax = (FIXP_DBL)MAX_QUANTIZED_VALUE;
+ }
+ pSfbSclHcr[window * 16 + band] =
+ msb - GetScaleFromValue(
+ locMax, lsb); /* save global scale maxima in this sfb */
+ }
+ }
+ groupoffset +=
+ GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo, group);
+ }
+ } else {
+ /* copy straight for long-blocks */
+ pQuantizedSpectralCoefficients =
+ SPEC_LONG(pQuantizedSpectralCoefficientsBase);
+ for (i = 1024; i != 0; i--) {
+ *pQuantizedSpectralCoefficients++ = *pBak++;
+ }
+ }
+
+ if (lavErrorCnt != 0) {
+ pHcr->decInOut.errorLog |= LAV_VIOLATION;
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: This function calculates the number of codewords
+ for each section (numCodewordInSection) and the number of
+codewords for all sections (numCodeword). For zero and intensity codebooks a
+entry is also done in the variable numCodewordInSection. It is assumed that the
+codebook is a two tuples codebook. This is needed later for the calculation of
+the base addresses for the reordering of the quantize spectral coefficients at
+the end of the hcr tool. The variable numCodeword contain the number of
+codewords which are really in the bitstream. Zero or intensity codebooks does
+not increase the variable numCodewords.
+-----------------------------------------------------------------------------------------------
+ return: -
+--------------------------------------------------------------------------------------------
+*/
+
+static void HcrCalcNumCodeword(H_HCR_INFO pHcr) {
+ int hcrSection;
+ UINT numCodeword;
+
+ UINT numSection = pHcr->decInOut.numSection;
+ UCHAR *pCodebook = pHcr->decInOut.pCodebook;
+ SHORT *pNumLineInSection = pHcr->decInOut.pNumLineInSect;
+ const UCHAR *pCbDimShift = aDimCbShift;
+
+ USHORT *pNumCodewordInSection = pHcr->sectionInfo.pNumCodewordInSection;
+
+ numCodeword = 0;
+ for (hcrSection = numSection; hcrSection != 0; hcrSection--) {
+ *pNumCodewordInSection = *pNumLineInSection++ >> pCbDimShift[*pCodebook];
+ if (*pCodebook != 0) {
+ numCodeword += *pNumCodewordInSection;
+ }
+ pNumCodewordInSection++;
+ pCodebook++;
+ }
+ pHcr->sectionInfo.numCodeword = numCodeword;
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: This function calculates the number
+ of sorted codebooks and sorts the codebooks and the
+numCodewordInSection according to the priority.
+--------------------------------------------------------------------------------------------
+*/
+
+static void HcrSortCodebookAndNumCodewordInSection(H_HCR_INFO pHcr) {
+ UINT i, j, k;
+ UCHAR temp;
+ UINT counter;
+ UINT startOffset;
+ UINT numZeroSection;
+ UCHAR *pDest;
+ UINT numSectionDec;
+
+ UINT numSection = pHcr->decInOut.numSection;
+ UCHAR *pCodebook = pHcr->decInOut.pCodebook;
+ UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook;
+ USHORT *pNumCodewordInSection = pHcr->sectionInfo.pNumCodewordInSection;
+ USHORT *pNumSortedCodewordInSection =
+ pHcr->sectionInfo.pNumSortedCodewordInSection;
+ UCHAR *pCodebookSwitch = pHcr->sectionInfo.pCodebookSwitch;
+ USHORT *pReorderOffset = pHcr->sectionInfo.pReorderOffset;
+ const UCHAR *pCbPriority = aCbPriority;
+ const UCHAR *pMinOfCbPair = aMinOfCbPair;
+ const UCHAR *pMaxOfCbPair = aMaxOfCbPair;
+ const UCHAR *pCbDimShift = aDimCbShift;
+
+ UINT searchStart = 0;
+
+ /* calculate *pNumSortedSection and store the priorities in array
+ * pSortedCdebook */
+ pDest = pSortedCodebook;
+ numZeroSection = 0;
+ for (i = numSection; i != 0; i--) {
+ if (pCbPriority[*pCodebook] == 0) {
+ numZeroSection += 1;
+ }
+ *pDest++ = pCbPriority[*pCodebook++];
+ }
+ pHcr->sectionInfo.numSortedSection =
+ numSection - numZeroSection; /* numSortedSection contains no zero or
+ intensity section */
+ pCodebook = pHcr->decInOut.pCodebook;
+
+ /* sort priorities of the codebooks in array pSortedCdebook[] */
+ numSectionDec = numSection - 1;
+ if (numSectionDec > 0) {
+ counter = numSectionDec;
+ for (j = numSectionDec; j != 0; j--) {
+ for (i = 0; i < counter; i++) {
+ /* swap priorities */
+ if (pSortedCodebook[i + 1] > pSortedCodebook[i]) {
+ temp = pSortedCodebook[i];
+ pSortedCodebook[i] = pSortedCodebook[i + 1];
+ pSortedCodebook[i + 1] = temp;
+ }
+ }
+ counter -= 1;
+ }
+ }
+
+ /* clear codebookSwitch array */
+ for (i = numSection; i != 0; i--) {
+ *pCodebookSwitch++ = 0;
+ }
+ pCodebookSwitch = pHcr->sectionInfo.pCodebookSwitch;
+
+ /* sort sectionCodebooks and numCodwordsInSection and calculate
+ * pReorderOffst[j] */
+ for (j = 0; j < numSection; j++) {
+ for (i = searchStart; i < numSection; i++) {
+ if (pCodebookSwitch[i] == 0 &&
+ (pMinOfCbPair[pSortedCodebook[j]] == pCodebook[i] ||
+ pMaxOfCbPair[pSortedCodebook[j]] == pCodebook[i])) {
+ pCodebookSwitch[i] = 1;
+ pSortedCodebook[j] = pCodebook[i]; /* sort codebook */
+ pNumSortedCodewordInSection[j] =
+ pNumCodewordInSection[i]; /* sort NumCodewordInSection */
+
+ startOffset = 0;
+ for (k = 0; k < i; k++) { /* make entry in pReorderOffst */
+ startOffset += pNumCodewordInSection[k] << pCbDimShift[pCodebook[k]];
+ }
+ pReorderOffset[j] =
+ startOffset; /* offset for reordering the codewords */
+
+ if (i == searchStart) {
+ k = i;
+ while (pCodebookSwitch[k++] == 1) searchStart++;
+ }
+ break;
+ }
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: This function calculates the segmentation, which includes
+numSegment, leftStartOfSegment, rightStartOfSegment and remainingBitsInSegment.
+ The segmentation could be visualized a as kind of
+'overlay-grid' for the bitstream-block holding the HCR-encoded
+quantized-spectral-coefficients.
+--------------------------------------------------------------------------------------------
+*/
+
+static void HcrPrepareSegmentationGrid(H_HCR_INFO pHcr) {
+ USHORT i, j;
+ USHORT numSegment = 0;
+ INT segmentStart = 0;
+ UCHAR segmentWidth;
+ UCHAR lastSegmentWidth;
+ UCHAR sortedCodebook;
+ UCHAR endFlag = 0;
+ INT intermediateResult;
+
+ SCHAR lengthOfLongestCodeword = pHcr->decInOut.lengthOfLongestCodeword;
+ SHORT lengthOfReorderedSpectralData =
+ pHcr->decInOut.lengthOfReorderedSpectralData;
+ UINT numSortedSection = pHcr->sectionInfo.numSortedSection;
+ UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook;
+ USHORT *pNumSortedCodewordInSection =
+ pHcr->sectionInfo.pNumSortedCodewordInSection;
+ INT *pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment;
+ INT *pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment;
+ SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+ const UCHAR *pMaxCwLength = aMaxCwLen;
+
+ for (i = numSortedSection; i != 0; i--) {
+ sortedCodebook = *pSortedCodebook++;
+ segmentWidth =
+ fMin((INT)pMaxCwLength[sortedCodebook], (INT)lengthOfLongestCodeword);
+
+ for (j = *pNumSortedCodewordInSection; j != 0; j--) {
+ /* width allows a new segment */
+ intermediateResult = segmentStart;
+ if ((segmentStart + segmentWidth) <= lengthOfReorderedSpectralData) {
+ /* store segment start, segment length and increment the number of
+ * segments */
+ *pLeftStartOfSegment++ = intermediateResult;
+ *pRightStartOfSegment++ = intermediateResult + segmentWidth - 1;
+ *pRemainingBitsInSegment++ = segmentWidth;
+ segmentStart += segmentWidth;
+ numSegment += 1;
+ }
+ /* width does not allow a new segment */
+ else {
+ /* correct the last segment length */
+ pLeftStartOfSegment--;
+ pRightStartOfSegment--;
+ pRemainingBitsInSegment--;
+ segmentStart = *pLeftStartOfSegment;
+
+ lastSegmentWidth = lengthOfReorderedSpectralData - segmentStart;
+ *pRemainingBitsInSegment = lastSegmentWidth;
+ *pRightStartOfSegment = segmentStart + lastSegmentWidth - 1;
+ endFlag = 1;
+ break;
+ }
+ }
+ pNumSortedCodewordInSection++;
+ if (endFlag != 0) {
+ break;
+ }
+ }
+ pHcr->segmentInfo.numSegment = numSegment;
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: This function adapts the sorted section boundaries to the
+boundaries of segmentation. If the section lengths does not fit completely into
+the current segment, the section is spitted into two so called 'extended
+ sections'. The extended-section-info
+(pNumExtendedSortedCodewordInSectin and pExtendedSortedCodebook) is updated in
+this case.
+
+--------------------------------------------------------------------------------------------
+*/
+
+static void HcrExtendedSectionInfo(H_HCR_INFO pHcr) {
+ UINT srtSecCnt = 0; /* counter for sorted sections */
+ UINT xSrtScCnt = 0; /* counter for extended sorted sections */
+ UINT remainNumCwInSortSec;
+ UINT inSegmentRemainNumCW;
+
+ UINT numSortedSection = pHcr->sectionInfo.numSortedSection;
+ UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook;
+ USHORT *pNumSortedCodewordInSection =
+ pHcr->sectionInfo.pNumSortedCodewordInSection;
+ UCHAR *pExtendedSortedCoBo = pHcr->sectionInfo.pExtendedSortedCodebook;
+ USHORT *pNumExtSortCwInSect =
+ pHcr->sectionInfo.pNumExtendedSortedCodewordInSection;
+ UINT numSegment = pHcr->segmentInfo.numSegment;
+ UCHAR *pMaxLenOfCbInExtSrtSec = pHcr->sectionInfo.pMaxLenOfCbInExtSrtSec;
+ SCHAR lengthOfLongestCodeword = pHcr->decInOut.lengthOfLongestCodeword;
+ const UCHAR *pMaxCwLength = aMaxCwLen;
+
+ remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt];
+ inSegmentRemainNumCW = numSegment;
+
+ while (srtSecCnt < numSortedSection) {
+ if (inSegmentRemainNumCW < remainNumCwInSortSec) {
+ pNumExtSortCwInSect[xSrtScCnt] = inSegmentRemainNumCW;
+ pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt];
+
+ remainNumCwInSortSec -= inSegmentRemainNumCW;
+ inSegmentRemainNumCW = numSegment;
+ /* data of a sorted section was not integrated in extended sorted section
+ */
+ } else if (inSegmentRemainNumCW == remainNumCwInSortSec) {
+ pNumExtSortCwInSect[xSrtScCnt] = inSegmentRemainNumCW;
+ pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt];
+
+ srtSecCnt++;
+ remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt];
+ inSegmentRemainNumCW = numSegment;
+ /* data of a sorted section was integrated in extended sorted section */
+ } else { /* inSegmentRemainNumCW > remainNumCwInSortSec */
+ pNumExtSortCwInSect[xSrtScCnt] = remainNumCwInSortSec;
+ pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt];
+
+ inSegmentRemainNumCW -= remainNumCwInSortSec;
+ srtSecCnt++;
+ remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt];
+ /* data of a sorted section was integrated in extended sorted section */
+ }
+ pMaxLenOfCbInExtSrtSec[xSrtScCnt] =
+ fMin((INT)pMaxCwLength[pExtendedSortedCoBo[xSrtScCnt]],
+ (INT)lengthOfLongestCodeword);
+
+ xSrtScCnt += 1;
+
+ if (xSrtScCnt >= (MAX_SFB_HCR + MAX_HCR_SETS)) {
+ pHcr->decInOut.errorLog |= EXTENDED_SORTED_COUNTER_OVERFLOW;
+ return;
+ }
+ }
+ pNumExtSortCwInSect[xSrtScCnt] = 0;
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: This function calculates the number of extended sorted
+sections which belong to the sets. Each set from set 0 (one and only set for the
+PCWs) till to the last set gets a entry in the array to which
+ 'pNumExtendedSortedSectinsInSets' points to.
+
+ Calculation: The entrys in
+pNumExtendedSortedCodewordInSectin are added untill the value numSegment is
+reached. Then the sum_variable is cleared and the calculation starts from the
+beginning. As much extended sorted Sections are summed up to reach the value
+numSegment, as much is the current entry in *pNumExtendedSortedCodewordInSectin.
+--------------------------------------------------------------------------------------------
+*/
+static void DeriveNumberOfExtendedSortedSectionsInSets(
+ UINT numSegment, USHORT *pNumExtendedSortedCodewordInSection,
+ int numExtendedSortedCodewordInSectionIdx,
+ USHORT *pNumExtendedSortedSectionsInSets,
+ int numExtendedSortedSectionsInSetsIdx) {
+ USHORT counter = 0;
+ UINT cwSum = 0;
+ USHORT *pNumExSortCwInSec = pNumExtendedSortedCodewordInSection;
+ USHORT *pNumExSortSecInSets = pNumExtendedSortedSectionsInSets;
+
+ while (pNumExSortCwInSec[numExtendedSortedCodewordInSectionIdx] != 0) {
+ cwSum += pNumExSortCwInSec[numExtendedSortedCodewordInSectionIdx];
+ numExtendedSortedCodewordInSectionIdx++;
+ if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) {
+ return;
+ }
+ if (cwSum > numSegment) {
+ return;
+ }
+ counter++;
+ if (counter > 1024 / 4) {
+ return;
+ }
+ if (cwSum == numSegment) {
+ pNumExSortSecInSets[numExtendedSortedSectionsInSetsIdx] = counter;
+ numExtendedSortedSectionsInSetsIdx++;
+ if (numExtendedSortedSectionsInSetsIdx >= MAX_HCR_SETS) {
+ return;
+ }
+ counter = 0;
+ cwSum = 0;
+ }
+ }
+ pNumExSortSecInSets[numExtendedSortedSectionsInSetsIdx] =
+ counter; /* save last entry for the last - probably shorter - set */
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: This function decodes all priority codewords (PCWs) in a
+spectrum (within set 0). The calculation of the PCWs is managed in two loops.
+The loopcounter of the outer loop is set to the first value pointer
+ pNumExtendedSortedSectionsInSets points to. This value
+represents the number of extended sorted sections within set 0. The loopcounter
+of the inner loop is set to the first value pointer
+ pNumExtendedSortedCodewordInSectin points to. The value
+represents the number of extended sorted codewords in sections (the original
+sections have been splitted to go along with the borders of the sets). Each time
+the number of the extended sorted codewords in sections are de- coded, the
+pointer 'pNumExtendedSortedCodewordInSectin' is incremented by one.
+--------------------------------------------------------------------------------------------
+*/
+static void DecodePCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr) {
+ UINT i;
+ USHORT extSortSec;
+ USHORT curExtSortCwInSec;
+ UCHAR codebook;
+ UCHAR dimension;
+ const UINT *pCurrentTree;
+ const SCHAR *pQuantValBase;
+ const SCHAR *pQuantVal;
+
+ USHORT *pNumExtendedSortedCodewordInSection =
+ pHcr->sectionInfo.pNumExtendedSortedCodewordInSection;
+ int numExtendedSortedCodewordInSectionIdx =
+ pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx;
+ UCHAR *pExtendedSortedCodebook = pHcr->sectionInfo.pExtendedSortedCodebook;
+ int extendedSortedCodebookIdx = pHcr->sectionInfo.extendedSortedCodebookIdx;
+ USHORT *pNumExtendedSortedSectionsInSets =
+ pHcr->sectionInfo.pNumExtendedSortedSectionsInSets;
+ int numExtendedSortedSectionsInSetsIdx =
+ pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx;
+ FIXP_DBL *pQuantizedSpectralCoefficients =
+ SPEC_LONG(pHcr->decInOut.pQuantizedSpectralCoefficientsBase);
+ int quantizedSpectralCoefficientsIdx =
+ pHcr->decInOut.quantizedSpectralCoefficientsIdx;
+ INT *pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment;
+ SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+ UCHAR *pMaxLenOfCbInExtSrtSec = pHcr->sectionInfo.pMaxLenOfCbInExtSrtSec;
+ int maxLenOfCbInExtSrtSecIdx = pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx;
+ UCHAR maxAllowedCwLen;
+ int numDecodedBits;
+ const UCHAR *pCbDimension = aDimCb;
+ const UCHAR *pCbSign = aSignCb;
+
+ /* clear result array */
+ FDKmemclear(pQuantizedSpectralCoefficients + quantizedSpectralCoefficientsIdx,
+ 1024 * sizeof(FIXP_DBL));
+
+ /* decode all PCWs in the extended sorted section(s) belonging to set 0 */
+ for (extSortSec =
+ pNumExtendedSortedSectionsInSets[numExtendedSortedSectionsInSetsIdx];
+ extSortSec != 0; extSortSec--) {
+ codebook =
+ pExtendedSortedCodebook[extendedSortedCodebookIdx]; /* get codebook for
+ this extended
+ sorted section
+ and increment ptr
+ to cb of next
+ ext. sort sec */
+ extendedSortedCodebookIdx++;
+ if (extendedSortedCodebookIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) {
+ return;
+ }
+ dimension = pCbDimension[codebook]; /* get dimension of codebook of this
+ extended sort. sec. */
+ pCurrentTree =
+ aHuffTable[codebook]; /* convert codebook to pointer to QSCs */
+ pQuantValBase =
+ aQuantTable[codebook]; /* convert codebook to index to table of QSCs */
+ maxAllowedCwLen = pMaxLenOfCbInExtSrtSec[maxLenOfCbInExtSrtSecIdx];
+ maxLenOfCbInExtSrtSecIdx++;
+ if (maxLenOfCbInExtSrtSecIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) {
+ return;
+ }
+
+ /* switch for decoding with different codebooks: */
+ if (pCbSign[codebook] ==
+ 0) { /* no sign bits follow after the codeword-body */
+ /* PCW_BodyONLY */
+ /*==============*/
+
+ for (curExtSortCwInSec = pNumExtendedSortedCodewordInSection
+ [numExtendedSortedCodewordInSectionIdx];
+ curExtSortCwInSec != 0; curExtSortCwInSec--) {
+ numDecodedBits = 0;
+
+ /* decode PCW_BODY */
+ pQuantVal = DecodePCW_Body(
+ bs, pHcr->decInOut.bitstreamAnchor, pCurrentTree, pQuantValBase,
+ pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits);
+
+ /* result is written out here because NO sign bits follow the body */
+ for (i = dimension; i != 0; i--) {
+ pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] =
+ (FIXP_DBL)*pQuantVal++; /* write quant. spec. coef. into
+ spectrum; sign is already valid */
+ quantizedSpectralCoefficientsIdx++;
+ if (quantizedSpectralCoefficientsIdx >= 1024) {
+ return;
+ }
+ }
+
+ /* one more PCW should be decoded */
+
+ if (maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_ONLY_TOO_LONG)) {
+ pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_BITS_DECODED;
+ }
+
+ if (1 == errDetectPcwSegmentation(
+ *pRemainingBitsInSegment - ERROR_PCW_BODY, pHcr, PCW_BODY,
+ pQuantizedSpectralCoefficients +
+ quantizedSpectralCoefficientsIdx - dimension,
+ dimension)) {
+ return;
+ }
+ pLeftStartOfSegment++; /* update pointer for decoding the next PCW */
+ pRemainingBitsInSegment++; /* update pointer for decoding the next PCW
+ */
+ }
+ } else if ((codebook < 11) && (pCbSign[codebook] ==
+ 1)) { /* possibly there follow 1,2,3 or 4
+ sign bits after the codeword-body */
+ /* PCW_Body and PCW_Sign */
+ /*=======================*/
+
+ for (curExtSortCwInSec = pNumExtendedSortedCodewordInSection
+ [numExtendedSortedCodewordInSectionIdx];
+ curExtSortCwInSec != 0; curExtSortCwInSec--) {
+ int err;
+ numDecodedBits = 0;
+
+ pQuantVal = DecodePCW_Body(
+ bs, pHcr->decInOut.bitstreamAnchor, pCurrentTree, pQuantValBase,
+ pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits);
+
+ err = DecodePCW_Sign(
+ bs, pHcr->decInOut.bitstreamAnchor, dimension, pQuantVal,
+ pQuantizedSpectralCoefficients, &quantizedSpectralCoefficientsIdx,
+ pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits);
+ if (err != 0) {
+ return;
+ }
+ /* one more PCW should be decoded */
+
+ if (maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_SIGN_TOO_LONG)) {
+ pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_SIGN_BITS_DECODED;
+ }
+
+ if (1 == errDetectPcwSegmentation(
+ *pRemainingBitsInSegment - ERROR_PCW_BODY_SIGN, pHcr,
+ PCW_BODY_SIGN,
+ pQuantizedSpectralCoefficients +
+ quantizedSpectralCoefficientsIdx - dimension,
+ dimension)) {
+ return;
+ }
+ pLeftStartOfSegment++;
+ pRemainingBitsInSegment++;
+ }
+ } else if ((pCbSign[codebook] == 1) &&
+ (codebook >= 11)) { /* possibly there follow some sign bits and
+ maybe one or two escape sequences after
+ the cw-body */
+ /* PCW_Body, PCW_Sign and maybe PCW_Escape */
+ /*=========================================*/
+
+ for (curExtSortCwInSec = pNumExtendedSortedCodewordInSection
+ [numExtendedSortedCodewordInSectionIdx];
+ curExtSortCwInSec != 0; curExtSortCwInSec--) {
+ int err;
+ numDecodedBits = 0;
+
+ /* decode PCW_BODY */
+ pQuantVal = DecodePCW_Body(
+ bs, pHcr->decInOut.bitstreamAnchor, pCurrentTree, pQuantValBase,
+ pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits);
+
+ err = DecodePCW_Sign(
+ bs, pHcr->decInOut.bitstreamAnchor, dimension, pQuantVal,
+ pQuantizedSpectralCoefficients, &quantizedSpectralCoefficientsIdx,
+ pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits);
+ if (err != 0) {
+ return;
+ }
+
+ /* decode PCW_ESCAPE if present */
+ quantizedSpectralCoefficientsIdx -= DIMENSION_OF_ESCAPE_CODEBOOK;
+
+ if (fixp_abs(pQuantizedSpectralCoefficients
+ [quantizedSpectralCoefficientsIdx]) ==
+ (FIXP_DBL)ESCAPE_VALUE) {
+ pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] =
+ (FIXP_DBL)DecodeEscapeSequence(
+ bs, pHcr->decInOut.bitstreamAnchor,
+ pQuantizedSpectralCoefficients
+ [quantizedSpectralCoefficientsIdx],
+ pLeftStartOfSegment, pRemainingBitsInSegment,
+ &numDecodedBits);
+ }
+ quantizedSpectralCoefficientsIdx++;
+ if (quantizedSpectralCoefficientsIdx >= 1024) {
+ return;
+ }
+
+ if (fixp_abs(pQuantizedSpectralCoefficients
+ [quantizedSpectralCoefficientsIdx]) ==
+ (FIXP_DBL)ESCAPE_VALUE) {
+ pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] =
+ (FIXP_DBL)DecodeEscapeSequence(
+ bs, pHcr->decInOut.bitstreamAnchor,
+ pQuantizedSpectralCoefficients
+ [quantizedSpectralCoefficientsIdx],
+ pLeftStartOfSegment, pRemainingBitsInSegment,
+ &numDecodedBits);
+ }
+ quantizedSpectralCoefficientsIdx++;
+ if (quantizedSpectralCoefficientsIdx >= 1024) {
+ return;
+ }
+
+ /* one more PCW should be decoded */
+
+ if (maxAllowedCwLen <
+ (numDecodedBits + ERROR_PCW_BODY_SIGN_ESC_TOO_LONG)) {
+ pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_SIGN_ESC_BITS_DECODED;
+ }
+
+ if (1 == errDetectPcwSegmentation(
+ *pRemainingBitsInSegment - ERROR_PCW_BODY_SIGN_ESC, pHcr,
+ PCW_BODY_SIGN_ESC,
+ pQuantizedSpectralCoefficients +
+ quantizedSpectralCoefficientsIdx -
+ DIMENSION_OF_ESCAPE_CODEBOOK,
+ DIMENSION_OF_ESCAPE_CODEBOOK)) {
+ return;
+ }
+ pLeftStartOfSegment++;
+ pRemainingBitsInSegment++;
+ }
+ }
+
+ /* all PCWs belonging to this extended section should be decoded */
+ numExtendedSortedCodewordInSectionIdx++;
+ if (numExtendedSortedCodewordInSectionIdx >= MAX_SFB_HCR + MAX_HCR_SETS) {
+ return;
+ }
+ }
+ /* all PCWs should be decoded */
+
+ numExtendedSortedSectionsInSetsIdx++;
+ if (numExtendedSortedSectionsInSetsIdx >= MAX_HCR_SETS) {
+ return;
+ }
+
+ /* Write back indexes into structure */
+ pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx =
+ numExtendedSortedCodewordInSectionIdx;
+ pHcr->sectionInfo.extendedSortedCodebookIdx = extendedSortedCodebookIdx;
+ pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx =
+ numExtendedSortedSectionsInSetsIdx;
+ pHcr->decInOut.quantizedSpectralCoefficientsIdx =
+ quantizedSpectralCoefficientsIdx;
+ pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx = maxLenOfCbInExtSrtSecIdx;
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: This function checks immediately after every decoded PCW,
+whether out of the current segment too many bits have been read or not. If an
+error occurrs, probably the sideinfo or the HCR-bitstream block holding the
+huffman encoded quantized spectral coefficients is distorted. In this case the
+two or four quantized spectral coefficients belonging to the current codeword
+ are marked (for being detected by concealment later).
+--------------------------------------------------------------------------------------------
+*/
+static UCHAR errDetectPcwSegmentation(SCHAR remainingBitsInSegment,
+ H_HCR_INFO pHcr, PCW_TYPE kind,
+ FIXP_DBL *qsc_base_of_cw,
+ UCHAR dimension) {
+ SCHAR i;
+ if (remainingBitsInSegment < 0) {
+ /* log the error */
+ switch (kind) {
+ case PCW_BODY:
+ pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY;
+ break;
+ case PCW_BODY_SIGN:
+ pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN;
+ break;
+ case PCW_BODY_SIGN_ESC:
+ pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN_ESC;
+ break;
+ }
+ /* mark the erred lines */
+ for (i = dimension; i != 0; i--) {
+ *qsc_base_of_cw++ = (FIXP_DBL)Q_VALUE_INVALID;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: This function checks if all segments are empty after
+decoding. There are _no lines markded_ as invalid because it could not be traced
+back where from the remaining bits are.
+--------------------------------------------------------------------------------------------
+*/
+static void errDetectWithinSegmentationFinal(H_HCR_INFO pHcr) {
+ UCHAR segmentationErrorFlag = 0;
+ USHORT i;
+ SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+ UINT numSegment = pHcr->segmentInfo.numSegment;
+
+ for (i = numSegment; i != 0; i--) {
+ if (*pRemainingBitsInSegment++ != 0) {
+ segmentationErrorFlag = 1;
+ }
+ }
+ if (segmentationErrorFlag == 1) {
+ pHcr->decInOut.errorLog |= BIT_IN_SEGMENTATION_ERROR;
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: This function walks one step within the decoding tree. Which
+branch is taken depends on the decoded carryBit input parameter.
+--------------------------------------------------------------------------------------------
+*/
+void CarryBitToBranchValue(UCHAR carryBit, UINT treeNode, UINT *branchValue,
+ UINT *branchNode) {
+ if (carryBit == 0) {
+ *branchNode =
+ (treeNode & MASK_LEFT) >> LEFT_OFFSET; /* MASK_LEFT: 00FFF000 */
+ } else {
+ *branchNode = treeNode & MASK_RIGHT; /* MASK_RIGHT: 00000FFF */
+ }
+
+ *branchValue = *branchNode & CLR_BIT_10; /* clear bit 10 (if set) */
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: Decodes the body of a priority codeword (PCW)
+-----------------------------------------------------------------------------------------------
+ return: - return value is pointer to first of two or four quantized
+spectral coefficients
+--------------------------------------------------------------------------------------------
+*/
+static const SCHAR *DecodePCW_Body(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor,
+ const UINT *pCurrentTree,
+ const SCHAR *pQuantValBase,
+ INT *pLeftStartOfSegment,
+ SCHAR *pRemainingBitsInSegment,
+ int *pNumDecodedBits) {
+ UCHAR carryBit;
+ UINT branchNode;
+ UINT treeNode;
+ UINT branchValue;
+ const SCHAR *pQuantVal;
+
+ /* decode PCW_BODY */
+ treeNode = *pCurrentTree; /* get first node of current tree belonging to
+ current codebook */
+
+ /* decode whole PCW-codeword-body */
+ while (1) {
+ carryBit = HcrGetABitFromBitstream(bs, bsAnchor, pLeftStartOfSegment,
+ pLeftStartOfSegment, /* dummy */
+ FROM_LEFT_TO_RIGHT);
+ *pRemainingBitsInSegment -= 1;
+ *pNumDecodedBits += 1;
+
+ CarryBitToBranchValue(carryBit, treeNode, &branchValue, &branchNode);
+
+ if ((branchNode & TEST_BIT_10) ==
+ TEST_BIT_10) { /* test bit 10 ; if set --> codeword-body is complete */
+ break; /* end of branch in tree reached i.e. a whole PCW-Body is decoded
+ */
+ } else {
+ treeNode = *(
+ pCurrentTree +
+ branchValue); /* update treeNode for further step in decoding tree */
+ }
+ }
+
+ pQuantVal =
+ pQuantValBase + branchValue; /* update pointer to valid first of 2 or 4
+ quantized values */
+
+ return pQuantVal;
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: This function decodes one escape sequence. In case of a
+escape codebook and in case of the absolute value of the quantized spectral
+value == 16, a escapeSequence is decoded in two steps:
+ 1. escape prefix
+ 2. escape word
+--------------------------------------------------------------------------------------------
+*/
+
+static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor,
+ INT quantSpecCoef, INT *pLeftStartOfSegment,
+ SCHAR *pRemainingBitsInSegment,
+ int *pNumDecodedBits) {
+ UINT i;
+ INT sign;
+ UINT escapeOnesCounter = 0;
+ UINT carryBit;
+ INT escape_word = 0;
+
+ /* decode escape prefix */
+ while (1) {
+ carryBit = HcrGetABitFromBitstream(bs, bsAnchor, pLeftStartOfSegment,
+ pLeftStartOfSegment, /* dummy */
+ FROM_LEFT_TO_RIGHT);
+ *pRemainingBitsInSegment -= 1;
+ *pNumDecodedBits += 1;
+
+ if (carryBit != 0) {
+ escapeOnesCounter += 1;
+ } else {
+ escapeOnesCounter += 4;
+ break;
+ }
+ }
+
+ /* decode escape word */
+ for (i = escapeOnesCounter; i != 0; i--) {
+ carryBit = HcrGetABitFromBitstream(bs, bsAnchor, pLeftStartOfSegment,
+ pLeftStartOfSegment, /* dummy */
+ FROM_LEFT_TO_RIGHT);
+ *pRemainingBitsInSegment -= 1;
+ *pNumDecodedBits += 1;
+
+ escape_word <<= 1;
+ escape_word = escape_word | carryBit;
+ }
+
+ sign = (quantSpecCoef >= 0) ? 1 : -1;
+
+ quantSpecCoef = sign * (((INT)1 << escapeOnesCounter) + escape_word);
+
+ return quantSpecCoef;
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: Decodes the Signbits of a priority codeword (PCW) and writes
+out the resulting quantized spectral values into unsorted sections
+-----------------------------------------------------------------------------------------------
+ output: - two or four lines at position in corresponding section
+(which are not located at the desired position, i.e. they must be reordered in
+the last of eight function of HCR)
+-----------------------------------------------------------------------------------------------
+ return: - updated pQuantSpecCoef pointer (to next empty storage for a
+line)
+--------------------------------------------------------------------------------------------
+*/
+static int DecodePCW_Sign(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor,
+ UINT codebookDim, const SCHAR *pQuantVal,
+ FIXP_DBL *pQuantSpecCoef, int *quantSpecCoefIdx,
+ INT *pLeftStartOfSegment,
+ SCHAR *pRemainingBitsInSegment,
+ int *pNumDecodedBits) {
+ UINT i;
+ UINT carryBit;
+ INT quantSpecCoef;
+
+ for (i = codebookDim; i != 0; i--) {
+ quantSpecCoef = *pQuantVal++;
+ if (quantSpecCoef != 0) {
+ carryBit = HcrGetABitFromBitstream(bs, bsAnchor, pLeftStartOfSegment,
+ pLeftStartOfSegment, /* dummy */
+ FROM_LEFT_TO_RIGHT);
+ *pRemainingBitsInSegment -= 1;
+ *pNumDecodedBits += 1;
+ if (*pRemainingBitsInSegment < 0 || *pNumDecodedBits >= (1024 >> 1)) {
+ return -1;
+ }
+
+ /* adapt sign of values according to the decoded sign bit */
+ if (carryBit != 0) {
+ pQuantSpecCoef[*quantSpecCoefIdx] = -(FIXP_DBL)quantSpecCoef;
+ } else {
+ pQuantSpecCoef[*quantSpecCoefIdx] = (FIXP_DBL)quantSpecCoef;
+ }
+ } else {
+ pQuantSpecCoef[*quantSpecCoefIdx] = FL2FXCONST_DBL(0.0f);
+ }
+ *quantSpecCoefIdx += 1;
+ if (*quantSpecCoefIdx >= 1024) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: Mutes spectral lines which have been marked as erroneous
+(Q_VALUE_INVALID)
+--------------------------------------------------------------------------------------------
+*/
+void HcrMuteErroneousLines(H_HCR_INFO hHcr) {
+ int c;
+ FIXP_DBL *RESTRICT pLong =
+ SPEC_LONG(hHcr->decInOut.pQuantizedSpectralCoefficientsBase);
+
+ /* if there is a line with value Q_VALUE_INVALID mute it */
+ for (c = 0; c < 1024; c++) {
+ if (pLong[c] == (FIXP_DBL)Q_VALUE_INVALID) {
+ pLong[c] = FL2FXCONST_DBL(0.0f); /* muting */
+ }
+ }
+}