adj_thr.c revision b5325c8a8fff4d735c24d9a8138e4213ee0833d5
1/*
2 ** Copyright 2003-2010, VisualOn, Inc.
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 **     http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16/*******************************************************************************
17	File:		adj_thr.c
18
19	Content:	Threshold compensation functions
20
21*******************************************************************************/
22
23/* Include system headers before local headers - the local headers
24 * redefine __inline, which can mess up definitions in libc headers if
25 * they happen to use __inline. */
26#include <string.h>
27#include "basic_op.h"
28#include "oper_32b.h"
29#include "adj_thr_data.h"
30#include "adj_thr.h"
31#include "qc_data.h"
32#include "line_pe.h"
33
34
35#define  minSnrLimit    0x6666 /* 1 dB */
36#define  PEBITS_COEF	0x170a /* 0.18*(1 << 15)*/
37
38#define  HOLE_THR_LONG	0x2873	/* 0.316*(1 << 15) */
39#define  HOLE_THR_SHORT 0x4000  /* 0.5  *(1 << 15) */
40
41#define  MS_THRSPREAD_COEF 0x7333  /* 0.9 * (1 << 15) */
42
43#define	 MIN_SNR_COEF	   0x651f  /* 3.16* (1 << (15 - 2)) */
44
45/* values for avoid hole flag */
46enum _avoid_hole_state {
47  NO_AH              =0,
48  AH_INACTIVE        =1,
49  AH_ACTIVE          =2
50};
51
52/********************************************************************************
53*
54* function name:bits2pe
55* description: convert from bits to pe
56*			   pe = 1.18*desiredBits
57*
58**********************************************************************************/
59Word16 bits2pe(const Word16 bits) {
60  return (bits + ((PEBITS_COEF * bits) >> 15));
61}
62
63/********************************************************************************
64*
65* function name:calcThreshExp
66* description: loudness calculation (threshold to the power of redExp)
67*			   thr(n)^0.25
68*
69**********************************************************************************/
70static void calcThreshExp(Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB],
71                          PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
72                          const Word16 nChannels)
73{
74  Word16 ch, sfb, sfbGrp;
75  Word32 *pthrExp, *psfbThre;
76  for (ch=0; ch<nChannels; ch++) {
77    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
78	 for(sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; sfbGrp+= psyOutChan->sfbPerGroup)
79	  pthrExp = &(thrExp[ch][sfbGrp]);
80	  psfbThre = psyOutChan->sfbThreshold + sfbGrp;
81	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
82		*pthrExp = rsqrt(rsqrt(*psfbThre,INT_BITS),INT_BITS);
83		pthrExp++; psfbThre++;
84      }
85  }
86}
87
88/********************************************************************************
89*
90* function name:adaptMinSnr
91* description: reduce minSnr requirements for bands with relative low energies
92*
93**********************************************************************************/
94static void adaptMinSnr(PSY_OUT_CHANNEL     psyOutChannel[MAX_CHANNELS],
95                        Word16              logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
96                        MINSNR_ADAPT_PARAM *msaParam,
97                        const Word16        nChannels)
98{
99  Word16 ch, sfb, sfbOffs, shift;
100  Word32 nSfb, avgEn;
101  Word16 log_avgEn = 0;
102  Word32 startRatio_x_avgEn = 0;
103
104
105  for (ch=0; ch<nChannels; ch++) {
106    PSY_OUT_CHANNEL* psyOutChan = &psyOutChannel[ch];
107
108    /* calc average energy per scalefactor band */
109    avgEn = 0;
110    nSfb = 0;
111    for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) {
112      for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
113        avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfbOffs+sfb]);
114        nSfb = nSfb + 1;
115      }
116    }
117
118    if (nSfb > 0) {
119	  avgEn = avgEn / nSfb;
120
121      log_avgEn = iLog4(avgEn);
122      startRatio_x_avgEn = fixmul(msaParam->startRatio, avgEn);
123    }
124
125
126    /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */
127    for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) {
128      for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
129        if (psyOutChan->sfbEnergy[sfbOffs+sfb] < startRatio_x_avgEn) {
130          Word16 dbRatio, minSnrRed;
131          Word32 snrRed;
132          Word16 newMinSnr;
133
134          dbRatio = log_avgEn - logSfbEnergy[ch][sfbOffs+sfb];
135          dbRatio = dbRatio + (dbRatio << 1);
136
137          minSnrRed = 110 - ((dbRatio + (dbRatio << 1)) >> 2);
138          minSnrRed = max(minSnrRed, 20); /* 110: (0.375(redOffs)+1)*80,
139                                               3: 0.00375(redRatioFac)*80
140                                               20: 0.25(maxRed) * 80 */
141
142          snrRed = minSnrRed * iLog4((psyOutChan->sfbMinSnr[sfbOffs+sfb] << 16));
143          /*
144             snrRedI si now scaled by 80 (minSnrRed) and 4 (ffr_iLog4)
145          */
146
147          newMinSnr = round16(pow2_xy(snrRed,80*4));
148
149          psyOutChan->sfbMinSnr[sfbOffs+sfb] = min(newMinSnr, minSnrLimit);
150        }
151      }
152    }
153  }
154
155}
156
157
158/********************************************************************************
159*
160* function name:initAvoidHoleFlag
161* description: determine bands where avoid hole is not necessary resp. possible
162*
163**********************************************************************************/
164static void initAvoidHoleFlag(Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
165                              PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
166                              PSY_OUT_ELEMENT* psyOutElement,
167                              const Word16 nChannels,
168                              AH_PARAM *ahParam)
169{
170  Word16 ch, sfb, sfbGrp, shift;
171  Word32 threshold;
172  Word32* psfbSpreadEn;
173
174  for (ch=0; ch<nChannels; ch++) {
175    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
176
177    if (psyOutChan->windowSequence != SHORT_WINDOW) {
178      for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
179         psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp;
180		 for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
181			*psfbSpreadEn = *psfbSpreadEn >> 1;  /* 0.5 */
182			++psfbSpreadEn;
183        }
184      }
185    }
186    else {
187      for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
188		psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp;
189        for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
190          *psfbSpreadEn = (*psfbSpreadEn >> 1) + (*psfbSpreadEn >> 3);  /* 0.63 */
191		  ++psfbSpreadEn;
192        }
193      }
194    }
195  }
196
197  /* increase minSnr for local peaks, decrease it for valleys */
198  if (ahParam->modifyMinSnr) {
199    for(ch=0; ch<nChannels; ch++) {
200      PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
201
202      if (psyOutChan->windowSequence != SHORT_WINDOW)
203        threshold = HOLE_THR_LONG;
204      else
205        threshold = HOLE_THR_SHORT;
206
207      for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
208        Word16 *psfbMinSnr = psyOutChan->sfbMinSnr + sfbGrp;
209		for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
210          Word32 sfbEn, sfbEnm1, sfbEnp1, avgEn;
211
212          if (sfb > 0)
213            sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp+sfb-1];
214          else
215            sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp];
216
217          if (sfb < (psyOutChan->maxSfbPerGroup-1))
218            sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb+1];
219          else
220            sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb];
221          avgEn = (sfbEnm1 + sfbEnp1) >> 1;
222          sfbEn = psyOutChan->sfbEnergy[sfbGrp+sfb];
223
224          if (sfbEn > avgEn && avgEn > 0) {
225            Word32 tmpMinSnr;
226            shift = norm_l(sfbEn);
227			tmpMinSnr = Div_32(L_mpy_ls(avgEn, minSnrLimit) << shift, sfbEn << shift );
228            tmpMinSnr = max(tmpMinSnr, HOLE_THR_LONG);
229            tmpMinSnr = max(tmpMinSnr, threshold);
230            *psfbMinSnr = min(*psfbMinSnr, tmpMinSnr);
231          }
232          /* valley ? */
233
234          if ((sfbEn < (avgEn >> 1)) && (sfbEn > 0)) {
235            Word32 tmpMinSnr;
236            Word32 minSnrEn = L_mpy_wx(avgEn, *psfbMinSnr);
237
238            if(minSnrEn < sfbEn) {
239			  shift = norm_l(sfbEn);
240              tmpMinSnr = Div_32( minSnrEn << shift, sfbEn<<shift);
241            }
242            else {
243              tmpMinSnr = MAX_16;
244            }
245            tmpMinSnr = min(minSnrLimit, tmpMinSnr);
246
247            *psfbMinSnr =
248              (min((tmpMinSnr >>  2), mult(*psfbMinSnr, MIN_SNR_COEF)) << 2);
249          }
250		  psfbMinSnr++;
251        }
252      }
253    }
254  }
255
256  /* stereo: adapt the minimum requirements sfbMinSnr of mid and
257     side channels */
258
259  if (nChannels == 2) {
260    PSY_OUT_CHANNEL *psyOutChanM = &psyOutChannel[0];
261    PSY_OUT_CHANNEL *psyOutChanS = &psyOutChannel[1];
262    for (sfb=0; sfb<psyOutChanM->sfbCnt; sfb++) {
263      if (psyOutElement->toolsInfo.msMask[sfb]) {
264        Word32 sfbEnM = psyOutChanM->sfbEnergy[sfb];
265        Word32 sfbEnS = psyOutChanS->sfbEnergy[sfb];
266        Word32 maxSfbEn = max(sfbEnM, sfbEnS);
267        Word32 maxThr = L_mpy_wx(maxSfbEn, psyOutChanM->sfbMinSnr[sfb]) >> 1;
268
269        if(maxThr >= sfbEnM) {
270          psyOutChanM->sfbMinSnr[sfb] = MAX_16;
271        }
272        else {
273          shift = norm_l(sfbEnM);
274		  psyOutChanM->sfbMinSnr[sfb] = min(max(psyOutChanM->sfbMinSnr[sfb],
275			  round16(Div_32(maxThr<<shift, sfbEnM << shift))), minSnrLimit);
276        }
277
278        if(maxThr >= sfbEnS) {
279          psyOutChanS->sfbMinSnr[sfb] = MAX_16;
280        }
281        else {
282		  shift = norm_l(sfbEnS);
283          psyOutChanS->sfbMinSnr[sfb] = min(max(psyOutChanS->sfbMinSnr[sfb],
284			  round16(Div_32(maxThr << shift, sfbEnS << shift))), minSnrLimit);
285        }
286
287
288        if (sfbEnM > psyOutChanM->sfbSpreadedEnergy[sfb])
289          psyOutChanS->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnS, MS_THRSPREAD_COEF);
290
291        if (sfbEnS > psyOutChanS->sfbSpreadedEnergy[sfb])
292          psyOutChanM->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnM, MS_THRSPREAD_COEF);
293      }
294    }
295  }
296
297
298  /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
299  for(ch=0; ch<nChannels; ch++) {
300    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
301    for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
302      Word16 *pahFlag = ahFlag[ch] + sfbGrp;
303	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
304
305        if ((psyOutChan->sfbSpreadedEnergy[sfbGrp+sfb] > psyOutChan->sfbEnergy[sfbGrp+sfb]) ||
306            (psyOutChan->sfbEnergy[sfbGrp+sfb] <= psyOutChan->sfbThreshold[sfbGrp+sfb]) ||
307            (psyOutChan->sfbMinSnr[sfbGrp+sfb] == MAX_16)) {
308          *pahFlag++ = NO_AH;
309        }
310        else {
311          *pahFlag++ = AH_INACTIVE;
312        }
313      }
314      for (sfb=psyOutChan->maxSfbPerGroup; sfb<psyOutChan->sfbPerGroup; sfb++) {
315        *pahFlag++ = NO_AH;
316      }
317    }
318  }
319}
320
321/********************************************************************************
322*
323* function name:calcPeNoAH
324* description: sum the pe data only for bands where avoid hole is inactive
325*
326**********************************************************************************/
327static void calcPeNoAH(Word16          *pe,
328                       Word16          *constPart,
329                       Word16          *nActiveLines,
330                       PE_DATA         *peData,
331                       Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
332                       PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
333                       const Word16     nChannels)
334{
335  Word16 ch, sfb, sfbGrp;
336  int ipe, iconstPart, inActiveLines;
337
338  ipe = 0;
339  iconstPart = 0;
340  inActiveLines = 0;
341  for(ch=0; ch<nChannels; ch++) {
342    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
343    PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch];
344    for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
345      for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
346
347        if (ahFlag[ch][sfbGrp+sfb] < AH_ACTIVE) {
348          ipe = ipe + peChanData->sfbPe[sfbGrp+sfb];
349          iconstPart = iconstPart + peChanData->sfbConstPart[sfbGrp+sfb];
350          inActiveLines = inActiveLines + peChanData->sfbNActiveLines[sfbGrp+sfb];
351        }
352      }
353    }
354  }
355
356  *pe = saturate(ipe);
357  *constPart = saturate(iconstPart);
358  *nActiveLines = saturate(inActiveLines);
359}
360
361/********************************************************************************
362*
363* function name:reduceThresholds
364* description: apply reduction formula
365*
366**********************************************************************************/
367static void reduceThresholds(PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
368                             Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
369                             Word32           thrExp[MAX_CHANNELS][MAX_GROUPED_SFB],
370                             const Word16     nChannels,
371                             const Word32     redVal)
372{
373  Word32 sfbThrReduced;
374  Word32 *psfbEn, *psfbThr;
375  Word16 ch, sfb, sfbGrp;
376
377  for(ch=0; ch<nChannels; ch++) {
378    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
379    for(sfbGrp=0; sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) {
380 	  psfbEn  = psyOutChan->sfbEnergy + sfbGrp;
381      psfbThr = psyOutChan->sfbThreshold + sfbGrp;
382	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
383
384        if (*psfbEn > *psfbThr) {
385          /* threshold reduction formula */
386          Word32 tmp = thrExp[ch][sfbGrp+sfb] + redVal;
387          tmp = fixmul(tmp, tmp);
388          sfbThrReduced = fixmul(tmp, tmp);
389          /* avoid holes */
390          tmp = L_mpy_ls(*psfbEn, psyOutChan->sfbMinSnr[sfbGrp+sfb]);
391
392          if ((sfbThrReduced > tmp) &&
393              (ahFlag[ch][sfbGrp+sfb] != NO_AH)){
394            sfbThrReduced = max(tmp, *psfbThr);
395            ahFlag[ch][sfbGrp+sfb] = AH_ACTIVE;
396          }
397		  *psfbThr = sfbThrReduced;
398        }
399
400		psfbEn++;  psfbThr++;
401      }
402    }
403  }
404}
405
406
407/********************************************************************************
408*
409* function name:correctThresh
410* description: if pe difference deltaPe between desired pe and real pe is small enough,
411*             the difference can be distributed among the scale factor bands.
412*
413**********************************************************************************/
414static void correctThresh(PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
415                          Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
416                          PE_DATA          *peData,
417                          Word32           thrExp[MAX_CHANNELS][MAX_GROUPED_SFB],
418                          const Word32     redVal,
419                          const Word16     nChannels,
420                          const Word32     deltaPe)
421{
422  Word16 ch, sfb, sfbGrp,shift;
423  PSY_OUT_CHANNEL *psyOutChan;
424  PE_CHANNEL_DATA *peChanData;
425  Word32 deltaSfbPe;
426  Word32 normFactor;
427  Word32 *psfbPeFactors;
428  Word16 *psfbNActiveLines, *pahFlag;
429  Word32 sfbEn, sfbThr;
430  Word32 sfbThrReduced;
431
432  /* for each sfb calc relative factors for pe changes */
433  normFactor = 1;
434  for(ch=0; ch<nChannels; ch++) {
435    psyOutChan = &psyOutChannel[ch];
436    peChanData = &peData->peChannelData[ch];
437    for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
438      psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp;
439	  psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp;
440	  pahFlag = ahFlag[ch] + sfbGrp;
441	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
442        Word32 redThrExp = thrExp[ch][sfbGrp+sfb] + redVal;
443
444        if (((*pahFlag < AH_ACTIVE) || (deltaPe > 0)) && (redThrExp > 0) && (redThrExp >= *psfbNActiveLines)) {
445
446          *psfbPeFactors = (*psfbNActiveLines) * (0x7fffffff / redThrExp);
447          normFactor = L_add(normFactor, *psfbPeFactors);
448        }
449        else {
450          *psfbPeFactors = 0;
451        }
452		psfbPeFactors++;
453		pahFlag++; psfbNActiveLines++;
454      }
455    }
456  }
457
458
459  /* calculate new thresholds */
460  for(ch=0; ch<nChannels; ch++) {
461    psyOutChan = &psyOutChannel[ch];
462    peChanData = &peData->peChannelData[ch];
463    for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
464      psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp;
465	  psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp;
466	  pahFlag = ahFlag[ch] + sfbGrp;
467	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
468        /* pe difference for this sfb */
469        deltaSfbPe = *psfbPeFactors * deltaPe;
470
471		/* thr3(n) = thr2(n)*2^deltaSfbPe/b(n) */
472        if (*psfbNActiveLines > 0 && (normFactor* (*psfbNActiveLines)) != 0) {
473          /* new threshold */
474          Word32 thrFactor;
475          sfbEn  = psyOutChan->sfbEnergy[sfbGrp+sfb];
476          sfbThr = psyOutChan->sfbThreshold[sfbGrp+sfb];
477
478           if(deltaSfbPe >= 0){
479            /*
480              reduce threshold
481            */
482            thrFactor = pow2_xy(L_negate(deltaSfbPe), (normFactor* (*psfbNActiveLines)));
483
484            sfbThrReduced = L_mpy_ls(sfbThr, round16(thrFactor));
485          }
486          else {
487            /*
488              increase threshold
489            */
490            thrFactor = pow2_xy(deltaSfbPe, (normFactor * (*psfbNActiveLines)));
491
492
493            if(thrFactor > sfbThr) {
494              shift = norm_l(thrFactor);
495			  sfbThrReduced = Div_32( sfbThr << shift, thrFactor<<shift );
496            }
497            else {
498              sfbThrReduced = MAX_32;
499            }
500
501          }
502
503          /* avoid hole */
504          sfbEn = L_mpy_ls(sfbEn, psyOutChan->sfbMinSnr[sfbGrp+sfb]);
505
506          if ((sfbThrReduced > sfbEn) &&
507              (*pahFlag == AH_INACTIVE)) {
508            sfbThrReduced = max(sfbEn, sfbThr);
509            *pahFlag = AH_ACTIVE;
510          }
511
512          psyOutChan->sfbThreshold[sfbGrp+sfb] = sfbThrReduced;
513        }
514
515		pahFlag++; psfbNActiveLines++; psfbPeFactors++;
516      }
517    }
518  }
519}
520
521
522/********************************************************************************
523*
524* function name:reduceMinSnr
525* description: if the desired pe can not be reached, reduce pe by reducing minSnr
526*
527**********************************************************************************/
528static void reduceMinSnr(PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
529                         PE_DATA         *peData,
530                         Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
531                         const Word16     nChannels,
532                         const Word16     desiredPe)
533{
534  Word16 ch, sfb, sfbSubWin;
535  Word16 deltaPe;
536
537  /* start at highest freq down to 0 */
538  sfbSubWin = psyOutChannel[0].maxSfbPerGroup;
539  while (peData->pe > desiredPe && sfbSubWin > 0) {
540
541    sfbSubWin = sfbSubWin - 1;
542    /* loop over all subwindows */
543    for (sfb=sfbSubWin; sfb<psyOutChannel[0].sfbCnt;
544        sfb+=psyOutChannel[0].sfbPerGroup) {
545      /* loop over all channels */
546		PE_CHANNEL_DATA* peChan = peData->peChannelData;
547		PSY_OUT_CHANNEL* psyOutCh = psyOutChannel;
548		for (ch=0; ch<nChannels; ch++) {
549        if (ahFlag[ch][sfb] != NO_AH &&
550            psyOutCh->sfbMinSnr[sfb] < minSnrLimit) {
551          psyOutCh->sfbMinSnr[sfb] = minSnrLimit;
552          psyOutCh->sfbThreshold[sfb] =
553            L_mpy_ls(psyOutCh->sfbEnergy[sfb], psyOutCh->sfbMinSnr[sfb]);
554
555          /* calc new pe */
556          deltaPe = ((peChan->sfbNLines4[sfb] + (peChan->sfbNLines4[sfb] >> 1)) >> 2) -
557              peChan->sfbPe[sfb];
558          peData->pe = peData->pe + deltaPe;
559          peChan->pe = peChan->pe + deltaPe;
560        }
561		peChan += 1; psyOutCh += 1;
562      }
563      /* stop if enough has been saved */
564
565      if (peData->pe <= desiredPe)
566        break;
567    }
568  }
569}
570
571/********************************************************************************
572*
573* function name:allowMoreHoles
574* description: if the desired pe can not be reached, some more scalefactor bands
575*              have to be quantized to zero
576*
577**********************************************************************************/
578static void allowMoreHoles(PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
579                           PSY_OUT_ELEMENT *psyOutElement,
580                           PE_DATA         *peData,
581                           Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
582                           const AH_PARAM  *ahParam,
583                           const Word16     nChannels,
584                           const Word16     desiredPe)
585{
586  Word16 ch, sfb;
587  Word16 actPe, shift;
588
589  actPe = peData->pe;
590
591  /* for MS allow hole in the channel with less energy */
592
593  if (nChannels==2 &&
594      psyOutChannel[0].windowSequence==psyOutChannel[1].windowSequence) {
595    PSY_OUT_CHANNEL *psyOutChanL = &psyOutChannel[0];
596    PSY_OUT_CHANNEL *psyOutChanR = &psyOutChannel[1];
597    for (sfb=0; sfb<psyOutChanL->sfbCnt; sfb++) {
598      Word32 minEn;
599
600      if (psyOutElement->toolsInfo.msMask[sfb]) {
601        /* allow hole in side channel ? */
602        minEn = L_mpy_ls(psyOutChanL->sfbEnergy[sfb], (minSnrLimit * psyOutChanL->sfbMinSnr[sfb]) >> 16);
603
604        if (ahFlag[1][sfb] != NO_AH &&
605            minEn > psyOutChanR->sfbEnergy[sfb]) {
606          ahFlag[1][sfb] = NO_AH;
607          psyOutChanR->sfbThreshold[sfb] = L_add(psyOutChanR->sfbEnergy[sfb], psyOutChanR->sfbEnergy[sfb]);
608          actPe = actPe - peData->peChannelData[1].sfbPe[sfb];
609        }
610        /* allow hole in mid channel ? */
611        else {
612        minEn = L_mpy_ls(psyOutChanR->sfbEnergy[sfb], (minSnrLimit * psyOutChanR->sfbMinSnr[sfb]) >> 16);
613
614          if (ahFlag[0][sfb]!= NO_AH &&
615              minEn > psyOutChanL->sfbEnergy[sfb]) {
616            ahFlag[0][sfb] = NO_AH;
617            psyOutChanL->sfbThreshold[sfb] = L_add(psyOutChanL->sfbEnergy[sfb], psyOutChanL->sfbEnergy[sfb]);
618            actPe = actPe - peData->peChannelData[0].sfbPe[sfb];
619          }
620        }
621
622        if (actPe < desiredPe)
623          break;
624      }
625    }
626  }
627
628  /* subsequently erase bands */
629  if (actPe > desiredPe) {
630    Word16 startSfb[2];
631    Word32 avgEn, minEn;
632    Word16 ahCnt;
633    Word16 enIdx;
634    Word16 enDiff;
635    Word32 en[4];
636    Word16 minSfb, maxSfb;
637    Flag   done;
638
639    /* do not go below startSfb */
640    for (ch=0; ch<nChannels; ch++) {
641
642      if (psyOutChannel[ch].windowSequence != SHORT_WINDOW)
643        startSfb[ch] = ahParam->startSfbL;
644      else
645        startSfb[ch] = ahParam->startSfbS;
646    }
647
648    avgEn = 0;
649    minEn = MAX_32;
650    ahCnt = 0;
651    for (ch=0; ch<nChannels; ch++) {
652      PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
653      for (sfb=startSfb[ch]; sfb<psyOutChan->sfbCnt; sfb++) {
654
655        if ((ahFlag[ch][sfb] != NO_AH) &&
656            (psyOutChan->sfbEnergy[sfb] > psyOutChan->sfbThreshold[sfb])) {
657          minEn = min(minEn, psyOutChan->sfbEnergy[sfb]);
658          avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfb]);
659          ahCnt++;
660        }
661      }
662    }
663
664    if(ahCnt) {
665      Word32 iahCnt;
666      shift = norm_l(ahCnt);
667	  iahCnt = Div_32( 1 << shift, ahCnt << shift );
668      avgEn = fixmul(avgEn, iahCnt);
669    }
670
671    enDiff = iLog4(avgEn) - iLog4(minEn);
672    /* calc some energy borders between minEn and avgEn */
673    for (enIdx=0; enIdx<4; enIdx++) {
674      Word32 enFac;
675      enFac = ((6-(enIdx << 1)) * enDiff);
676      en[enIdx] = fixmul(avgEn, pow2_xy(L_negate(enFac),7*4));
677    }
678
679    /* start with lowest energy border at highest sfb */
680    maxSfb = psyOutChannel[0].sfbCnt - 1;
681    minSfb = startSfb[0];
682
683    if (nChannels == 2) {
684      maxSfb = max(maxSfb, (psyOutChannel[1].sfbCnt - 1));
685      minSfb = min(minSfb, startSfb[1]);
686    }
687
688    sfb = maxSfb;
689    enIdx = 0;
690    done = 0;
691    while (!done) {
692
693      for (ch=0; ch<nChannels; ch++) {
694        PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
695
696        if (sfb>=startSfb[ch] && sfb<psyOutChan->sfbCnt) {
697          /* sfb energy below border ? */
698
699          if (ahFlag[ch][sfb] != NO_AH && psyOutChan->sfbEnergy[sfb] < en[enIdx]){
700            /* allow hole */
701            ahFlag[ch][sfb] = NO_AH;
702            psyOutChan->sfbThreshold[sfb] = L_add(psyOutChan->sfbEnergy[sfb], psyOutChan->sfbEnergy[sfb]);
703            actPe = actPe - peData->peChannelData[ch].sfbPe[sfb];
704          }
705
706          if (actPe < desiredPe) {
707            done = 1;
708            break;
709          }
710        }
711      }
712      sfb = sfb - 1;
713
714      if (sfb < minSfb) {
715        /* restart with next energy border */
716        sfb = maxSfb;
717        enIdx = enIdx + 1;
718
719        if (enIdx - 4 >= 0)
720          done = 1;
721      }
722    }
723  }
724}
725
726/********************************************************************************
727*
728* function name:adaptThresholdsToPe
729* description: two guesses for the reduction value and one final correction of the
730*              thresholds
731*
732**********************************************************************************/
733static void adaptThresholdsToPe(PSY_OUT_CHANNEL     psyOutChannel[MAX_CHANNELS],
734                                PSY_OUT_ELEMENT    *psyOutElement,
735                                Word16              logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
736                                PE_DATA            *peData,
737                                const Word16        nChannels,
738                                const Word16        desiredPe,
739                                AH_PARAM           *ahParam,
740                                MINSNR_ADAPT_PARAM *msaParam)
741{
742  Word16 noRedPe, redPe, redPeNoAH;
743  Word16 constPart, constPartNoAH;
744  Word16 nActiveLines, nActiveLinesNoAH;
745  Word16 desiredPeNoAH;
746  Word32 redVal, avgThrExp;
747  Word32 iter;
748
749  calcThreshExp(peData->thrExp, psyOutChannel, nChannels);
750
751  adaptMinSnr(psyOutChannel, logSfbEnergy, msaParam, nChannels);
752
753  initAvoidHoleFlag(peData->ahFlag, psyOutChannel, psyOutElement, nChannels, ahParam);
754
755  noRedPe = peData->pe;
756  constPart = peData->constPart;
757  nActiveLines = peData->nActiveLines;
758
759  /* first guess of reduction value t^0.25 = 2^((a-pen)/4*b) */
760  avgThrExp = pow2_xy((constPart - noRedPe), (nActiveLines << 2));
761
762  /* r1 = 2^((a-per)/4*b) - t^0.25 */
763  redVal = pow2_xy((constPart - desiredPe), (nActiveLines << 2)) - avgThrExp;
764
765  /* reduce thresholds */
766  reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal);
767
768  /* pe after first guess */
769  calcSfbPe(peData, psyOutChannel, nChannels);
770  redPe = peData->pe;
771
772  iter = 0;
773  do {
774    /* pe for bands where avoid hole is inactive */
775    calcPeNoAH(&redPeNoAH, &constPartNoAH, &nActiveLinesNoAH,
776               peData, peData->ahFlag, psyOutChannel, nChannels);
777
778    desiredPeNoAH = desiredPe -(redPe - redPeNoAH);
779
780    if (desiredPeNoAH < 0) {
781      desiredPeNoAH = 0;
782    }
783
784    /* second guess */
785
786    if (nActiveLinesNoAH > 0) {
787
788		avgThrExp = pow2_xy((constPartNoAH - redPeNoAH), (nActiveLinesNoAH << 2));
789
790		redVal = (redVal + pow2_xy((constPartNoAH - desiredPeNoAH), (nActiveLinesNoAH << 2))) - avgThrExp;
791
792		/* reduce thresholds */
793		reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal);
794    }
795
796    calcSfbPe(peData, psyOutChannel, nChannels);
797    redPe = peData->pe;
798
799    iter = iter+1;
800
801  } while ((20 * abs_s(redPe - desiredPe) > desiredPe) && (iter < 2));
802
803
804  if ((100 * redPe < 115 * desiredPe)) {
805    correctThresh(psyOutChannel, peData->ahFlag, peData, peData->thrExp, redVal,
806                  nChannels, desiredPe - redPe);
807  }
808  else {
809    Word16 desiredPe105 = (105 * desiredPe) / 100;
810    reduceMinSnr(psyOutChannel, peData, peData->ahFlag,
811                 nChannels, desiredPe105);
812    allowMoreHoles(psyOutChannel, psyOutElement, peData, peData->ahFlag,
813                   ahParam, nChannels, desiredPe105);
814  }
815}
816
817
818/*****************************************************************************
819*
820* function name: calcBitSave
821* description:  Calculates percentage of bit save, see figure below
822* returns:
823* input:        parameters and bitres-fullness
824* output:       percentage of bit save
825*
826*****************************************************************************/
827static Word16 calcBitSave(Word16 fillLevel,
828                          const Word16 clipLow,
829                          const Word16 clipHigh,
830                          const Word16 minBitSave,
831                          const Word16 maxBitSave)
832{
833  Word16 bitsave = 0;
834
835  fillLevel = max(fillLevel, clipLow);
836  fillLevel = min(fillLevel, clipHigh);
837
838  if(clipHigh-clipLow)
839  bitsave = (maxBitSave - (((maxBitSave-minBitSave)*(fillLevel-clipLow))/
840                              (clipHigh-clipLow)));
841
842  return (bitsave);
843}
844
845
846
847/*****************************************************************************
848*
849* function name: calcBitSpend
850* description:  Calculates percentage of bit spend, see figure below
851* returns:
852* input:        parameters and bitres-fullness
853* output:       percentage of bit spend
854*
855*****************************************************************************/
856static Word16 calcBitSpend(Word16 fillLevel,
857                           const Word16 clipLow,
858                           const Word16 clipHigh,
859                           const Word16 minBitSpend,
860                           const Word16 maxBitSpend)
861{
862  Word16 bitspend = 1;
863
864  fillLevel = max(fillLevel, clipLow);
865  fillLevel = min(fillLevel, clipHigh);
866
867  if(clipHigh-clipLow)
868  bitspend = (minBitSpend + ((maxBitSpend - minBitSpend)*(fillLevel - clipLow) /
869                                (clipHigh-clipLow)));
870
871  return (bitspend);
872}
873
874
875/*****************************************************************************
876*
877* function name: adjustPeMinMax()
878* description:  adjusts peMin and peMax parameters over time
879* returns:
880* input:        current pe, peMin, peMax
881* output:       adjusted peMin/peMax
882*
883*****************************************************************************/
884static void adjustPeMinMax(const Word16 currPe,
885                           Word16      *peMin,
886                           Word16      *peMax)
887{
888  Word16 minFacHi, maxFacHi, minFacLo, maxFacLo;
889  Word16 diff;
890  Word16 minDiff = extract_l(currPe / 6);
891  minFacHi = 30;
892  maxFacHi = 100;
893  minFacLo = 14;
894  maxFacLo = 7;
895
896  diff = currPe - *peMax ;
897
898  if (diff > 0) {
899    *peMin = *peMin + ((diff * minFacHi) / 100);
900    *peMax = *peMax + ((diff * maxFacHi) / 100);
901  } else {
902    diff = *peMin - currPe;
903
904    if (diff > 0) {
905      *peMin = *peMin - ((diff * minFacLo) / 100);
906      *peMax = *peMax - ((diff * maxFacLo) / 100);
907    } else {
908      *peMin = *peMin + ((currPe - *peMin) * minFacHi / 100);
909      *peMax = *peMax - ((*peMax - currPe) * maxFacLo / 100);
910    }
911  }
912
913
914  if ((*peMax - *peMin) < minDiff) {
915    Word16 partLo, partHi;
916
917    partLo = max(0, (currPe - *peMin));
918    partHi = max(0, (*peMax - currPe));
919
920    *peMax = currPe + ((partHi * minDiff) / (partLo + partHi));
921    *peMin = currPe - ((partLo * minDiff) / (partLo + partHi));
922    *peMin = max(0, *peMin);
923  }
924}
925
926
927/*****************************************************************************
928*
929* function name: BitresCalcBitFac
930* description:  calculates factor of spending bits for one frame
931*                1.0 : take all frame dynpart bits
932*                >1.0 : take all frame dynpart bits + bitres
933*                <1.0 : put bits in bitreservoir
934*  returns:      BitFac*100
935*  input:        bitres-fullness, pe, blockType, parameter-settings
936*  output:
937*
938*****************************************************************************/
939static Word16 bitresCalcBitFac( const Word16   bitresBits,
940                                const Word16   maxBitresBits,
941                                const Word16   pe,
942                                const Word16   windowSequence,
943                                const Word16   avgBits,
944                                const Word16   maxBitFac,
945                                ADJ_THR_STATE *AdjThr,
946                                ATS_ELEMENT   *adjThrChan)
947{
948  BRES_PARAM *bresParam;
949  Word16 pex;
950  Word16 fillLevel;
951  Word16 bitSave, bitSpend, bitresFac;
952
953  fillLevel = extract_l((100* bitresBits) / maxBitresBits);
954
955  if (windowSequence != SHORT_WINDOW)
956    bresParam = &(AdjThr->bresParamLong);
957  else
958    bresParam = &(AdjThr->bresParamShort);
959
960  pex = max(pe, adjThrChan->peMin);
961  pex = min(pex,adjThrChan->peMax);
962
963  bitSave = calcBitSave(fillLevel,
964                        bresParam->clipSaveLow, bresParam->clipSaveHigh,
965                        bresParam->minBitSave, bresParam->maxBitSave);
966
967  bitSpend = calcBitSpend(fillLevel,
968                          bresParam->clipSpendLow, bresParam->clipSpendHigh,
969                          bresParam->minBitSpend, bresParam->maxBitSpend);
970
971  if(adjThrChan->peMax != adjThrChan->peMin)
972	bitresFac = (100 - bitSave) + extract_l(((bitSpend + bitSave) * (pex - adjThrChan->peMin)) /
973                    (adjThrChan->peMax - adjThrChan->peMin));
974  else
975	bitresFac = 0x7fff;
976
977  bitresFac = min(bitresFac,
978                    (100-30 + extract_l((100 * bitresBits) / avgBits)));
979
980  bitresFac = min(bitresFac, maxBitFac);
981
982  adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax);
983
984  return bitresFac;
985}
986
987/*****************************************************************************
988*
989* function name: AdjThrInit
990* description:  init thresholds parameter
991*
992*****************************************************************************/
993void AdjThrInit(ADJ_THR_STATE *hAdjThr,
994                const Word32   meanPe,
995                Word32         chBitrate)
996{
997  ATS_ELEMENT* atsElem = &hAdjThr->adjThrStateElem;
998  MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam;
999
1000  /* common for all elements: */
1001  /* parameters for bitres control */
1002  hAdjThr->bresParamLong.clipSaveLow   =  20;
1003  hAdjThr->bresParamLong.clipSaveHigh  =  95;
1004  hAdjThr->bresParamLong.minBitSave    =  -5;
1005  hAdjThr->bresParamLong.maxBitSave    =  30;
1006  hAdjThr->bresParamLong.clipSpendLow  =  20;
1007  hAdjThr->bresParamLong.clipSpendHigh =  95;
1008  hAdjThr->bresParamLong.minBitSpend   = -10;
1009  hAdjThr->bresParamLong.maxBitSpend   =  40;
1010
1011  hAdjThr->bresParamShort.clipSaveLow   =  20;
1012  hAdjThr->bresParamShort.clipSaveHigh  =  75;
1013  hAdjThr->bresParamShort.minBitSave    =   0;
1014  hAdjThr->bresParamShort.maxBitSave    =  20;
1015  hAdjThr->bresParamShort.clipSpendLow  =  20;
1016  hAdjThr->bresParamShort.clipSpendHigh =  75;
1017  hAdjThr->bresParamShort.minBitSpend   = -5;
1018  hAdjThr->bresParamShort.maxBitSpend   =  50;
1019
1020  /* specific for each element: */
1021
1022  /* parameters for bitres control */
1023  atsElem->peMin = extract_l(((80*meanPe) / 100));
1024  atsElem->peMax = extract_l(((120*meanPe) / 100));
1025
1026  /* additional pe offset to correct pe2bits for low bitrates */
1027  atsElem->peOffset = 0;
1028  if (chBitrate < 32000) {
1029    atsElem->peOffset = max(50, (100 - extract_l((100 * chBitrate) / 32000)));
1030  }
1031
1032  /* avoid hole parameters */
1033  if (chBitrate > 20000) {
1034    atsElem->ahParam.modifyMinSnr = TRUE;
1035    atsElem->ahParam.startSfbL = 15;
1036    atsElem->ahParam.startSfbS = 3;
1037  }
1038  else {
1039    atsElem->ahParam.modifyMinSnr = FALSE;
1040    atsElem->ahParam.startSfbL = 0;
1041    atsElem->ahParam.startSfbS = 0;
1042  }
1043
1044  /* minSnr adaptation */
1045  /* maximum reduction of minSnr goes down to minSnr^maxRed */
1046  msaParam->maxRed = 0x20000000;     /* *0.25f */
1047  /* start adaptation of minSnr for avgEn/sfbEn > startRatio */
1048  msaParam->startRatio = 0x0ccccccd; /* 10 */
1049  /* maximum minSnr reduction to minSnr^maxRed is reached for
1050     avgEn/sfbEn >= maxRatio */
1051  msaParam->maxRatio =  0x0020c49c; /* 1000 */
1052  /* helper variables to interpolate minSnr reduction for
1053     avgEn/sfbEn between startRatio and maxRatio */
1054
1055  msaParam->redRatioFac = 0xfb333333; /* -0.75/20 */
1056
1057  msaParam->redOffs = 0x30000000;  /* msaParam->redRatioFac * 10*log10(msaParam->startRatio) */
1058
1059
1060  /* pe correction */
1061  atsElem->peLast = 0;
1062  atsElem->dynBitsLast = 0;
1063  atsElem->peCorrectionFactor = 100; /* 1.0 */
1064
1065}
1066
1067/*****************************************************************************
1068*
1069* function name: calcPeCorrection
1070* description:  calculates the desired perceptual entropy factor
1071*				It is between 0.85 and 1.15
1072*
1073*****************************************************************************/
1074static void calcPeCorrection(Word16 *correctionFac,
1075                             const Word16 peAct,
1076                             const Word16 peLast,
1077                             const Word16 bitsLast)
1078{
1079  Word32 peAct100 = 100 * peAct;
1080  Word32 peLast100 = 100 * peLast;
1081  Word16 peBitsLast = bits2pe(bitsLast);
1082
1083  if ((bitsLast > 0) &&
1084      (peAct100 < (150 * peLast)) &&  (peAct100 > (70 * peLast)) &&
1085      ((120 * peBitsLast) > peLast100 ) && (( 65 * peBitsLast) < peLast100))
1086    {
1087      Word16 newFac = (100 * peLast) / peBitsLast;
1088      /* dead zone */
1089
1090      if (newFac < 100) {
1091        newFac = min(((110 * newFac) / 100), 100);
1092        newFac = max(newFac, 85);
1093      }
1094      else {
1095        newFac = max(((90 * newFac) / 100), 100);
1096        newFac = min(newFac, 115);
1097      }
1098
1099      if ((newFac > 100 && *correctionFac < 100) ||
1100          (newFac < 100 && *correctionFac > 100)) {
1101        *correctionFac = 100;
1102      }
1103      /* faster adaptation towards 1.0, slower in the other direction */
1104
1105      if ((*correctionFac < 100 && newFac < *correctionFac) ||
1106          (*correctionFac > 100 && newFac > *correctionFac))
1107        *correctionFac = (85 * *correctionFac + 15 * newFac) / 100;
1108      else
1109        *correctionFac = (70 * *correctionFac + 30 * newFac) / 100;
1110      *correctionFac = min(*correctionFac, 115);
1111      *correctionFac = max(*correctionFac, 85);
1112    }
1113  else {
1114    *correctionFac = 100;
1115  }
1116}
1117
1118/********************************************************************************
1119*
1120* function name: AdjustThresholds
1121* description:  Adjust thresholds to the desired bitrate
1122*
1123**********************************************************************************/
1124void AdjustThresholds(ADJ_THR_STATE   *adjThrState,
1125                      ATS_ELEMENT     *AdjThrStateElement,
1126                      PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
1127                      PSY_OUT_ELEMENT *psyOutElement,
1128                      Word16          *chBitDistribution,
1129                      Word16           logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
1130                      Word16           sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
1131                      QC_OUT_ELEMENT  *qcOE,
1132					  ELEMENT_BITS	  *elBits,
1133					  const Word16     nChannels,
1134                      const Word16     maxBitFac)
1135{
1136  PE_DATA peData;
1137  Word16 noRedPe, grantedPe, grantedPeCorr;
1138  Word16 curWindowSequence;
1139  Word16 bitFactor;
1140  Word16 avgBits = (elBits->averageBits - (qcOE->staticBitsUsed + qcOE->ancBitsUsed));
1141  Word16 bitresBits = elBits->bitResLevel;
1142  Word16 maxBitresBits = elBits->maxBits;
1143  Word16 sideInfoBits = (qcOE->staticBitsUsed + qcOE->ancBitsUsed);
1144  Word16 ch;
1145  memset(&peData, 0, sizeof(peData));
1146
1147  prepareSfbPe(&peData, psyOutChannel, logSfbEnergy, sfbNRelevantLines, nChannels, AdjThrStateElement->peOffset);
1148
1149  /* pe without reduction */
1150  calcSfbPe(&peData, psyOutChannel, nChannels);
1151  noRedPe = peData.pe;
1152
1153
1154  curWindowSequence = LONG_WINDOW;
1155
1156  if (nChannels == 2) {
1157
1158    if ((psyOutChannel[0].windowSequence == SHORT_WINDOW) ||
1159        (psyOutChannel[1].windowSequence == SHORT_WINDOW)) {
1160      curWindowSequence = SHORT_WINDOW;
1161    }
1162  }
1163  else {
1164    curWindowSequence = psyOutChannel[0].windowSequence;
1165  }
1166
1167
1168  /* bit factor */
1169  bitFactor = bitresCalcBitFac(bitresBits, maxBitresBits, noRedPe+5*sideInfoBits,
1170                               curWindowSequence, avgBits, maxBitFac,
1171                               adjThrState,
1172                               AdjThrStateElement);
1173
1174  /* desired pe */
1175  grantedPe = ((bitFactor * bits2pe(avgBits)) / 100);
1176
1177  /* correction of pe value */
1178  calcPeCorrection(&(AdjThrStateElement->peCorrectionFactor),
1179                   min(grantedPe, noRedPe),
1180                   AdjThrStateElement->peLast,
1181                   AdjThrStateElement->dynBitsLast);
1182  grantedPeCorr = (grantedPe * AdjThrStateElement->peCorrectionFactor) / 100;
1183
1184
1185  if (grantedPeCorr < noRedPe && noRedPe > peData.offset) {
1186    /* calc threshold necessary for desired pe */
1187    adaptThresholdsToPe(psyOutChannel,
1188                        psyOutElement,
1189                        logSfbEnergy,
1190                        &peData,
1191                        nChannels,
1192                        grantedPeCorr,
1193                        &AdjThrStateElement->ahParam,
1194                        &AdjThrStateElement->minSnrAdaptParam);
1195  }
1196
1197  /* calculate relative distribution */
1198  for (ch=0; ch<nChannels; ch++) {
1199    Word16 peOffsDiff = peData.pe - peData.offset;
1200    chBitDistribution[ch] = 200;
1201
1202    if (peOffsDiff > 0) {
1203      Word32 temp = 1000 - (nChannels * 200);
1204      chBitDistribution[ch] = chBitDistribution[ch] +
1205		  (temp * peData.peChannelData[ch].pe) / peOffsDiff;
1206    }
1207  }
1208
1209  /* store pe */
1210  qcOE->pe = noRedPe;
1211
1212  /* update last pe */
1213  AdjThrStateElement->peLast = grantedPe;
1214}
1215
1216/********************************************************************************
1217*
1218* function name: AdjThrUpdate
1219* description:  save dynBitsUsed for correction of bits2pe relation
1220*
1221**********************************************************************************/
1222void AdjThrUpdate(ATS_ELEMENT *AdjThrStateElement,
1223                  const Word16 dynBitsUsed)
1224{
1225  AdjThrStateElement->dynBitsLast = dynBitsUsed;
1226}
1227
1228
1229