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