1219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard/*
2219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** Copyright 2003-2010, VisualOn, Inc.
3219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard **
4219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** Licensed under the Apache License, Version 2.0 (the "License");
5219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** you may not use this file except in compliance with the License.
6219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** You may obtain a copy of the License at
7219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard **
8219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard **     http://www.apache.org/licenses/LICENSE-2.0
9219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard **
10219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** Unless required by applicable law or agreed to in writing, software
11219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** distributed under the License is distributed on an "AS IS" BASIS,
12219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** See the License for the specific language governing permissions and
14219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** limitations under the License.
15219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard */
16219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard/*******************************************************************************
17219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	File:		adj_thr.c
18219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
19219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	Content:	Threshold compensation functions
20219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
2117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*******************************************************************************/
2217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
23219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard#include "basic_op.h"
2417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong#include "oper_32b.h"
2517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong#include "adj_thr_data.h"
2617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong#include "adj_thr.h"
2717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong#include "qc_data.h"
2817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong#include "line_pe.h"
2917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
3017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
3117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong#define  minSnrLimit    0x6666 /* 1 dB */
32219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard#define  PEBITS_COEF	0x170a /* 0.18*(1 << 15)*/
33219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
34219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard#define  HOLE_THR_LONG	0x2873	/* 0.316*(1 << 15) */
35219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard#define  HOLE_THR_SHORT 0x4000  /* 0.5  *(1 << 15) */
36219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
37219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard#define  MS_THRSPREAD_COEF 0x7333  /* 0.9 * (1 << 15) */
38219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
39219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard#define	 MIN_SNR_COEF	   0x651f  /* 3.16* (1 << (15 - 2)) */
4017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
4117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/* values for avoid hole flag */
4217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongenum _avoid_hole_state {
4317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  NO_AH              =0,
4417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  AH_INACTIVE        =1,
4517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  AH_ACTIVE          =2
4617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong};
4717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
4817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/********************************************************************************
4917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
5017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name:bits2pe
5117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description: convert from bits to pe
5217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*			   pe = 1.18*desiredBits
5317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
5417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
5517299ab50ceb70d904e610e3b2d7fb2361a11e03James DongWord16 bits2pe(const Word16 bits) {
5617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  return (bits + ((PEBITS_COEF * bits) >> 15));
5717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
5817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
5917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/********************************************************************************
6017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
6117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name:calcThreshExp
6217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description: loudness calculation (threshold to the power of redExp)
6317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*			   thr(n)^0.25
6417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
6517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
6617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic void calcThreshExp(Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB],
6717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
6817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          const Word16 nChannels)
6917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
70219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  Word16 ch, sfb, sfbGrp;
7117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 *pthrExp, *psfbThre;
7217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  for (ch=0; ch<nChannels; ch++) {
73219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
74219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	 for(sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; sfbGrp+= psyOutChan->sfbPerGroup)
75219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  pthrExp = &(thrExp[ch][sfbGrp]);
76219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  psfbThre = psyOutChan->sfbThreshold + sfbGrp;
7717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
78219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard		*pthrExp = rsqrt(rsqrt(*psfbThre,INT_BITS),INT_BITS);
7917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		pthrExp++; psfbThre++;
8017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
8117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
8217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
8317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
8417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/********************************************************************************
8517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
8617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name:adaptMinSnr
8717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description: reduce minSnr requirements for bands with relative low energies
8817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
8917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
9017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic void adaptMinSnr(PSY_OUT_CHANNEL     psyOutChannel[MAX_CHANNELS],
9117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        Word16              logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
9217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        MINSNR_ADAPT_PARAM *msaParam,
9317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        const Word16        nChannels)
9417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
9517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 ch, sfb, sfbOffs, shift;
9617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 nSfb, avgEn;
9717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 log_avgEn = 0;
9817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 startRatio_x_avgEn = 0;
9917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
10017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
10117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  for (ch=0; ch<nChannels; ch++) {
10217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    PSY_OUT_CHANNEL* psyOutChan = &psyOutChannel[ch];
10317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
10417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    /* calc average energy per scalefactor band */
10517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    avgEn = 0;
10617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    nSfb = 0;
10717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) {
10817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
10917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfbOffs+sfb]);
11017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        nSfb = nSfb + 1;
11117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
11217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
11317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
11417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if (nSfb > 0) {
115219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  avgEn = avgEn / nSfb;
11617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
11717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      log_avgEn = iLog4(avgEn);
11817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      startRatio_x_avgEn = fixmul(msaParam->startRatio, avgEn);
11917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
12017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
12117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
12217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */
12317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) {
12417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
12517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if (psyOutChan->sfbEnergy[sfbOffs+sfb] < startRatio_x_avgEn) {
12617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          Word16 dbRatio, minSnrRed;
12717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          Word32 snrRed;
12817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          Word16 newMinSnr;
12917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
13017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          dbRatio = log_avgEn - logSfbEnergy[ch][sfbOffs+sfb];
13117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          dbRatio = dbRatio + (dbRatio << 1);
13217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
13317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          minSnrRed = 110 - ((dbRatio + (dbRatio << 1)) >> 2);
13417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          minSnrRed = max(minSnrRed, 20); /* 110: (0.375(redOffs)+1)*80,
13517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                               3: 0.00375(redRatioFac)*80
13617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                               20: 0.25(maxRed) * 80 */
13717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
13817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          snrRed = minSnrRed * iLog4((psyOutChan->sfbMinSnr[sfbOffs+sfb] << 16));
13917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          /*
14017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong             snrRedI si now scaled by 80 (minSnrRed) and 4 (ffr_iLog4)
14117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          */
14217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
14317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          newMinSnr = round16(pow2_xy(snrRed,80*4));
14417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
14517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          psyOutChan->sfbMinSnr[sfbOffs+sfb] = min(newMinSnr, minSnrLimit);
14617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
14717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
14817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
14917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
15017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
15117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
15217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
15317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
15417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/********************************************************************************
15517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
15617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name:initAvoidHoleFlag
15717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description: determine bands where avoid hole is not necessary resp. possible
15817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
15917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
16017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic void initAvoidHoleFlag(Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
16117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                              PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
16217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                              PSY_OUT_ELEMENT* psyOutElement,
16317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                              const Word16 nChannels,
16417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                              AH_PARAM *ahParam)
16517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
16617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 ch, sfb, sfbGrp, shift;
16717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 threshold;
16817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32* psfbSpreadEn;
16917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
17017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  for (ch=0; ch<nChannels; ch++) {
17117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
17217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
17317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if (psyOutChan->windowSequence != SHORT_WINDOW) {
17417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
175219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard         psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp;
17617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		 for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
177219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard			*psfbSpreadEn = *psfbSpreadEn >> 1;  /* 0.5 */
17817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong			++psfbSpreadEn;
17917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
18017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
18117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
18217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    else {
183219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard      for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
18417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp;
18517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
186219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard          *psfbSpreadEn = (*psfbSpreadEn >> 1) + (*psfbSpreadEn >> 3);  /* 0.63 */
18717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  ++psfbSpreadEn;
18817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
18917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
19017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
19117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
19217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
19317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* increase minSnr for local peaks, decrease it for valleys */
19417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if (ahParam->modifyMinSnr) {
19517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for(ch=0; ch<nChannels; ch++) {
19617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
19717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
19817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      if (psyOutChan->windowSequence != SHORT_WINDOW)
19917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        threshold = HOLE_THR_LONG;
20017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      else
20117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        threshold = HOLE_THR_SHORT;
20217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
20317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
204219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard        Word16 *psfbMinSnr = psyOutChan->sfbMinSnr + sfbGrp;
20517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
20617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          Word32 sfbEn, sfbEnm1, sfbEnp1, avgEn;
20717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
20817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          if (sfb > 0)
20917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp+sfb-1];
21017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          else
21117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp];
21217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
21317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          if (sfb < (psyOutChan->maxSfbPerGroup-1))
21417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb+1];
21517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          else
21617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb];
21717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          avgEn = (sfbEnm1 + sfbEnp1) >> 1;
21817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          sfbEn = psyOutChan->sfbEnergy[sfbGrp+sfb];
21917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
22017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          if (sfbEn > avgEn && avgEn > 0) {
22117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            Word32 tmpMinSnr;
222219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard            shift = norm_l(sfbEn);
22317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong			tmpMinSnr = Div_32(L_mpy_ls(avgEn, minSnrLimit) << shift, sfbEn << shift );
22417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            tmpMinSnr = max(tmpMinSnr, HOLE_THR_LONG);
22517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            tmpMinSnr = max(tmpMinSnr, threshold);
22617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            *psfbMinSnr = min(*psfbMinSnr, tmpMinSnr);
22717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          }
22817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          /* valley ? */
22917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
23017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          if ((sfbEn < (avgEn >> 1)) && (sfbEn > 0)) {
23117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            Word32 tmpMinSnr;
23217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            Word32 minSnrEn = L_mpy_wx(avgEn, *psfbMinSnr);
23317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
234219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard            if(minSnrEn < sfbEn) {
23517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong			  shift = norm_l(sfbEn);
23617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong              tmpMinSnr = Div_32( minSnrEn << shift, sfbEn<<shift);
23717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            }
23817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            else {
23917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong              tmpMinSnr = MAX_16;
24017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            }
24117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            tmpMinSnr = min(minSnrLimit, tmpMinSnr);
24217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
24317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            *psfbMinSnr =
24417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong              (min((tmpMinSnr >>  2), mult(*psfbMinSnr, MIN_SNR_COEF)) << 2);
245219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard          }
24617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  psfbMinSnr++;
24717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
24817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
24917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
25017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
25117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
25217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* stereo: adapt the minimum requirements sfbMinSnr of mid and
25317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong     side channels */
25417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
25517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if (nChannels == 2) {
25617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    PSY_OUT_CHANNEL *psyOutChanM = &psyOutChannel[0];
25717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    PSY_OUT_CHANNEL *psyOutChanS = &psyOutChannel[1];
25817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for (sfb=0; sfb<psyOutChanM->sfbCnt; sfb++) {
25917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      if (psyOutElement->toolsInfo.msMask[sfb]) {
26017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        Word32 sfbEnM = psyOutChanM->sfbEnergy[sfb];
26117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        Word32 sfbEnS = psyOutChanS->sfbEnergy[sfb];
26217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        Word32 maxSfbEn = max(sfbEnM, sfbEnS);
26317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        Word32 maxThr = L_mpy_wx(maxSfbEn, psyOutChanM->sfbMinSnr[sfb]) >> 1;
26417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
26517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if(maxThr >= sfbEnM) {
26617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          psyOutChanM->sfbMinSnr[sfb] = MAX_16;
26717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
26817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        else {
269219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard          shift = norm_l(sfbEnM);
270219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard		  psyOutChanM->sfbMinSnr[sfb] = min(max(psyOutChanM->sfbMinSnr[sfb],
27117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong			  round16(Div_32(maxThr<<shift, sfbEnM << shift))), minSnrLimit);
27217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
27317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
27417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if(maxThr >= sfbEnS) {
27517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          psyOutChanS->sfbMinSnr[sfb] = MAX_16;
27617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
277219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard        else {
27817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  shift = norm_l(sfbEnS);
279219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard          psyOutChanS->sfbMinSnr[sfb] = min(max(psyOutChanS->sfbMinSnr[sfb],
28017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong			  round16(Div_32(maxThr << shift, sfbEnS << shift))), minSnrLimit);
28117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
28217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
28317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
28417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if (sfbEnM > psyOutChanM->sfbSpreadedEnergy[sfb])
28517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          psyOutChanS->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnS, MS_THRSPREAD_COEF);
28617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
28717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if (sfbEnS > psyOutChanS->sfbSpreadedEnergy[sfb])
28817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          psyOutChanM->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnM, MS_THRSPREAD_COEF);
28917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
29017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
29117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
29217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
29317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
29417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
29517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  for(ch=0; ch<nChannels; ch++) {
29617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
29717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
298219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard      Word16 *pahFlag = ahFlag[ch] + sfbGrp;
29917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
30017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
30117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if ((psyOutChan->sfbSpreadedEnergy[sfbGrp+sfb] > psyOutChan->sfbEnergy[sfbGrp+sfb]) ||
30217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            (psyOutChan->sfbEnergy[sfbGrp+sfb] <= psyOutChan->sfbThreshold[sfbGrp+sfb]) ||
30317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            (psyOutChan->sfbMinSnr[sfbGrp+sfb] == MAX_16)) {
30417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          *pahFlag++ = NO_AH;
30517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
30617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        else {
30717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          *pahFlag++ = AH_INACTIVE;
30817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
30917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
31017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      for (sfb=psyOutChan->maxSfbPerGroup; sfb<psyOutChan->sfbPerGroup; sfb++) {
31117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        *pahFlag++ = NO_AH;
31217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
31317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
31417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
31517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
31617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
31717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/********************************************************************************
31817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
31917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name:calcPeNoAH
32017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description: sum the pe data only for bands where avoid hole is inactive
32117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
32217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
32317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic void calcPeNoAH(Word16          *pe,
32417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                       Word16          *constPart,
32517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                       Word16          *nActiveLines,
32617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                       PE_DATA         *peData,
32717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                       Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
32817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                       PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
32917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                       const Word16     nChannels)
33017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
331219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  Word16 ch, sfb, sfbGrp;
33217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  int ipe, iconstPart, inActiveLines;
33317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
33417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  ipe = 0;
33517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  iconstPart = 0;
33617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  inActiveLines = 0;
33717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  for(ch=0; ch<nChannels; ch++) {
33817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
33917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch];
34017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
34117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
34217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
34317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if (ahFlag[ch][sfbGrp+sfb] < AH_ACTIVE) {
34417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          ipe = ipe + peChanData->sfbPe[sfbGrp+sfb];
34517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          iconstPart = iconstPart + peChanData->sfbConstPart[sfbGrp+sfb];
34617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          inActiveLines = inActiveLines + peChanData->sfbNActiveLines[sfbGrp+sfb];
34717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
34817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
34917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
350219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  }
35117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
35217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  *pe = saturate(ipe);
35317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  *constPart = saturate(iconstPart);
35417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  *nActiveLines = saturate(inActiveLines);
35517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
35617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
35717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/********************************************************************************
35817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
35917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name:reduceThresholds
36017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description: apply reduction formula
36117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
36217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
36317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic void reduceThresholds(PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
36417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                             Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
36517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                             Word32           thrExp[MAX_CHANNELS][MAX_GROUPED_SFB],
36617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                             const Word16     nChannels,
36717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                             const Word32     redVal)
36817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
36917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 sfbThrReduced;
370219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  Word32 *psfbEn, *psfbThr;
371219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  Word16 ch, sfb, sfbGrp;
37217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
37317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  for(ch=0; ch<nChannels; ch++) {
37417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
37517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for(sfbGrp=0; sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) {
376219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard 	  psfbEn  = psyOutChan->sfbEnergy + sfbGrp;
377219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard      psfbThr = psyOutChan->sfbThreshold + sfbGrp;
37817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
37917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
38017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if (*psfbEn > *psfbThr) {
38117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          /* threshold reduction formula */
38217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          Word32 tmp = thrExp[ch][sfbGrp+sfb] + redVal;
38317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          tmp = fixmul(tmp, tmp);
38417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          sfbThrReduced = fixmul(tmp, tmp);
38517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          /* avoid holes */
38617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          tmp = L_mpy_ls(*psfbEn, psyOutChan->sfbMinSnr[sfbGrp+sfb]);
38717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
38817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          if ((sfbThrReduced > tmp) &&
38917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong              (ahFlag[ch][sfbGrp+sfb] != NO_AH)){
39017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            sfbThrReduced = max(tmp, *psfbThr);
39117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            ahFlag[ch][sfbGrp+sfb] = AH_ACTIVE;
39217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          }
39317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  *psfbThr = sfbThrReduced;
394219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard        }
395219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
39617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		psfbEn++;  psfbThr++;
39717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
39817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
39917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
40017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
40117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
40217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
40317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/********************************************************************************
40417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
40517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name:correctThresh
40617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description: if pe difference deltaPe between desired pe and real pe is small enough,
40717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*             the difference can be distributed among the scale factor bands.
40817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
40917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
41017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic void correctThresh(PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
41117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
41217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          PE_DATA          *peData,
41317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          Word32           thrExp[MAX_CHANNELS][MAX_GROUPED_SFB],
41417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          const Word32     redVal,
41517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          const Word16     nChannels,
41617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          const Word32     deltaPe)
41717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
41817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 ch, sfb, sfbGrp,shift;
41917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  PSY_OUT_CHANNEL *psyOutChan;
42017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  PE_CHANNEL_DATA *peChanData;
42117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 deltaSfbPe;
422219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  Word32 normFactor;
423219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  Word32 *psfbPeFactors;
42417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 *psfbNActiveLines, *pahFlag;
42517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 sfbEn, sfbThr;
42617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 sfbThrReduced;
42717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
42817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* for each sfb calc relative factors for pe changes */
42917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  normFactor = 1;
43017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  for(ch=0; ch<nChannels; ch++) {
43117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    psyOutChan = &psyOutChannel[ch];
43217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    peChanData = &peData->peChannelData[ch];
43317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
434219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard      psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp;
435219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp;
436219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  pahFlag = ahFlag[ch] + sfbGrp;
43717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
43817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        Word32 redThrExp = thrExp[ch][sfbGrp+sfb] + redVal;
43917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
44017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if (((*pahFlag < AH_ACTIVE) || (deltaPe > 0)) && (redThrExp > 0) ) {
44117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
44217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          *psfbPeFactors = (*psfbNActiveLines) * (0x7fffffff / redThrExp);
44317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          normFactor = L_add(normFactor, *psfbPeFactors);
44417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
44517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        else {
44617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          *psfbPeFactors = 0;
447219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard        }
448219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard		psfbPeFactors++;
44917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		pahFlag++; psfbNActiveLines++;
45017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
45117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
45217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
45317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
45417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
45517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* calculate new thresholds */
45617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  for(ch=0; ch<nChannels; ch++) {
45717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    psyOutChan = &psyOutChannel[ch];
45817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    peChanData = &peData->peChannelData[ch];
45917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
460219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard      psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp;
461219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp;
462219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  pahFlag = ahFlag[ch] + sfbGrp;
46317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
46417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        /* pe difference for this sfb */
46517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        deltaSfbPe = *psfbPeFactors * deltaPe;
46617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
46717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		/* thr3(n) = thr2(n)*2^deltaSfbPe/b(n) */
46817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if (*psfbNActiveLines > 0) {
46917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          /* new threshold */
47017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          Word32 thrFactor;
47117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          sfbEn  = psyOutChan->sfbEnergy[sfbGrp+sfb];
47217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          sfbThr = psyOutChan->sfbThreshold[sfbGrp+sfb];
47317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
47417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong           if(deltaSfbPe >= 0){
47517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            /*
47617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong              reduce threshold
47717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            */
47817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            thrFactor = pow2_xy(L_negate(deltaSfbPe), (normFactor* (*psfbNActiveLines)));
47917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
48017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            sfbThrReduced = L_mpy_ls(sfbThr, round16(thrFactor));
48117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          }
48217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          else {
48317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            /*
48417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong              increase threshold
48517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            */
48617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            thrFactor = pow2_xy(deltaSfbPe, (normFactor * (*psfbNActiveLines)));
48717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
48817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
48917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            if(thrFactor > sfbThr) {
490219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard              shift = norm_l(thrFactor);
49117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong			  sfbThrReduced = Div_32( sfbThr << shift, thrFactor<<shift );
49217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            }
49317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            else {
49417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong              sfbThrReduced = MAX_32;
49517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            }
49617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
49717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          }
49817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
49917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          /* avoid hole */
50017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          sfbEn = L_mpy_ls(sfbEn, psyOutChan->sfbMinSnr[sfbGrp+sfb]);
50117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
50217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          if ((sfbThrReduced > sfbEn) &&
50317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong              (*pahFlag == AH_INACTIVE)) {
50417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            sfbThrReduced = max(sfbEn, sfbThr);
50517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            *pahFlag = AH_ACTIVE;
50617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          }
50717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
50817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          psyOutChan->sfbThreshold[sfbGrp+sfb] = sfbThrReduced;
509219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard        }
510219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
51117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		pahFlag++; psfbNActiveLines++; psfbPeFactors++;
51217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
51317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
51417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
51517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
51617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
51717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
51817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/********************************************************************************
51917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
52017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name:reduceMinSnr
52117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description: if the desired pe can not be reached, reduce pe by reducing minSnr
52217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
52317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
52417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic void reduceMinSnr(PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
52517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                         PE_DATA         *peData,
52617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                         Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
52717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                         const Word16     nChannels,
52817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                         const Word16     desiredPe)
52917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
53017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 ch, sfb, sfbSubWin;
53117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 deltaPe;
53217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
53317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* start at highest freq down to 0 */
53417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  sfbSubWin = psyOutChannel[0].maxSfbPerGroup;
53517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  while (peData->pe > desiredPe && sfbSubWin > 0) {
53617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
53717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    sfbSubWin = sfbSubWin - 1;
53817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    /* loop over all subwindows */
53917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for (sfb=sfbSubWin; sfb<psyOutChannel[0].sfbCnt;
54017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        sfb+=psyOutChannel[0].sfbPerGroup) {
54117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      /* loop over all channels */
542219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard		PE_CHANNEL_DATA* peChan = peData->peChannelData;
543219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard		PSY_OUT_CHANNEL* psyOutCh = psyOutChannel;
54417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		for (ch=0; ch<nChannels; ch++) {
54517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if (ahFlag[ch][sfb] != NO_AH &&
54617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            psyOutCh->sfbMinSnr[sfb] < minSnrLimit) {
54717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          psyOutCh->sfbMinSnr[sfb] = minSnrLimit;
54817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          psyOutCh->sfbThreshold[sfb] =
54917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            L_mpy_ls(psyOutCh->sfbEnergy[sfb], psyOutCh->sfbMinSnr[sfb]);
55017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
55117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          /* calc new pe */
55217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          deltaPe = ((peChan->sfbNLines4[sfb] + (peChan->sfbNLines4[sfb] >> 1)) >> 2) -
55317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong              peChan->sfbPe[sfb];
55417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          peData->pe = peData->pe + deltaPe;
55517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          peChan->pe = peChan->pe + deltaPe;
556219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard        }
55717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		peChan += 1; psyOutCh += 1;
55817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
55917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      /* stop if enough has been saved */
56017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
56117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      if (peData->pe <= desiredPe)
56217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        break;
56317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
56417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
56517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
56617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
56717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/********************************************************************************
56817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
56917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name:allowMoreHoles
57017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description: if the desired pe can not be reached, some more scalefactor bands
57117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*              have to be quantized to zero
57217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
57317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
57417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic void allowMoreHoles(PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
57517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                           PSY_OUT_ELEMENT *psyOutElement,
57617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                           PE_DATA         *peData,
57717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                           Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
57817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                           const AH_PARAM  *ahParam,
57917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                           const Word16     nChannels,
58017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                           const Word16     desiredPe)
58117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
58217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 ch, sfb;
58317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 actPe, shift;
58417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
58517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  actPe = peData->pe;
58617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
58717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* for MS allow hole in the channel with less energy */
58817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
58917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if (nChannels==2 &&
59017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      psyOutChannel[0].windowSequence==psyOutChannel[1].windowSequence) {
59117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    PSY_OUT_CHANNEL *psyOutChanL = &psyOutChannel[0];
59217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    PSY_OUT_CHANNEL *psyOutChanR = &psyOutChannel[1];
59317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for (sfb=0; sfb<psyOutChanL->sfbCnt; sfb++) {
59417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      Word32 minEn;
59517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
59617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      if (psyOutElement->toolsInfo.msMask[sfb]) {
59717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        /* allow hole in side channel ? */
59817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        minEn = L_mpy_ls(psyOutChanL->sfbEnergy[sfb], (minSnrLimit * psyOutChanL->sfbMinSnr[sfb]) >> 16);
59917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
60017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if (ahFlag[1][sfb] != NO_AH &&
60117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            minEn > psyOutChanR->sfbEnergy[sfb]) {
60217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          ahFlag[1][sfb] = NO_AH;
60317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          psyOutChanR->sfbThreshold[sfb] = L_add(psyOutChanR->sfbEnergy[sfb], psyOutChanR->sfbEnergy[sfb]);
60417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          actPe = actPe - peData->peChannelData[1].sfbPe[sfb];
60517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
60617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        /* allow hole in mid channel ? */
60717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        else {
60817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        minEn = L_mpy_ls(psyOutChanR->sfbEnergy[sfb], (minSnrLimit * psyOutChanR->sfbMinSnr[sfb]) >> 16);
60917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
61017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          if (ahFlag[0][sfb]!= NO_AH &&
61117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong              minEn > psyOutChanL->sfbEnergy[sfb]) {
61217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            ahFlag[0][sfb] = NO_AH;
61317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            psyOutChanL->sfbThreshold[sfb] = L_add(psyOutChanL->sfbEnergy[sfb], psyOutChanL->sfbEnergy[sfb]);
61417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            actPe = actPe - peData->peChannelData[0].sfbPe[sfb];
61517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          }
61617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
61717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
61817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if (actPe < desiredPe)
61917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          break;
62017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
62117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
62217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
62317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
62417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* subsequently erase bands */
62517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if (actPe > desiredPe) {
62617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    Word16 startSfb[2];
62717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    Word32 avgEn, minEn;
62817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    Word16 ahCnt;
62917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    Word16 enIdx;
63017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    Word16 enDiff;
63117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    Word32 en[4];
63217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    Word16 minSfb, maxSfb;
63317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    Flag   done;
63417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
63517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    /* do not go below startSfb */
63617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for (ch=0; ch<nChannels; ch++) {
63717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
63817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      if (psyOutChannel[ch].windowSequence != SHORT_WINDOW)
63917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        startSfb[ch] = ahParam->startSfbL;
64017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      else
64117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        startSfb[ch] = ahParam->startSfbS;
64217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
64317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
64417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    avgEn = 0;
64517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    minEn = MAX_32;
64617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    ahCnt = 0;
64717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for (ch=0; ch<nChannels; ch++) {
64817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
64917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      for (sfb=startSfb[ch]; sfb<psyOutChan->sfbCnt; sfb++) {
65017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
65117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if ((ahFlag[ch][sfb] != NO_AH) &&
65217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            (psyOutChan->sfbEnergy[sfb] > psyOutChan->sfbThreshold[sfb])) {
65317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          minEn = min(minEn, psyOutChan->sfbEnergy[sfb]);
65417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfb]);
65517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          ahCnt++;
65617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
65717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
65817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
65917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
66017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if(ahCnt) {
66117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      Word32 iahCnt;
662219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard      shift = norm_l(ahCnt);
66317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  iahCnt = Div_32( 1 << shift, ahCnt << shift );
66417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      avgEn = fixmul(avgEn, iahCnt);
66517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
66617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
66717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    enDiff = iLog4(avgEn) - iLog4(minEn);
66817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    /* calc some energy borders between minEn and avgEn */
66917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for (enIdx=0; enIdx<4; enIdx++) {
67017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      Word32 enFac;
67117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      enFac = ((6-(enIdx << 1)) * enDiff);
67217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      en[enIdx] = fixmul(avgEn, pow2_xy(L_negate(enFac),7*4));
67317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
67417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
67517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    /* start with lowest energy border at highest sfb */
67617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    maxSfb = psyOutChannel[0].sfbCnt - 1;
67717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    minSfb = startSfb[0];
67817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
67917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if (nChannels == 2) {
68017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      maxSfb = max(maxSfb, (psyOutChannel[1].sfbCnt - 1));
68117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      minSfb = min(minSfb, startSfb[1]);
68217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
68317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
68417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    sfb = maxSfb;
68517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    enIdx = 0;
68617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    done = 0;
68717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    while (!done) {
68817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
68917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      for (ch=0; ch<nChannels; ch++) {
69017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
69117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
69217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if (sfb>=startSfb[ch] && sfb<psyOutChan->sfbCnt) {
69317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          /* sfb energy below border ? */
69417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
69517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          if (ahFlag[ch][sfb] != NO_AH && psyOutChan->sfbEnergy[sfb] < en[enIdx]){
69617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            /* allow hole */
69717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            ahFlag[ch][sfb] = NO_AH;
69817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            psyOutChan->sfbThreshold[sfb] = L_add(psyOutChan->sfbEnergy[sfb], psyOutChan->sfbEnergy[sfb]);
69917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            actPe = actPe - peData->peChannelData[ch].sfbPe[sfb];
70017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          }
70117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
70217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          if (actPe < desiredPe) {
70317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            done = 1;
70417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong            break;
70517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          }
70617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
70717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
70817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      sfb = sfb - 1;
70917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
71017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      if (sfb < minSfb) {
71117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        /* restart with next energy border */
71217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        sfb = maxSfb;
71317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        enIdx = enIdx + 1;
71417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
71517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        if (enIdx - 4 >= 0)
71617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          done = 1;
71717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
71817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
71917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
72017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
72117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
72217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/********************************************************************************
72317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
72417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name:adaptThresholdsToPe
72517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description: two guesses for the reduction value and one final correction of the
72617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*              thresholds
72717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
72817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
72917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic void adaptThresholdsToPe(PSY_OUT_CHANNEL     psyOutChannel[MAX_CHANNELS],
73017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                PSY_OUT_ELEMENT    *psyOutElement,
73117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                Word16              logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
73217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                PE_DATA            *peData,
73317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                const Word16        nChannels,
73417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                const Word16        desiredPe,
73517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                AH_PARAM           *ahParam,
73617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                MINSNR_ADAPT_PARAM *msaParam)
73717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
73817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 noRedPe, redPe, redPeNoAH;
73917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 constPart, constPartNoAH;
74017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 nActiveLines, nActiveLinesNoAH;
74117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 desiredPeNoAH;
74217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 redVal, avgThrExp;
74317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 iter;
74417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
74517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  calcThreshExp(peData->thrExp, psyOutChannel, nChannels);
74617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
74717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  adaptMinSnr(psyOutChannel, logSfbEnergy, msaParam, nChannels);
74817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
74917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  initAvoidHoleFlag(peData->ahFlag, psyOutChannel, psyOutElement, nChannels, ahParam);
75017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
75117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  noRedPe = peData->pe;
75217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  constPart = peData->constPart;
75317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  nActiveLines = peData->nActiveLines;
75417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
75517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* first guess of reduction value t^0.25 = 2^((a-pen)/4*b) */
75617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  avgThrExp = pow2_xy((constPart - noRedPe), (nActiveLines << 2));
75717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
75817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* r1 = 2^((a-per)/4*b) - t^0.25 */
75917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  redVal = pow2_xy((constPart - desiredPe), (nActiveLines << 2)) - avgThrExp;
76017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
76117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* reduce thresholds */
76217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal);
76317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
76417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* pe after first guess */
76517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  calcSfbPe(peData, psyOutChannel, nChannels);
76617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  redPe = peData->pe;
76717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
76817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  iter = 0;
76917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  do {
77017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    /* pe for bands where avoid hole is inactive */
77117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    calcPeNoAH(&redPeNoAH, &constPartNoAH, &nActiveLinesNoAH,
77217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong               peData, peData->ahFlag, psyOutChannel, nChannels);
77317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
77417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    desiredPeNoAH = desiredPe -(redPe - redPeNoAH);
77517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
77617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if (desiredPeNoAH < 0) {
77717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      desiredPeNoAH = 0;
77817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
77917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
78017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    /* second guess */
78117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
78217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if (nActiveLinesNoAH > 0) {
78317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
78417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		avgThrExp = pow2_xy((constPartNoAH - redPeNoAH), (nActiveLinesNoAH << 2));
78517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
78617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		redVal = (redVal + pow2_xy((constPartNoAH - desiredPeNoAH), (nActiveLinesNoAH << 2))) - avgThrExp;
78717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
78817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		/* reduce thresholds */
78917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal);
79017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
79117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
79217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    calcSfbPe(peData, psyOutChannel, nChannels);
79317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    redPe = peData->pe;
79417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
79517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    iter = iter+1;
79617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
79717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  } while ((20 * abs_s(redPe - desiredPe) > desiredPe) && (iter < 2));
79817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
79917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
80017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if ((100 * redPe < 115 * desiredPe)) {
80117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    correctThresh(psyOutChannel, peData->ahFlag, peData, peData->thrExp, redVal,
80217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                  nChannels, desiredPe - redPe);
80317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
80417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  else {
80517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    Word16 desiredPe105 = (105 * desiredPe) / 100;
80617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    reduceMinSnr(psyOutChannel, peData, peData->ahFlag,
80717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                 nChannels, desiredPe105);
80817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    allowMoreHoles(psyOutChannel, psyOutElement, peData, peData->ahFlag,
80917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                   ahParam, nChannels, desiredPe105);
81017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
81117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
81217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
81317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
81417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/*****************************************************************************
81517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
81617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name: calcBitSave
81717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description:  Calculates percentage of bit save, see figure below
81817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* returns:
81917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* input:        parameters and bitres-fullness
82017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* output:       percentage of bit save
82117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
82217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*****************************************************************************/
82317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic Word16 calcBitSave(Word16 fillLevel,
82417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          const Word16 clipLow,
82517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          const Word16 clipHigh,
82617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          const Word16 minBitSave,
82717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          const Word16 maxBitSave)
82817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
82917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 bitsave = 0;
83017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
83117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  fillLevel = max(fillLevel, clipLow);
83217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  fillLevel = min(fillLevel, clipHigh);
83317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
834219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  if(clipHigh-clipLow)
83517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  bitsave = (maxBitSave - (((maxBitSave-minBitSave)*(fillLevel-clipLow))/
83617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                              (clipHigh-clipLow)));
83717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
83817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  return (bitsave);
83917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
84017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
84117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
84217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
84317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/*****************************************************************************
84417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
84517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name: calcBitSpend
84617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description:  Calculates percentage of bit spend, see figure below
84717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* returns:
84817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* input:        parameters and bitres-fullness
84917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* output:       percentage of bit spend
85017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
85117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*****************************************************************************/
85217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic Word16 calcBitSpend(Word16 fillLevel,
85317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                           const Word16 clipLow,
85417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                           const Word16 clipHigh,
85517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                           const Word16 minBitSpend,
85617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                           const Word16 maxBitSpend)
85717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
85817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 bitspend = 1;
85917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
86017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  fillLevel = max(fillLevel, clipLow);
86117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  fillLevel = min(fillLevel, clipHigh);
86217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
863219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  if(clipHigh-clipLow)
86417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  bitspend = (minBitSpend + ((maxBitSpend - minBitSpend)*(fillLevel - clipLow) /
86517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                (clipHigh-clipLow)));
86617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
86717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  return (bitspend);
86817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
86917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
87017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
87117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/*****************************************************************************
87217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
87317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name: adjustPeMinMax()
87417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description:  adjusts peMin and peMax parameters over time
87517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* returns:
87617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* input:        current pe, peMin, peMax
87717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* output:       adjusted peMin/peMax
87817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
87917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*****************************************************************************/
88017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic void adjustPeMinMax(const Word16 currPe,
88117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                           Word16      *peMin,
88217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                           Word16      *peMax)
88317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
88417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 minFacHi, maxFacHi, minFacLo, maxFacLo;
88517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 diff;
88617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 minDiff = extract_l(currPe / 6);
88717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  minFacHi = 30;
88817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  maxFacHi = 100;
88917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  minFacLo = 14;
89017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  maxFacLo = 7;
89117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
89217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  diff = currPe - *peMax ;
89317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
89417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if (diff > 0) {
89517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    *peMin = *peMin + ((diff * minFacHi) / 100);
89617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    *peMax = *peMax + ((diff * maxFacHi) / 100);
89717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  } else {
89817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    diff = *peMin - currPe;
89917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
90017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if (diff > 0) {
90117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      *peMin = *peMin - ((diff * minFacLo) / 100);
90217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      *peMax = *peMax - ((diff * maxFacLo) / 100);
90317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    } else {
90417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      *peMin = *peMin + ((currPe - *peMin) * minFacHi / 100);
90517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      *peMax = *peMax - ((*peMax - currPe) * maxFacLo / 100);
90617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
90717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
90817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
90917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
91017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if ((*peMax - *peMin) < minDiff) {
91117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    Word16 partLo, partHi;
91217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
91317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    partLo = max(0, (currPe - *peMin));
91417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    partHi = max(0, (*peMax - currPe));
91517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
91617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    *peMax = currPe + ((partHi * minDiff) / (partLo + partHi));
91717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    *peMin = currPe - ((partLo * minDiff) / (partLo + partHi));
91817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    *peMin = max(0, *peMin);
91917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
92017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
92117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
92217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
92317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/*****************************************************************************
92417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
92517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name: BitresCalcBitFac
92617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description:  calculates factor of spending bits for one frame
92717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*                1.0 : take all frame dynpart bits
92817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*                >1.0 : take all frame dynpart bits + bitres
92917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*                <1.0 : put bits in bitreservoir
93017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*  returns:      BitFac*100
93117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*  input:        bitres-fullness, pe, blockType, parameter-settings
93217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*  output:
93317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
93417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*****************************************************************************/
93517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic Word16 bitresCalcBitFac( const Word16   bitresBits,
93617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                const Word16   maxBitresBits,
93717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                const Word16   pe,
93817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                const Word16   windowSequence,
93917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                const Word16   avgBits,
94017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                const Word16   maxBitFac,
94117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                ADJ_THR_STATE *AdjThr,
94217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                ATS_ELEMENT   *adjThrChan)
94317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
94417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  BRES_PARAM *bresParam;
94517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 pex;
94617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 fillLevel;
94717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 bitSave, bitSpend, bitresFac;
94817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
94917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  fillLevel = extract_l((100* bitresBits) / maxBitresBits);
95017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
95117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if (windowSequence != SHORT_WINDOW)
95217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    bresParam = &(AdjThr->bresParamLong);
95317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  else
95417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    bresParam = &(AdjThr->bresParamShort);
95517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
95617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  pex = max(pe, adjThrChan->peMin);
95717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  pex = min(pex,adjThrChan->peMax);
95817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
95917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  bitSave = calcBitSave(fillLevel,
96017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        bresParam->clipSaveLow, bresParam->clipSaveHigh,
96117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        bresParam->minBitSave, bresParam->maxBitSave);
96217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
96317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  bitSpend = calcBitSpend(fillLevel,
96417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          bresParam->clipSpendLow, bresParam->clipSpendHigh,
96517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          bresParam->minBitSpend, bresParam->maxBitSpend);
96617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
967219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  if(adjThrChan->peMax != adjThrChan->peMin)
96817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	bitresFac = (100 - bitSave) + extract_l(((bitSpend + bitSave) * (pex - adjThrChan->peMin)) /
96917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                    (adjThrChan->peMax - adjThrChan->peMin));
97017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  else
97117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	bitresFac = 0x7fff;
97217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
97317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  bitresFac = min(bitresFac,
97417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                    (100-30 + extract_l((100 * bitresBits) / avgBits)));
97517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
97617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  bitresFac = min(bitresFac, maxBitFac);
97717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
97817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax);
97917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
98017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  return bitresFac;
98117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
98217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
98317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/*****************************************************************************
98417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
98517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name: AdjThrInit
98617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description:  init thresholds parameter
98717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
98817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*****************************************************************************/
98917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongvoid AdjThrInit(ADJ_THR_STATE *hAdjThr,
99017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                const Word32   meanPe,
99117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                Word32         chBitrate)
99217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
99317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  ATS_ELEMENT* atsElem = &hAdjThr->adjThrStateElem;
99417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam;
99517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
99617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* common for all elements: */
99717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* parameters for bitres control */
99817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamLong.clipSaveLow   =  20;
99917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamLong.clipSaveHigh  =  95;
100017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamLong.minBitSave    =  -5;
100117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamLong.maxBitSave    =  30;
100217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamLong.clipSpendLow  =  20;
100317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamLong.clipSpendHigh =  95;
100417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamLong.minBitSpend   = -10;
100517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamLong.maxBitSpend   =  40;
100617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
100717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamShort.clipSaveLow   =  20;
100817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamShort.clipSaveHigh  =  75;
100917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamShort.minBitSave    =   0;
101017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamShort.maxBitSave    =  20;
101117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamShort.clipSpendLow  =  20;
101217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamShort.clipSpendHigh =  75;
101317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamShort.minBitSpend   = -5;
101417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  hAdjThr->bresParamShort.maxBitSpend   =  50;
101517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
101617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* specific for each element: */
101717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
101817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* parameters for bitres control */
101917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  atsElem->peMin = extract_l(((80*meanPe) / 100));
102017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  atsElem->peMax = extract_l(((120*meanPe) / 100));
102117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
102217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* additional pe offset to correct pe2bits for low bitrates */
102317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  atsElem->peOffset = 0;
102417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if (chBitrate < 32000) {
102517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    atsElem->peOffset = max(50, (100 - extract_l((100 * chBitrate) / 32000)));
102617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
102717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
102817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* avoid hole parameters */
102917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if (chBitrate > 20000) {
103017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    atsElem->ahParam.modifyMinSnr = TRUE;
103117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    atsElem->ahParam.startSfbL = 15;
103217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    atsElem->ahParam.startSfbS = 3;
103317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
103417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  else {
103517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    atsElem->ahParam.modifyMinSnr = FALSE;
103617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    atsElem->ahParam.startSfbL = 0;
103717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    atsElem->ahParam.startSfbS = 0;
103817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
103917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
104017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* minSnr adaptation */
104117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* maximum reduction of minSnr goes down to minSnr^maxRed */
104217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  msaParam->maxRed = 0x20000000;     /* *0.25f /
104317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* start adaptation of minSnr for avgEn/sfbEn > startRatio */
104417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  msaParam->startRatio = 0x0ccccccd; /* 10 */
104517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* maximum minSnr reduction to minSnr^maxRed is reached for
104617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong     avgEn/sfbEn >= maxRatio */
104717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  msaParam->maxRatio =  0x0020c49c; /* 1000 */
104817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* helper variables to interpolate minSnr reduction for
104917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong     avgEn/sfbEn between startRatio and maxRatio */
105017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
105117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  msaParam->redRatioFac = 0xfb333333; /* -0.75/20 */
105217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
105317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  msaParam->redOffs = 0x30000000;  /* msaParam->redRatioFac * 10*log10(msaParam->startRatio) */
105417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
105517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
105617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* pe correction */
105717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  atsElem->peLast = 0;
105817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  atsElem->dynBitsLast = 0;
105917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  atsElem->peCorrectionFactor = 100; /* 1.0 */
106017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
106117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
106217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
106317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/*****************************************************************************
106417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
106517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name: calcPeCorrection
106617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description:  calculates the desired perceptual entropy factor
106717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*				It is between 0.85 and 1.15
106817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
106917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*****************************************************************************/
107017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic void calcPeCorrection(Word16 *correctionFac,
107117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                             const Word16 peAct,
107217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                             const Word16 peLast,
107317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                             const Word16 bitsLast)
107417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
107517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 peAct100 = 100 * peAct;
107617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 peLast100 = 100 * peLast;
107717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 peBitsLast = bits2pe(bitsLast);
107817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
107917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if ((bitsLast > 0) &&
108017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      (peAct100 < (150 * peLast)) &&  (peAct100 > (70 * peLast)) &&
108117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      ((120 * peBitsLast) > peLast100 ) && (( 65 * peBitsLast) < peLast100))
108217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    {
108317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      Word16 newFac = (100 * peLast) / peBitsLast;
108417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      /* dead zone */
108517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
108617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      if (newFac < 100) {
108717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        newFac = min(((110 * newFac) / 100), 100);
108817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        newFac = max(newFac, 85);
108917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
109017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      else {
109117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        newFac = max(((90 * newFac) / 100), 100);
109217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        newFac = min(newFac, 115);
109317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
109417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
109517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      if ((newFac > 100 && *correctionFac < 100) ||
109617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          (newFac < 100 && *correctionFac > 100)) {
109717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        *correctionFac = 100;
109817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
109917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      /* faster adaptation towards 1.0, slower in the other direction */
110017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
110117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      if ((*correctionFac < 100 && newFac < *correctionFac) ||
110217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          (*correctionFac > 100 && newFac > *correctionFac))
110317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        *correctionFac = (85 * *correctionFac + 15 * newFac) / 100;
110417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      else
110517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        *correctionFac = (70 * *correctionFac + 30 * newFac) / 100;
110617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      *correctionFac = min(*correctionFac, 115);
110717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      *correctionFac = max(*correctionFac, 85);
110817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
110917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  else {
111017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    *correctionFac = 100;
111117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
111217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
111317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
111417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/********************************************************************************
111517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
111617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name: AdjustThresholds
111717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description:  Adjust thresholds to the desired bitrate
111817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
111917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
112017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongvoid AdjustThresholds(ADJ_THR_STATE   *adjThrState,
112117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                      ATS_ELEMENT     *AdjThrStateElement,
112217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                      PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
112317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                      PSY_OUT_ELEMENT *psyOutElement,
112417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                      Word16          *chBitDistribution,
112517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                      Word16           logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
112617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                      Word16           sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
112717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                      QC_OUT_ELEMENT  *qcOE,
112817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong					  ELEMENT_BITS	  *elBits,
112917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong					  const Word16     nChannels,
113017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                      const Word16     maxBitFac)
113117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
113217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  PE_DATA peData;
113317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 noRedPe, grantedPe, grantedPeCorr;
113417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 curWindowSequence;
113517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 bitFactor;
113617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 avgBits = (elBits->averageBits - (qcOE->staticBitsUsed + qcOE->ancBitsUsed));
113717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 bitresBits = elBits->bitResLevel;
113817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 maxBitresBits = elBits->maxBits;
113917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 sideInfoBits = (qcOE->staticBitsUsed + qcOE->ancBitsUsed);
114017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 ch;
114117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
114217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  prepareSfbPe(&peData, psyOutChannel, logSfbEnergy, sfbNRelevantLines, nChannels, AdjThrStateElement->peOffset);
114317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
114417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* pe without reduction */
114517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  calcSfbPe(&peData, psyOutChannel, nChannels);
114617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  noRedPe = peData.pe;
114717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
114817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
114917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  curWindowSequence = LONG_WINDOW;
115017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
115117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if (nChannels == 2) {
115217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
115317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if ((psyOutChannel[0].windowSequence == SHORT_WINDOW) ||
115417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        (psyOutChannel[1].windowSequence == SHORT_WINDOW)) {
115517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      curWindowSequence = SHORT_WINDOW;
115617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
115717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
115817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  else {
115917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    curWindowSequence = psyOutChannel[0].windowSequence;
116017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
116117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
116217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
116317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* bit factor */
116417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  bitFactor = bitresCalcBitFac(bitresBits, maxBitresBits, noRedPe+5*sideInfoBits,
116517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                               curWindowSequence, avgBits, maxBitFac,
116617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                               adjThrState,
116717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                               AdjThrStateElement);
116817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
116917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* desired pe */
117017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  grantedPe = ((bitFactor * bits2pe(avgBits)) / 100);
117117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
117217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* correction of pe value */
117317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  calcPeCorrection(&(AdjThrStateElement->peCorrectionFactor),
117417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                   min(grantedPe, noRedPe),
117517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                   AdjThrStateElement->peLast,
117617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                   AdjThrStateElement->dynBitsLast);
117717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  grantedPeCorr = (grantedPe * AdjThrStateElement->peCorrectionFactor) / 100;
117817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
117917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
118017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if (grantedPeCorr < noRedPe && noRedPe > peData.offset) {
118117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    /* calc threshold necessary for desired pe */
118217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    adaptThresholdsToPe(psyOutChannel,
118317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        psyOutElement,
118417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        logSfbEnergy,
118517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        &peData,
118617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        nChannels,
118717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        grantedPeCorr,
118817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        &AdjThrStateElement->ahParam,
118917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        &AdjThrStateElement->minSnrAdaptParam);
119017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
119117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
119217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* calculate relative distribution */
119317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  for (ch=0; ch<nChannels; ch++) {
119417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    Word16 peOffsDiff = peData.pe - peData.offset;
119517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    chBitDistribution[ch] = 200;
119617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
119717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if (peOffsDiff > 0) {
119817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      Word32 temp = 1000 - (nChannels * 200);
1199219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard      chBitDistribution[ch] = chBitDistribution[ch] +
120017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  (temp * peData.peChannelData[ch].pe) / peOffsDiff;
120117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
120217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
120317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
120417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* store pe */
120517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  qcOE->pe = noRedPe;
120617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
120717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* update last pe */
120817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  AdjThrStateElement->peLast = grantedPe;
120917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
121017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
121117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/********************************************************************************
121217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
121317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name: AdjThrUpdate
121417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description:  save dynBitsUsed for correction of bits2pe relation
121517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
121617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
121717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongvoid AdjThrUpdate(ATS_ELEMENT *AdjThrStateElement,
121817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                  const Word16 dynBitsUsed)
121917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
122017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  AdjThrStateElement->dynBitsLast = dynBitsUsed;
122117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
122217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
122317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
1224