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