| /* ----------------------------------------------------------------------------- |
| 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: Prepare decoding of non-PCWs, segmentation- and |
| bitfield-handling, HCR-Statemachine |
| |
| *******************************************************************************/ |
| |
| #include "aacdec_hcrs.h" |
| |
| #include "aacdec_hcr.h" |
| |
| #include "aacdec_hcr_bit.h" |
| #include "aac_rom.h" |
| #include "aac_ram.h" |
| |
| static UINT InitSegmentBitfield(UINT *pNumSegment, |
| SCHAR *pRemainingBitsInSegment, |
| UINT *pSegmentBitfield, |
| UCHAR *pNumWordForBitfield, |
| USHORT *pNumBitValidInLastWord); |
| |
| static void InitNonPCWSideInformationForCurrentSet(H_HCR_INFO pHcr); |
| |
| static INT ModuloValue(INT input, INT bufferlength); |
| |
| static void ClearBitFromBitfield(STATEFUNC *ptrState, UINT offset, |
| UINT *pBitfield); |
| |
| /*--------------------------------------------------------------------------------------------- |
| description: This function decodes all non-priority codewords (non-PCWs) by |
| using a state-machine. |
| -------------------------------------------------------------------------------------------- |
| */ |
| void DecodeNonPCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr) { |
| UINT numValidSegment; |
| INT segmentOffset; |
| INT codewordOffsetBase; |
| INT codewordOffset; |
| UINT trial; |
| |
| UINT *pNumSegment; |
| SCHAR *pRemainingBitsInSegment; |
| UINT *pSegmentBitfield; |
| UCHAR *pNumWordForBitfield; |
| USHORT *pNumBitValidInLastWord; |
| UINT *pCodewordBitfield; |
| INT bitfieldWord; |
| INT bitInWord; |
| UINT tempWord; |
| UINT interMediateWord; |
| INT tempBit; |
| INT carry; |
| |
| UINT numCodeword; |
| UCHAR numSet; |
| UCHAR currentSet; |
| UINT codewordInSet; |
| UINT remainingCodewordsInSet; |
| SCHAR *pSta; |
| UINT ret; |
| |
| pNumSegment = &(pHcr->segmentInfo.numSegment); |
| pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; |
| pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; |
| pNumWordForBitfield = &(pHcr->segmentInfo.numWordForBitfield); |
| pNumBitValidInLastWord = &(pHcr->segmentInfo.pNumBitValidInLastWord); |
| pSta = pHcr->nonPcwSideinfo.pSta; |
| |
| numValidSegment = InitSegmentBitfield(pNumSegment, pRemainingBitsInSegment, |
| pSegmentBitfield, pNumWordForBitfield, |
| pNumBitValidInLastWord); |
| |
| if (numValidSegment != 0) { |
| numCodeword = pHcr->sectionInfo.numCodeword; |
| numSet = ((numCodeword - 1) / *pNumSegment) + 1; |
| |
| pHcr->segmentInfo.readDirection = FROM_RIGHT_TO_LEFT; |
| |
| /* Process sets subsequently */ |
| for (currentSet = 1; currentSet < numSet; currentSet++) { |
| /* step 1 */ |
| numCodeword -= |
| *pNumSegment; /* number of remaining non PCWs [for all sets] */ |
| if (numCodeword < *pNumSegment) { |
| codewordInSet = numCodeword; /* for last set */ |
| } else { |
| codewordInSet = *pNumSegment; /* for all sets except last set */ |
| } |
| |
| /* step 2 */ |
| /* prepare array 'CodewordBitfield'; as much ones are written from left in |
| * all words, as much decodedCodewordInSetCounter nonPCWs exist in this |
| * set */ |
| tempWord = 0xFFFFFFFF; |
| pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; |
| |
| for (bitfieldWord = *pNumWordForBitfield; bitfieldWord != 0; |
| bitfieldWord--) { /* loop over all used words */ |
| if (codewordInSet > NUMBER_OF_BIT_IN_WORD) { /* more codewords than |
| number of bits => fill |
| ones */ |
| /* fill a whole word with ones */ |
| *pCodewordBitfield++ = tempWord; |
| codewordInSet -= NUMBER_OF_BIT_IN_WORD; /* subtract number of bits */ |
| } else { |
| /* prepare last tempWord */ |
| for (remainingCodewordsInSet = codewordInSet; |
| remainingCodewordsInSet < NUMBER_OF_BIT_IN_WORD; |
| remainingCodewordsInSet++) { |
| tempWord = |
| tempWord & |
| ~(1 |
| << (NUMBER_OF_BIT_IN_WORD - 1 - |
| remainingCodewordsInSet)); /* set a zero at bit number |
| (NUMBER_OF_BIT_IN_WORD-1-i) |
| in tempWord */ |
| } |
| *pCodewordBitfield++ = tempWord; |
| tempWord = 0x00000000; |
| } |
| } |
| pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; |
| |
| /* step 3 */ |
| /* build non-PCW sideinfo for each non-PCW of the current set */ |
| InitNonPCWSideInformationForCurrentSet(pHcr); |
| |
| /* step 4 */ |
| /* decode all non-PCWs belonging to this set */ |
| |
| /* loop over trials */ |
| codewordOffsetBase = 0; |
| for (trial = *pNumSegment; trial > 0; trial--) { |
| /* loop over number of words in bitfields */ |
| segmentOffset = 0; /* start at zero in every segment */ |
| pHcr->segmentInfo.segmentOffset = |
| segmentOffset; /* store in structure for states */ |
| codewordOffset = codewordOffsetBase; |
| pHcr->nonPcwSideinfo.codewordOffset = |
| codewordOffset; /* store in structure for states */ |
| |
| for (bitfieldWord = 0; bitfieldWord < *pNumWordForBitfield; |
| bitfieldWord++) { |
| /* derive tempWord with bitwise and */ |
| tempWord = |
| pSegmentBitfield[bitfieldWord] & pCodewordBitfield[bitfieldWord]; |
| |
| /* if tempWord is not zero, decode something */ |
| if (tempWord != 0) { |
| /* loop over all bits in tempWord; start state machine if & is true |
| */ |
| for (bitInWord = NUMBER_OF_BIT_IN_WORD; bitInWord > 0; |
| bitInWord--) { |
| interMediateWord = ((UINT)1 << (bitInWord - 1)); |
| if ((tempWord & interMediateWord) == interMediateWord) { |
| /* get state and start state machine */ |
| pHcr->nonPcwSideinfo.pState = |
| aStateConstant2State[pSta[codewordOffset]]; |
| |
| while (pHcr->nonPcwSideinfo.pState) { |
| ret = ((STATEFUNC)pHcr->nonPcwSideinfo.pState)(bs, pHcr); |
| if (ret != 0) { |
| return; |
| } |
| } |
| } |
| |
| /* update both offsets */ |
| segmentOffset += 1; /* add NUMBER_OF_BIT_IN_WORD times one */ |
| pHcr->segmentInfo.segmentOffset = segmentOffset; |
| codewordOffset += 1; /* add NUMBER_OF_BIT_IN_WORD times one */ |
| codewordOffset = |
| ModuloValue(codewordOffset, |
| *pNumSegment); /* index of the current codeword |
| lies within modulo range */ |
| pHcr->nonPcwSideinfo.codewordOffset = codewordOffset; |
| } |
| } else { |
| segmentOffset += |
| NUMBER_OF_BIT_IN_WORD; /* add NUMBER_OF_BIT_IN_WORD at once */ |
| pHcr->segmentInfo.segmentOffset = segmentOffset; |
| codewordOffset += |
| NUMBER_OF_BIT_IN_WORD; /* add NUMBER_OF_BIT_IN_WORD at once */ |
| codewordOffset = ModuloValue( |
| codewordOffset, |
| *pNumSegment); /* index of the current codeword lies within |
| modulo range */ |
| pHcr->nonPcwSideinfo.codewordOffset = codewordOffset; |
| } |
| } /* end of bitfield word loop */ |
| |
| /* decrement codeword - pointer */ |
| codewordOffsetBase -= 1; |
| codewordOffsetBase = |
| ModuloValue(codewordOffsetBase, *pNumSegment); /* index of the |
| current codeword |
| base lies within |
| modulo range */ |
| |
| /* rotate numSegment bits in codewordBitfield */ |
| /* rotation of *numSegment bits in bitfield of codewords |
| * (circle-rotation) */ |
| /* get last valid bit */ |
| tempBit = pCodewordBitfield[*pNumWordForBitfield - 1] & |
| (1 << (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord)); |
| tempBit = tempBit >> (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord); |
| |
| /* write zero into place where tempBit was fetched from */ |
| pCodewordBitfield[*pNumWordForBitfield - 1] = |
| pCodewordBitfield[*pNumWordForBitfield - 1] & |
| ~(1 << (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord)); |
| |
| /* rotate last valid word */ |
| pCodewordBitfield[*pNumWordForBitfield - 1] = |
| pCodewordBitfield[*pNumWordForBitfield - 1] >> 1; |
| |
| /* transfare carry bit 0 from current word into bitposition 31 from next |
| * word and rotate current word */ |
| for (bitfieldWord = *pNumWordForBitfield - 2; bitfieldWord > -1; |
| bitfieldWord--) { |
| /* get carry (=bit at position 0) from current word */ |
| carry = pCodewordBitfield[bitfieldWord] & 1; |
| |
| /* put the carry bit at position 31 into word right from current word |
| */ |
| pCodewordBitfield[bitfieldWord + 1] = |
| pCodewordBitfield[bitfieldWord + 1] | |
| (carry << (NUMBER_OF_BIT_IN_WORD - 1)); |
| |
| /* shift current word */ |
| pCodewordBitfield[bitfieldWord] = |
| pCodewordBitfield[bitfieldWord] >> 1; |
| } |
| |
| /* put tempBit into free bit-position 31 from first word */ |
| pCodewordBitfield[0] = |
| pCodewordBitfield[0] | (tempBit << (NUMBER_OF_BIT_IN_WORD - 1)); |
| |
| } /* end of trial loop */ |
| |
| /* toggle read direction */ |
| pHcr->segmentInfo.readDirection = |
| ToggleReadDirection(pHcr->segmentInfo.readDirection); |
| } |
| /* end of set loop */ |
| |
| /* all non-PCWs of this spectrum are decoded */ |
| } |
| |
| /* all PCWs and all non PCWs are decoded. They are unbacksorted in output |
| * buffer. Here is the Interface with comparing QSCs to asm decoding */ |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| description: This function prepares the bitfield used for the |
| segments. The list is set up once to be used in all |
| following sets. If a segment is decoded empty, the according bit from the |
| Bitfield is removed. |
| ----------------------------------------------------------------------------------------------- |
| return: numValidSegment = the number of valid segments |
| -------------------------------------------------------------------------------------------- |
| */ |
| static UINT InitSegmentBitfield(UINT *pNumSegment, |
| SCHAR *pRemainingBitsInSegment, |
| UINT *pSegmentBitfield, |
| UCHAR *pNumWordForBitfield, |
| USHORT *pNumBitValidInLastWord) { |
| SHORT i; |
| USHORT r; |
| UCHAR bitfieldWord; |
| UINT tempWord; |
| USHORT numValidSegment; |
| |
| *pNumWordForBitfield = ((*pNumSegment - 1) >> THIRTYTWO_LOG_DIV_TWO_LOG) + 1; |
| |
| /* loop over all words, which are completely used or only partial */ |
| /* bit in pSegmentBitfield is zero if segment is empty; bit in |
| * pSegmentBitfield is one if segment is not empty */ |
| numValidSegment = 0; |
| *pNumBitValidInLastWord = *pNumSegment; |
| |
| /* loop over words */ |
| for (bitfieldWord = 0; bitfieldWord < *pNumWordForBitfield - 1; |
| bitfieldWord++) { |
| tempWord = 0xFFFFFFFF; /* set ones */ |
| r = bitfieldWord << THIRTYTWO_LOG_DIV_TWO_LOG; |
| for (i = 0; i < NUMBER_OF_BIT_IN_WORD; i++) { |
| if (pRemainingBitsInSegment[r + i] == 0) { |
| tempWord = tempWord & ~(1 << (NUMBER_OF_BIT_IN_WORD - 1 - |
| i)); /* set a zero at bit number |
| (NUMBER_OF_BIT_IN_WORD-1-i) in |
| tempWord */ |
| } else { |
| numValidSegment += 1; /* count segments which are not empty */ |
| } |
| } |
| pSegmentBitfield[bitfieldWord] = tempWord; /* store result */ |
| *pNumBitValidInLastWord -= NUMBER_OF_BIT_IN_WORD; /* calculate number of |
| zeros on LSB side in |
| the last word */ |
| } |
| |
| /* calculate last word: prepare special tempWord */ |
| tempWord = 0xFFFFFFFF; |
| for (i = 0; i < (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord); i++) { |
| tempWord = tempWord & ~(1 << i); /* clear bit i in tempWord */ |
| } |
| |
| /* calculate last word */ |
| r = bitfieldWord << THIRTYTWO_LOG_DIV_TWO_LOG; |
| for (i = 0; i < *pNumBitValidInLastWord; i++) { |
| if (pRemainingBitsInSegment[r + i] == 0) { |
| tempWord = tempWord & ~(1 << (NUMBER_OF_BIT_IN_WORD - 1 - |
| i)); /* set a zero at bit number |
| (NUMBER_OF_BIT_IN_WORD-1-i) in |
| tempWord */ |
| } else { |
| numValidSegment += 1; /* count segments which are not empty */ |
| } |
| } |
| pSegmentBitfield[bitfieldWord] = tempWord; /* store result */ |
| |
| return numValidSegment; |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| description: This function sets up sideinfo for the non-PCW decoder (for the |
| current set). |
| ---------------------------------------------------------------------------------------------*/ |
| static void InitNonPCWSideInformationForCurrentSet(H_HCR_INFO pHcr) { |
| USHORT i, k; |
| UCHAR codebookDim; |
| UINT startNode; |
| |
| UCHAR *pCodebook = pHcr->nonPcwSideinfo.pCodebook; |
| UINT *iNode = pHcr->nonPcwSideinfo.iNode; |
| UCHAR *pCntSign = pHcr->nonPcwSideinfo.pCntSign; |
| USHORT *iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; |
| UINT *pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; |
| SCHAR *pSta = pHcr->nonPcwSideinfo.pSta; |
| 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; |
| int quantizedSpectralCoefficientsIdx = |
| pHcr->decInOut.quantizedSpectralCoefficientsIdx; |
| const UCHAR *pCbDimension = aDimCb; |
| int iterationCounter = 0; |
| |
| /* loop over number of extended sorted sections in the current set so all |
| * codewords sideinfo variables within this set can be prepared for decoding |
| */ |
| for (i = pNumExtendedSortedSectionsInSets[numExtendedSortedSectionsInSetsIdx]; |
| i != 0; i--) { |
| codebookDim = |
| pCbDimension[pExtendedSortedCodebook[extendedSortedCodebookIdx]]; |
| startNode = *aHuffTable[pExtendedSortedCodebook[extendedSortedCodebookIdx]]; |
| |
| for (k = pNumExtendedSortedCodewordInSection |
| [numExtendedSortedCodewordInSectionIdx]; |
| k != 0; k--) { |
| iterationCounter++; |
| if (iterationCounter > (1024 >> 2)) { |
| return; |
| } |
| *pSta++ = aCodebook2StartInt |
| [pExtendedSortedCodebook[extendedSortedCodebookIdx]]; |
| *pCodebook++ = pExtendedSortedCodebook[extendedSortedCodebookIdx]; |
| *iNode++ = startNode; |
| *pCntSign++ = 0; |
| *iResultPointer++ = quantizedSpectralCoefficientsIdx; |
| *pEscapeSequenceInfo++ = 0; |
| quantizedSpectralCoefficientsIdx += |
| codebookDim; /* update pointer by codebookDim --> point to next |
| starting value for writing out */ |
| if (quantizedSpectralCoefficientsIdx >= 1024) { |
| return; |
| } |
| } |
| numExtendedSortedCodewordInSectionIdx++; /* inc ptr for next ext sort sec in |
| current set */ |
| extendedSortedCodebookIdx++; /* inc ptr for next ext sort sec in current set |
| */ |
| if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR + MAX_HCR_SETS) || |
| extendedSortedCodebookIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) { |
| return; |
| } |
| } |
| numExtendedSortedSectionsInSetsIdx++; /* inc ptr for next set of non-PCWs */ |
| if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) { |
| return; |
| } |
| |
| /* Write back indexes */ |
| pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = |
| numExtendedSortedCodewordInSectionIdx; |
| pHcr->sectionInfo.extendedSortedCodebookIdx = extendedSortedCodebookIdx; |
| pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = |
| numExtendedSortedSectionsInSetsIdx; |
| pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = |
| numExtendedSortedCodewordInSectionIdx; |
| pHcr->decInOut.quantizedSpectralCoefficientsIdx = |
| quantizedSpectralCoefficientsIdx; |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| description: This function returns the input value if the value is in the |
| range of bufferlength. If <input> is smaller, one bufferlength |
| is added, if <input> is bigger one bufferlength is subtracted. |
| ----------------------------------------------------------------------------------------------- |
| return: modulo result |
| -------------------------------------------------------------------------------------------- |
| */ |
| static INT ModuloValue(INT input, INT bufferlength) { |
| if (input > (bufferlength - 1)) { |
| return (input - bufferlength); |
| } |
| if (input < 0) { |
| return (input + bufferlength); |
| } |
| return input; |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| description: This function clears a bit from current bitfield and |
| switches off the statemachine. |
| |
| A bit is cleared in two cases: |
| a) a codeword is decoded, then a bit is cleared in codeword |
| bitfield b) a segment is decoded empty, then a bit is cleared in segment |
| bitfield |
| -------------------------------------------------------------------------------------------- |
| */ |
| static void ClearBitFromBitfield(STATEFUNC *ptrState, UINT offset, |
| UINT *pBitfield) { |
| UINT numBitfieldWord; |
| UINT numBitfieldBit; |
| |
| /* get both values needed for clearing the bit */ |
| numBitfieldWord = offset >> THIRTYTWO_LOG_DIV_TWO_LOG; /* int = wordNr */ |
| numBitfieldBit = offset - (numBitfieldWord |
| << THIRTYTWO_LOG_DIV_TWO_LOG); /* fract = bitNr */ |
| |
| /* clear a bit in bitfield */ |
| pBitfield[numBitfieldWord] = |
| pBitfield[numBitfieldWord] & |
| ~(1 << (NUMBER_OF_BIT_IN_WORD - 1 - numBitfieldBit)); |
| |
| /* switch off state machine because codeword is decoded and/or because segment |
| * is empty */ |
| *ptrState = NULL; |
| } |
| |
| /* ========================================================================================= |
| the states of the statemachine |
| ========================================================================================= |
| */ |
| |
| /*--------------------------------------------------------------------------------------------- |
| description: Decodes the body of a codeword. This State is used for |
| codebooks 1,2,5 and 6. No sign bits are decoded, because the table of the |
| quantized spectral values has got a valid sign at the quantized spectral lines. |
| ----------------------------------------------------------------------------------------------- |
| output: Two or four quantizes spectral values written at position |
| where pResultPointr points to |
| ----------------------------------------------------------------------------------------------- |
| return: 0 |
| -------------------------------------------------------------------------------------------- |
| */ |
| UINT Hcr_State_BODY_ONLY(HANDLE_FDK_BITSTREAM bs, void *ptr) { |
| H_HCR_INFO pHcr = (H_HCR_INFO)ptr; |
| UINT *pSegmentBitfield; |
| UINT *pCodewordBitfield; |
| UINT segmentOffset; |
| FIXP_DBL *pResultBase; |
| UINT *iNode; |
| USHORT *iResultPointer; |
| UINT codewordOffset; |
| UINT branchNode; |
| UINT branchValue; |
| UINT iQSC; |
| UINT treeNode; |
| UCHAR carryBit; |
| INT *pLeftStartOfSegment; |
| INT *pRightStartOfSegment; |
| SCHAR *pRemainingBitsInSegment; |
| UCHAR readDirection; |
| UCHAR *pCodebook; |
| UCHAR dimCntr; |
| const UINT *pCurrentTree; |
| const UCHAR *pCbDimension; |
| const SCHAR *pQuantVal; |
| const SCHAR *pQuantValBase; |
| |
| pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; |
| pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; |
| pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; |
| readDirection = pHcr->segmentInfo.readDirection; |
| pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; |
| pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; |
| segmentOffset = pHcr->segmentInfo.segmentOffset; |
| |
| pCodebook = pHcr->nonPcwSideinfo.pCodebook; |
| iNode = pHcr->nonPcwSideinfo.iNode; |
| pResultBase = pHcr->nonPcwSideinfo.pResultBase; |
| iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; |
| codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; |
| |
| pCbDimension = aDimCb; |
| |
| treeNode = iNode[codewordOffset]; |
| pCurrentTree = aHuffTable[pCodebook[codewordOffset]]; |
| |
| for (; pRemainingBitsInSegment[segmentOffset] > 0; |
| pRemainingBitsInSegment[segmentOffset] -= 1) { |
| carryBit = HcrGetABitFromBitstream( |
| bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], |
| &pRightStartOfSegment[segmentOffset], readDirection); |
| |
| CarryBitToBranchValue(carryBit, /* make a step in decoding tree */ |
| treeNode, &branchValue, &branchNode); |
| |
| /* if end of branch reached write out lines and count bits needed for sign, |
| * otherwise store node in codeword sideinfo */ |
| if ((branchNode & TEST_BIT_10) == |
| TEST_BIT_10) { /* test bit 10 ; ==> body is complete */ |
| pQuantValBase = aQuantTable[pCodebook[codewordOffset]]; /* get base |
| address of |
| quantized |
| values |
| belonging to |
| current |
| codebook */ |
| pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid |
| line [of 2 or 4 quantized |
| values] */ |
| |
| iQSC = iResultPointer[codewordOffset]; /* get position of first line for |
| writing out result */ |
| |
| for (dimCntr = pCbDimension[pCodebook[codewordOffset]]; dimCntr != 0; |
| dimCntr--) { |
| pResultBase[iQSC++] = |
| (FIXP_DBL)*pQuantVal++; /* write out 2 or 4 lines into |
| spectrum; no Sign bits |
| available in this state */ |
| } |
| |
| ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, |
| pCodewordBitfield); /* clear a bit in bitfield and |
| switch off statemachine */ |
| pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of |
| for loop counter (see |
| above) is done here */ |
| break; /* end of branch in tree reached i.e. a whole nonPCW-Body is |
| decoded */ |
| } else { /* body is not decoded completely: */ |
| treeNode = *( |
| pCurrentTree + |
| branchValue); /* update treeNode for further step in decoding tree */ |
| } |
| } |
| iNode[codewordOffset] = treeNode; /* store updated treeNode because maybe |
| decoding of codeword body not finished |
| yet */ |
| |
| if (pRemainingBitsInSegment[segmentOffset] <= 0) { |
| ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, |
| pSegmentBitfield); /* clear a bit in bitfield and |
| switch off statemachine */ |
| |
| if (pRemainingBitsInSegment[segmentOffset] < 0) { |
| pHcr->decInOut.errorLog |= STATE_ERROR_BODY_ONLY; |
| return BODY_ONLY; |
| } |
| } |
| |
| return STOP_THIS_STATE; |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| description: Decodes the codeword body, writes out result and counts the |
| number of quantized spectral values, which are different form zero. For those |
| values sign bits are needed. |
| |
| If sign bit counter cntSign is different from zero, switch to |
| next state to decode sign Bits there. If sign bit counter cntSign is zero, no |
| sign bits are needed and codeword is decoded. |
| ----------------------------------------------------------------------------------------------- |
| output: Two or four written quantizes spectral values written at |
| position where pResultPointr points to. The signs of those lines may be wrong. |
| If the signs [on just one signle sign] is wrong, the next state will correct it. |
| ----------------------------------------------------------------------------------------------- |
| return: 0 |
| -------------------------------------------------------------------------------------------- |
| */ |
| UINT Hcr_State_BODY_SIGN__BODY(HANDLE_FDK_BITSTREAM bs, void *ptr) { |
| H_HCR_INFO pHcr = (H_HCR_INFO)ptr; |
| SCHAR *pRemainingBitsInSegment; |
| INT *pLeftStartOfSegment; |
| INT *pRightStartOfSegment; |
| UCHAR readDirection; |
| UINT *pSegmentBitfield; |
| UINT *pCodewordBitfield; |
| UINT segmentOffset; |
| |
| UCHAR *pCodebook; |
| UINT *iNode; |
| UCHAR *pCntSign; |
| FIXP_DBL *pResultBase; |
| USHORT *iResultPointer; |
| UINT codewordOffset; |
| |
| UINT iQSC; |
| UINT cntSign; |
| UCHAR dimCntr; |
| UCHAR carryBit; |
| SCHAR *pSta; |
| UINT treeNode; |
| UINT branchValue; |
| UINT branchNode; |
| const UCHAR *pCbDimension; |
| const UINT *pCurrentTree; |
| const SCHAR *pQuantValBase; |
| const SCHAR *pQuantVal; |
| |
| pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; |
| pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; |
| pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; |
| readDirection = pHcr->segmentInfo.readDirection; |
| pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; |
| pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; |
| segmentOffset = pHcr->segmentInfo.segmentOffset; |
| |
| pCodebook = pHcr->nonPcwSideinfo.pCodebook; |
| iNode = pHcr->nonPcwSideinfo.iNode; |
| pCntSign = pHcr->nonPcwSideinfo.pCntSign; |
| pResultBase = pHcr->nonPcwSideinfo.pResultBase; |
| iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; |
| codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; |
| pSta = pHcr->nonPcwSideinfo.pSta; |
| |
| pCbDimension = aDimCb; |
| |
| treeNode = iNode[codewordOffset]; |
| pCurrentTree = aHuffTable[pCodebook[codewordOffset]]; |
| |
| for (; pRemainingBitsInSegment[segmentOffset] > 0; |
| pRemainingBitsInSegment[segmentOffset] -= 1) { |
| carryBit = HcrGetABitFromBitstream( |
| bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], |
| &pRightStartOfSegment[segmentOffset], readDirection); |
| |
| CarryBitToBranchValue(carryBit, /* make a step in decoding tree */ |
| treeNode, &branchValue, &branchNode); |
| |
| /* if end of branch reached write out lines and count bits needed for sign, |
| * otherwise store node in codeword sideinfo */ |
| if ((branchNode & TEST_BIT_10) == |
| TEST_BIT_10) { /* test bit 10 ; if set body complete */ |
| /* body completely decoded; branchValue is valid, set pQuantVal to first |
| * (of two or four) quantized spectral coefficients */ |
| pQuantValBase = aQuantTable[pCodebook[codewordOffset]]; /* get base |
| address of |
| quantized |
| values |
| belonging to |
| current |
| codebook */ |
| pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid |
| line [of 2 or 4 quantized |
| values] */ |
| |
| iQSC = iResultPointer[codewordOffset]; /* get position of first line for |
| writing result */ |
| |
| /* codeword decoding result is written out here: Write out 2 or 4 |
| * quantized spectral values with probably */ |
| /* wrong sign and count number of values which are different from zero for |
| * sign bit decoding [which happens in next state] */ |
| cntSign = 0; |
| for (dimCntr = pCbDimension[pCodebook[codewordOffset]]; dimCntr != 0; |
| dimCntr--) { |
| pResultBase[iQSC++] = |
| (FIXP_DBL)*pQuantVal; /* write quant. spec. coef. into spectrum */ |
| if (*pQuantVal++ != 0) { |
| cntSign += 1; |
| } |
| } |
| |
| if (cntSign == 0) { |
| ClearBitFromBitfield( |
| &(pHcr->nonPcwSideinfo.pState), segmentOffset, |
| pCodewordBitfield); /* clear a bit in bitfield and switch off |
| statemachine */ |
| } else { |
| pCntSign[codewordOffset] = cntSign; /* write sign count result into |
| codewordsideinfo of current |
| codeword */ |
| pSta[codewordOffset] = BODY_SIGN__SIGN; /* change state */ |
| pHcr->nonPcwSideinfo.pState = |
| aStateConstant2State[pSta[codewordOffset]]; /* get state from |
| separate array of |
| cw-sideinfo */ |
| } |
| pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of |
| for loop counter (see |
| above) is done here */ |
| break; /* end of branch in tree reached i.e. a whole nonPCW-Body is |
| decoded */ |
| } else { /* body is not decoded completely: */ |
| treeNode = *( |
| pCurrentTree + |
| branchValue); /* update treeNode for further step in decoding tree */ |
| } |
| } |
| iNode[codewordOffset] = treeNode; /* store updated treeNode because maybe |
| decoding of codeword body not finished |
| yet */ |
| |
| if (pRemainingBitsInSegment[segmentOffset] <= 0) { |
| ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, |
| pSegmentBitfield); /* clear a bit in bitfield and |
| switch off statemachine */ |
| |
| if (pRemainingBitsInSegment[segmentOffset] < 0) { |
| pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN__BODY; |
| return BODY_SIGN__BODY; |
| } |
| } |
| |
| return STOP_THIS_STATE; |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| description: This state decodes the sign bits belonging to a codeword. The |
| state is called as often in different "trials" until pCntSgn[codewordOffset] is |
| zero. |
| ----------------------------------------------------------------------------------------------- |
| output: The two or four quantizes spectral values (written in previous |
| state) have now the correct sign. |
| ----------------------------------------------------------------------------------------------- |
| return: 0 |
| -------------------------------------------------------------------------------------------- |
| */ |
| UINT Hcr_State_BODY_SIGN__SIGN(HANDLE_FDK_BITSTREAM bs, void *ptr) { |
| H_HCR_INFO pHcr = (H_HCR_INFO)ptr; |
| SCHAR *pRemainingBitsInSegment; |
| INT *pLeftStartOfSegment; |
| INT *pRightStartOfSegment; |
| UCHAR readDirection; |
| UINT *pSegmentBitfield; |
| UINT *pCodewordBitfield; |
| UINT segmentOffset; |
| |
| UCHAR *pCntSign; |
| FIXP_DBL *pResultBase; |
| USHORT *iResultPointer; |
| UINT codewordOffset; |
| |
| UCHAR carryBit; |
| UINT iQSC; |
| UCHAR cntSign; |
| |
| pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; |
| pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; |
| pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; |
| readDirection = pHcr->segmentInfo.readDirection; |
| pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; |
| pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; |
| segmentOffset = pHcr->segmentInfo.segmentOffset; |
| |
| /*pCodebook = */ |
| pCntSign = pHcr->nonPcwSideinfo.pCntSign; |
| pResultBase = pHcr->nonPcwSideinfo.pResultBase; |
| iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; |
| codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; |
| |
| iQSC = iResultPointer[codewordOffset]; |
| cntSign = pCntSign[codewordOffset]; |
| |
| /* loop for sign bit decoding */ |
| for (; pRemainingBitsInSegment[segmentOffset] > 0; |
| pRemainingBitsInSegment[segmentOffset] -= 1) { |
| carryBit = HcrGetABitFromBitstream( |
| bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], |
| &pRightStartOfSegment[segmentOffset], readDirection); |
| cntSign -= |
| 1; /* decrement sign counter because one sign bit has been read */ |
| |
| /* search for a line (which was decoded in previous state) which is not |
| * zero. [This value will get a sign] */ |
| while (pResultBase[iQSC] == (FIXP_DBL)0) { |
| if (++iQSC >= 1024) { /* points to current value different from zero */ |
| return BODY_SIGN__SIGN; |
| } |
| } |
| |
| /* put sign together with line; if carryBit is zero, the sign is ok already; |
| * no write operation necessary in this case */ |
| if (carryBit != 0) { |
| pResultBase[iQSC] = -pResultBase[iQSC]; /* carryBit = 1 --> minus */ |
| } |
| |
| iQSC++; /* update pointer to next (maybe valid) value */ |
| |
| if (cntSign == 0) { /* if (cntSign==0) ==> set state CODEWORD_DECODED */ |
| ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, |
| pCodewordBitfield); /* clear a bit in bitfield and |
| switch off statemachine */ |
| pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of |
| for loop counter (see |
| above) is done here */ |
| break; /* whole nonPCW-Body and according sign bits are decoded */ |
| } |
| } |
| pCntSign[codewordOffset] = cntSign; |
| iResultPointer[codewordOffset] = iQSC; /* store updated pResultPointer */ |
| |
| if (pRemainingBitsInSegment[segmentOffset] <= 0) { |
| ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, |
| pSegmentBitfield); /* clear a bit in bitfield and |
| switch off statemachine */ |
| |
| if (pRemainingBitsInSegment[segmentOffset] < 0) { |
| pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN__SIGN; |
| return BODY_SIGN__SIGN; |
| } |
| } |
| |
| return STOP_THIS_STATE; |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| description: Decodes the codeword body in case of codebook is 11. Writes |
| out resulting two or four lines [with probably wrong sign] and counts the number |
| of lines, which are different form zero. This information is needed in next |
| state where sign bits will be decoded, if necessary. |
| If sign bit counter cntSign is zero, no sign bits are needed |
| and codeword is decoded completely. |
| ----------------------------------------------------------------------------------------------- |
| output: Two lines (quantizes spectral coefficients) which are probably |
| wrong. The sign may be wrong and if one or two values is/are 16, the following |
| states will decode the escape sequence to correct the values which are wirtten |
| here. |
| ----------------------------------------------------------------------------------------------- |
| return: 0 |
| -------------------------------------------------------------------------------------------- |
| */ |
| UINT Hcr_State_BODY_SIGN_ESC__BODY(HANDLE_FDK_BITSTREAM bs, void *ptr) { |
| H_HCR_INFO pHcr = (H_HCR_INFO)ptr; |
| SCHAR *pRemainingBitsInSegment; |
| INT *pLeftStartOfSegment; |
| INT *pRightStartOfSegment; |
| UCHAR readDirection; |
| UINT *pSegmentBitfield; |
| UINT *pCodewordBitfield; |
| UINT segmentOffset; |
| |
| UINT *iNode; |
| UCHAR *pCntSign; |
| FIXP_DBL *pResultBase; |
| USHORT *iResultPointer; |
| UINT codewordOffset; |
| |
| UCHAR carryBit; |
| UINT iQSC; |
| UINT cntSign; |
| UINT dimCntr; |
| UINT treeNode; |
| SCHAR *pSta; |
| UINT branchNode; |
| UINT branchValue; |
| const UINT *pCurrentTree; |
| const SCHAR *pQuantValBase; |
| const SCHAR *pQuantVal; |
| |
| pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; |
| pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; |
| pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; |
| readDirection = pHcr->segmentInfo.readDirection; |
| pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; |
| pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; |
| segmentOffset = pHcr->segmentInfo.segmentOffset; |
| |
| iNode = pHcr->nonPcwSideinfo.iNode; |
| pCntSign = pHcr->nonPcwSideinfo.pCntSign; |
| pResultBase = pHcr->nonPcwSideinfo.pResultBase; |
| iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; |
| codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; |
| pSta = pHcr->nonPcwSideinfo.pSta; |
| |
| treeNode = iNode[codewordOffset]; |
| pCurrentTree = aHuffTable[ESCAPE_CODEBOOK]; |
| |
| for (; pRemainingBitsInSegment[segmentOffset] > 0; |
| pRemainingBitsInSegment[segmentOffset] -= 1) { |
| carryBit = HcrGetABitFromBitstream( |
| bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], |
| &pRightStartOfSegment[segmentOffset], readDirection); |
| |
| /* make a step in tree */ |
| CarryBitToBranchValue(carryBit, treeNode, &branchValue, &branchNode); |
| |
| /* if end of branch reached write out lines and count bits needed for sign, |
| * otherwise store node in codeword sideinfo */ |
| if ((branchNode & TEST_BIT_10) == |
| TEST_BIT_10) { /* test bit 10 ; if set body complete */ |
| |
| /* body completely decoded; branchValue is valid */ |
| /* set pQuantVol to first (of two or four) quantized spectral coefficients |
| */ |
| pQuantValBase = aQuantTable[ESCAPE_CODEBOOK]; /* get base address of |
| quantized values |
| belonging to current |
| codebook */ |
| pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid |
| line [of 2 or 4 quantized |
| values] */ |
| |
| /* make backup from original resultPointer in node storage for state |
| * BODY_SIGN_ESC__SIGN */ |
| iNode[codewordOffset] = iResultPointer[codewordOffset]; |
| |
| /* get position of first line for writing result */ |
| iQSC = iResultPointer[codewordOffset]; |
| |
| /* codeword decoding result is written out here: Write out 2 or 4 |
| * quantized spectral values with probably */ |
| /* wrong sign and count number of values which are different from zero for |
| * sign bit decoding [which happens in next state] */ |
| cntSign = 0; |
| |
| for (dimCntr = DIMENSION_OF_ESCAPE_CODEBOOK; dimCntr != 0; dimCntr--) { |
| pResultBase[iQSC++] = |
| (FIXP_DBL)*pQuantVal; /* write quant. spec. coef. into spectrum */ |
| if (*pQuantVal++ != 0) { |
| cntSign += 1; |
| } |
| } |
| |
| if (cntSign == 0) { |
| ClearBitFromBitfield( |
| &(pHcr->nonPcwSideinfo.pState), segmentOffset, |
| pCodewordBitfield); /* clear a bit in bitfield and switch off |
| statemachine */ |
| /* codeword decoded */ |
| } else { |
| /* write sign count result into codewordsideinfo of current codeword */ |
| pCntSign[codewordOffset] = cntSign; |
| pSta[codewordOffset] = BODY_SIGN_ESC__SIGN; /* change state */ |
| pHcr->nonPcwSideinfo.pState = |
| aStateConstant2State[pSta[codewordOffset]]; /* get state from |
| separate array of |
| cw-sideinfo */ |
| } |
| pRemainingBitsInSegment[segmentOffset] -= 1; /* the last reinitialzation |
| of for loop counter (see |
| above) is done here */ |
| break; /* end of branch in tree reached i.e. a whole nonPCW-Body is |
| decoded */ |
| } else { /* body is not decoded completely: */ |
| /* update treeNode for further step in decoding tree and store updated |
| * treeNode because maybe no more bits left in segment */ |
| treeNode = *(pCurrentTree + branchValue); |
| iNode[codewordOffset] = treeNode; |
| } |
| } |
| |
| if (pRemainingBitsInSegment[segmentOffset] <= 0) { |
| ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, |
| pSegmentBitfield); /* clear a bit in bitfield and |
| switch off statemachine */ |
| |
| if (pRemainingBitsInSegment[segmentOffset] < 0) { |
| pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__BODY; |
| return BODY_SIGN_ESC__BODY; |
| } |
| } |
| |
| return STOP_THIS_STATE; |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| description: This state decodes the sign bits, if a codeword of codebook 11 |
| needs some. A flag named 'flagB' in codeword sideinfo is set, if the second line |
| of quantized spectral values is 16. The 'flagB' is used in case of decoding of a |
| escape sequence is necessary as far as the second line is concerned. |
| |
| If only the first line needs an escape sequence, the flagB is |
| cleared. If only the second line needs an escape sequence, the flagB is not |
| used. |
| |
| For storing sideinfo in case of escape sequence decoding one |
| single word can be used for both escape sequences because they are decoded not |
| at the same time: |
| |
| |
| bit 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |
| 4 3 2 1 0 |
| ===== == == =========== =========== |
| =================================== ^ ^ ^ ^ ^ |
| ^ | | | | | | res. flagA flagB |
| escapePrefixUp escapePrefixDown escapeWord |
| |
| ----------------------------------------------------------------------------------------------- |
| output: Two lines with correct sign. If one or two values is/are 16, |
| the lines are not valid, otherwise they are. |
| ----------------------------------------------------------------------------------------------- |
| return: 0 |
| -------------------------------------------------------------------------------------------- |
| */ |
| UINT Hcr_State_BODY_SIGN_ESC__SIGN(HANDLE_FDK_BITSTREAM bs, void *ptr) { |
| H_HCR_INFO pHcr = (H_HCR_INFO)ptr; |
| SCHAR *pRemainingBitsInSegment; |
| INT *pLeftStartOfSegment; |
| INT *pRightStartOfSegment; |
| UCHAR readDirection; |
| UINT *pSegmentBitfield; |
| UINT *pCodewordBitfield; |
| UINT segmentOffset; |
| |
| UINT *iNode; |
| UCHAR *pCntSign; |
| FIXP_DBL *pResultBase; |
| USHORT *iResultPointer; |
| UINT *pEscapeSequenceInfo; |
| UINT codewordOffset; |
| |
| UINT iQSC; |
| UCHAR cntSign; |
| UINT flagA; |
| UINT flagB; |
| UINT flags; |
| UCHAR carryBit; |
| SCHAR *pSta; |
| |
| pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; |
| pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; |
| pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; |
| readDirection = pHcr->segmentInfo.readDirection; |
| pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; |
| pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; |
| segmentOffset = pHcr->segmentInfo.segmentOffset; |
| |
| iNode = pHcr->nonPcwSideinfo.iNode; |
| pCntSign = pHcr->nonPcwSideinfo.pCntSign; |
| pResultBase = pHcr->nonPcwSideinfo.pResultBase; |
| iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; |
| pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; |
| codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; |
| pSta = pHcr->nonPcwSideinfo.pSta; |
| |
| iQSC = iResultPointer[codewordOffset]; |
| cntSign = pCntSign[codewordOffset]; |
| |
| /* loop for sign bit decoding */ |
| for (; pRemainingBitsInSegment[segmentOffset] > 0; |
| pRemainingBitsInSegment[segmentOffset] -= 1) { |
| carryBit = HcrGetABitFromBitstream( |
| bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], |
| &pRightStartOfSegment[segmentOffset], readDirection); |
| |
| /* decrement sign counter because one sign bit has been read */ |
| cntSign -= 1; |
| pCntSign[codewordOffset] = cntSign; |
| |
| /* get a quantized spectral value (which was decoded in previous state) |
| * which is not zero. [This value will get a sign] */ |
| while (pResultBase[iQSC] == (FIXP_DBL)0) { |
| if (++iQSC >= 1024) { |
| return BODY_SIGN_ESC__SIGN; |
| } |
| } |
| iResultPointer[codewordOffset] = iQSC; |
| |
| /* put negative sign together with quantized spectral value; if carryBit is |
| * zero, the sign is ok already; no write operation necessary in this case |
| */ |
| if (carryBit != 0) { |
| pResultBase[iQSC] = -pResultBase[iQSC]; /* carryBit = 1 --> minus */ |
| } |
| iQSC++; /* update index to next (maybe valid) value */ |
| iResultPointer[codewordOffset] = iQSC; |
| |
| if (cntSign == 0) { |
| /* all sign bits are decoded now */ |
| pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of |
| for loop counter (see |
| above) is done here */ |
| |
| /* check decoded values if codeword is decoded: Check if one or two escape |
| * sequences 16 follow */ |
| |
| /* step 0 */ |
| /* restore pointer to first decoded quantized value [ = original |
| * pResultPointr] from index iNode prepared in State_BODY_SIGN_ESC__BODY |
| */ |
| iQSC = iNode[codewordOffset]; |
| |
| /* step 1 */ |
| /* test first value if escape sequence follows */ |
| flagA = 0; /* for first possible escape sequence */ |
| if (fixp_abs(pResultBase[iQSC++]) == (FIXP_DBL)ESCAPE_VALUE) { |
| flagA = 1; |
| } |
| |
| /* step 2 */ |
| /* test second value if escape sequence follows */ |
| flagB = 0; /* for second possible escape sequence */ |
| if (fixp_abs(pResultBase[iQSC]) == (FIXP_DBL)ESCAPE_VALUE) { |
| flagB = 1; |
| } |
| |
| /* step 3 */ |
| /* evaluate flag result and go on if necessary */ |
| if (!flagA && !flagB) { |
| ClearBitFromBitfield( |
| &(pHcr->nonPcwSideinfo.pState), segmentOffset, |
| pCodewordBitfield); /* clear a bit in bitfield and switch off |
| statemachine */ |
| } else { |
| /* at least one of two lines is 16 */ |
| /* store both flags at correct positions in non PCW codeword sideinfo |
| * pEscapeSequenceInfo[codewordOffset] */ |
| flags = flagA << POSITION_OF_FLAG_A; |
| flags |= (flagB << POSITION_OF_FLAG_B); |
| pEscapeSequenceInfo[codewordOffset] = flags; |
| |
| /* set next state */ |
| pSta[codewordOffset] = BODY_SIGN_ESC__ESC_PREFIX; |
| pHcr->nonPcwSideinfo.pState = |
| aStateConstant2State[pSta[codewordOffset]]; /* get state from |
| separate array of |
| cw-sideinfo */ |
| |
| /* set result pointer to the first line of the two decoded lines */ |
| iResultPointer[codewordOffset] = iNode[codewordOffset]; |
| |
| if (!flagA && flagB) { |
| /* update pResultPointr ==> state Stat_BODY_SIGN_ESC__ESC_WORD writes |
| * to correct position. Second value is the one and only escape value |
| */ |
| iQSC = iResultPointer[codewordOffset]; |
| iQSC++; |
| iResultPointer[codewordOffset] = iQSC; |
| } |
| |
| } /* at least one of two lines is 16 */ |
| break; /* nonPCW-Body at cb 11 and according sign bits are decoded */ |
| |
| } /* if ( cntSign == 0 ) */ |
| } /* loop over remaining Bits in segment */ |
| |
| if (pRemainingBitsInSegment[segmentOffset] <= 0) { |
| ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, |
| pSegmentBitfield); /* clear a bit in bitfield and |
| switch off statemachine */ |
| |
| if (pRemainingBitsInSegment[segmentOffset] < 0) { |
| pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__SIGN; |
| return BODY_SIGN_ESC__SIGN; |
| } |
| } |
| return STOP_THIS_STATE; |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| description: Decode escape prefix of first or second escape sequence. The |
| escape prefix consists of ones. The following zero is also decoded here. |
| ----------------------------------------------------------------------------------------------- |
| output: If the single separator-zero which follows the |
| escape-prefix-ones is not yet decoded: The value 'escapePrefixUp' in word |
| pEscapeSequenceInfo[codewordOffset] is updated. |
| |
| If the single separator-zero which follows the |
| escape-prefix-ones is decoded: Two updated values 'escapePrefixUp' and |
| 'escapePrefixDown' in word pEscapeSequenceInfo[codewordOffset]. This State is |
| finished. Switch to next state. |
| ----------------------------------------------------------------------------------------------- |
| return: 0 |
| -------------------------------------------------------------------------------------------- |
| */ |
| UINT Hcr_State_BODY_SIGN_ESC__ESC_PREFIX(HANDLE_FDK_BITSTREAM bs, void *ptr) { |
| H_HCR_INFO pHcr = (H_HCR_INFO)ptr; |
| SCHAR *pRemainingBitsInSegment; |
| INT *pLeftStartOfSegment; |
| INT *pRightStartOfSegment; |
| UCHAR readDirection; |
| UINT *pSegmentBitfield; |
| UINT segmentOffset; |
| UINT *pEscapeSequenceInfo; |
| UINT codewordOffset; |
| UCHAR carryBit; |
| UINT escapePrefixUp; |
| SCHAR *pSta; |
| |
| pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; |
| pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; |
| pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; |
| readDirection = pHcr->segmentInfo.readDirection; |
| pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; |
| segmentOffset = pHcr->segmentInfo.segmentOffset; |
| pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; |
| codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; |
| pSta = pHcr->nonPcwSideinfo.pSta; |
| |
| escapePrefixUp = |
| (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_UP) >> |
| LSB_ESCAPE_PREFIX_UP; |
| |
| /* decode escape prefix */ |
| for (; pRemainingBitsInSegment[segmentOffset] > 0; |
| pRemainingBitsInSegment[segmentOffset] -= 1) { |
| carryBit = HcrGetABitFromBitstream( |
| bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], |
| &pRightStartOfSegment[segmentOffset], readDirection); |
| |
| /* count ones and store sum in escapePrefixUp */ |
| if (carryBit == 1) { |
| escapePrefixUp += 1; /* update conter for ones */ |
| |
| /* store updated counter in sideinfo of current codeword */ |
| pEscapeSequenceInfo[codewordOffset] &= |
| ~MASK_ESCAPE_PREFIX_UP; /* delete old escapePrefixUp */ |
| escapePrefixUp <<= LSB_ESCAPE_PREFIX_UP; /* shift to correct position */ |
| pEscapeSequenceInfo[codewordOffset] |= |
| escapePrefixUp; /* insert new escapePrefixUp */ |
| escapePrefixUp >>= LSB_ESCAPE_PREFIX_UP; /* shift back down */ |
| } else { /* separator [zero] reached */ |
| pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of |
| for loop counter (see |
| above) is done here */ |
| escapePrefixUp += |
| 4; /* if escape_separator '0' appears, add 4 and ==> break */ |
| |
| /* store escapePrefixUp in pEscapeSequenceInfo[codewordOffset] at bit |
| * position escapePrefixUp */ |
| pEscapeSequenceInfo[codewordOffset] &= |
| ~MASK_ESCAPE_PREFIX_UP; /* delete old escapePrefixUp */ |
| escapePrefixUp <<= LSB_ESCAPE_PREFIX_UP; /* shift to correct position */ |
| pEscapeSequenceInfo[codewordOffset] |= |
| escapePrefixUp; /* insert new escapePrefixUp */ |
| escapePrefixUp >>= LSB_ESCAPE_PREFIX_UP; /* shift back down */ |
| |
| /* store escapePrefixUp in pEscapeSequenceInfo[codewordOffset] at bit |
| * position escapePrefixDown */ |
| pEscapeSequenceInfo[codewordOffset] &= |
| ~MASK_ESCAPE_PREFIX_DOWN; /* delete old escapePrefixDown */ |
| escapePrefixUp <<= LSB_ESCAPE_PREFIX_DOWN; /* shift to correct position */ |
| pEscapeSequenceInfo[codewordOffset] |= |
| escapePrefixUp; /* insert new escapePrefixDown */ |
| |
| pSta[codewordOffset] = BODY_SIGN_ESC__ESC_WORD; /* set next state */ |
| pHcr->nonPcwSideinfo.pState = |
| aStateConstant2State[pSta[codewordOffset]]; /* get state from separate |
| array of cw-sideinfo */ |
| break; |
| } |
| } |
| |
| if (pRemainingBitsInSegment[segmentOffset] <= 0) { |
| ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, |
| pSegmentBitfield); /* clear a bit in bitfield and |
| switch off statemachine */ |
| |
| if (pRemainingBitsInSegment[segmentOffset] < 0) { |
| pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_PREFIX; |
| return BODY_SIGN_ESC__ESC_PREFIX; |
| } |
| } |
| |
| return STOP_THIS_STATE; |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| description: Decode escapeWord of escape sequence. If the escape sequence |
| is decoded completely, assemble quantized-spectral-escape-coefficient and |
| replace the previous decoded 16 by the new value. Test flagB. If flagB is set, |
| the second escape sequence must be decoded. If flagB is not set, the codeword is |
| decoded and the state machine is switched off. |
| ----------------------------------------------------------------------------------------------- |
| output: Two lines with valid sign. At least one of both lines has got |
| the correct value. |
| ----------------------------------------------------------------------------------------------- |
| return: 0 |
| -------------------------------------------------------------------------------------------- |
| */ |
| UINT Hcr_State_BODY_SIGN_ESC__ESC_WORD(HANDLE_FDK_BITSTREAM bs, void *ptr) { |
| H_HCR_INFO pHcr = (H_HCR_INFO)ptr; |
| SCHAR *pRemainingBitsInSegment; |
| INT *pLeftStartOfSegment; |
| INT *pRightStartOfSegment; |
| UCHAR readDirection; |
| UINT *pSegmentBitfield; |
| UINT *pCodewordBitfield; |
| UINT segmentOffset; |
| |
| FIXP_DBL *pResultBase; |
| USHORT *iResultPointer; |
| UINT *pEscapeSequenceInfo; |
| UINT codewordOffset; |
| |
| UINT escapeWord; |
| UINT escapePrefixDown; |
| UINT escapePrefixUp; |
| UCHAR carryBit; |
| UINT iQSC; |
| INT sign; |
| UINT flagA; |
| UINT flagB; |
| SCHAR *pSta; |
| |
| pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; |
| pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; |
| pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; |
| readDirection = pHcr->segmentInfo.readDirection; |
| pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; |
| pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; |
| segmentOffset = pHcr->segmentInfo.segmentOffset; |
| |
| pResultBase = pHcr->nonPcwSideinfo.pResultBase; |
| iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; |
| pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; |
| codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; |
| pSta = pHcr->nonPcwSideinfo.pSta; |
| |
| escapeWord = pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_WORD; |
| escapePrefixDown = |
| (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_DOWN) >> |
| LSB_ESCAPE_PREFIX_DOWN; |
| |
| /* decode escape word */ |
| for (; pRemainingBitsInSegment[segmentOffset] > 0; |
| pRemainingBitsInSegment[segmentOffset] -= 1) { |
| carryBit = HcrGetABitFromBitstream( |
| bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], |
| &pRightStartOfSegment[segmentOffset], readDirection); |
| |
| /* build escape word */ |
| escapeWord <<= |
| 1; /* left shift previous decoded part of escapeWord by on bit */ |
| escapeWord = escapeWord | carryBit; /* assemble escape word by bitwise or */ |
| |
| /* decrement counter for length of escape word because one more bit was |
| * decoded */ |
| escapePrefixDown -= 1; |
| |
| /* store updated escapePrefixDown */ |
| pEscapeSequenceInfo[codewordOffset] &= |
| ~MASK_ESCAPE_PREFIX_DOWN; /* delete old escapePrefixDown */ |
| escapePrefixDown <<= LSB_ESCAPE_PREFIX_DOWN; /* shift to correct position */ |
| pEscapeSequenceInfo[codewordOffset] |= |
| escapePrefixDown; /* insert new escapePrefixDown */ |
| escapePrefixDown >>= LSB_ESCAPE_PREFIX_DOWN; /* shift back */ |
| |
| /* store updated escapeWord */ |
| pEscapeSequenceInfo[codewordOffset] &= |
| ~MASK_ESCAPE_WORD; /* delete old escapeWord */ |
| pEscapeSequenceInfo[codewordOffset] |= |
| escapeWord; /* insert new escapeWord */ |
| |
| if (escapePrefixDown == 0) { |
| pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of |
| for loop counter (see |
| above) is done here */ |
| |
| /* escape sequence decoded. Assemble escape-line and replace original line |
| */ |
| |
| /* step 0 */ |
| /* derive sign */ |
| iQSC = iResultPointer[codewordOffset]; |
| sign = (pResultBase[iQSC] >= (FIXP_DBL)0) |
| ? 1 |
| : -1; /* get sign of escape value 16 */ |
| |
| /* step 1 */ |
| /* get escapePrefixUp */ |
| escapePrefixUp = |
| (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_UP) >> |
| LSB_ESCAPE_PREFIX_UP; |
| |
| /* step 2 */ |
| /* calculate escape value */ |
| pResultBase[iQSC] = |
| (FIXP_DBL)(sign * (((INT)1 << escapePrefixUp) + (INT)escapeWord)); |
| |
| /* get both flags from sideinfo (flags are not shifted to the |
| * lsb-position) */ |
| flagA = pEscapeSequenceInfo[codewordOffset] & MASK_FLAG_A; |
| flagB = pEscapeSequenceInfo[codewordOffset] & MASK_FLAG_B; |
| |
| /* step 3 */ |
| /* clear the whole escape sideinfo word */ |
| pEscapeSequenceInfo[codewordOffset] = 0; |
| |
| /* change state in dependence of flag flagB */ |
| if (flagA != 0) { |
| /* first escape sequence decoded; previous decoded 16 has been replaced |
| * by valid line */ |
| |
| /* clear flagA in sideinfo word because this escape sequence has already |
| * beed decoded */ |
| pEscapeSequenceInfo[codewordOffset] &= ~MASK_FLAG_A; |
| |
| if (flagB == 0) { |
| ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, |
| pCodewordBitfield); /* clear a bit in bitfield |
| and switch off |
| statemachine */ |
| } else { |
| /* updated pointer to next and last 16 */ |
| iQSC++; |
| iResultPointer[codewordOffset] = iQSC; |
| |
| /* change state */ |
| pSta[codewordOffset] = BODY_SIGN_ESC__ESC_PREFIX; |
| pHcr->nonPcwSideinfo.pState = |
| aStateConstant2State[pSta[codewordOffset]]; /* get state from |
| separate array of |
| cw-sideinfo */ |
| } |
| } else { |
| ClearBitFromBitfield( |
| &(pHcr->nonPcwSideinfo.pState), segmentOffset, |
| pCodewordBitfield); /* clear a bit in bitfield and switch off |
| statemachine */ |
| } |
| break; |
| } |
| } |
| |
| if (pRemainingBitsInSegment[segmentOffset] <= 0) { |
| ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, |
| pSegmentBitfield); /* clear a bit in bitfield and |
| switch off statemachine */ |
| |
| if (pRemainingBitsInSegment[segmentOffset] < 0) { |
| pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_WORD; |
| return BODY_SIGN_ESC__ESC_WORD; |
| } |
| } |
| |
| return STOP_THIS_STATE; |
| } |