summaryrefslogtreecommitdiffstats
path: root/libAACdec/src/aacdec_hcr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libAACdec/src/aacdec_hcr.cpp')
-rw-r--r--libAACdec/src/aacdec_hcr.cpp1591
1 files changed, 1591 insertions, 0 deletions
diff --git a/libAACdec/src/aacdec_hcr.cpp b/libAACdec/src/aacdec_hcr.cpp
new file mode 100644
index 0000000..5b86833
--- /dev/null
+++ b/libAACdec/src/aacdec_hcr.cpp
@@ -0,0 +1,1591 @@
+
+/* -----------------------------------------------------------------------------------------------------------
+Software License for The Fraunhofer FDK AAC Codec Library for Android
+
+© Copyright 1995 - 2012 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
+----------------------------------------------------------------------------------------------------------- */
+
+/***************************** MPEG-4 AAC Decoder ***************************
+
+ 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,
+ INT quantSpecCoef,
+ USHORT *pLeftStartOfSegment,
+ SCHAR *pRemainingBitsInSegment,
+ int *pNumDecodedBits
+ );
+
+static int DecodePCW_Sign(HANDLE_FDK_BITSTREAM bs,
+ UINT codebookDim,
+ const SCHAR *pQuantVal,
+ FIXP_DBL *pQuantSpecCoef,
+ int *quantSpecCoefIdx,
+ USHORT *pLeftStartOfSegment,
+ SCHAR *pRemainingBitsInSegment,
+ int *pNumDecodedBits
+ );
+
+static const SCHAR *DecodePCW_Body(HANDLE_FDK_BITSTREAM bs,
+ const UINT *pCurrentTree,
+ const SCHAR *pQuantValBase,
+ USHORT *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
+ );
+
+
+#if CHECK_SEGMENTATION_IMMEDIATELY
+static UCHAR errDetectPcwSegmentation(SCHAR remainingBitsInSegment,
+ H_HCR_INFO pHcr,
+ PCW_TYPE kind,
+ FIXP_DBL *qsc_base_of_cw,
+ UCHAR dimension);
+#endif
+
+#if CHECK_SEGMENTATION_FINAL
+static void errDetectWithinSegmentationFinal(H_HCR_INFO pHcr);
+#endif
+
+/*---------------------------------------------------------------------------------------------
+ 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)
+{
+ INT globalHcrType = getHcrType(&pAacDecoderChannelInfo->pComData->overlay.aac.erHcrInfo);
+ 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: Sets up HCR ROM-Tables
+-------------------------------------------------------------------------------------------- */
+
+void HcrInitRom(H_HCR_INFO pHcr)
+{
+ pHcr->cbPairs.pMinOfCbPair = aMinOfCbPair;
+ pHcr->cbPairs.pMaxOfCbPair = aMaxOfCbPair;
+
+ pHcr->tableInfo.pMaxCwLength = aMaxCwLen;
+ pHcr->tableInfo.pCbDimension = aDimCb;
+ pHcr->tableInfo.pCbDimShift = aDimCbShift;
+ pHcr->tableInfo.pCbSign = aSignCb;
+ pHcr->tableInfo.pCbPriority = aCbPriority;
+ pHcr->tableInfo.pLargestAbsVal = aLargestAbsoluteValue;
+}
+
+/*---------------------------------------------------------------------------------------------
+ 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.bitstreamIndex = FDKgetBitCnt(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 = GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group);
+ for (groupWin = winGroupLen; groupWin != 0; groupWin--, window++) {
+ cb = pCodeBook[group * 16 + band];
+ if (cb != cb_prev) {
+#if CHECK_VALID_HCR_INPUT /* short-block 1 of 2 */
+ errDetectorInHcrSideinfoShrt(cb,numLine,&pHcr->decInOut.errorLog );
+ if (pHcr->decInOut.errorLog != 0 ) {
+ return ( pHcr->decInOut.errorLog );
+ }
+#endif
+ *pCodeBk++ = cb;
+ *pNumLinesInSec++ = numLine;
+ numSection++;
+
+ cb_prev = cb;
+ numLine = LINES_PER_UNIT;
+ }
+ else {
+ numLine += LINES_PER_UNIT;
+ }
+ }
+ }
+ }
+ }
+
+ numSection++;
+
+#if CHECK_VALID_HCR_INPUT /* short-block 2 of 2 */
+ 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 );
+ }
+#endif
+
+ *pCodeBk = cb;
+ *pNumLinesInSec = numLine;
+ pHcr->decInOut.numSection = numSection;
+
+ } else /* end short block prepare SI */
+ { /* long block */
+#if CHECK_VALID_HCR_INPUT /* long-block 1 of 1 */
+ 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 );
+ }
+#endif /* CHECK_VALID_HCR_INPUT */
+ }
+
+ 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 );
+}
+
+
+
+
+#if USE_HCR_DUMMY
+
+/*---------------------------------------------------------------------------------------------
+
+ description: This HCR - dummy - function writes only a dirac-sequence in output buffer
+
+-------------------------------------------------------------------------------------------- */
+UINT HcrDecoder(H_HCR_INFO pHcr,
+ const CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ HANDLE_FDK_BITSTREAM bs)
+{
+ for (SHORT i=0; i < 1024; i++ ) {
+ pHcr->decInOut.pQuantizedSpectralCoefficients->Long[i] = FL2FXCONST_DBL(0.0f);
+ if ( i % 30 == 0) {
+ pHcr->decInOut.pQuantizedSpectralCoefficients->Long[i] = (FIXP_DBL)HCR_DIRAC;
+ }
+ }
+ return 0;
+}
+
+#else /* USE_HCR_DUMMY */
+
+/*---------------------------------------------------------------------------------------------
+ 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;
+#if DETECT_TOO_LONG_CW_READS
+ int pTmp5;
+#endif
+
+ INT bitCntOffst;
+ UINT saveBitCnt = FDKgetBitCnt(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;
+#if DETECT_TOO_LONG_CW_READS
+ pTmp5 = pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx;
+#endif
+
+ /* ------- decode meaningful PCWs ------ */
+ DecodePCWs(bs, pHcr);
+
+ if (( pHcr->decInOut.errorLog & HCR_FATAL_PCW_ERROR_MASK ) == 0 ) {
+ /* ------ decode the non-PCWs -------- */
+ DecodeNonPCWs(bs, pHcr);
+ }
+
+
+#if CHECK_SEGMENTATION_FINAL
+ errDetectWithinSegmentationFinal(pHcr);
+#endif
+
+ /* restore */
+ pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = pTmp1;
+ pHcr->sectionInfo.extendedSortedCodebookIdx = pTmp2;
+ pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = pTmp3;
+ pHcr->decInOut.quantizedSpectralCoefficientsIdx = pTmp4;
+#if DETECT_TOO_LONG_CW_READS
+ pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx = pTmp5;
+#endif
+
+ HcrReorderQuantizedSpectralCoefficients(pHcr, pAacDecoderChannelInfo, pSamplingRateInfo);
+
+ /* restore bitstream position */
+ bitCntOffst = saveBitCnt - FDKgetBitCnt(bs);
+ if( bitCntOffst ) {
+ FDKpushBiDirectional(bs, bitCntOffst);
+ }
+
+ return ( pHcr->decInOut.errorLog );
+}
+
+
+#endif /* USE_HCR_DUMMY */
+
+
+
+
+/*---------------------------------------------------------------------------------------------
+ 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 = pHcr->tableInfo.pCbDimShift;
+ const USHORT *pLargestAbsVal = pHcr->tableInfo.pLargestAbsVal;
+ UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook;
+ USHORT *pNumSortedCodewordInSection = pHcr->sectionInfo.pNumSortedCodewordInSection;
+ USHORT *pReorderOffset = pHcr->sectionInfo.pReorderOffset;
+ FIXP_DBL *pTempValues = pHcr->segmentInfo.pTempValues;
+ FIXP_DBL *pBak = pHcr->segmentInfo.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 = FDKabs(qsc);
+#if VALID_LAV_ERROR_TRIGGER
+ 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;
+ }
+ }
+#else
+ if ( abs_qsc <= pLargestAbsVal[*pSortedCodebook] ) {
+ *pTeVa++ = qsc;
+ }
+ else {
+ *pTeVa++ = Q_VALUE_INVALID;
+ lavErrorCnt += 1;
+ }
+#endif
+ }
+ 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 = pHcr->segmentInfo.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 = pHcr->tableInfo.pCbDimShift;
+ 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 = pHcr->tableInfo.pCbPriority;
+ const UCHAR *pMinOfCbPair = pHcr->cbPairs.pMinOfCbPair;
+ const UCHAR *pMaxOfCbPair = pHcr->cbPairs.pMaxOfCbPair;
+ const UCHAR *pCbDimShift = pHcr->tableInfo.pCbDimShift;
+
+ 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) {
+ UINT 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;
+ USHORT segmentStart = 0;
+ UCHAR segmentWidth;
+ UCHAR lastSegmentWidth;
+ UCHAR sortedCodebook;
+ UCHAR endFlag = 0;
+ USHORT 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;
+ USHORT *pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment;
+ USHORT *pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment;
+ SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+ USHORT bitstreamIndex = pHcr->decInOut.bitstreamIndex;
+ const UCHAR *pMaxCwLength = pHcr->tableInfo.pMaxCwLength;
+
+ for ( i=numSortedSection; i != 0; i-- ) {
+ sortedCodebook = *pSortedCodebook++;
+ segmentWidth = FDKmin(pMaxCwLength[sortedCodebook],lengthOfLongestCodeword);
+
+ for ( j = *pNumSortedCodewordInSection; j != 0 ; j-- ) {
+ /* width allows a new segment */
+ intermediateResult = bitstreamIndex + 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 - bitstreamIndex;
+
+ lastSegmentWidth = lengthOfReorderedSpectralData - segmentStart;
+ *pRemainingBitsInSegment = lastSegmentWidth;
+ *pRightStartOfSegment = bitstreamIndex + 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;
+#if DETECT_TOO_LONG_CW_READS
+ UCHAR *pMaxLenOfCbInExtSrtSec = pHcr->sectionInfo.pMaxLenOfCbInExtSrtSec;
+ SCHAR lengthOfLongestCodeword = pHcr->decInOut.lengthOfLongestCodeword;
+ const UCHAR *pMaxCwLength = pHcr->tableInfo.pMaxCwLength;
+#endif
+
+ 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 */
+ }
+#if DETECT_TOO_LONG_CW_READS
+ pMaxLenOfCbInExtSrtSec[xSrtScCnt] = FDKmin(pMaxCwLength[pExtendedSortedCoBo[xSrtScCnt]],lengthOfLongestCodeword);
+#endif
+
+
+
+ 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;
+ USHORT *pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment;
+ SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+#if DETECT_TOO_LONG_CW_READS
+ UCHAR *pMaxLenOfCbInExtSrtSec = pHcr->sectionInfo.pMaxLenOfCbInExtSrtSec;
+ int maxLenOfCbInExtSrtSecIdx = pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx;
+ UCHAR maxAllowedCwLen;
+ int numDecodedBits;
+#endif
+ const UCHAR *pCbDimension = pHcr->tableInfo.pCbDimension;
+ const UCHAR *pCbSign = pHcr->tableInfo.pCbSign;
+
+ /* clear result array */
+ //pQSC = &pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx];
+ //pQSC = *pQuantizedSpectralCoefficients;
+
+ 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 */
+#if DETECT_TOO_LONG_CW_READS
+ maxAllowedCwLen = pMaxLenOfCbInExtSrtSec[maxLenOfCbInExtSrtSecIdx];
+ maxLenOfCbInExtSrtSecIdx++;
+ if (maxLenOfCbInExtSrtSecIdx >= (MAX_SFB_HCR+MAX_HCR_SETS)) {
+ return;
+ }
+#endif
+
+ /* 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,
+ 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 DETECT_TOO_LONG_CW_READS
+ if ( maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_ONLY_TOO_LONG) ) {
+ pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_BITS_DECODED;
+ }
+#endif
+
+#if CHECK_SEGMENTATION_IMMEDIATELY
+ if (1 == errDetectPcwSegmentation(*pRemainingBitsInSegment-ERROR_PCW_BODY,pHcr,PCW_BODY,pQuantizedSpectralCoefficients+quantizedSpectralCoefficientsIdx-dimension,dimension)) {
+ return;
+ }
+#endif
+ pLeftStartOfSegment++; /* update pointer for decoding the next PCW */
+ pRemainingBitsInSegment++; /* update pointer for decoding the next PCW */
+ }
+ }
+ else if (( pCbSign[codebook] == 1 ) && ( codebook < 11 )) { /* 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,
+ pCurrentTree,
+ pQuantValBase,
+ pLeftStartOfSegment,
+ pRemainingBitsInSegment,
+ &numDecodedBits
+ );
+
+ err = DecodePCW_Sign( bs,
+ dimension,
+ pQuantVal,
+ pQuantizedSpectralCoefficients,
+ &quantizedSpectralCoefficientsIdx,
+ pLeftStartOfSegment,
+ pRemainingBitsInSegment,
+ &numDecodedBits
+ );
+ if (err != 0) {
+ return;
+ }
+ /* one more PCW should be decoded */
+
+#if DETECT_TOO_LONG_CW_READS
+ if ( maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_SIGN_TOO_LONG) ) {
+ pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_SIGN_BITS_DECODED;
+ }
+#endif
+
+#if CHECK_SEGMENTATION_IMMEDIATELY
+ if (1 == errDetectPcwSegmentation(*pRemainingBitsInSegment-ERROR_PCW_BODY_SIGN,pHcr,PCW_BODY_SIGN, pQuantizedSpectralCoefficients+quantizedSpectralCoefficientsIdx-dimension,dimension)) {
+ return;
+ }
+#endif
+ 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,
+ pCurrentTree,
+ pQuantValBase,
+ pLeftStartOfSegment,
+ pRemainingBitsInSegment,
+ &numDecodedBits
+ );
+
+ err = DecodePCW_Sign( bs,
+ 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,
+ 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,
+ pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx],
+ pLeftStartOfSegment,
+ pRemainingBitsInSegment,
+ &numDecodedBits
+ );
+ }
+ quantizedSpectralCoefficientsIdx++;
+ if (quantizedSpectralCoefficientsIdx >= 1024) {
+ return;
+ }
+
+ /* one more PCW should be decoded */
+
+#if DETECT_TOO_LONG_CW_READS
+ if ( maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_SIGN_ESC_TOO_LONG) ) {
+ pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_SIGN_ESC_BITS_DECODED;
+ }
+#endif
+
+#if CHECK_SEGMENTATION_IMMEDIATELY
+ 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;
+ }
+#endif
+ 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;
+}
+
+#if CHECK_SEGMENTATION_IMMEDIATELY
+/*---------------------------------------------------------------------------------------------
+ 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;
+}
+#endif
+
+#if CHECK_SEGMENTATION_FINAL
+/*---------------------------------------------------------------------------------------------
+ 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;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------------------------
+ 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 UINT *pCurrentTree,
+ const SCHAR *pQuantValBase,
+ USHORT *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,
+ 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,
+ INT quantSpecCoef,
+ USHORT *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,
+ 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,
+ 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,
+ UINT codebookDim,
+ const SCHAR *pQuantVal,
+ FIXP_DBL *pQuantSpecCoef,
+ int *quantSpecCoefIdx,
+ USHORT *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,
+ 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) {
+#if HCR_LISTEN_TO_MUTED_LINES
+ pLong[c] = (FIXP_DBL)HCR_DIRAC; /* marking */
+#else
+ pLong[c] = FL2FXCONST_DBL(0.0f); /* muting */
+#endif
+ }
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: Sets global HCR type
+-------------------------------------------------------------------------------------------- */
+void setHcrType(H_HCR_INFO hHcr, MP4_ELEMENT_ID type)
+{
+ switch (type) {
+ case ID_SCE:
+ hHcr->globalHcrType = 0;
+ break;
+ case ID_CPE:
+ hHcr->globalHcrType = 1;
+ break;
+ default:
+ break;
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: Gets HCR type from the HCR data structure
+-----------------------------------------------------------------------------------------------
+ return: - global HCR type
+-------------------------------------------------------------------------------------------- */
+INT getHcrType(H_HCR_INFO hHcr)
+{
+ return hHcr->globalHcrType;
+}
+
+
+
+