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