/*
 ** 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<maxSfb; i++) {
    Word16 sfbWidth, maxVal;

    sectionInfo[i].sfbCnt = 1;
    sectionInfo[i].sfbStart = i;
    sectionInfo[i].sectionBits = INVALID_BITCOUNT;
    sectionInfo[i].codeBook = -1;
    sfbWidth = sfbOffset[i + 1] - sfbOffset[i];
    maxVal = sfbMax[i];
    bitCount(quantSpectrum + sfbOffset[i], sfbWidth, maxVal, bitLookUp[i]);
  }
}


/*****************************************************************************
*
* function name: findBestBook
* description:  essential helper functions
*
*****************************************************************************/
static Word16
findBestBook(const Word16 *bc, Word16 *book)
{
  Word32 minBits, j;
  minBits = INVALID_BITCOUNT;

  for (j=0; j<=CODE_BOOK_ESC_NDX; j++) {

    if (bc[j] < minBits) {
      minBits = bc[j];
      *book = j;
    }
  }
  return extract_l(minBits);
}

static Word16
findMinMergeBits(const Word16 *bc1, const Word16 *bc2)
{
  Word32 minBits, j, sum;
  minBits = INVALID_BITCOUNT;

  for (j=0; j<=CODE_BOOK_ESC_NDX; j++) {
    sum = bc1[j] + bc2[j];
    if (sum < minBits) {
      minBits = sum;
    }
  }
  return extract_l(minBits);
}

static void
mergeBitLookUp(Word16 *bc1, const Word16 *bc2)
{
  Word32 j;

  for (j=0; j<=CODE_BOOK_ESC_NDX; j++) {
    bc1[j] = min(bc1[j] + bc2[j], INVALID_BITCOUNT);
  }
}

static Word16
findMaxMerge(const Word16 mergeGainLookUp[MAX_SFB_LONG],
             const SECTION_INFO *sectionInfo,
             const Word16 maxSfb, Word16 *maxNdx)
{
  Word32 i, maxMergeGain;
  maxMergeGain = 0;

  for (i=0; i+sectionInfo[i].sfbCnt < maxSfb; i += sectionInfo[i].sfbCnt) {

    if (mergeGainLookUp[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; i<maxSfb; i++) {
    /* Side-Info bits will be calculated in Stage 1!  */

    if (sectionInfo[i].sectionBits == INVALID_BITCOUNT) {
      sectionInfo[i].sectionBits = findBestBook(bitLookUp[i], &(sectionInfo[i].codeBook));
    }
  }
}

/*
  sectioning Stage 1:merge all connected regions with the same code book and
  calculate side info
*/

static void
gmStage1(SECTION_INFO * sectionInfo,
         Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
         const Word16 maxSfb,
         const Word16 *sideInfoTab)
{
  SECTION_INFO * sectionInfo_s;
  SECTION_INFO * sectionInfo_e;
  Word32 mergeStart, mergeEnd;
  mergeStart = 0;

  do {

    sectionInfo_s = sectionInfo + mergeStart;
	for (mergeEnd=mergeStart+1; mergeEnd<maxSfb; mergeEnd++) {
      sectionInfo_e = sectionInfo + mergeEnd;
      if (sectionInfo_s->codeBook != 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].sfbCnt<maxSfb; i+=sectionInfo[i].sfbCnt) {
    mergeGainLookUp[i] = CalcMergeGain(sectionInfo,
                                       bitLookUp,
                                       sideInfoTab,
                                       i,
                                       (i + sectionInfo[i].sfbCnt));
  }

  while (TRUE) {
    Word16 maxMergeGain, maxNdx, maxNdxNext, maxNdxLast;

    maxMergeGain = findMaxMerge(mergeGainLookUp, sectionInfo, maxSfb, &maxNdx);


    if (maxMergeGain <= 0)
      break;


    maxNdxNext = maxNdx + sectionInfo[maxNdx].sfbCnt;

    sectionInfo[maxNdx].sfbCnt = sectionInfo[maxNdx].sfbCnt + sectionInfo[maxNdxNext].sfbCnt;
    sectionInfo[maxNdx].sectionBits = sectionInfo[maxNdx].sectionBits +
                                          (sectionInfo[maxNdxNext].sectionBits - maxMergeGain);


    mergeBitLookUp(bitLookUp[maxNdx], bitLookUp[maxNdxNext]);


    if (maxNdx != 0) {
      maxNdxLast = sectionInfo[maxNdx - 1].sfbStart;
      mergeGainLookUp[maxNdxLast] = CalcMergeGain(sectionInfo,
                                                  bitLookUp,
                                                  sideInfoTab,
                                                  maxNdxLast,
                                                  maxNdx);
    }
    maxNdxNext = maxNdx + sectionInfo[maxNdx].sfbCnt;

    sectionInfo[maxNdxNext - 1].sfbStart = sectionInfo[maxNdx].sfbStart;


    if (maxNdxNext - maxSfb < 0) {
      mergeGainLookUp[maxNdx] = CalcMergeGain(sectionInfo,
                                              bitLookUp,
                                              sideInfoTab,
                                              maxNdx,
                                              maxNdxNext);
    }
  }
}

/*
  count bits used by the noiseless coder
*/
static void
noiselessCounter(SECTION_DATA *sectionData,
                 Word16 mergeGainLookUp[MAX_SFB_LONG],
                 Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
                 const Word16 *quantSpectrum,
                 const UWord16 *maxValueInSfb,
                 const Word16 *sfbOffset,
                 const Word32 blockType)
{
  Word32 grpNdx, i;
  const Word16 *sideInfoTab = NULL;
  SECTION_INFO *sectionInfo;

  /*
    use appropriate side info table
  */
  switch (blockType)
  {
    case LONG_WINDOW:
    case START_WINDOW:
    case STOP_WINDOW:
      sideInfoTab = sideInfoTabLong;
      break;
    case SHORT_WINDOW:
      sideInfoTab = 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) {

    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; i<sectionData->maxSfbPerGroup; 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; i<sectionData->noOfSections; 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; i<sectionData->noOfSections; 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);
}

