/* ** Copyright 2003-2010, VisualOn, Inc. ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ /******************************************************************************* File: dyn_bits.c Content: Noiseless coder module functions *******************************************************************************/ #include "aac_rom.h" #include "dyn_bits.h" #include "bit_cnt.h" #include "psy_const.h" /***************************************************************************** * * function name: buildBitLookUp * description: count bits using all possible tables * *****************************************************************************/ static void buildBitLookUp(const Word16 *quantSpectrum, const Word16 maxSfb, const Word16 *sfbOffset, const UWord16 *sfbMax, Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], SECTION_INFO * sectionInfo) { Word32 i; for (i=0; i maxMergeGain) { maxMergeGain = mergeGainLookUp[i]; *maxNdx = i; } } return extract_l(maxMergeGain); } static Word16 CalcMergeGain(const SECTION_INFO *sectionInfo, Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], const Word16 *sideInfoTab, const Word16 ndx1, const Word16 ndx2) { Word32 SplitBits; Word32 MergeBits; Word32 MergeGain; /* Bit amount for splitted sections */ SplitBits = sectionInfo[ndx1].sectionBits + sectionInfo[ndx2].sectionBits; MergeBits = sideInfoTab[sectionInfo[ndx1].sfbCnt + sectionInfo[ndx2].sfbCnt] + findMinMergeBits(bitLookUp[ndx1], bitLookUp[ndx2]); MergeGain = (SplitBits - MergeBits); return extract_l(MergeGain); } /* sectioning Stage 0:find minimum codbooks */ static void gmStage0(SECTION_INFO * sectionInfo, Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], const Word16 maxSfb) { Word32 i; for (i=0; icodeBook != sectionInfo_e->codeBook) break; sectionInfo_s->sfbCnt += 1; sectionInfo_s->sectionBits += sectionInfo_e->sectionBits; mergeBitLookUp(bitLookUp[mergeStart], bitLookUp[mergeEnd]); } sectionInfo_s->sectionBits += sideInfoTab[sectionInfo_s->sfbCnt]; sectionInfo[mergeEnd - 1].sfbStart = sectionInfo_s->sfbStart; /* speed up prev search */ mergeStart = mergeEnd; } while (mergeStart - maxSfb < 0); } /* sectioning Stage 2:greedy merge algorithm, merge connected sections with maximum bit gain until no more gain is possible */ static void gmStage2(SECTION_INFO *sectionInfo, Word16 mergeGainLookUp[MAX_SFB_LONG], Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], const Word16 maxSfb, const Word16 *sideInfoTab) { Word16 i; for (i=0; i+sectionInfo[i].sfbCntnoOfSections = 0; sectionData->huffmanBits = 0; sectionData->sideInfoBits = 0; if (sectionData->maxSfbPerGroup == 0) return; /* loop trough groups */ for (grpNdx=0; grpNdxsfbCnt; grpNdx+=sectionData->sfbPerGroup) { sectionInfo = sectionData->sectionInfo + sectionData->noOfSections; buildBitLookUp(quantSpectrum, sectionData->maxSfbPerGroup, sfbOffset + grpNdx, maxValueInSfb + grpNdx, bitLookUp, sectionInfo); /* 0.Stage */ gmStage0(sectionInfo, bitLookUp, sectionData->maxSfbPerGroup); /* 1.Stage */ gmStage1(sectionInfo, bitLookUp, sectionData->maxSfbPerGroup, sideInfoTab); /* 2.Stage */ gmStage2(sectionInfo, mergeGainLookUp, bitLookUp, sectionData->maxSfbPerGroup, sideInfoTab); /* compress output, calculate total huff and side bits */ for (i=0; imaxSfbPerGroup; i+=sectionInfo[i].sfbCnt) { findBestBook(bitLookUp[i], &(sectionInfo[i].codeBook)); sectionInfo[i].sfbStart = sectionInfo[i].sfbStart + grpNdx; sectionData->huffmanBits = (sectionData->huffmanBits + (sectionInfo[i].sectionBits - sideInfoTab[sectionInfo[i].sfbCnt])); sectionData->sideInfoBits = (sectionData->sideInfoBits + sideInfoTab[sectionInfo[i].sfbCnt]); sectionData->sectionInfo[sectionData->noOfSections] = sectionInfo[i]; sectionData->noOfSections = sectionData->noOfSections + 1; } } } /******************************************************************************* * * functionname: scfCount * returns : --- * description : count bits used by scalefactors. * ********************************************************************************/ static void scfCount(const Word16 *scalefacGain, const UWord16 *maxValueInSfb, SECTION_DATA * sectionData) { SECTION_INFO *psectionInfo; SECTION_INFO *psectionInfom; /* counter */ Word32 i = 0; /* section counter */ Word32 j = 0; /* sfb counter */ Word32 k = 0; /* current section auxiliary counter */ Word32 m = 0; /* other section auxiliary counter */ Word32 n = 0; /* other sfb auxiliary counter */ /* further variables */ Word32 lastValScf = 0; Word32 deltaScf = 0; Flag found = 0; Word32 scfSkipCounter = 0; sectionData->scalefacBits = 0; if (scalefacGain == NULL) { return; } lastValScf = 0; sectionData->firstScf = 0; psectionInfo = sectionData->sectionInfo; for (i=0; inoOfSections; i++) { if (psectionInfo->codeBook != CODE_BOOK_ZERO_NO) { sectionData->firstScf = psectionInfo->sfbStart; lastValScf = scalefacGain[sectionData->firstScf]; break; } psectionInfo += 1; } psectionInfo = sectionData->sectionInfo; for (i=0; inoOfSections; i++, psectionInfo += 1) { if (psectionInfo->codeBook != CODE_BOOK_ZERO_NO && psectionInfo->codeBook != CODE_BOOK_PNS_NO) { for (j = psectionInfo->sfbStart; j < (psectionInfo->sfbStart + psectionInfo->sfbCnt); j++) { /* check if we can repeat the last value to save bits */ if (maxValueInSfb[j] == 0) { found = 0; if (scfSkipCounter == 0) { /* end of section */ if (j - ((psectionInfo->sfbStart + psectionInfo->sfbCnt) - 1) == 0) { found = 0; } else { for (k = j + 1; k < psectionInfo->sfbStart + psectionInfo->sfbCnt; k++) { if (maxValueInSfb[k] != 0) { int tmp = L_abs(scalefacGain[k] - lastValScf); found = 1; if ( tmp < CODE_BOOK_SCF_LAV) { /* save bits */ deltaScf = 0; } else { /* do not save bits */ deltaScf = lastValScf - scalefacGain[j]; lastValScf = scalefacGain[j]; scfSkipCounter = 0; } break; } /* count scalefactor skip */ scfSkipCounter = scfSkipCounter + 1; } } psectionInfom = psectionInfo + 1; /* search for the next maxValueInSfb[] != 0 in all other sections */ for (m = i + 1; (m < sectionData->noOfSections) && (found == 0); m++) { if ((psectionInfom->codeBook != CODE_BOOK_ZERO_NO) && (psectionInfom->codeBook != CODE_BOOK_PNS_NO)) { for (n = psectionInfom->sfbStart; n < (psectionInfom->sfbStart + psectionInfom->sfbCnt); n++) { if (maxValueInSfb[n] != 0) { found = 1; if ( (abs_s(scalefacGain[n] - lastValScf) < CODE_BOOK_SCF_LAV)) { deltaScf = 0; } else { deltaScf = (lastValScf - scalefacGain[j]); lastValScf = scalefacGain[j]; scfSkipCounter = 0; } break; } /* count scalefactor skip */ scfSkipCounter = scfSkipCounter + 1; } } psectionInfom += 1; } if (found == 0) { deltaScf = 0; scfSkipCounter = 0; } } else { deltaScf = 0; scfSkipCounter = scfSkipCounter - 1; } } else { deltaScf = lastValScf - scalefacGain[j]; lastValScf = scalefacGain[j]; } sectionData->scalefacBits += bitCountScalefactorDelta(deltaScf); } } } } typedef Word16 (*lookUpTable)[CODE_BOOK_ESC_NDX + 1]; Word16 dynBitCount(const Word16 *quantSpectrum, const UWord16 *maxValueInSfb, const Word16 *scalefac, const Word16 blockType, const Word16 sfbCnt, const Word16 maxSfbPerGroup, const Word16 sfbPerGroup, const Word16 *sfbOffset, SECTION_DATA *sectionData) { sectionData->blockType = blockType; sectionData->sfbCnt = sfbCnt; sectionData->sfbPerGroup = sfbPerGroup; if(sfbPerGroup) sectionData->noOfGroups = sfbCnt/sfbPerGroup; else sectionData->noOfGroups = 0x7fff; sectionData->maxSfbPerGroup = maxSfbPerGroup; noiselessCounter(sectionData, sectionData->mergeGainLookUp, (lookUpTable)sectionData->bitLookUp, quantSpectrum, maxValueInSfb, sfbOffset, blockType); scfCount(scalefac, maxValueInSfb, sectionData); return (sectionData->huffmanBits + sectionData->sideInfoBits + sectionData->scalefacBits); }