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