diff options
Diffstat (limited to 'libAACenc/src/dyn_bits.cpp')
-rw-r--r-- | libAACenc/src/dyn_bits.cpp | 743 |
1 files changed, 743 insertions, 0 deletions
diff --git a/libAACenc/src/dyn_bits.cpp b/libAACenc/src/dyn_bits.cpp new file mode 100644 index 0000000..8a94b6c --- /dev/null +++ b/libAACenc/src/dyn_bits.cpp @@ -0,0 +1,743 @@ +/******************************** MPEG Audio Encoder ************************** + + (C) Copyright Fraunhofer IIS (1999) + All Rights Reserved + + Please be advised that this software and/or program delivery is + Confidential Information of Fraunhofer and subject to and covered by the + + Fraunhofer IIS Software Evaluation Agreement + between Google Inc. and Fraunhofer + effective and in full force since March 1, 2012. + + You may use this software and/or program only under the terms and + conditions described in the above mentioned Fraunhofer IIS Software + Evaluation Agreement. Any other and/or further use requires a separate agreement. + + + This software and/or program is protected by copyright law and international + treaties. Any reproduction or distribution of this software and/or program, + or any portion of it, may result in severe civil and criminal penalties, and + will be prosecuted to the maximum extent possible under law. + + $Id$ + Initial author: M.Werner + contents/description: Noiseless coder module + +******************************************************************************/ + +#include "dyn_bits.h" +#include "bit_cnt.h" +#include "psy_const.h" +#include "aacenc_pns.h" +#include "aacEnc_ram.h" +#include "aacEnc_rom.h" + +typedef INT (*lookUpTable)[CODE_BOOK_ESC_NDX + 1]; + +static INT FDKaacEnc_getSideInfoBits( + const SECTION_INFO* const huffsection, + const SHORT* const sideInfoTab, + const INT useHCR + ) +{ + INT sideInfoBits; + + if ( useHCR && ((huffsection->codeBook == 11) || (huffsection->codeBook >= 16)) ) { + sideInfoBits = 5; + } + else { + sideInfoBits = sideInfoTab[huffsection->sfbCnt]; + } + + return (sideInfoBits); +} + +/* count bits using all possible tables */ +static void FDKaacEnc_buildBitLookUp( + const SHORT* const quantSpectrum, + const INT maxSfb, + const INT* const sfbOffset, + const UINT* const sfbMax, + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + SECTION_INFO* const huffsection + ) +{ + INT i, sfbWidth; + + for (i = 0; i < maxSfb; i++) + { + huffsection[i].sfbCnt = 1; + huffsection[i].sfbStart = i; + huffsection[i].sectionBits = INVALID_BITCOUNT; + huffsection[i].codeBook = -1; + sfbWidth = sfbOffset[i + 1] - sfbOffset[i]; + FDKaacEnc_bitCount(quantSpectrum + sfbOffset[i], sfbWidth, sfbMax[i], bitLookUp[i]); + } +} + +/* essential helper functions */ +static INT FDKaacEnc_findBestBook( + const INT* const bc, + INT* const book, + const INT useVCB11 + ) +{ + INT minBits = INVALID_BITCOUNT, j; + + int end = CODE_BOOK_ESC_NDX; + + + for (j = 0; j <= end; j++) + { + if (bc[j] < minBits) + { + minBits = bc[j]; + *book = j; + } + } + return (minBits); +} + +static INT FDKaacEnc_findMinMergeBits( + const INT* const bc1, + const INT* const bc2, + const INT useVCB11 + ) +{ + INT minBits = INVALID_BITCOUNT, j; + + int end = CODE_BOOK_ESC_NDX; + + + for (j = 0; j <= end; j++) + { + if (bc1[j] + bc2[j] < minBits) + { + minBits = bc1[j] + bc2[j]; + } + } + return (minBits); +} + +static void FDKaacEnc_mergeBitLookUp( + INT* const bc1, + const INT* const bc2 + ) +{ + int j; + + for (j = 0; j <= CODE_BOOK_ESC_NDX; j++) + { + bc1[j] = fixMin(bc1[j] + bc2[j], INVALID_BITCOUNT); + } +} + +static INT FDKaacEnc_findMaxMerge( + const INT* const mergeGainLookUp, + const SECTION_INFO* const huffsection, + const INT maxSfb, + INT* const maxNdx + ) +{ + INT i, maxMergeGain = 0; + + for (i = 0; i + huffsection[i].sfbCnt < maxSfb; i += huffsection[i].sfbCnt) + { + if (mergeGainLookUp[i] > maxMergeGain) + { + maxMergeGain = mergeGainLookUp[i]; + *maxNdx = i; + } + } + return (maxMergeGain); +} + +static INT FDKaacEnc_CalcMergeGain( + const SECTION_INFO* const huffsection, + const INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const SHORT* const sideInfoTab, + const INT ndx1, + const INT ndx2, + const INT useVCB11 + ) +{ + INT MergeGain, MergeBits, SplitBits; + + MergeBits = sideInfoTab[huffsection[ndx1].sfbCnt + huffsection[ndx2].sfbCnt] + FDKaacEnc_findMinMergeBits(bitLookUp[ndx1], bitLookUp[ndx2], useVCB11); + SplitBits = huffsection[ndx1].sectionBits + huffsection[ndx2].sectionBits; /* Bit amount for splitted huffsections */ + MergeGain = SplitBits - MergeBits; + + if ( (huffsection[ndx1].codeBook==CODE_BOOK_PNS_NO)||(huffsection[ndx2].codeBook==CODE_BOOK_PNS_NO) + || (huffsection[ndx1].codeBook==CODE_BOOK_IS_OUT_OF_PHASE_NO)||(huffsection[ndx2].codeBook==CODE_BOOK_IS_OUT_OF_PHASE_NO) + || (huffsection[ndx1].codeBook==CODE_BOOK_IS_IN_PHASE_NO)||(huffsection[ndx2].codeBook==CODE_BOOK_IS_IN_PHASE_NO) + ) + { + MergeGain = -1; + } + + return (MergeGain); +} + + +/* sectioning Stage 0:find minimum codbooks */ +static void FDKaacEnc_gmStage0( + SECTION_INFO* const RESTRICT huffsection, + const INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const INT maxSfb, + const INT* const noiseNrg, + const INT* const isBook + ) +{ + INT i; + + for (i = 0; i < maxSfb; i++) + { + /* Side-Info bits will be calculated in Stage 1! */ + if (huffsection[i].sectionBits == INVALID_BITCOUNT) + { + /* intensity and pns codebooks are already allocated in bitcount.c */ + if(noiseNrg[i] != NO_NOISE_PNS){ + huffsection[i].codeBook=CODE_BOOK_PNS_NO; + huffsection[i].sectionBits = 0; + } + else if( isBook[i] ) { + huffsection[i].codeBook=isBook[i]; + huffsection[i].sectionBits = 0; + } + else { + huffsection[i].sectionBits = FDKaacEnc_findBestBook(bitLookUp[i], &(huffsection[i].codeBook), 0); /* useVCB11 must be 0!!! */ + } + } + } +} + +/* + sectioning Stage 1:merge all connected regions with the same code book and + calculate side info + */ +static void FDKaacEnc_gmStage1( + SECTION_INFO* const RESTRICT huffsection, + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const INT maxSfb, + const SHORT* const sideInfoTab, + const INT useVCB11 + ) +{ + INT mergeStart = 0, mergeEnd; + + do + { + for (mergeEnd = mergeStart + 1; mergeEnd < maxSfb; mergeEnd++) + { + if (huffsection[mergeStart].codeBook != huffsection[mergeEnd].codeBook) + break; + + + /* we can merge. update tables, side info bits will be updated outside of this loop */ + huffsection[mergeStart].sfbCnt++; + huffsection[mergeStart].sectionBits += huffsection[mergeEnd].sectionBits; + + /* update bit look up for all code books */ + FDKaacEnc_mergeBitLookUp(bitLookUp[mergeStart], bitLookUp[mergeEnd]); + } + + /* add side info info bits */ + huffsection[mergeStart].sectionBits += FDKaacEnc_getSideInfoBits(&huffsection[mergeStart], sideInfoTab, useVCB11); + huffsection[mergeEnd - 1].sfbStart = huffsection[mergeStart].sfbStart; /* speed up prev search */ + + mergeStart = mergeEnd; + + } while (mergeStart < maxSfb); +} + +/* + sectioning Stage 2:greedy merge algorithm, merge connected sections with + maximum bit gain until no more gain is possible + */ +static void +FDKaacEnc_gmStage2( + SECTION_INFO* const RESTRICT huffsection, + INT* const RESTRICT mergeGainLookUp, + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const INT maxSfb, + const SHORT* const sideInfoTab, + const INT useVCB11 + ) +{ + INT i; + + for (i = 0; i + huffsection[i].sfbCnt < maxSfb; i += huffsection[i].sfbCnt) + { + mergeGainLookUp[i] = FDKaacEnc_CalcMergeGain(huffsection, + bitLookUp, + sideInfoTab, + i, + i + huffsection[i].sfbCnt, + useVCB11); + } + + while (TRUE) + { + INT maxMergeGain, maxNdx = 0, maxNdxNext, maxNdxLast; + + maxMergeGain = FDKaacEnc_findMaxMerge(mergeGainLookUp, huffsection, maxSfb, &maxNdx); + + /* exit while loop if no more gain is possible */ + if (maxMergeGain <= 0) + break; + + maxNdxNext = maxNdx + huffsection[maxNdx].sfbCnt; + + /* merge sections with maximum bit gain */ + huffsection[maxNdx].sfbCnt += huffsection[maxNdxNext].sfbCnt; + huffsection[maxNdx].sectionBits += huffsection[maxNdxNext].sectionBits - maxMergeGain; + + /* update bit look up table for merged huffsection */ + FDKaacEnc_mergeBitLookUp(bitLookUp[maxNdx], bitLookUp[maxNdxNext]); + + /* update mergeLookUpTable */ + if (maxNdx != 0) + { + maxNdxLast = huffsection[maxNdx - 1].sfbStart; + mergeGainLookUp[maxNdxLast] = FDKaacEnc_CalcMergeGain(huffsection, + bitLookUp, + sideInfoTab, + maxNdxLast, + maxNdx, + useVCB11); + + } + maxNdxNext = maxNdx + huffsection[maxNdx].sfbCnt; + + huffsection[maxNdxNext - 1].sfbStart = huffsection[maxNdx].sfbStart; + + if (maxNdxNext < maxSfb) + mergeGainLookUp[maxNdx] = FDKaacEnc_CalcMergeGain(huffsection, + bitLookUp, + sideInfoTab, + maxNdx, + maxNdxNext, + useVCB11); + + } +} + +/* count bits used by the noiseless coder */ +static void FDKaacEnc_noiselessCounter( + SECTION_DATA* const RESTRICT sectionData, + INT mergeGainLookUp[MAX_SFB_LONG], + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const SHORT* const quantSpectrum, + const UINT* const maxValueInSfb, + const INT* const sfbOffset, + const INT blockType, + const INT* const noiseNrg, + const INT* const isBook, + const INT useVCB11 + ) +{ + INT grpNdx, i; + const SHORT *sideInfoTab = NULL; + SECTION_INFO *huffsection; + + /* use appropriate side info table */ + switch (blockType) + { + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + sideInfoTab = FDKaacEnc_sideInfoTabLong; + break; + case SHORT_WINDOW: + sideInfoTab = FDKaacEnc_sideInfoTabShort; + break; + } + + sectionData->noOfSections = 0; + sectionData->huffmanBits = 0; + sectionData->sideInfoBits = 0; + + + if (sectionData->maxSfbPerGroup == 0) + return; + + /* loop trough groups */ + for (grpNdx = 0; grpNdx < sectionData->sfbCnt; grpNdx += sectionData->sfbPerGroup) + { + huffsection = sectionData->huffsection + sectionData->noOfSections; + + /* count bits in this group */ + FDKaacEnc_buildBitLookUp(quantSpectrum, + sectionData->maxSfbPerGroup, + sfbOffset + grpNdx, + maxValueInSfb + grpNdx, + bitLookUp, + huffsection); + + /* 0.Stage :Find minimum Codebooks */ + FDKaacEnc_gmStage0(huffsection, bitLookUp, sectionData->maxSfbPerGroup, noiseNrg+grpNdx, isBook+grpNdx); + + /* 1.Stage :Merge all connected regions with the same code book */ + FDKaacEnc_gmStage1(huffsection, bitLookUp, sectionData->maxSfbPerGroup, sideInfoTab, useVCB11); + + + /* + 2.Stage + greedy merge algorithm, merge connected huffsections with maximum bit + gain until no more gain is possible + */ + + FDKaacEnc_gmStage2(huffsection, + mergeGainLookUp, + bitLookUp, + sectionData->maxSfbPerGroup, + sideInfoTab, + useVCB11); + + + + /* + compress output, calculate total huff and side bits + since we did not update the actual codebook in stage 2 + to save time, we must set it here for later use in bitenc + */ + + for (i = 0; i < sectionData->maxSfbPerGroup; i += huffsection[i].sfbCnt) + { + if ((huffsection[i].codeBook==CODE_BOOK_PNS_NO) || + (huffsection[i].codeBook==CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (huffsection[i].codeBook==CODE_BOOK_IS_IN_PHASE_NO)) + { + huffsection[i].sectionBits=0; + } else { + /* the sections in the sectionData are now marked with the optimal code book */ + + FDKaacEnc_findBestBook(bitLookUp[i], &(huffsection[i].codeBook), useVCB11); + + sectionData->huffmanBits += huffsection[i].sectionBits - FDKaacEnc_getSideInfoBits(&huffsection[i], sideInfoTab, useVCB11); + } + + huffsection[i].sfbStart += grpNdx; + + /* sum up side info bits (section data bits) */ + sectionData->sideInfoBits += FDKaacEnc_getSideInfoBits(&huffsection[i], sideInfoTab, useVCB11); + sectionData->huffsection[sectionData->noOfSections++] = huffsection[i]; + } + } +} + + +/******************************************************************************* + + functionname: FDKaacEnc_scfCount + returns : --- + description : count bits used by scalefactors. + + not in all cases if maxValueInSfb[] == 0 we set deltaScf + to zero. only if the difference of the last and future + scalefacGain is not greater then CODE_BOOK_SCF_LAV (60). + + example: + ^ + scalefacGain | + | + | last 75 + | | + | | + | | + | | current 50 + | | | + | | | + | | | + | | | + | | | future 5 + | | | | + --- ... ---------------------------- ... ---------> + sfb + + + if maxValueInSfb[] of current is zero because of a + notfallstrategie, we do not save bits and transmit a + deltaScf of 25. otherwise the deltaScf between the last + scalfacGain (75) and the future scalefacGain (5) is 70. + +********************************************************************************/ +static void FDKaacEnc_scfCount( + const INT* const scalefacGain, + const UINT* const maxValueInSfb, + SECTION_DATA* const RESTRICT sectionData, + const INT* const isScale + ) +{ + INT i, j, k, m, n; + + INT lastValScf = 0; + INT deltaScf = 0; + INT found = 0; + INT scfSkipCounter = 0; + INT lastValIs = 0; + + sectionData->scalefacBits = 0; + + if (scalefacGain == NULL) + return; + + sectionData->firstScf = 0; + + for (i=0; i<sectionData->noOfSections; i++) + { + if (sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO) + { + sectionData->firstScf = sectionData->huffsection[i].sfbStart; + lastValScf = scalefacGain[sectionData->firstScf]; + break; + } + } + + for (i=0; i<sectionData->noOfSections; i++) + { + if ((sectionData->huffsection[i].codeBook == CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (sectionData->huffsection[i].codeBook == CODE_BOOK_IS_IN_PHASE_NO)) + { + for (j = sectionData->huffsection[i].sfbStart; + j < sectionData->huffsection[i].sfbStart + sectionData->huffsection[i].sfbCnt; + j++) + { + INT deltaIs = isScale[j]-lastValIs; + lastValIs = isScale[j]; + sectionData->scalefacBits+=FDKaacEnc_bitCountScalefactorDelta(deltaIs); + } + } /* Intensity */ + else if ((sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO) && + (sectionData->huffsection[i].codeBook != CODE_BOOK_PNS_NO)) + { + INT tmp = sectionData->huffsection[i].sfbStart + sectionData->huffsection[i].sfbCnt; + for (j = sectionData->huffsection[i].sfbStart; j<tmp; j++) + { + /* check if we can repeat the last value to save bits */ + if (maxValueInSfb[j] == 0) + { + found = 0; + /* are scalefactors skipped? */ + if (scfSkipCounter == 0) + { + /* end of section */ + if (j == (tmp - 1) ) + found = 0; /* search in other sections for maxValueInSfb != 0 */ + else + { + /* search in this section for the next maxValueInSfb[] != 0 */ + for (k = (j+1); k < tmp; k++) + { + if (maxValueInSfb[k] != 0) + { + found = 1; + if ( (fixp_abs(scalefacGain[k] - lastValScf)) <= CODE_BOOK_SCF_LAV) + deltaScf = 0; /* save bits */ + else + { + /* do not save bits */ + deltaScf = lastValScf - scalefacGain[j]; + lastValScf = scalefacGain[j]; + scfSkipCounter = 0; + } + break; + } + /* count scalefactor skip */ + scfSkipCounter++; + } + } + + /* search for the next maxValueInSfb[] != 0 in all other sections */ + for (m=(i+1); (m < sectionData->noOfSections) && (found == 0); m++) + { + if ((sectionData->huffsection[m].codeBook != CODE_BOOK_ZERO_NO) && (sectionData->huffsection[m].codeBook != CODE_BOOK_PNS_NO)) + { + INT end = sectionData->huffsection[m].sfbStart + sectionData->huffsection[m].sfbCnt; + for (n = sectionData->huffsection[m].sfbStart; n<end; n++) + { + if (maxValueInSfb[n] != 0) + { + found = 1; + if (fixp_abs(scalefacGain[n] - lastValScf) <= CODE_BOOK_SCF_LAV) + deltaScf = 0; /* save bits */ + else + { + /* do not save bits */ + deltaScf = lastValScf - scalefacGain[j]; + lastValScf = scalefacGain[j]; + scfSkipCounter = 0; + } + break; + } + /* count scalefactor skip */ + scfSkipCounter++; + } + } + } + /* no maxValueInSfb[] != 0 found */ + if (found == 0) + { + deltaScf = 0; + scfSkipCounter = 0; + } + } + else { + /* consider skipped scalefactors */ + deltaScf = 0; + scfSkipCounter--; + } + } + else { + deltaScf = lastValScf - scalefacGain[j]; + lastValScf = scalefacGain[j]; + } + sectionData->scalefacBits += FDKaacEnc_bitCountScalefactorDelta(deltaScf); + } + } + } /* for (i=0; i<sectionData->noOfSections; i++) */ +} + +#ifdef PNS_PRECOUNT_ENABLE +/* + preCount bits used pns +*/ +/* estimate bits used by pns for correction of static bits */ +/* no codebook switch estimation, see AAC LD FASTENC */ +INT noisePreCount(const INT *noiseNrg, INT maxSfb) +{ + INT noisePCMFlag = TRUE; + INT lastValPns = 0, deltaPns; + int i, bits=0; + + for (i = 0; i < maxSfb; i++) { + if (noiseNrg[i] != NO_NOISE_PNS) { + + if (noisePCMFlag) { + bits+=PNS_PCM_BITS; + lastValPns = noiseNrg[i]; + noisePCMFlag = FALSE; + }else { + deltaPns = noiseNrg[i]-lastValPns; + lastValPns = noiseNrg[i]; + bits+=FDKaacEnc_bitCountScalefactorDelta(deltaPns); + } + } + } + return ( bits ); +} +#endif /* PNS_PRECOUNT_ENABLE */ + +/* count bits used by pns */ +static void FDKaacEnc_noiseCount( + SECTION_DATA* const RESTRICT sectionData, + const INT* const noiseNrg + ) +{ + INT noisePCMFlag = TRUE; + INT lastValPns = 0, deltaPns; + int i, j; + + sectionData->noiseNrgBits = 0; + + for (i = 0; i < sectionData->noOfSections; i++) { + if (sectionData->huffsection[i].codeBook == CODE_BOOK_PNS_NO) { + int sfbStart = sectionData->huffsection[i].sfbStart; + int sfbEnd = sfbStart + sectionData->huffsection[i].sfbCnt; + for (j=sfbStart; j<sfbEnd; j++) { + + if (noisePCMFlag) { + sectionData->noiseNrgBits+=PNS_PCM_BITS; + lastValPns = noiseNrg[j]; + noisePCMFlag = FALSE; + } else { + deltaPns = noiseNrg[j]-lastValPns; + lastValPns = noiseNrg[j]; + sectionData->noiseNrgBits+=FDKaacEnc_bitCountScalefactorDelta(deltaPns); + } + } + } + } +} + +INT FDKaacEnc_dynBitCount( + BITCNTR_STATE* const hBC, + const SHORT* const quantSpectrum, + const UINT* const maxValueInSfb, + const INT* const scalefac, + const INT blockType, + const INT sfbCnt, + const INT maxSfbPerGroup, + const INT sfbPerGroup, + const INT* const sfbOffset, + SECTION_DATA* const RESTRICT sectionData, + const INT* const noiseNrg, + const INT* const isBook, + const INT* const isScale, + const UINT syntaxFlags + ) +{ + sectionData->blockType = blockType; + sectionData->sfbCnt = sfbCnt; + sectionData->sfbPerGroup = sfbPerGroup; + sectionData->noOfGroups = sfbCnt / sfbPerGroup; + sectionData->maxSfbPerGroup = maxSfbPerGroup; + + FDKaacEnc_noiselessCounter( + sectionData, + hBC->mergeGainLookUp, + (lookUpTable)hBC->bitLookUp, + quantSpectrum, + maxValueInSfb, + sfbOffset, + blockType, + noiseNrg, + isBook, + (syntaxFlags & AC_ER_VCB11)?1:0); + + FDKaacEnc_scfCount( + scalefac, + maxValueInSfb, + sectionData, + isScale); + + FDKaacEnc_noiseCount(sectionData, + noiseNrg); + + return (sectionData->huffmanBits + + sectionData->sideInfoBits + + sectionData->scalefacBits + + sectionData->noiseNrgBits); +} + +INT FDKaacEnc_BCNew(BITCNTR_STATE **phBC + ,UCHAR* dynamic_RAM + ) +{ + BITCNTR_STATE *hBC = GetRam_aacEnc_BitCntrState(); + + if (hBC) + { + *phBC = hBC; + hBC->bitLookUp = GetRam_aacEnc_BitLookUp(0,dynamic_RAM); + hBC->mergeGainLookUp = GetRam_aacEnc_MergeGainLookUp(0,dynamic_RAM); + if (hBC->bitLookUp == 0 || + hBC->mergeGainLookUp == 0) + { + return 1; + } + } + return (hBC == 0) ? 1 : 0; +} + +void FDKaacEnc_BCClose(BITCNTR_STATE **phBC) +{ + if (*phBC!=NULL) { + + FreeRam_aacEnc_BitCntrState(phBC); + } +} + + + |